initial commit
[rofl0r-KOL.git] / KOL.pas
blobe87bd5bbcbaff4b3431edc024c873ba65fa82dfd
1 //[START OF KOL.pas]
2 {****************************************************************
4 KKKKK KKKKK OOOOOOOOO LLLLL
5 KKKKK KKKKK OOOOOOOOOOOOO LLLLL
6 KKKKK KKKKK OOOOO OOOOO LLLLL
7 KKKKK KKKKK OOOOO OOOOO LLLLL
8 KKKKKKKKKK OOOOO OOOOO LLLLL
9 KKKKK KKKKK OOOOO OOOOO LLLLL
10 KKKKK KKKKK OOOOO OOOOO LLLLL
11 KKKKK KKKKK OOOOOOOOOOOOO LLLLLLLLLLLLL
12 KKKKK KKKKK OOOOOOOOO LLLLLLLLLLLLL
14 Key Objects Library (C) 2000 by Kladov Vladimir.
16 //[VERSION]
17 ****************************************************************
18 * VERSION 2.00
19 ****************************************************************
20 //[END OF VERSION]
22 K.O.L. - is a set of objects to create small programs
23 with the Delphi, but without the VCL. KOL allows to
24 create executables of size about 10 times smaller then
25 those created with the VCL. But this does not mean that
26 KOL is less power then the VCL - perhaps just the opposite...
28 KOL is provided free with the source code.
29 Copyright (C) Vladimir Kladov, 2000-2003.
31 For code provided by other developers (even if later
32 changed by me) authors are noted in the source.
34 mailto: bonanzas@online.sinor.ru
35 Web-Page: http://bonanzas.rinet.ru
37 See also Mirror Classes Kit (M.C.K.) which allows
38 to create KOL programs visually.
40 ****************************************************************}
42 //[UNIT DEFINES]
43 {$INCLUDE delphidef.inc}
45 //[START OF UNIT]
46 unit KOL;
47 {-}
49 Please note, that KOL does not use keyword 'class'. Instead,
50 poor Pascal 'object' is the base of our objects. So, remember,
51 how we worked earlier with such Object Pascal's objects:
52 |<br>
53 - to create objects dynamically, use P<objname> instead of
54 T<objname> to allocate a pointer for dynamically created
55 object instance;
56 |<br>
57 - remember, that constructors of objects can not be virtual.
58 Override procedure Init instead in your own derived objects;
59 |<br>
60 - rather then call constructors of objects, call global procedures
61 New<objname> (e.g. NewLabel). If not, first (for virtualally
62 created objects) call New( ); then call constructor Create
63 (which calls Init) - but this is possible only if the constructor
64 is overriden by a new one.
65 |<br>
66 - the operator 'is' is not applicable to objects. And operator 'as'
67 is not necessary (and is not applicable too), use typecast to desired
68 object type, e.g.: "PSomeObjectType( C )" inplace of "C as TSomeClassType".
69 |<br>
70 |<hr>
71 Also remember, that IF [ MyObj: PMyObj ] THEN
73 NOT[ with MyObj do ] BUT[ with MyObj^ do ]
75 Though it is possible to skip '^' symbol when accessing member
76 fields, methods, properties, e.g. [ MyObj.Execute; ]
77 |<hr>
78 |&U=&nbsp;&nbsp;&nbsp;<a href="#%0">%0</a><br>
79 |&B=<a href="%1.htm">%0</a><br>
80 |&C=<a href="%1.htm">%0</a>
81 | <table border=1 cellpadding=6 width=100%>
82 | <colgroup valign=top span=2>
83 | <tr>
84 | <td> objects </td> <td> functions by category </td>
85 | </tr>
86 | <td>
87 <C _TObj> <B TObj>
88 <C TList> <C TListEx> <C TStrList> <B TStrListEx>
89 <C TTree> <C TDirList> <C TIniFile> <C TCabFile>
90 <B TStream>
91 <B TControl>
92 <C TGraphicTool> <C TCanvas> <C TImageList> <C TIcon> <C TBitmap>
93 <C TGif> <C TGifDecoder> <B TJpeg>
94 <C TTimer> <C TThread> <C TTrayIcon> <C TDirChange> <B TMediaPlayer>
95 <C TMenu> <C TOpenSaveDialog> <C TOpenDirDialog> <B TColorDialog>
96 <C TAction> <B TActionList>
97 <B Exception>
98 | </td>
99 | <td>
100 |<a href="kol_pas.htm#visual_objects_constructors">
101 Visual objects constructing functions
102 |</a><br><br>
103 <U Working with null-terminated and ansi strings>
104 <U Small bit arrays (max 32 bits in array)>
105 <U Arithmetics, geometry and other utility functions>
106 <U Data sorting (quicksort implementation)>
107 <U String to number and number to string conversions>
108 <U 64-bit integer numbers>
109 <U Floating point numbers>
110 <U Date and time handling>
111 <U File and directory routines>
112 <U System functions and working with windows>
113 <U Text in clipboard operations>
114 <U Wrappers to registry API functions>
115 | </td>
116 | </table>
118 Several conditional symbols can be used in a project
119 (Project | Options | Directories/Conditional Defines)
120 to change code generated a bit. There are following:
121 |<pre>
123 PAS_VERSION - to use Pascal version of the code.
124 PARANOIA - to force short versions of asm instructions (for D5
125 and below, D6 and higher use those instructions always).
126 USE_CONSTRUCTORS - to use constructors like in VCL.
127 USE_CUSTOMEXTENSIONS - to extend TControl with custom additions.
128 UNICODE_CTRLS - to use Unicode versions of controls (WM_XXXXW messages,
129 etc.)
130 USE_MHTOOLTIP - to use MHTOOLTIP.
131 NOT_USE_OnIdle - to stop using OnIdle event (to make code smaller
132 if it is not used actually).
133 USE_ASM_DODRAG - to use assembler version of code for DoDrag.
134 ENUM_DYN_HANDLERS_AFTER_RUN - to allow all the events handling even when
135 AppletTerminated become TRUE.
136 ALL_BUTTONS_RESPOND_TO_ENTER - obvious (by default, buttons respond to key
137 SPACE, since those are working this way in Windows).
138 ESC_CLOSE_DIALOGS - to allow closing all dialogs with ESCAPE.
139 OpenSaveDialog_Extended - to allow using custom extensions for OpenSaveDialog.
140 AUTO_CONTEXT_HELP - to use automatic respond to WM_CONTEXTMENU to call
141 context help.
142 NOT_FIX_CURINDEX - to use old version of TControl.SetItems, which could
143 lead to loose CurIndex value (e.g. for Combobox)
144 NEW_MODAL - to use extended madalness.
145 USE_SETMODALRESULT - to guarantee ModalResult property assigninig handling.
146 USE_MENU_CURCTL - to use CurCtl property in popup menu to detect which
147 control initiated a pop-up.
148 NEW_MENU_ACCELL - to use another menu accelerators handling, without
149 AcceleratorTable
150 USE_DROPDOWNCOUNT - to force setting combobox dropdown count.
151 NOT_UNLOAD_RICHEDITLIB - to stop unload Rich Edit library in finalization
152 section (to economy several byte of code).
153 DEBUG_GDIOBJECTS - to allow counting all the GDI objects used.
154 CHK_BITBLT - to check BitBlt operations.
155 DEBUG_ENDSESSION - to allow debugging WM_ENDSESSION handling.
156 DEBUG_CREATEWINDOW - to debug CreateWindow.
157 TEST_CLOSE - to debug Close.
158 DEBUG_MENU - to debug menu.
159 DEBUG_DBLBUFF - to debug DoubleBuffered.
160 DEBUG - other debugging.
162 |</pre>
164 {= K.O.L - êëþ÷åâàÿ áèáëèîòåêà îáúåêòîâ. (C) Êëàäîâ Âëàäèìèð, 2000-2003.
167 //[OPTIONS]
168 {$A-} // align off, otherwise code is not good
171 {$Q-} // no overflow check: this option makes code wrong
172 {$R-} // no range checking: this option makes code wrong
173 {$T-} // not typed @-operator
174 {$D-}
175 {$IFDEF INPACKAGE} // use this symbol in packages requiring kol.pas
176 {$WARNINGS OFF}
177 {$ENDIF}
178 {$IFDEF _D7orHigher}
179 {$WARN UNSAFE_TYPE OFF} // Too many such warnings in Delphi7
180 {$WARN UNSAFE_CODE OFF}
181 {$WARN UNSAFE_CAST OFF}
182 {$ENDIF}
185 //[START OF INTERFACE]
186 interface
188 //{$DEFINE DEBUG_GDIOBJECTS}
189 //{$DEFINE CHK_GDI}
191 //[USES]
192 uses
193 messages, windows, RichEdit {$IFDEF CHK_GDI}, ChkGdi {$ENDIF};
194 //[END OF USES]
196 {$IFDEF DEBUG_GDIOBJECTS}
198 BrushCount: Integer;
199 FontCount: Integer;
200 PenCount: Integer;
201 {$ENDIF}
204 //{_#IF [DELPHI]}
205 {$INCLUDE delphicommctrl.inc}
206 //{_#ENDIF}
208 type
209 //[_TObj DEFINITION]
212 _TObj = object
213 {* auxiliary object type. See TObj. }
214 protected
215 procedure Init; virtual;
216 {* Is called from a constructor to initialize created object instance
217 filling its fields with 0. Can be overriden in descendant objects
218 to add another initialization code there. (Main reason of intending
219 is what constructors can not be virtual in poor objects). }
220 {= Âûçûâàåòñÿ äëÿ èíèöèàëèçàöèè îáúåêòà. }
221 public
222 function VmtAddr: Pointer;
223 {* Returns addres of virtual methods table of object. ? }
224 {= âîçâðàùàåò àäðåñ òàáëèöû âèðòóàëüíûõ ìåòîäîâ (VMT). ? }
225 end;
228 {++}(* TObj = class;*){--}
229 PObj = {-}^{+}TObj;
230 {* }
232 {++}(* TList = class;*){--}
233 PList = {-}^{+}TList;
234 {* }
236 //[TObjectMethod DECLARATION]
237 TObjectMethod = procedure of object;
238 {* }
239 TOnEvent = procedure( Sender: PObj ) of object;
240 {* This type of event is the most common - event handler when called can
241 know only what object was a sender of this call. Replaces good known
242 VCL TNotifyEvent event type. }
244 //[TPointerList DECLARATION]
245 PPointerList = ^TPointerList;
246 TPointerList = array[0..MaxInt div 4 - 1] of Pointer;
248 { ---------------------------------------------------------------------
250 TObj - base object to derive all others
252 ---------------------------------------------------------------------- }
253 //[TObj DEFINITION]
254 TObj = {-} object( _TObj ) {+}{++}(*class*){--}
255 {* Prototype for all objects of KOL. All its methods are important to
256 implement objects in a manner similar to Delphi TObject class. }
257 {= Áàçîâûé êëàññ äëÿ âñåõ ïðî÷èõ îáúåêòîâ KOL. }
258 protected
259 fRefCount: Integer;
260 fOnDestroy: TOnEvent;
261 procedure DoDestroy;
262 protected
263 fAutoFree: PList;
264 {* Is called from a constructor to initialize created object instance
265 filling its fields with 0. Can be overriden in descendant objects
266 to add another initialization code there. (Main reason of intending
267 is what constructors can not be virtual in poor objects). }
268 {= Âûçûâàåòñÿ äëÿ èíèöèàëèçàöèè îáúåêòà. }
269 fTag: DWORD;
270 {* Custom data. }
271 {++}(*public*){--}
272 destructor Destroy; {-} virtual; {+}{++}(* override; *){--}
273 {* Disposes memory, allocated to an object. Does not release huge strings,
274 dynamic arrays and so on. Such memory should be freeing in overriden
275 destructor. }
276 {= Îñâîáîæäàåò ïàìÿòü, âûäåëåííóþ äëÿ îáúåêòà. Íå îñâîáîæäàåò ïàìÿòü, âûäåëåííóþ
277 äëÿ ñòðîê, äèíàìè÷èñêèõ ìàññèâîâ è ò.ï. Òàêàÿ ïàìÿòü äîëæíà áûòü îñâîáîæäåíà
278 â ïåðåîïðåäåëåííîì äåñòðóêòîðå îáúåêòà. }
279 {++}(*protected*){--}
280 {++}(*
281 procedure Init; virtual;
282 {* Can be overriden in descendant objects
283 to add initialization code there. (Main reason of intending
284 is what constructors can not be virtual in poor objects). }
285 *){--}
286 procedure Final;
287 {* Is called in destructor to perform OnDestroy event call and to
288 released objects, added to fAutoFree list. }
289 public
290 procedure Free;
291 {* Before calling destructor of object, checks if passed pointer is not
292 nil - similar what is done in VCL for TObject. It is ALWAYS recommended
293 to use Free instead of Destroy - see also comments to RefInc, RefDec. }
294 {= Äî âûçîâà äåñòðóêòîðà, ïðîâåðÿåò, íå ïåðåäàí ëè nil â êà÷åñòâå ïàðàìåòðà.
295 ÂÑÅÃÄÀ ðåêîìåíäóåòñÿ èñïîëüçîâàòü Free âìåñòî Destroy - ñì. òàê æå RefInc,
296 RefDec. }
299 // By Vyacheslav Gavrik:
300 function InstanceSize: Integer;
301 {* Returns a size of object instance. }
304 constructor Create;
305 {* Constructor. Do not call it. Instead, use New<objectname> function
306 call for certain object, e.g., NewLabel( AParent, 'caption' ); }
307 {= Êîíñòðóêòîð. Íå ñëåäóåò âûçûâàòü åãî. Äëÿ êîíñòðóèðîâàíèÿ îáúåêòîâ,
308 âûçûâàéòå ñîîòâåòñòâóþùóþ ãëîáàëüíóþ ôóíêöèþ New<èìÿ-îáúåêòà>. Íàïðèìåð,
309 NewLabel( MyForm, 'Ìåòêà¹1' ); }
311 class function AncestorOfObject( Obj: Pointer ): Boolean;
312 {* Is intended to replace 'is' operator, which is not applicable to objects. }
313 {= }
314 function VmtAddr: Pointer;
315 {* Returns addres of virtual methods table of object. }
316 {= âîçâðàùàåò àëðåñ òàáëèöû âèðòóàëüíûõ ìåòîäîâ (VMT). }
318 procedure RefInc;
319 {* See comments below. }
320 {= Ñì. RefDec íèæå. }
321 procedure RefDec;
322 {* Decrements reference count. If it is becoming <0, and Free
323 method was already called, object is (self-) destroyed. Otherwise,
324 Free method does not destroy object, but only sets flag
325 "Free was called".
326 |<br>
327 Use RefInc..RefDec to provide a block of code, where
328 object can not be destroyed by call of Free method.
329 This makes code more safe from intersecting flows of processing,
330 where some code want to destroy object, but others suppose that it
331 is yet existing.
332 |<br>
333 If You want to release object at the end of block RefInc..RefDec,
334 do it immediately BEFORE call of last RefDec (to avoid situation,
335 when object is released in result of RefDec, and attempt to
336 destroy it follow leads to AV exception).
338 {= Óìåíüøàåò ñ÷åò÷èê èñïîëüçîâàíèÿ. Åñëè â ðåçóëüòàòå ñ÷åò÷èê ñòàíîâèòñÿ
339 < 0, è ìåòîä Free óæå áûë âûçâàí, îáúåêò (ñàìî-) ðàçðóøàåòñÿ. Èíà÷å,
340 ìåòîä Free íå ðàçðóøàåò îáúåêò, à òîëüêî óñòàíàâëèâàåò ôëàã "Free áûë
341 âûçâàí".
342 |<br>
343 Èñïîëüçóéòå RefInc..RefDec äëÿ ïðåäîòâðàùåíèÿ ðàçðóøåíèÿ îáúåêòà íà
344 íåêîòîðîì ó÷àñòêå êîäà (åñëè åñòü òàêàÿ íåîáõîäèìîñòü).
345 |<br>
346 Åñëè íóæíî óáèòü (âðåìåííûé) îáúåêò âìåñòå ñ ïîñëåäíèì RefDec, ñäåëàéòå
347 âûçîâ Free íåìåäëåííî ÏÅÐÅÄ ïîñëåäíèì RefDec. }
348 property RefCount: Integer read fRefCount;
349 {* }
350 property OnDestroy: TOnEvent read fOnDestroy write fOnDestroy;
351 {* This event is provided for any KOL object, so You can provide your own
352 OnDestroy event for it. }
353 {= Äàííîå ñîáûòèå îáåñïå÷èâàåòñÿ äëÿ âñåõ îáúåêòîâ KOL. Ïîçâîëÿåò ñäåëàòü
354 ÷òî-íèáóäü â ñâÿçè ñ ðàçðóøåíèåì îáúåêòà. }
355 procedure Add2AutoFree( Obj: PObj );
356 {* Adds an object to the list of objects, destroyed automatically
357 when the object is destroyed. Do not add here child controls of
358 the TControl (these are destroyed by another way). Only non-control
359 objects, which are not destroyed automatically, should be added here. }
360 procedure Add2AutoFreeEx( Proc: TObjectMethod );
361 {* Adds an event handler to the list of events, called in destructor.
362 This method is mainly for internal use, and allows to auto-destroy
363 VCL components, located on KOL form at design time (in MCK project). }
364 property Tag: DWORD read fTag write fTag;
365 {* Custom data field. }
366 end;
367 //[END OF TObj DEFINITION]
369 { ---------------------------------------------------------------------
371 TList - object to implement list of pointers (or dwords)
373 ---------------------------------------------------------------------- }
374 //[TList DEFINITION]
375 TList = object( TObj )
376 {* Simple list of pointers. It is used in KOL instead of standard VCL
377 TList to store any kind data (or pointers to these ones). Can be created
378 calling function NewList. }
379 {= Ïðîñòîé ñïèñîê óêàçàòåëåé. }
380 protected
381 fItems: PPointerList;
382 fCount: Integer;
383 fCapacity: Integer;
384 fAddBy: Integer;
385 procedure SetCount(const Value: Integer);
386 procedure SetAddBy(Value: Integer);
387 {++}(*public*){--}
388 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
389 {* Destroys list, freeing memory, allocated for pointers. Programmer
390 is resposible for destroying of data, referenced by the pointers. }
391 {= }
392 {++}(*protected*){--}
393 procedure SetCapacity( Value: Integer );
394 function Get( Idx: Integer ): Pointer;
395 procedure Put( Idx: Integer; Value: Pointer );
396 {$IFDEF USE_CONSTRUCTORS}
397 procedure Init; virtual;
398 {$ENDIF USE_CONSTRUCTORS}
399 public
400 procedure Clear;
401 {* Makes Count equal to 0. Not responsible for freeing (or destroying)
402 data, referenced by released pointers. }
403 procedure Add( Value: Pointer );
404 {* Adds pointer to the end of list, increasing Count by one. }
405 procedure Insert( Idx: Integer; Value: Pointer );
406 {* Inserts pointer before given item. Returns Idx, i.e. index of
407 inserted item in the list. Indeces of items, located after insertion
408 point, are increasing. To add item to the end of list, pass Count
409 as index parameter. To insert item before first item, pass 0 there. }
410 function IndexOf( Value: Pointer ): Integer;
411 {* Searches first (from start) item pointer with given value and returns
412 its index (zero-based) if found. If not found, returns -1. }
413 procedure Delete( Idx: Integer );
414 {* Deletes given (by index) pointer item from the list, shifting all
415 follow item indeces up by one. }
416 procedure DeleteRange( Idx, Len: Integer );
417 {* Deletes Len items starting from Idx. }
418 procedure Remove( Value: Pointer );
419 {* Removes first entry of a Value in the list. }
420 property Count: Integer read fCount write SetCount;
421 {* Returns count of items in the list. It is possible to delete a number
422 of items at the end of the list, keeping only first Count items alive,
423 assigning new value to Count property (less then Count it is). }
424 property Capacity: Integer read fCapacity write SetCapacity;
425 {* Returns number of pointers which could be stored in the list
426 without reallocating of memory. It is possible change this value
427 for optimize usage of the list (for minimize number of reallocating
428 memory operations). }
429 property Items[ Idx: Integer ]: Pointer read Get write Put; default;
430 {* Provides access (read and write) to items of the list. Please note,
431 that TList is not responsible for freeing memory, referenced by stored
432 pointers. }
433 function Last: Pointer;
434 {* Returns the last item (or nil, if the list is empty). }
435 procedure Swap( Idx1, Idx2: Integer );
436 {* Swaps two items in list directly (fast, but without testing of
437 index bounds). }
438 procedure MoveItem( OldIdx, NewIdx: Integer );
439 {* Moves item to new position. Pass NewIdx >= Count to move item
440 after the last one. }
441 procedure Release;
442 {* Especially for lists of pointers to dynamically allocated memory.
443 Releases all pointed memory blocks and destroys object itself. }
444 procedure ReleaseObjects;
445 {* Especially for a list of objects derived from TObj.
446 Calls Free for every of the object in the list, and then calls
447 Free for the object itself. }
448 property AddBy: Integer read fAddBy write SetAddBy;
449 {* Value to increment capacity when new items are added or inserted
450 and capacity need to be increased. }
451 property DataMemory: PPointerList read fItems;
452 {* Raw data memory. Can be used for direct access to items of a list. }
453 procedure Assign( SrcList: PList );
454 {* Copies all source list items. }
455 end;
456 //[END OF TList DEFINITION]
458 //[NewList DECLARATION]
459 function NewList: PList;
460 {* Returns pointer to newly created TList object. Use it instead usual
461 TList.Create as it is done in VCL or XCL. }
463 procedure FastIncNum2Elements( List: TList; FromIdx, Count, Value: Integer );
464 {* Very fast adds Value to List elements from List[FromIdx] to List[FromIdx+Count-1].
465 Given elements must exist. Count must be > 0. }
467 procedure Free_And_Nil( var Obj );
468 {* Obj.Free and Obj := nil, where Obj *MUST* be TObj or its descendant
469 (TControl, TMenu, etc.) This procedure is not compatible with VCL's
470 FreeAndNil, which works with TObject, since this it has another name. }
472 type
474 //[TListEx DEFINITION]
475 {++}(*TListEx = class;*){--}
476 PListEx = {-}^{+}TListEx;
477 TListEx = object( TObj )
478 {* Extended list, with Objects[ ] property. Created calling NewListEx function. }
479 protected
480 fList: PList;
481 fObjects: PList;
482 function GetEx(Idx: Integer): Pointer;
483 procedure PutEx(Idx: Integer; const Value: Pointer);
484 function GetCount: Integer;
485 function GetAddBy: Integer;
486 procedure Set_AddBy(const Value: Integer);
487 public
488 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
489 {* }
490 property AddBy: Integer read GetAddBy write Set_AddBy;
491 {* }
492 property Items[ Idx: Integer ]: Pointer read GetEx write PutEx;
493 {* }
494 property Count: Integer read GetCount;
495 {* }
496 procedure Clear;
497 {* }
498 procedure Add( Value: Pointer );
499 {* }
500 procedure AddObj( Value, Obj: Pointer );
501 {* }
502 procedure Insert( Idx: Integer; Value: Pointer );
503 {* }
504 procedure InsertObj( Idx: Integer; Value, Obj: Pointer );
505 {* }
506 procedure Delete( Idx: Integer );
507 {* }
508 procedure DeleteRange( Idx, Len: Integer );
509 {* }
510 function IndexOf( Value: Pointer ): Integer;
511 {* }
512 function IndexOfObj( Obj: Pointer ): Integer;
513 {* }
514 procedure Swap( Idx1, Idx2: Integer );
515 {* }
516 procedure MoveItem( OldIdx, NewIdx: Integer );
517 {* }
518 property ItemsList: PList read fList;
519 {* }
520 property ObjList: PList read fObjects;
521 {* }
522 function Last: Pointer;
523 {* }
524 function LastObj: Pointer;
525 {* }
526 end;
527 //[END OF TListEx DEFINITION]
529 //[NewListEx DECLARATION]
530 function NewListEx: PListEx;
531 {* Creates extended list. }
539 { -- tree (non-visual) -- }
541 type
542 //[TTree DEFINITION]
543 {++}(*TTree = class;*){--}
544 PTree = {-}^{+}TTree;
545 TTree = object( TObj )
546 {* Object to store tree-like data in memory (non-visual). }
547 protected
548 fParent: PTree;
549 fChildren: PList;
550 fPrev: PTree;
551 fNext: PTree;
552 fName: String;
553 fData: Pointer;
554 function GetCount: Integer;
555 function GetItems(Idx: Integer): PTree;
556 procedure Unlink;
557 function GetRoot: PTree;
558 function GetLevel: Integer;
559 function GetTotal: Integer;
560 function GetIndexAmongSiblings: Integer;
561 protected
562 {$IFDEF USE_CONSTRUCTORS}
563 constructor CreateTree( AParent: PTree; const AName: String );
564 {* }
565 {$ENDIF}
566 {++}(*public*){--}
567 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
568 {* }
569 {++}(*protected*){--}
570 procedure Init; {-}virtual;{+}{++}(*override;*){--}
571 public
572 procedure Clear;
573 {* Destoyes all child nodes. }
574 property Name: String read fName write fName;
575 {* Optional node name. }
576 property Data: Pointer read fData write fData;
577 {* Optional user-defined pointer. }
578 property Count: Integer read GetCount;
579 {* Number of child nodes of given node. }
580 property Items[ Idx: Integer ]: PTree read GetItems;
581 {* Child nodes list items. }
582 procedure Add( Node: PTree );
583 {* Adds another node as a child of given tree node. This operation
584 as well as Insert can be used to move node together with its children
585 to another location of the same tree or even from another tree.
586 Anyway, added Node first correctly removed from old place (if it is
587 defined for it). But for simplest task, such as filling of tree with
588 nodes, code should looking as follows:
589 ! Node := NewTree( nil, 'test of creating node without parent' );
590 ! RootOfMyTree.Add( Node );
591 Though, this code gives the same result as:
592 ! Node := NewTree( RootOfMyTree, 'test of creatign node as a child' ); }
593 procedure Insert( Before, Node: PTree );
594 {* Inserts earlier created 'Node' just before given child node 'Before'
595 as a child of given tree node. See also Add method. }
596 property Parent: PTree read fParent;
597 {* Returns parent node (or nil, if there is no parent). }
598 property Index: Integer read GetIndexAmongSiblings;
599 {* Returns an index of the node in a list of nodes of the same parent
600 (or -1, if Parent is not defined). }
601 property PrevSibling: PTree read fPrev;
602 {* Returns previous node in a list of children of the Parent. Nil is
603 returned, if given node is the first child of the Parent or has
604 no Parent. }
605 property NextSibling: PTree read fNext;
606 {* Returns next node in a list of children of the Parent. Nil is returned,
607 if given node is the last child of the Parent or has no Parent at all. }
608 property Root: PTree read GetRoot;
609 {* Returns root node (i.e. the last Parent, enumerating parents recursively). }
610 property Level: Integer read GetLevel;
611 {* Returns level of the node, i.e. integer value, equal to 0 for root
612 of a tree, 1 for its children, etc. }
613 property Total: Integer read GetTotal;
614 {* Returns total number of children of the node and all its children
615 counting its recursively (but node itself is not considered, i.e.
616 Total for node without children is equal to 0). }
617 procedure SortByName;
618 {* Sorts children of the node in ascending order. Sorting is not
619 recursive, i.e. only immediate children are sorted. }
620 procedure SwapNodes( i1, i2: Integer );
621 {* Swaps two child nodes. }
622 function IsParentOfNode( Node: PTree ): Boolean;
623 {* Returns true, if Node is the tree itself or is a parent of the given node
624 on any level. }
625 function IndexOf( Node: PTree ): Integer;
626 {* Total index of the child node (on any level under this node). }
628 end;
629 //[END OF TTree DEFINITION]
631 //[NewTree DECLARATION]
632 function NewTree( AParent: PTree; const AName: String ): PTree;
633 {* Constructs tree node, adding it to the end of children list of
634 the AParent. If AParent is nil, new root tree node is created. }
642 //[DummyObjProc, DummyObjProcParam DECLARATION]
643 procedure DummyObjProc( Sender: PObj );
644 procedure DummyObjProcParam( Sender: PObj; Param: Pointer );
649 { --- threads --- }
650 //[THREADS]
652 const
653 ABOVE_NORMAL_PRIORITY_CLASS = $8000; // only for Windows 2K
654 BELOW_NORMAL_PRIORITY_CLASS = $4000; // and higher !
656 type
657 {++}(*TThread = class;*){--}
658 PThread = {-}^{+}TThread;
660 TThreadMethod = procedure of object;
661 TThreadMethodEx = procedure( Sender: PThread; Param: Pointer ) of object;
663 TOnThreadExecute = function(Sender:PThread): Integer of object;
664 {* Event to be called when Execute method is called for TThread }
666 { ---------------------------------------------------------------------
668 TThread object
670 ---------------------------------------------------------------------- }
671 //[TThread DEFINITION]
672 TThread = object(TObj)
673 {* Thread object. It is possible not to derive Your own thread-based
674 object, but instead create thread Suspended and assign event
675 OnExecute. To create, use one of NewThread of NewThreadEx functions,
676 or derive Your own descendant object and write creation function
677 (or constructor) for it.
678 |<br><br>
679 Aknowledgements. Originally class ZThread was developed for XCL:
680 |<br> * By: Tim Slusher : junior@nlcomm.com
681 |<br> * Home: http://www.nlcomm.com/~junior
683 protected
684 FSuspended,
685 FTerminated: boolean;
686 FHandle: THandle;
687 FThreadId: DWORD;
688 FOnSuspend: TObjectMethod;
689 FOnResume: TOnEvent;
690 FData : Pointer;
691 FOnExecute : TOnThreadExecute;
692 FMethod: TThreadMethod;
693 FMethodEx: TThreadMethodEx;
694 F_AutoFree: Boolean;
695 function GetPriorityCls: Integer;
696 function GetThrdPriority: Integer;
697 procedure SetPriorityCls(Value: Integer);
698 procedure SetThrdPriority(Value: Integer);
699 {++}(*public*){--}
700 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
701 {* }
702 public
703 function Execute: integer; virtual;
704 {* Executes thread. Do not call this method from another thread! (Even do
705 not call this method at all!) Instead, use Resume.
706 |<br>
707 Note also that in contrast to VCL, it is not necessary to create your
708 own descendant object from TThread and override Execute method. In KOL,
709 it is sufficient to create an instance of TThread object (see NewThread,
710 NewThreadEx, NewThreadAutoFree functions) and assign OnExecute event
711 handler for it. }
712 procedure Resume;
713 {* Continues executing. It is necessary to make call for every
714 nested Suspend. }
715 procedure Suspend;
716 {* Suspends thread until it will be resumed. Can be called from another
717 thread or from the thread itself. }
718 procedure Terminate;
719 {* Terminates thread. }
720 function WaitFor: Integer;
721 {* Waits (infinitively) until thead will be finished. }
723 property Handle: THandle read FHandle;
724 {* Thread handle. It is created immediately when object is created
725 (using NewThread). }
726 property Suspended: boolean read FSuspended;
727 {* True, if suspended. }
728 property Terminated: boolean read FTerminated;
729 {* True, if terminated. }
730 property ThreadId: DWORD read FThreadId;
731 {* Thread id. }
732 property PriorityClass: Integer read GetPriorityCls write SetPriorityCls;
733 {* Thread priority class. One of following values: HIGH_PRIORITY_CLASS,
734 IDLE_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS. }
735 property ThreadPriority: Integer read GetThrdPriority write SetThrdPriority;
736 {* Thread priority value. One of following values: THREAD_PRIORITY_ABOVE_NORMAL,
737 THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_IDLE,
738 THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_TIME_CRITICAL. }
739 property Data : Pointer read FData write FData;
740 {* Custom data pointer. Use it for Youe own purpose. }
742 property OnExecute: TOnThreadExecute read FOnExecute write FOnExecute;
743 {* Is called, when Execute is starting. }
744 property OnSuspend: TObjectMethod read FOnSuspend write FOnSuspend;
745 {* Is called, when Suspend is performed. }
746 property OnResume: TOnEvent read FOnResume write FOnResume;
747 {* Is called, when resumed. }
748 procedure Synchronize( Method: TThreadMethod );
749 {* Call it to execute given method in main thread context. Applet variable
750 must exist for that time. }
751 procedure SynchronizeEx( Method: TThreadMethodEx; Param: Pointer );
752 {* Call it to execute given method in main thread context, with a given
753 parameter. Applet variable must exist for that time. Param must not be nil. }
754 {$IFDEF USE_CONSTRUCTORS}
755 constructor ThreadCreate;
756 constructor ThreadCreateEx( const Proc: TOnThreadExecute );
757 {$ENDIF USE_CONSTRUCTORS}
759 property AutoFree: Boolean read F_AutoFree write F_AutoFree;
760 {* Set this property to true to provide automatic destroying of thread
761 object when its executing is finished. }
762 end;
763 //[END OF TThread DEFINITION]
765 //[NewThread, NewThreadEx, NewThreadAutoFree, Global_Synchronized DECLARATIONS]
766 function NewThread: PThread;
767 {* Creates thread object (always suspended). After creating, set event
768 OnExecute and perform Resume operation. }
770 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
771 {* Creates thread object, assigns Proc to its OnExecute event and runs
772 it. }
774 function NewThreadAutoFree( const Proc: TOnThreadExecute ): PThread;
775 {* Creates thread object similar to NewThreadEx, but freeing automatically
776 when executing of such thread finished. Be sure that a thread is resumed
777 at least to provide its object keeper freeing. }
779 var Global_Synchronized: procedure( Sender: PObj; Param: Pointer ) = DummyObjProcParam;
780 // It is not necessary to declare it as threadvar.
795 { -- streams -- }
796 //[STREAMS]
798 type
799 TMoveMethod = ( spBegin, spCurrent, spEnd );
801 {++}(*TStream = class;*){--}
802 PStream = {-}^{+}TStream;
804 PStreamMethods = ^TStreamMethods;
805 TStreamMethods = Packed Record
806 fSeek: function( Strm: PStream; MoveTo: Integer; MoveMethod: TMoveMethod ): DWORD;
807 fGetSiz: function( Strm: PStream ): DWORD;
808 fSetSiz: procedure( Strm: PStream; Value: DWORD );
809 fRead: function( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
810 fWrite: function( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
811 fClose: procedure( Strm: PStream );
812 fCustom: Pointer;
813 fWait: procedure( Strm: PStream );
814 end;
816 TStreamData = Packed Record
817 fHandle: THandle;
818 fCapacity, fSize, fPosition: DWORD;
819 fThread: PThread;
820 end;
822 { ---------------------------------------------------------------------
824 TStream - streaming objects incapsulation
826 ---------------------------------------------------------------------- }
827 //[TStream DEFINITION]
828 TStream = object(TObj)
829 {* Simple stream object. Can be opened for file, or as memory stream (see
830 NewReadFileStream, NewWriteFileStream, NewMemoryStream, etc.). And, another
831 type of streaming object can be derived (without inheriting new object
832 type, just by writing another New...Stream method, which calls
833 _NewStream and pass methods record to it). }
834 protected
835 fPMethods: PStreamMethods;
836 fMethods: TStreamMethods;
837 fMemory: Pointer;
838 fData: TStreamData;
839 fParam1, fParam2: DWORD; // parameters to use in thread
840 function GetCapacity: DWORD;
841 procedure SetCapacity(const Value: DWORD);
842 function DoAsyncRead( Sender: PThread ): Integer;
843 function DoAsyncWrite( Sender: PThread ): Integer;
844 function DoAsyncSeek( Sender: PThread ): Integer;
845 protected
846 function GetFileStreamHandle: THandle;
847 procedure SetPosition(Value: DWord);
848 function GetPosition: DWord;
849 function GetSize: DWord;
850 procedure SetSize(NewSize: DWord);
851 {++}(*public*){--}
852 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
853 public
854 function Read(var Buffer; Count: DWord): DWord;
855 {* Reads Count bytes from a stream. Returns number of bytes read. }
856 function Seek(MoveTo: Integer; MoveMethod: TMoveMethod): DWord;
857 {* Allows to change current position or to obtain it. Property
858 Position uses this method both for get and set position. }
859 function Write(var Buffer; Count: DWord): DWord;
860 {* Writes Count bytes from Buffer, starting from current position
861 in a stream. Returns how much bytes are written. }
862 function WriteStr( S: String ): DWORD;
863 {* Writes string to the stream, not including ending #0. Exactly
864 Length( S ) characters are written. }
865 function WriteStrZ( S: String ): DWORD;
866 {* Writes string, adding #0. Number of bytes written is returned. }
867 function ReadStrZ: String;
868 {* Reads string, finished by #0. After reading, current position in
869 the stream is set to the byte, follows #0. }
870 function ReadStr: String;
871 {* Reads string, finished by #13, #10 or #13#10 symbols. Terminating symbols
872 #13 and/or #10 are not added to the end of returned string though
873 stream positioned follow it. }
874 function WriteStrEx(S: String): DWord;
875 {* Writes string S to stream, also saving its size for future use by
876 ReadStrEx* functions. Returns number of actually written characters. }
877 function ReadStrExVar(var S: String): DWord;
878 {* Reads string from stream and assigns it to S.
879 Returns number of actually read characters.
880 Note:
881 String must be written by using WriteStrEx function.
882 Return value is count of characters READ, not the length of string. }
883 function ReadStrEx: String;
884 {* Reads string from stream and returns it. }
885 function WriteStrPas( S: String ): DWORD;
886 {* Writes a string in Pascal short string format - 1 byte length, then string
887 itself without trailing #0 char. S parameter length should not exceed 255
888 chars, rest chars are truncated while writing. Total amount of bytes
889 written is returned. }
890 function ReadStrPas: String;
891 {* Reads 1 byte from a stream, then treat it as a length of following string
892 which is read and returned. A purpose of this function is reading strings
893 written using WriteStrPas. }
894 property Size: DWord read GetSize write SetSize;
895 {* Returns stream size. For some custom streams, can be slow
896 operation, or even always return undefined value (-1 recommended). }
897 property Position: DWord read GetPosition write SetPosition;
898 {* Current position. }
900 property Memory: Pointer read fMemory;
901 {* Only for memory stream. }
902 property Handle: THandle read GetFileStreamHandle;
903 {* Only for file stream. It is possible to check that Handle <>
904 INVALID_HANDLE_VALUE to ensure that file stream is created OK. }
906 //---------- for asynchronous operations (using thread - not tested):
907 procedure SeekAsync(MoveTo: Integer; MoveMethod: TMoveMethod);
908 {* Changes current position asynchronously. To wait for finishing the
909 operation, use method Wait. }
910 procedure ReadAsync(var Buffer; Count: DWord);
911 {* Reads Count bytes from a stream asynchronously. To wait finishing the
912 operation, use method Wait. }
913 procedure WriteAsync(var Buffer; Count: DWord);
914 {* Writes Count bytes from Buffer, starting from current position
915 in a stream - asynchronously. To wait finishing the operation,
916 use method Wait. }
917 function Busy: Boolean;
918 {* Returns TRUE until finishing the last asynchronous operation
919 started by calling SeekAsync, ReadAsync, WriteAsync methods. }
920 procedure Wait;
921 {* Waits for finishing the last asynchronous operation. }
923 property Methods: PStreamMethods read fPMethods;
924 {* Pointer to TStreamMethods record. Useful to implement custom-defined
925 streams, which can access its fCustom field, or even to change
926 methods when necessary. }
927 property Data: TStreamData read fData;
928 {* Pointer to TStreamData record. Useful to implement custom-defined
929 streams, which can access Data fields directly when implemented. }
931 property Capacity: DWORD read GetCapacity write SetCapacity;
932 {* Amound of memory allocated for data (MemoryStream). }
934 end;
935 //[END OF TStream DEFINITION]
937 //[_NewStream DECLARATION]
938 function _NewStream( const StreamMethods: TStreamMethods ): PStream;
939 {* Use this method only to define your own stream type. See also declared
940 below (in KOL.pas) methods used to implement standard KOL streams. You can use it in
941 your code to create streams, which are partially based on standard
942 methods. }
944 // Methods below are declared here to simplify creating your
945 // own streams with some methods standard and some non-standard
946 // together:
947 function SeekFileStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
948 function GetSizeFileStream( Strm: PStream ): DWORD;
949 function ReadFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
950 function WriteFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
951 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
952 procedure CloseFileStream( Strm: PStream );
953 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
954 function GetSizeMemStream( Strm: PStream ): DWORD;
955 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );
956 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
957 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
958 procedure CloseMemStream( Strm: PStream );
959 procedure SetSizeFileStream( Strm: PStream; NewSize: DWORD );
961 function DummyReadWrite( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
962 procedure DummySetSize( Strm: PStream; Value: DWORD );
963 procedure DummyStreamProc(Strm: PStream);
966 //[NewFileStream DECLARATION]
967 function NewFileStream( const FileName: String; Options: DWORD ): PStream;
968 {* Creates file stream for read and write. Exact set of open attributes
969 should be passed through Options parameter (see FileCreate where those
970 flags are listed). }
972 function NewReadFileStream( const FileName: String ): PStream;
973 {* Creates file stream for read only. }
975 function NewWriteFileStream( const FileName: String ): PStream;
976 {* Creates file stream for write only. Truncating of file (if needed)
977 is provided automatically. }
979 function NewReadWriteFileStream( const FileName: String ): PStream;
980 {* Creates stream for read and write file. To truncate file, if it is
981 necessary, change Size property. }
983 //[NewMemoryStream DECLARATION]
984 function NewMemoryStream: PStream;
985 {* Creates memory stream (read and write). }
987 function NewExMemoryStream( ExistingMem: Pointer; Size: DWORD ): PStream;
988 {* Creates memory stream on base of existing memory. It is not possible
989 to write out of top bound given by Size (i.e. memory can not be resized,
990 or reallocated. When stream object is destroyed this memory is not freed. }
992 //[Stream2Stream DECLARATION]
993 function Stream2Stream( Dst, Src: PStream; Count: DWORD ): DWORD;
994 {* Copies Count (or less, if the rest of Src is not sufficiently long)
995 bytes from Src to Dst, but with optimizing in cases, when Src or/and
996 Dst are memory streams (intermediate buffer is not allocated). }
997 function Stream2StreamEx( Dst, Src: PStream; Count: DWORD ): DWORD;
998 {* Copies Count bytes from Src to Dst, but without any optimization.
999 Unlike Stream2Stream function, it can be applied to very large streams.
1000 See also Stream2StreamExBufSz. }
1001 function Stream2StreamExBufSz( Dst, Src: PStream; Count, BufSz: DWORD ): DWORD;
1002 {* Copies Count bytes from Src to Dst using buffer of given size, but without
1003 other optimizations.
1004 Unlike Stream2Stream function, it can be applied to very large streams }
1006 //[Resource2Stream DECLARATION]
1007 function Resource2Stream( DestStrm : PStream; Inst : HInst;
1008 ResName : PChar; ResType : PChar ): Integer;
1009 {* Loads given resource to DestStrm. Useful for non-standard
1010 resources to load it into memory (use memory stream for such
1011 purpose). Use one of following resource types to pass as ResType:
1012 |<pre>
1013 RT_ACCELERATOR Accelerator table
1014 RT_ANICURSOR Animated cursor
1015 RT_ANIICON Animated icon
1016 RT_BITMAP Bitmap resource
1017 RT_CURSOR Hardware-dependent cursor resource
1018 RT_DIALOG Dialog box
1019 RT_FONT Font resource
1020 RT_FONTDIR Font directory resource
1021 RT_GROUP_CURSOR Hardware-independent cursor resource
1022 RT_GROUP_ICON Hardware-independent icon resource
1023 RT_ICON Hardware-dependent icon resource
1024 RT_MENU Menu resource
1025 RT_MESSAGETABLE Message-table entry
1026 RT_RCDATA Application-defined resource (raw data)
1027 RT_STRING String-table entry
1028 RT_VERSION Version resource
1029 |</pre>
1030 |<br>For example:
1031 !var MemStrm: PStream;
1032 ! JpgObj: PJpeg;
1033 !......
1034 ! MemStrm := NewMemoryStream;
1035 ! JpgObj := NewJpeg;
1036 !......
1037 ! Resource2Stream( MemStrm, hInstance, 'MYJPEG', RT_RCDATA );
1038 ! MemStrm.Position := 0;
1039 ! JpgObj.LoadFromStream( MemStrm );
1040 ! MemStrm.Free;
1041 !......
1067 type
1068 //[TBits DEFINITION]
1069 {++}(*TBits = class;*){--}
1070 PBits = {-}^{+}TBits;
1071 TBits = object( TObj )
1072 {* Variable-length bits array object. Created using function NewBits. See also
1073 |<a href="kol_pas.htm#Small bit arrays (max 32 bits in array)">
1074 Small bit arrays (max 32 bits in array)
1075 |</a>. }
1076 protected
1077 fList: PList;
1078 fCount: Integer;
1079 function GetBit(Idx: Integer): Boolean;
1080 function GetCapacity: Integer;
1081 function GetSize: Integer;
1082 procedure SetBit(Idx: Integer; const Value: Boolean);
1083 procedure SetCapacity(const Value: Integer);
1084 public
1085 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1086 {* }
1087 property Bits[ Idx: Integer ]: Boolean read GetBit write SetBit;
1088 {* }
1089 property Size: Integer read GetSize;
1090 {* Size in bytes of the array. To get know number of bits, use property Count. }
1091 property Count: Integer read fCount;
1092 {* Number of bits an the array. }
1093 property Capacity: Integer read GetCapacity write SetCapacity;
1094 {* Number of bytes allocated. Can be set before assigning bit values
1095 to improve performance (minimizing amount of memory allocation
1096 operations). }
1097 function Copy( From, BitsCount: Integer ): PBits;
1098 {* Use this property to get a sub-range of bits starting from given bit
1099 and of BitsCount bits count. }
1100 function IndexOf( Value: Boolean ): Integer;
1101 {* Returns index of first bit with given value (True or False). }
1102 function OpenBit: Integer;
1103 {* Returns index of the first bit not set to true. }
1104 procedure Clear;
1105 {* Clears bits array. Count, Size and Capacity become 0. }
1106 function LoadFromStream( strm: PStream ): Integer;
1107 {* Loads bits from the stream. Data should be stored in the stream
1108 earlier using SaveToStream method. While loading, previous bits
1109 data are discarded and replaced with new one totally. In part,
1110 Count of bits also is changed. Count of bytes read from the stream
1111 while loading data is returned. }
1112 function SaveToStream( strm: PStream ): Integer;
1113 {* Saves entire array of bits to the stream. First, Count of bits
1114 in the array is saved, then all bytes containing bits data. }
1115 function Range( Idx, N: Integer ): PBits;
1116 {* Creates and returns new TBits object instance containing N bits
1117 starting from index Idx. If you call this method, you are responsible
1118 for destroying returned object when it become not neccessary. }
1119 procedure AssignBits( ToIdx: Integer; FromBits: PBits; FromIdx, N: Integer );
1120 {* Assigns bits from another bits array object. N bits are assigned
1121 starting at index ToIdx. }
1122 end;
1123 //[END OF TBits DEFINITION]
1125 //[NewBits DECLARATION]
1126 function NewBits: PBits;
1127 {* Creates variable-length bits array object. }
1147 { -- string list objects -- }
1148 //[TStrList]
1150 type
1151 {++}(*TStrList = class;*){--}
1152 PStrList = {-}^{+}TStrList;
1153 { ---------------------------------------------------------------------
1155 TStrList - string list
1157 ---------------------------------------------------------------------- }
1158 //[TStrList DEFINITION]
1159 TStrList = object(TObj)
1160 {* Easy string list implementation (non-visual, just to store
1161 string data). It is well improved and has very high performance
1162 allowing to work fast with huge text files (more then megabyte
1163 of text data).
1165 Please note that #0 charaster if stored in string lines, will cut it
1166 preventing reading the rest of a line. Be careful, if your data
1167 contain such characters. }
1168 protected
1169 procedure Init; virtual;
1170 protected
1171 fList: PList;
1172 fCount: Integer;
1173 fCaseSensitiveSort: Boolean;
1174 fTextBuf: PChar;
1175 fTextSiz: DWORD;
1176 function GetPChars(Idx: Integer): PChar;
1177 //procedure AddTextBuf( Src: PChar; Len: DWORD );
1178 protected
1179 function Get(Idx: integer): string;
1180 function GetTextStr: string;
1181 procedure Put(Idx: integer; const Value: string);
1182 procedure SetTextStr(const Value: string);
1183 {++}(*public*){--}
1184 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1185 protected
1186 // by Dod:
1187 procedure SetValue(const Name, Value: string);
1188 function GetValue(const Name: string): string;
1189 public
1190 // by Dod:
1191 function IndexOfName(Name: string): Integer;
1192 {* by Dod. Returns index of line starting like Name=... }
1193 property Values[const Name: string]: string read GetValue write SetValue;
1194 {* by Dod. Returns right side of a line starting like Name=... }
1195 public
1196 function Add(const S: string): integer;
1197 {* Adds a string to list. }
1198 procedure AddStrings(Strings: PStrList);
1199 {* Merges string list with given one. Very fast - more preferrable to
1200 use than any loop with calling Add method. }
1201 procedure Assign(Strings: PStrList);
1202 {* Fills string list with strings from other one. The same as AddStrings,
1203 but Clear is called first. }
1204 procedure Clear;
1205 {* Makes string list empty. }
1206 procedure Delete(Idx: integer);
1207 {* Deletes string with given index (it *must* exist). }
1208 function IndexOf(const S: string): integer;
1209 {* Returns index of first string, equal to given one. }
1210 function IndexOf_NoCase(const S: string): integer;
1211 {* Returns index of first string, equal to given one (while comparing it
1212 without case sensitivity). }
1213 function IndexOfStrL_NoCase( Str: PChar; L: Integer ): integer;
1214 {* Returns index of first string, equal to given one (while comparing it
1215 without case sensitivity). }
1216 function Find(const S: String; var Index: Integer): Boolean;
1217 {* Returns Index of the first string, equal or greater to given pattern, but
1218 works only for sorted TStrList object. Returns TRUE if exact string found,
1219 otherwise nearest (greater then a pattern) string index is returned,
1220 and the result is FALSE. }
1221 procedure Insert(Idx: integer; const S: string);
1222 {* Inserts string before one with given index. }
1223 function LoadFromFile(const FileName: string): Boolean;
1224 {* Loads string list from a file. (If file does not exist, nothing
1225 happens). Very fast even for huge text files. }
1226 procedure LoadFromStream(Stream: PStream; Append2List: boolean);
1227 {* Loads string list from a stream (from current position to the end of
1228 a stream). Very fast even for huge text. }
1229 procedure MergeFromFile(const FileName: string);
1230 {* Merges string list with strings in a file. Fast. }
1231 procedure Move(CurIndex, NewIndex: integer);
1232 {* Moves string to another location. }
1233 procedure SetText(const S: string; Append2List: boolean);
1234 {* Allows to set strings of string list from given string (in which
1235 strings are separated by $0D,$0A or $0D characters). Text must not
1236 contain #0 characters. Works very fast. This method is used in
1237 all others, working with text arrays (LoadFromFile, MergeFromFile,
1238 Assign, AddStrings). }
1239 procedure SetUnixText( const S: String; Append2List: Boolean );
1240 {* Allows to assign UNIX-style text (with #10 as string separator). }
1241 function SaveToFile(const FileName: string): Boolean;
1242 {* Stores string list to a file. }
1243 procedure SaveToStream(Stream: PStream);
1244 {* Saves string list to a stream (from current position). }
1245 function AppendToFile(const FileName: string): Boolean;
1246 {* Appends strings of string list to the end of a file. }
1247 property Count: integer read fCount;
1248 {* Number of strings in a string list. }
1249 property Items[Idx: integer]: string read Get write Put; default;
1250 {* Strings array items. If item does not exist, empty string is returned.
1251 But for assign to property, string with given index *must* exist. }
1252 property ItemPtrs[ Idx: Integer ]: PChar read GetPChars;
1253 {* Fast access to item strings as PChars. }
1254 function Last: String;
1255 {* Last item (or '', if string list is empty). }
1256 property Text: string read GetTextStr write SetTextStr;
1257 {* Content of string list as a single string (where strings are separated
1258 by characters $0D,$0A). }
1259 procedure Swap( Idx1, Idx2 : Integer );
1260 {* Swaps to strings with given indeces. }
1261 procedure Sort( CaseSensitive: Boolean );
1262 {* Call it to sort string list. }
1263 procedure AnsiSort( CaseSensitive: Boolean );
1264 {* Call it to sort ANSI string list. }
1266 // by Alexander Pravdin:
1267 protected
1268 fNameDelim: Char;
1269 function GetLineName( Idx: Integer ): string;
1270 procedure SetLineName( Idx: Integer; const NV: string );
1271 function GetLineValue(Idx: Integer): string;
1272 procedure SetLineValue(Idx: Integer; const Value: string);
1273 public
1274 property LineName[ Idx: Integer ]: string read GetLineName write SetLineName;
1275 property LineValue[ Idx: Integer ]: string read GetLineValue write SetLineValue;
1276 property NameDelimiter: Char read fNameDelim write fNameDelim;
1277 end;
1278 //[END OF TStrList DEFINITION]
1280 //[DefaultNameDelimiter]
1281 var DefaultNameDelimiter: Char = '=';
1283 //[NewStrList DECLARATION]
1284 function NewStrList: PStrList;
1285 {* Creates string list object. }
1287 function GetFileList(const dir: string): PStrList;
1288 {* By Alexander Shakhaylo. Returns list of file names of the given directory. }
1293 //[TStrListEx]
1294 type
1295 {++}(*TStrListEx = class;*){--}
1296 PStrListEx = {-}^{+}TStrListEx;
1298 //[TStrListEx DEFINITION]
1299 TStrListEx = object( TStrList )
1300 {* Extended string list object. Has additional capability to associate
1301 numbers or objects with string list items. }
1302 protected
1303 FObjects: PList;
1304 function GetObjects(Idx: Integer): DWORD;
1305 procedure SetObjects(Idx: Integer; const Value: DWORD);
1306 procedure Init; {-}virtual;{+}{++}(*override;*){--}
1307 procedure ProvideObjCapacity( NewCap: Integer );
1308 public
1309 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1310 {* }
1311 property Objects[ Idx: Integer ]: DWORD read GetObjects write SetObjects;
1312 {* Objects are just 32-bit values. You can treat and use it as pointers to
1313 any other data in the memory. But it is your task to free allocated
1314 memory in such case therefore. }
1315 procedure AddStrings(Strings: PStrListEx);
1316 {* Merges string list with given one. Very fast - more preferrable to
1317 use than any loop with calling Add method. }
1318 procedure Assign(Strings: PStrListEx);
1319 {* Fills string list with strings from other one. The same as AddStrings,
1320 but Clear is called first. }
1321 procedure Clear;
1322 {* Makes string list empty. }
1323 procedure Delete(Idx: integer);
1324 {* Deletes string with given index (it *must* exist). }
1325 procedure Move(CurIndex, NewIndex: integer);
1326 {* Moves string to another location. }
1327 procedure Swap( Idx1, Idx2 : Integer );
1328 {* Swaps to strings with given indeces. }
1329 procedure Sort( CaseSensitive: Boolean );
1330 {* Call it to sort string list. }
1331 procedure AnsiSort( CaseSensitive: Boolean );
1332 {* Call it to sort ANSI string list. }
1333 function LastObj: DWORD;
1334 {* Object assotiated with the last string. }
1335 function AddObject( const S: String; Obj: DWORD ): Integer;
1336 {* Adds a string and associates given number with it. Index of the item added
1337 is returned. }
1338 procedure InsertObject( Before: Integer; const S: String; Obj: DWORD );
1339 {* Inserts a string together with object associated. }
1340 function IndexOfObj( Obj: Pointer ): Integer;
1341 {* Returns an index of a string associated with the object passed as a
1342 parameter. If there are no such strings, -1 is returned. }
1343 end;
1344 //[END OF TStrListEx DEFINITION]
1346 //[NewStrListEx DECLARATION]
1347 function NewStrListEx: PStrListEx;
1348 {* Creates extended string list object. }
1354 //[TWStrList]
1357 {$IFNDEF _D2} //------------------ WideString is not supported in D2 -----------
1359 type
1360 PWStrList = ^TWstrList;
1361 {* }
1362 //[TWstrList DEFINITION]
1363 TWStrList = object( TObj )
1364 {* String list to store Unicode (null-terminated) strings. }
1365 protected
1366 function GetCount: Integer;
1367 function GetItems(Idx: Integer): WideString;
1368 procedure SetItems(Idx: Integer; const Value: WideString);
1369 function GetPtrs(Idx: Integer): PWideChar;
1370 function GetText: WideString;
1371 protected
1372 fList: PList;
1373 fText: PWideChar;
1374 fTextBufSz: Integer;
1375 fTmp1, fTmp2: WideString;
1376 procedure Init; virtual;
1377 public
1378 procedure SetText(const Value: WideString);
1379 {* See also TStrList.SetText }
1380 destructor Destroy; virtual;
1381 {* }
1382 procedure Clear;
1383 {* See also TStrList.Clear }
1384 property Items[ Idx: Integer ]: WideString read GetItems write SetItems;
1385 {* See also TStrList.Items }
1386 property ItemPtrs[ Idx: Integer ]: PWideChar read GetPtrs;
1387 {* See also TStrList.ItemPtrs }
1388 property Count: Integer read GetCount;
1389 {* See also TStrList.Count }
1390 function Add( const W: WideString ): Integer;
1391 {* See also TStrList.Add }
1392 procedure Insert( Idx: Integer; const W: WideString );
1393 {* See also TStrList.Insert }
1394 procedure Delete( Idx: Integer );
1395 {* See also TStrList.Delete }
1396 property Text: WideString read GetText write SetText;
1397 {* See also TStrList.Text }
1398 procedure AddWStrings( WL: PWStrList );
1399 {* See also TStrList.AddStrings }
1400 procedure Assign( WL: PWStrList );
1401 {* See also TStrList.Assign }
1402 function LoadFromFile( const Filename: String ): Boolean;
1403 {* See also TStrList.LoadFromFile }
1404 procedure LoadFromStream( Strm: PStream );
1405 {* See also TStrList.LoadFromStream }
1406 function MergeFromFile( const Filename: String ): Boolean;
1407 {* See also TStrList.MergeFromFile }
1408 procedure MergeFromStream( Strm: PStream );
1409 {* See also TStrList.MergeFromStream }
1410 function SaveToFile( const Filename: String ): Boolean;
1411 {* See also TStrList.SaveToFile }
1412 procedure SaveToStream( Strm: PStream );
1413 {* See also TStrList.SaveToStream }
1414 function AppendToFile( const Filename: String ): Boolean;
1415 {* See also TStrList.AppendToFile }
1416 procedure Swap( Idx1, Idx2: Integer );
1417 {* See also TStrList.Swap }
1418 procedure Sort( CaseSensitive: Boolean );
1419 {* See also TStrList.Sort }
1420 procedure Move( IdxOld, IdxNew: Integer );
1421 {* See also TStrList.Move }
1422 end;
1423 //[END OF TWStrList DEFINITION]
1425 //[TWStrListEx]
1426 PWStrListEx = ^TWStrListEx;
1428 //[TWStrListEx DEFINITION]
1429 TWStrListEx = object( TWStrList )
1430 {* Extended Unicode string list (with Objects). }
1431 protected
1432 function GetObjects(Idx: Integer): DWORD;
1433 procedure SetObjects(Idx: Integer; const Value: DWORD);
1434 procedure ProvideObjectsCapacity( NewCap: Integer );
1435 protected
1436 fObjects: PList;
1437 procedure Init; virtual;
1438 public
1439 destructor Destroy; virtual;
1440 {* }
1441 property Objects[ Idx: Integer ]: DWORD read GetObjects write SetObjects;
1442 {* }
1443 procedure AddWStrings( WL: PWStrListEx );
1444 {* }
1445 procedure Assign( WL: PWStrListEx );
1446 {* }
1447 procedure Clear;
1448 {* }
1449 procedure Delete( Idx: Integer );
1450 {* }
1451 procedure Move( IdxOld, IdxNew: Integer );
1452 {* }
1453 function AddObject( const S: WideString; Obj: DWORD ): Integer;
1454 {* Adds a string and associates given number with it. Index of the item added
1455 is returned. }
1456 procedure InsertObject( Before: Integer; const S: WideString; Obj: DWORD );
1457 {* Inserts a string together with object associated. }
1458 function IndexOfObj( Obj: Pointer ): Integer;
1459 {* Returns an index of a string associated with the object passed as a
1460 parameter. If there are no such strings, -1 is returned. }
1461 end;
1462 //[END OF TWStrListEx DEFINITION]
1464 //[NewWStrList DECLARATION]
1465 function NewWStrList: PWStrList;
1466 {* Creates new TWStrList object and returns a pointer to it. }
1468 //[NewWStrListEx DECLARATION]
1469 function NewWStrListEx: PWStrListEx;
1470 {* Creates new TWStrListEx objects and returns a pointer to it. }
1472 {$ENDIF}
1490 ////////////////////////////////////////////////////////////////////////////////
1491 // GRAPHIC OBJECTS //
1492 ////////////////////////////////////////////////////////////////////////////////
1493 //[GRAPHIC OBJECTS]
1495 It is very important, that the most of code, implementing graphic objets
1496 from this section, is included into executable ONLY if really accessed in your
1497 project directly (e.g., if Font or Brush properies of a control are accessed
1498 or changed).
1500 type
1501 TColor = Integer;
1503 const
1504 //[COLOR CONSTANTS]
1505 clScrollBar = TColor(COLOR_SCROLLBAR or $80000000);
1506 clBackground = TColor(COLOR_BACKGROUND or $80000000);
1507 clActiveCaption = TColor(COLOR_ACTIVECAPTION or $80000000);
1508 clInactiveCaption = TColor(COLOR_INACTIVECAPTION or $80000000);
1509 clMenu = TColor(COLOR_MENU or $80000000);
1510 clWindow = TColor(COLOR_WINDOW or $80000000);
1511 clWindowFrame = TColor(COLOR_WINDOWFRAME or $80000000);
1512 clMenuText = TColor(COLOR_MENUTEXT or $80000000);
1513 clWindowText = TColor(COLOR_WINDOWTEXT or $80000000);
1514 clCaptionText = TColor(COLOR_CAPTIONTEXT or $80000000);
1515 clActiveBorder = TColor(COLOR_ACTIVEBORDER or $80000000);
1516 clInactiveBorder = TColor(COLOR_INACTIVEBORDER or $80000000);
1517 clAppWorkSpace = TColor(COLOR_APPWORKSPACE or $80000000);
1518 clHighlight = TColor(COLOR_HIGHLIGHT or $80000000);
1519 clHighlightText = TColor(COLOR_HIGHLIGHTTEXT or $80000000);
1520 clBtnFace = TColor(COLOR_BTNFACE or $80000000);
1521 clBtnShadow = TColor(COLOR_BTNSHADOW or $80000000);
1522 clGrayText = TColor(COLOR_GRAYTEXT or $80000000);
1523 clBtnText = TColor(COLOR_BTNTEXT or $80000000);
1524 clInactiveCaptionText = TColor(COLOR_INACTIVECAPTIONTEXT or $80000000);
1525 clBtnHighlight = TColor(COLOR_BTNHIGHLIGHT or $80000000);
1526 cl3DDkShadow = TColor(COLOR_3DDKSHADOW or $80000000);
1527 cl3DLight = TColor(COLOR_3DLIGHT or $80000000);
1528 clInfoText = TColor(COLOR_INFOTEXT or $80000000);
1529 clInfoBk = TColor(COLOR_INFOBK or $80000000);
1531 clBlack = TColor($000000);
1532 clMaroon = TColor($000080);
1533 clGreen = TColor($008000);
1534 clOlive = TColor($008080);
1535 clNavy = TColor($800000);
1536 clPurple = TColor($800080);
1537 clTeal = TColor($808000);
1538 clGray = TColor($808080);
1539 clSilver = TColor($C0C0C0);
1540 clRed = TColor($0000FF);
1541 clLime = TColor($00FF00);
1542 clYellow = TColor($00FFFF);
1543 clBlue = TColor($FF0000);
1544 clFuchsia = TColor($FF00FF);
1545 clAqua = TColor($FFFF00);
1546 clLtGray = TColor($C0C0C0);
1547 clDkGray = TColor($808080);
1548 clWhite = TColor($FFFFFF);
1549 clNone = TColor($1FFFFFFF);
1550 clDefault = TColor($20000000);
1552 clMoneyGreen = TColor($C0DCC0);
1553 clSkyBlue = TColor($F0CAA6);
1554 clCream = TColor($F0FBFF);
1555 clMedGray = TColor($A4A0A0);
1556 //[END OF COLOR CONSTANTS]
1558 const
1559 //[TGraphicTool FIELD OFFSET CONSTANTS]
1560 go_Color = 0;
1561 go_FontHeight = 4;
1562 go_FontWidth = 8;
1563 go_FontEscapement = 12;
1564 go_FontOrientation = 16;
1565 go_FontWeight = 20;
1566 go_FontItalic = 24;
1567 go_FontUnderline = 25;
1568 go_FontStrikeOut = 26;
1569 go_FontCharSet = 27;
1570 go_FontOutPrecision = 28;
1571 go_FontClipPrecision = 29;
1572 go_FontQuality = 30;
1573 go_FontPitch = 31;
1574 go_FontName = 32;
1575 go_BrushBitmap = 4;
1576 go_BrushStyle = 8;
1577 go_BrushLineColor = 9;
1578 go_PenBrushBitmap = 4;
1579 go_PenBrushStyle = 8;
1580 go_PenStyle = 9;
1581 go_PenWidth = 10;
1582 go_PenMode = 14;
1583 go_PenGeometric = 15;
1584 go_PenEndCap = 16;
1585 go_PenJoin = 17;
1586 //[END OF TGraphicTool FIELD OFFSET CONSTANTS]
1588 //[TGraphicTool]
1589 type
1590 TGraphicToolType = ( gttBrush, gttFont, gttPen );
1591 {* Graphic object types, mainly for internal use. }
1593 {++}(*TGraphicTool = class;*){--}
1594 PGraphicTool = {-}^{+}TGraphicTool;
1595 {* }
1596 TOnGraphicChange = procedure ( Sender: PGraphicTool ) of object;
1597 {* An event mainly for internal use. }
1599 TBrushStyle = (bsSolid, bsClear, bsHorizontal, bsVertical,
1600 bsFDiagonal, bsBDiagonal, bsCross, bsDiagCross);
1601 {* Available brush styles. }
1603 TFontStyles = (fsBold, fsItalic, fsUnderline, fsStrikeOut);
1604 {* Available font styles. }
1605 TFontStyle = set of TFontStyles;
1606 {* Font style is representing as a set of XFontStyles. }
1607 TFontPitch = (fpDefault, fpFixed, fpVariable);
1608 {* Availabe font pitch values. }
1609 TFontName = type string;
1610 {* Font name is represented as a string. }
1611 TFontCharset = 0..255;
1612 {* Font charset is represented by number from 0 to 255. }
1613 TFontQuality = (fqDefault, fqDraft, fqProof, fqNonAntialiased, fqAntialiased);
1614 {* Font quality. }
1616 TPenStyle = (psSolid, psDash, psDot, psDashDot, psDashDotDot, psClear,
1617 psInsideFrame);
1618 {* Available pen styles. For more info see Delphi or Win32 help files. }
1619 TPenMode = (pmBlack, pmNotMerge, pmMaskNotPen, pmNotCopy, pmMaskPenNot,
1620 pmNot, pmXor, pmNotMask, pmMask, pmNotXor, pmNop, pmMergePenNot,
1621 pmCopy, pmMergeNotPen, pmMerge, pmWhite);
1622 {* Available pen modes. For more info see Delphi or Win32 help files. }
1623 TPenEndCap = (pecRound, pecSquare, pecFlat);
1624 {* Avalable (for geometric pen) end cap styles. }
1625 TPenJoin = (pjRound, pjBevel, pjMiter);
1626 {* Available (for geometric pen) join styles. }
1628 //[TGdiFont]
1629 TGDIFont = packed record
1630 Height: Integer;
1631 Width: Integer;
1632 Escapement: Integer;
1633 Orientation: Integer;
1634 Weight: Integer;
1635 Italic: Boolean;
1636 Underline: Boolean;
1637 StrikeOut: Boolean;
1638 CharSet: TFontCharset;
1639 OutPrecision: Byte;
1640 ClipPrecision: Byte;
1641 Quality: TFontQuality;
1642 Pitch: TFontPitch;
1643 Name: array[0..LF_FACESIZE - 1] of Char;
1644 end;
1646 //[TGDIBrush]
1647 TGDIBrush = packed record
1648 Bitmap: HBitmap;
1649 Style: TBrushStyle;
1650 LineColor: TColor;
1651 end;
1653 //[TGDIPen]
1654 TGDIPen = packed record
1655 BrushBitmap: HBitmap;
1656 BrushStyle: TBrushStyle;
1657 Style: TPenStyle;
1658 Width: Integer;
1659 Mode: TPenMode;
1660 Geometric: Boolean;
1661 EndCap: TPenEndCap;
1662 Join: TPenJoin;
1663 end;
1665 //[TGDIToolData]
1666 TGDIToolData = packed record
1667 Color: TColor;
1668 case Integer of
1669 1: (Font: TGDIFont);
1670 2: (Pen: TGDIPen);
1671 3: (Brush: TGDIBrush);
1672 end;
1674 //[TNewGraphicTool]
1675 TNewGraphicTool = function: PGraphicTool;
1677 { ---------------------------------------------------------------------
1679 TGraphicTool - object to implement GDI-tools (brush, pen, font)
1681 ---------------------------------------------------------------------- }
1682 //[TGraphicTool DEFINITION]
1683 TGraphicTool = object( TObj )
1684 {* Incapsulates all GDI objects: Pen, Brush and Font. }
1685 protected
1686 fType: TGraphicToolType;
1687 fHandle: THandle;
1688 fParentGDITool: PGraphicTool;
1689 fOnChange: TOnGraphicChange;
1690 fColorRGB: TColor;
1691 fData: TGDIToolData;
1693 fNewProc: TNewGraphicTool;
1694 fMakeHandleProc: function( Self_: PGraphicTool ): THandle;
1696 procedure SetInt( const Index: Integer; Value: Integer );
1697 {$IFDEF F_P}
1698 function GetInt( const Index: Integer ): Integer;
1699 {$ENDIF}
1700 procedure SetColor( Value: TColor );
1701 procedure SetBrushBitmap(const Value: HBitmap);
1702 procedure SetBrushStyle(const Value: TBrushStyle);
1703 procedure SetFontCharset(const Value: TFontCharset);
1704 procedure SetFontQuality(const Value: TFontQuality);
1705 function GetFontName: String;
1706 procedure SetFontName(const Value: String);
1707 procedure SetFontOrientation(Value: Integer);
1708 procedure SetFontPitch(const Value: TFontPitch);
1709 function GetFontStyle: TFontStyle;
1710 procedure SetFontStyle(const Value: TFontStyle);
1711 procedure SetPenMode(const Value: TPenMode);
1712 procedure SetPenStyle(const Value: TPenStyle);
1713 procedure SetGeometricPen(const Value: Boolean);
1714 procedure SetPenEndCap(const Value: TPenEndCap);
1715 procedure SetPenJoin(const Value: TPenJoin);
1716 procedure SetFontWeight(const Value: Integer);
1717 procedure SetLogFontStruct(const Value: TLogFont);
1718 function GetLogFontStruct: TLogFont;
1719 protected
1720 procedure Changed;
1721 {* }
1722 function GetHandle: THandle;
1723 {* }
1724 public
1725 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1726 {* }
1727 property Handle: THandle read GetHandle;
1728 {* Every time, when accessed, real GDI object is created (if it is
1729 not yet created). So, to prevent creating of the handle, use
1730 HandleAllocated instead of comparing Handle with value 0. }
1731 function HandleAllocated: Boolean;
1732 {* Returns True, if handle is allocated (i.e., if real GDI
1733 objet is created. }
1734 property OnChange: TOnGraphicChange read fOnChange write fOnChange;
1735 {* Called, when object is changed. }
1736 function ReleaseHandle: Integer;
1737 {* Returns Handle value (if allocated), releasing it from the
1738 object (so, it is no more knows about this handle and its
1739 HandleAllocated function returns False. }
1740 property Color: TColor {index go_Color} read fData.Color write SetColor;
1741 {* Color is the most common property for all Pen, Brush and
1742 Font objects, so it is placed in its common for all of them. }
1743 function Assign( Value: PGraphicTool ): PGraphicTool;
1744 {* Assigns properties of the same (only) type graphic object,
1745 excluding Handle. If assigning is really leading to change
1746 object, procedure Changed is called. }
1747 procedure AssignHandle( NewHandle: Integer );
1748 {* Assigns value to Handle property. }
1750 property BrushBitmap: HBitmap read fData.Brush.Bitmap write SetBrushBitmap;
1751 {* Brush bitmap. For more info about using brush bitmap,
1752 see Delphi or Win32 help files. }
1753 property BrushStyle: TBrushStyle read fData.Brush.Style write SetBrushStyle;
1754 {* Brush style. }
1755 property BrushLineColor: TColor index go_BrushLineColor
1756 {$IFDEF F_P}
1757 read GetInt
1758 {$ELSE DELPHI}
1759 read fData.Brush.LineColor
1760 {$ENDIF F_P/DELPHI}
1761 write SetInt;
1762 {* Brush line color, used to represent lines in hatched brush. Default value is clBlack. }
1764 property FontHeight: Integer index go_FontHeight
1765 {$IFDEF F_P}
1766 read GetInt
1767 {$ELSE DELPHI}
1768 read fData.Font.Height
1769 {$ENDIF F_P/DELPHI}
1770 write SetInt;
1771 {* Font height. Value 0 (default) seys to use system default value,
1772 negative values are to represent font height in "points", positive
1773 - in pixels. In XCL usually positive values (if not 0) are used to
1774 make appearance independent from different local settings. }
1775 property FontWidth: Integer index go_FontWidth
1776 {$IFDEF F_P}
1777 read GetInt
1778 {$ELSE DELPHI}
1779 read fData.Font.Width
1780 {$ENDIF F_P/DELPHI}
1781 write SetInt;
1782 {* Font width in logical units. If FontWidth = 0, then as it is said
1783 in Win32.hlp, "the aspect ratio of the device is matched against the
1784 digitization aspect ratio of the available fonts to find the closest match,
1785 determined by the absolute value of the difference." }
1786 property FontPitch: TFontPitch read fData.Font.Pitch write SetFontPitch;
1787 {* Font pitch. Change it very rare. }
1788 property FontStyle: TFontStyle read GetFontStyle write SetFontStyle;
1789 {* Very useful property to control text appearance. }
1790 property FontCharset: TFontCharset read fData.Font.Charset write SetFontCharset;
1791 {* Do not change it if You do not know what You do. }
1792 property FontQuality: TFontQuality read fData.Font.Quality write SetFontQuality;
1793 {* Font quality. }
1794 property FontOrientation: Integer read fData.Font.Orientation write SetFontOrientation;
1795 {* It is possible to rotate text in XCL just by changing this
1796 property of a font (tenths of degree, i.e. value 900 represents
1797 90 degree - text written from bottom to top). }
1798 property FontWeight: Integer read fData.Font.Weight write SetFontWeight;
1799 {* Additional font weight for bold fonts (must be 0..1000). When set to
1800 value <> 0, fsBold is added to FontStyle. And otherwise, when set to 0,
1801 fsBold is removed from FontStyle. Value 700 corresponds to Bold,
1802 400 to Normal. }
1803 property FontName: String read GetFontName write SetFontName;
1804 {* Font face name. }
1805 function IsFontTrueType: Boolean;
1806 {* Returns True, if font is True Type. Requires of creating of a Handle,
1807 if it is not yet created. }
1809 property PenWidth: Integer index go_PenWidth
1810 {$IFDEF F_P}
1811 read GetInt
1812 {$ELSE DELPHI}
1813 read fData.Pen.Width
1814 {$ENDIF F_P/DELPHI}
1815 write SetInt;
1816 {* Value 0 means default pen width. }
1817 property PenStyle: TPenStyle read fData.Pen.Style write SetPenStyle;
1818 {* Pen style. }
1819 property PenMode: TPenMode read fData.Pen.Mode write SetPenMode;
1820 {* Pen mode. }
1822 property GeometricPen: Boolean read fData.Pen.Geometric write SetGeometricPen;
1823 {* True if Pen is geometric. Note, that under Win95/98 only pen styles
1824 psSolid, psNull, psInsideFrame are supported by OS. }
1825 property PenBrushStyle: TBrushStyle read fData.Pen.BrushStyle write SetBrushStyle;
1826 {* Brush style for hatched geometric pen. }
1827 property PenBrushBitmap: HBitmap read fData.Pen.BrushBitmap write SetBrushBitmap;
1828 {* Brush bitmap for geometric pen (if assigned Pen is functioning as
1829 its style = BS_PATTERN, regadless of PenBrushStyle value). }
1830 property PenEndCap: TPenEndCap read fData.Pen.EndCap write SetPenEndCap;
1831 {* Pen end cap mode - for GeometricPen only. }
1832 property PenJoin: TPenJoin read fData.Pen.Join write SetPenJoin;
1833 {* Pen join mode - for GeometricPen only. }
1834 property LogFontStruct: TLogFont read GetLogFontStruct write SetLogFontStruct;
1835 {* by Alex Pravdin: a property to change all font structure items at once. }
1836 end;
1837 //[END OF TGraphicTool DEFINITION]
1839 //[Color2XXX FUNCTIONS]
1840 function Color2RGB( Color: TColor ): TColor;
1841 {* Function to get RGB color from system color. Parameter can be also RGB
1842 color, in that case result is just equal to a parameter. }
1843 function ColorsMix( Color1, Color2: TColor ): TColor;
1844 {* Returns color, which RGB components are build as an (approximate)
1845 arithmetic mean of correspondent RGB components of both source
1846 colors (these both are first converted from system to RGB, and
1847 result is always RGB color). Please note: this function is fast,
1848 but can be not too exact. }
1849 function Color2RGBQuad( Color: TColor ): TRGBQuad;
1850 {* Converts color to RGB, used to represent RGB values in palette entries
1851 (actually swaps R and B bytes). }
1852 function Color2Color16( Color: TColor ): WORD;
1853 {* Converts Color to RGB, packed to word (as it is used in format pf16bit). }
1855 //[DefFont VARIABLE]
1856 var // New TFont instances are intialized with the values in this structure:
1857 DefFont: TGDIFont = (
1858 Height: 0;
1859 Width: 0;
1860 Escapement: 0;
1861 Orientation: 0;
1862 Weight: 0;
1863 Italic: FALSE;
1864 Underline: FALSE;
1865 StrikeOut: FALSE;
1866 CharSet: 1;
1867 OutPrecision: 0;
1868 ClipPrecision: 0;
1869 Quality: fqDefault;
1870 Pitch: fpDefault;
1871 Name: 'MS Sans Serif';
1873 DefFontColor: TColor = clWindowText;
1874 {* Default font color. }
1876 //[GlobalGraphics_UseFontOrient]
1877 GlobalGraphics_UseFontOrient: Boolean;
1878 {* Global flag. If stays False (default), Orientation property of Font
1879 objects is ignored. This flag is set to True automatically in
1880 RotateFonts add-on. }
1882 { -- Constructors for different GDI tools -- }
1884 //[New FUNCTIONS FOR TGraphicTool]
1885 function NewFont: PGraphicTool;
1886 {* Creates and returns font graphic tool object. }
1887 function NewBrush: PGraphicTool;
1888 {* Creates and returns new brush object. }
1889 function NewPen: PGraphicTool;
1890 {* Creates and returns new pen object. }
1905 { -- TCanvas object -- }
1906 //[TCanvas]
1907 const
1908 HandleValid = 1;
1909 PenValid = 2;
1910 BrushValid = 4;
1911 FontValid = 8;
1912 ChangingCanvas = 16;
1914 type
1915 TFillStyle = (fsSurface, fsBorder);
1916 {* Available filling styles. For more info see Win32 or Delphi help files. }
1917 TFillMode = (fmAlternate, fmWinding);
1918 {* Available filling modes. For more info see Win32 or Delphi help files. }
1919 TCopyMode = Integer;
1920 {* Available copying modes are following:
1921 | cmBlackness<br>
1922 | cmDstInvert<br>
1923 | cmMergeCopy<br>
1924 | cmMergePaint<br>
1925 | cmNotSrcCopy<br>
1926 | cmNotSrcErase<br>
1927 | cmPatCopy<br>
1928 | cmPatInvert<br>
1929 | cmPatPaint<br>
1930 | cmSrcAnd<br>
1931 | cmSrcCopy<br>
1932 | cmSrcErase<br>
1933 | cmSrcInvert<br>
1934 | cmSrcPaint<br>
1935 | cmWhiteness<br>&nbsp;&nbsp;&nbsp;
1936 Also it is possible to use any other available ROP2 modes. For more info,
1937 see Win32 help files. }
1939 const
1940 cmBlackness = BLACKNESS;
1941 cmDstInvert = DSTINVERT;
1942 cmMergeCopy = MERGECOPY;
1943 cmMergePaint = MERGEPAINT;
1944 cmNotSrcCopy = NOTSRCCOPY;
1945 cmNotSrcErase = NOTSRCERASE;
1946 cmPatCopy = PATCOPY;
1947 cmPatInvert = PATINVERT;
1948 cmPatPaint = PATPAINT;
1949 cmSrcAnd = SRCAND;
1950 cmSrcCopy = SRCCOPY;
1951 cmSrcErase = SRCERASE;
1952 cmSrcInvert = SRCINVERT;
1953 cmSrcPaint = SRCPAINT;
1954 cmWhiteness = WHITENESS;
1956 type
1957 {++}(*TCanvas = class;*){--}
1958 PCanvas = {-}^{+}TCanvas;
1959 {* }
1960 TOnGetHandle = function( Canvas: PCanvas ): HDC of object;
1961 {* For internal use mainly. }
1962 TOnTextArea = procedure( Sender: PCanvas; var Size : TSize; var P0 : TPoint );
1963 {* Event to calculate actual area, occupying by a text. It is used
1964 to optionally extend calculating of TextArea taking into considaration
1965 font Orientation property. }
1967 { ---------------------------------------------------------------------
1969 TCanvas - high-level drawing helper object
1971 ----------------------------------------------------------------------- }
1972 //[TCanvas DEFINITION]
1973 TCanvas = object( TObj )
1974 {* Very similar to VCL's TCanvas object. But with some changes, specific
1975 for KOL: there is no necessary to use canvases in all applications.
1976 And graphic tools objects are not created with canvas, but only
1977 if really accessed in program. (Actually, even if paint box used,
1978 only programmer decides, if to implement painting using Canvas or
1979 to call low level API drawing functions working directly with DC).
1980 Therefore TCanvas has some powerful extensions: rotated text support,
1981 geometric pen support - just by changing correspondent properties
1982 of certain graphic tool objects (Font.FontOrientation, Pen.GeometricPen).
1983 See also additional Font properties (Font.FontWeight, Font.FontQuality,
1984 etc. }
1985 protected
1986 fOwnerControl: Pointer; //PControl;
1987 fHandle : HDC;
1988 fPenPos : TPoint;
1989 fBrush, fFont, fPen : PGraphicTool; // order is important for ASM version
1990 fState : Byte;
1991 fCopyMode : TCopyMode;
1992 fOnChange: TOnEvent;
1993 fOnGetHandle: TOnGetHandle;
1994 procedure SetHandle( Value : HDC );
1995 procedure SetPenPos( const Value : TPoint );
1996 procedure CreatePen;
1997 procedure CreateBrush;
1998 procedure CreateFont;
1999 procedure ObjectChanged( Sender : PGraphicTool );
2000 procedure Changing;
2001 function GetBrush: PGraphicTool;
2002 function GetFont: PGraphicTool;
2003 function GetPen: PGraphicTool;
2004 function GetHandle: HDC;
2005 procedure AssignChangeEvents;
2006 function GetPixels(X, Y: Integer): TColor;
2007 procedure SetPixels(X, Y: Integer; const Value: TColor);
2008 protected
2009 fIsPaintDC : Boolean;
2010 {* TRUE, if DC obtained during current WM_PAINT (or WM_ERASEBKGND?)
2011 processing for a control. This affects a way how Handle is released. }
2012 {++}(*public*){--}
2013 destructor Destroy;{-}virtual;{+}{++}(*override;*){--}
2014 {* }
2015 {++}(*protected*){--}
2016 property OnGetHandle: TOnGetHandle read fOnGetHandle write fOnGetHandle;
2017 {* For internal use only. }
2018 public
2019 property Handle : HDC read GetHandle write SetHandle;
2020 {* GDI device context object handle. Never created by
2021 Canvas itself (to use Canvas with memory bitmaps,
2022 always create DC by yourself and assign it to the
2023 Handle property of Canvas object, or use property
2024 Canvas of a bitmap). }
2025 property PenPos : TPoint read FPenPos write SetPenPos;
2026 {* Position of a pen. }
2027 property Pen : PGraphicTool read GetPen;
2028 {* Pen of Canvas object. Do not change its Pen.OnChange event value. }
2029 property Brush : PGraphicTool read GetBrush;
2030 {* Brush of Canvas object. Do not change its Brush.OnChange event value. }
2031 property Font : PGraphicTool read GetFont;
2032 {* Font of Canvas object. Do not change its Font.OnChange event value. }
2033 procedure Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
2034 {* Draws arc. For more info, see Delphi TCanvas help. }
2035 procedure Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
2036 {* Draws chord. For more info, see Delphi TCanvas help. }
2037 procedure DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
2038 {* Draws rectangle to represent focused visual object.
2039 For more info, see Delphi TCanvas help. }
2040 procedure Ellipse(X1, Y1, X2, Y2: Integer);
2041 {* Draws an ellipse. For more info, see Delphi TCanvas help. }
2042 procedure FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
2043 {* Fills rectangle. For more info, see Delphi TCanvas help. }
2044 procedure FillRgn( const Rgn : HRgn );
2045 {* Fills region. For more info, see Delphi TCanvas help. }
2046 procedure FloodFill(X, Y: Integer; Color: TColor; FillStyle: TFillStyle);
2047 {* Fills a figure with givien color, floodfilling its surface.
2048 For more info, see Delphi TCanvas help. }
2049 procedure FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
2050 {* Draws a rectangle. For more info, see Delphi TCanvas help. }
2051 procedure MoveTo( X, Y : Integer );
2052 {* Moves current PenPos to a new position.
2053 For more info, see Delphi TCanvas help. }
2054 procedure LineTo( X, Y : Integer );
2055 {* Draws a line from current PenPos up to new position.
2056 For more info, see Delphi TCanvas help. }
2057 procedure Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
2058 {* Draws a pie. For more info, see Delphi TCanvas help. }
2059 procedure Polygon(const Points: array of TPoint);
2060 {* Draws a polygon. For more info, see Delphi TCanvas help. }
2061 procedure Polyline(const Points: array of TPoint);
2062 {* Draws a bound for polygon. For more info, see Delphi TCanvas help. }
2063 procedure Rectangle(X1, Y1, X2, Y2: Integer);
2064 {* Draws a rectangle using current Pen and/or Brush.
2065 For more info, see Delphi TCanvas help. }
2066 procedure RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
2067 {* Draws a rounded rectangle. For more info, see Delphi TCanvas help. }
2068 procedure TextOut(X, Y: Integer; const Text: String); stdcall;
2069 {* Draws a text. For more info, see Delphi TCanvas help. }
2070 procedure ExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect; const Text: String;
2071 const Spacing: array of Integer );
2072 {* }
2073 procedure DrawText(Text:String; var Rect:TRect; Flags:DWord);
2074 {* }
2075 procedure TextRect(const Rect: TRect; X, Y: Integer; const Text: string);
2076 {* Draws a text, clipping output into given rectangle.
2077 For more info, see Delphi TCanvas help. }
2078 function TextExtent(const Text: string): TSize;
2079 {* Calculates size of a Text, using current Font settings.
2080 Does not need in Handle for Canvas object (if it is not
2081 yet allocated, temporary device context is created and used. }
2082 procedure TextArea( const Text : String; var Sz : TSize; var P0 : TPoint );
2083 {* Calculates size and starting point to output Text,
2084 taking into considaration all Font attributes, including
2085 Orientation (only if GlobalGraphics_UseFontOrient flag
2086 is set to True, i.e. if rotated fonts are used).
2087 Like for TextExtent, does not need in Handle (and if this
2088 last is not yet allocated/assigned, temporary device context
2089 is created and used). }
2090 function TextWidth(const Text: string): Integer;
2091 {* Calculates text width (using TextArea). }
2092 function TextHeight(const Text: string): Integer;
2093 {* Calculates text height (using TextArea). }
2094 function ClipRect: TRect;
2095 {* returns ClipBox. by Dmitry Zharov. }
2097 {$IFNDEF _FPC}
2098 {$IFNDEF _D2} //------- WideString not supported in D2
2099 procedure WTextOut(X, Y: Integer; const WText: WideString); stdcall;
2100 {* Draws a Unicode text. }
2101 procedure WExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect;
2102 const WText: WideString; const Spacing: array of Integer );
2103 {* }
2104 procedure WDrawText(WText: WideString; var Rect:TRect; Flags:DWord);
2105 {* }
2106 procedure WTextRect(const Rect: TRect; X, Y: Integer;
2107 const WText: WideString);
2108 {* Draws a Unicode text, clipping output into given rectangle. }
2109 function WTextExtent( const WText: WideString ): TSize;
2110 {* Calculates Unicode text width and height. }
2111 function WTextWidth( const WText: WideString ): Integer;
2112 {* Calculates Unicode text width. }
2113 function WTextHeight( const WText: WideString ): Integer;
2114 {* Calculates Unicode text height. }
2115 {$ENDIF _D2}
2116 {$ENDIF _FPC}
2118 property ModeCopy : TCopyMode read fCopyMode write fCopyMode;
2119 {* Current copy mode. Is used in CopyRect method. }
2120 procedure CopyRect( const DstRect : TRect; SrcCanvas : PCanvas; const SrcRect : TRect );
2121 {* Copyes a rectangle from source to destination, using StretchBlt. }
2122 property OnChange: TOnEvent read fOnChange write fOnChange;
2123 {* }
2124 function Assign( SrcCanvas : PCanvas ) : Boolean;
2125 {* }
2126 function RequiredState( ReqState : DWORD ): Integer; stdcall;// public now
2127 {* It is possible to call this method before using Handle property
2128 to pass it into API calls - to provide valid combinations of
2129 pen, brush and font, selected into device context. This method
2130 can not provide valid Handle - You always must create it by
2131 yourself and assign to TCanvas.Handle property manually.
2132 To optimize assembler version, returns Handle value. }
2133 procedure DeselectHandles;
2134 {* Call this method to deselect all graphic tool objects from the canvas. }
2135 property Pixels[ X, Y: Integer ]: TColor read GetPixels write SetPixels;
2136 {* Obvious. }
2137 end;
2138 //[END OF TCanvas DEFINITION]
2140 //[GlobalCanvas_OnTextArea]
2142 GlobalCanvas_OnTextArea : TOnTextArea;
2143 {* Global event to extend Canvas with possible add-ons, applied
2144 when rotated fonts are used only (to take into consideration
2145 Font.Orientation property in TextArea method). }
2147 //[NewCanvas DECLARATION]
2148 function NewCanvas( DC: HDC ): PCanvas;
2149 {* Use to construct Canvas on base of memory DC. }
2151 //[Extended FUNCTIONS TO WORK WITH CANVAS]
2152 {++}(*
2153 {$IFDEF F_P}
2154 function Windows_Polygon(DC: HDC; var Points; Count: Integer): BOOL; stdcall;
2155 function Windows_Polyline(DC: HDC; var Points; Count: Integer): BOOL; stdcall;
2156 function FillRect(hDC: HDC; const lprc: TRect; hbr: HBRUSH): Integer; stdcall;
2157 function OffsetRect(var lprc: TRect; dx, dy: Integer): BOOL; stdcall;
2158 function CreateAcceleratorTable(var Accel; Count: Integer): HACCEL; stdcall;
2159 function TrackPopupMenu(hMenu: HMENU; uFlags: UINT; x, y, nReserved: Integer;
2160 hWnd: HWND; prcRect: PRect): BOOL; stdcall;
2161 function AdjustTokenPrivileges(TokenHandle: THandle; DisableAllPrivileges: BOOL;
2162 const NewState: TTokenPrivileges; BufferLength: DWORD;
2163 var PreviousState: TTokenPrivileges; var ReturnLength: DWORD): BOOL; stdcall;
2164 function InflateRect(var lprc: TRect; dx, dy: Integer): BOOL; stdcall;
2165 {$IFDEF F_P105ORBELOW}
2166 function InvalidateRect(hWnd: HWND; lpRect: PRect; bErase: BOOL): BOOL; stdcall;
2167 function ValidateRect(hWnd: HWND; lpRect: PRect): BOOL; stdcall;
2168 {$ENDIF F_P105ORBELOW}
2169 {$ENDIF}
2170 *){--}
2185 { -- Image list object -- }
2186 //[IMAGE LIST]
2188 type
2189 TImageListColors = (ilcColor,ilcColor4,ilcColor8,ilcColor16,
2190 ilcColor24,ilcColor32,ilcColorDDB,ilcDefault);
2191 {* ImageList color schemes available. }
2193 TDrawingStyles = ( dsBlend25, dsBlend50, dsMask, dsTransparent );
2194 {* ImageList drawing styles available. }
2195 TDrawingStyle = Set of TDrawingStyles;
2196 {* Style of drawing is a combination of all available drawing styles. }
2198 TImageType = (itBitmap,itIcon,itCursor);
2199 {* ImageList types available. }
2201 {++}(*TImageList = class;*){--}
2202 PImageList = {-}^{+}TImageList;
2203 {* }
2205 TImgLOVrlayIdx = 1..15;
2207 { ---------------------------------------------------------------------
2209 TImageList - images container
2211 ----------------------------------------------------------------------- }
2212 //[TImageList DEFINITION]
2213 TImageList = object( TObj )
2214 {* ImageList incapsulation. }
2215 protected
2216 FHandle: THandle;
2217 FControl: Pointer; // PControl;
2218 fPrev, fNext: PImageList;
2219 FColors: TImageListColors;
2220 FMasked: Boolean;
2221 FImgWidth: Integer;
2222 FImgHeight: Integer;
2223 FDrawingStyle: TDrawingStyle;
2224 FBlendColor: TColor;
2225 fBkColor: TColor;
2226 FAllocBy: Integer;
2227 FShareImages: Boolean;
2228 FOverlay: array[ TImgLOVrlayIdx ] of Integer;
2229 function HandleNeeded : Boolean;
2230 procedure SetColors(const Value: TImageListColors);
2231 procedure SetMasked(const Value: Boolean);
2232 procedure SetImgWidth(const Value: Integer);
2233 procedure SetImgHeight(const Value: Integer);
2234 function GetCount: Integer;
2235 function GetBkColor: TColor;
2236 procedure SetBkColor(const Value: TColor);
2237 function GetBitmap: HBitmap;
2238 function GetMask: HBitmap;
2239 function GetDrawStyle : DWord;
2240 procedure SetAllocBy(const Value: Integer);
2241 function GetHandle: THandle;
2242 function GetOverlay(Idx: TImgLOVrlayIdx): Integer;
2243 procedure SetOverlay(Idx: TImgLOVrlayIdx; const Value: Integer);
2244 protected
2245 procedure SetHandle(const Value: THandle);
2247 public
2248 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2250 property Handle : THandle read GetHandle write SetHandle;
2251 {* Handle of ImageList object. }
2252 property ShareImages : Boolean read FShareImages write FShareImages;
2253 {* True if images are shared between processes (it is set to True,
2254 if its Handle is assigned to given value, which is a handle of
2255 already existing ImageList object). }
2256 property Colors : TImageListColors read FColors write SetColors;
2257 {* Colors used to represent images. }
2258 property Masked : Boolean read FMasked write SetMasked;
2259 {* True, if mask is used. It is set to True, if first added image
2260 is icon, e.g. }
2261 property ImgWidth : Integer read FImgWidth write SetImgWidth;
2262 {* Width of every image in list. If change, ImageList is cleared. }
2263 property ImgHeight : Integer read FImgHeight write SetImgHeight;
2264 {* Height of every image in list. If change, ImageList is cleared. }
2265 property Count : Integer read GetCount;
2266 {* Number of images in list. }
2267 property AllocBy : Integer read FAllocBy write SetAllocBy;
2268 {* Allocation factor. Default is 1. Set it to size of ImageList if this
2269 value is known - to optimize speed of allocation. }
2270 property BkColor : TColor read GetBkColor write SetBkColor;
2271 {* Background color. }
2272 property BlendColor : TColor read FBlendColor write FBlendColor;
2273 {* Blend color. }
2275 property Bitmap : HBitmap read GetBitmap;
2276 {* Bitmap, containing all ImageList images (tiled horizontally). }
2277 property Mask : HBitmap read GetMask;
2278 {* Monochrome bitmap, containing masks for all images in list (if not
2279 Masked, always returns nil). }
2280 function ImgRect( Idx : Integer ) : TRect;
2281 {* Rectangle occupied of given image in ImageList. }
2283 function Add( Bmp, Msk : HBitmap ) : Integer;
2284 {* Adds bitmap and given mask to ImageList. }
2285 function AddMasked( Bmp : HBitmap; Color : TColor ) : Integer;
2286 {* Adds bitmap to ImageList, using given color to create mask. }
2287 function AddIcon( Ico : HIcon ) : Integer;
2288 {* Adds icon to ImageList (always masked). }
2289 procedure Delete( Idx : Integer );
2290 {* Deletes given image from ImageList. }
2291 procedure Clear;
2292 {* Makes ImageList empty. }
2293 function Replace( Idx : Integer; Bmp, Msk : HBitmap ) : Boolean;
2294 {* Replaces given (by index) image with bitmap and its mask with mask bitmap. }
2295 function ReplaceIcon( Idx : Integer; Ico : HIcon ) : Boolean;
2296 {* Replaces given (by index) image with an icon. }
2297 function Merge( Idx : Integer; ImgList2 : PImageList; Idx2 : Integer; X, Y : Integer )
2298 : PImageList;
2299 {* Merges two ImageList objects, returns resulting ImageList. }
2300 function ExtractIcon( Idx : Integer ) : HIcon;
2301 {* Extracts icon by index. }
2302 function ExtractIconEx( Idx : Integer ) : HIcon;
2303 {* Extracts icon (is created using current drawing style). }
2305 property DrawingStyle : TDrawingStyle read FDrawingStyle write FDrawingStyle;
2306 {* Drawing style. }
2307 procedure Draw( Idx : Integer; DC : HDC; X, Y : Integer );
2308 {* Draws given (by index) image from ImageList onto passed Device Context. }
2309 procedure StretchDraw( Idx : Integer; DC : HDC; const Rect : TRect );
2310 {* Draws given image with stratching. }
2312 function LoadBitmap( ResourceName : PChar; TranspColor : TColor ) : Boolean;
2313 {* Loads ImageList from resource. }
2314 //function LoadIcon( ResourceName : PChar ) : Boolean;
2315 //function LoadCursor( ResourceName : PChar ) : Boolean;
2316 function LoadFromFile( FileName : PChar; TranspColor : TColor; ImgType : TImageType ) : Boolean;
2317 {* Loads ImageList from file. }
2318 function LoadSystemIcons( SmallIcons : Boolean ) : Boolean;
2319 {* Assigns ImageList to system icons list (big or small). }
2321 property Overlay[ Idx: TImgLOVrlayIdx ]: Integer read GetOverlay write SetOverlay;
2322 {* Overlay images for image list (images, used as overlay images to draw over
2323 other images from the image list). These overalay images can be used in
2324 listview and treeview as overlaying images (up to four masks at the same
2325 time). }
2326 {$IFDEF USE_CONSTRUCTORS}
2327 constructor CreateImageList( POwner: Pointer );
2328 {$ENDIF USE_CONSTRUCTORS}
2329 end;
2330 //[END OF TImageList DEFINITION]
2332 //[IMAGE LIST API]
2334 const
2335 CLR_NONE = $FFFFFFFF;
2336 CLR_DEFAULT = $FF000000;
2338 type
2339 HImageList = THandle;
2341 const
2342 ILC_MASK = $0001;
2343 ILC_COLOR = $00FE;
2344 ILC_COLORDDB = $00FE;
2345 ILC_COLOR4 = $0004;
2346 ILC_COLOR8 = $0008;
2347 ILC_COLOR16 = $0010;
2348 ILC_COLOR24 = $0018;
2349 ILC_COLOR32 = $0020;
2350 ILC_PALETTE = $0800;
2352 const
2353 ILD_NORMAL = $0000;
2354 ILD_TRANSPARENT = $0001;
2355 ILD_MASK = $0010;
2356 ILD_IMAGE = $0020;
2357 ILD_BLEND25 = $0002;
2358 ILD_BLEND50 = $0004;
2359 ILD_OVERLAYMASK = $0F00;
2361 const
2362 ILD_SELECTED = ILD_BLEND50;
2363 ILD_FOCUS = ILD_BLEND25;
2364 ILD_BLEND = ILD_BLEND50;
2365 CLR_HILIGHT = CLR_DEFAULT;
2367 function ImageList_Create(CX, CY: Integer; Flags: UINT;
2368 Initial, Grow: Integer): HImageList; stdcall;
2369 function ImageList_Destroy(ImageList: HImageList): Bool; stdcall;
2370 function ImageList_GetImageCount(ImageList: HImageList): Integer; stdcall;
2371 function ImageList_SetImageCount(ImageList: HImageList; Count: Integer): Integer; stdcall;
2372 function ImageList_Add(ImageList: HImageList; Image, Mask: HBitmap): Integer; stdcall;
2373 function ImageList_ReplaceIcon(ImageList: HImageList; Index: Integer;
2374 Icon: HIcon): Integer; stdcall;
2375 function ImageList_SetBkColor(ImageList: HImageList; ClrBk: TColorRef): TColorRef; stdcall;
2376 function ImageList_GetBkColor(ImageList: HImageList): TColorRef; stdcall;
2377 function ImageList_SetOverlayImage(ImageList: HImageList; Image: Integer;
2378 Overlay: Integer): Bool; stdcall;
2380 function ImageList_AddIcon(ImageList: HImageList; Icon: HIcon): Integer;
2382 function Index2OverlayMask(Index: Integer): Integer;
2384 function ImageList_Draw(ImageList: HImageList; Index: Integer;
2385 Dest: HDC; X, Y: Integer; Style: UINT): Bool; stdcall;
2387 function ImageList_Replace(ImageList: HImageList; Index: Integer;
2388 Image, Mask: HBitmap): Bool; stdcall;
2389 function ImageList_AddMasked(ImageList: HImageList; Image: HBitmap;
2390 Mask: TColorRef): Integer; stdcall;
2391 function ImageList_DrawEx(ImageList: HImageList; Index: Integer;
2392 Dest: HDC; X, Y, DX, DY: Integer; Bk, Fg: TColorRef; Style: Cardinal): Bool; stdcall;
2393 function ImageList_Remove(ImageList: HImageList; Index: Integer): Bool; stdcall;
2394 function ImageList_GetIcon(ImageList: HImageList; Index: Integer;
2395 Flags: Cardinal): HIcon; stdcall;
2396 function ImageList_LoadImageA(Instance: THandle; Bmp: PAnsiChar; CX, Grow: Integer;
2397 Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;
2398 function ImageList_LoadImageW(Instance: THandle; Bmp: PWideChar; CX, Grow: Integer;
2399 Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;
2400 function ImageList_LoadImage(Instance: THandle; Bmp: PChar; CX, Grow: Integer;
2401 Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;
2402 function ImageList_BeginDrag(ImageList: HImageList; Track: Integer;
2403 XHotSpot, YHotSpot: Integer): Bool; stdcall;
2404 function ImageList_EndDrag: Bool; stdcall;
2405 function ImageList_DragEnter(LockWnd: HWnd; X, Y: Integer): Bool; stdcall;
2406 function ImageList_DragLeave(LockWnd: HWnd): Bool; stdcall;
2407 function ImageList_DragMove(X, Y: Integer): Bool; stdcall;
2408 function ImageList_SetDragCursorImage(ImageList: HImageList; Drag: Integer;
2409 XHotSpot, YHotSpot: Integer): Bool; stdcall;
2410 function ImageList_DragShowNolock(Show: Bool): Bool; stdcall;
2411 function ImageList_GetDragImage(Point, HotSpot: PPoint): HImageList; stdcall;
2413 { macros }
2414 procedure ImageList_RemoveAll(ImageList: HImageList); stdcall;
2415 function ImageList_ExtractIcon(Instance: THandle; ImageList: HImageList;
2416 Image: Integer): HIcon; stdcall;
2417 function ImageList_LoadBitmap(Instance: THandle; Bmp: PChar;
2418 CX, Grow: Integer; MasK: TColorRef): HImageList; stdcall;
2420 //function ImageList_Read(Stream: IStream): HImageList; stdcall;
2421 //function ImageList_Write(ImageList: HImageList; Stream: IStream): BOOL; stdcall;
2423 //[TImageInfo]
2424 type
2425 PImageInfo = ^TImageInfo;
2426 TImageInfo = packed record
2427 hbmImage: HBitmap;
2428 hbmMask: HBitmap;
2429 Unused1: Integer;
2430 Unused2: Integer;
2431 rcImage: TRect;
2432 end;
2434 function ImageList_GetIconSize(ImageList: HImageList; var CX, CY: Integer): Bool; stdcall;
2435 function ImageList_SetIconSize(ImageList: HImageList; CX, CY: Integer): Bool; stdcall;
2436 function ImageList_GetImageInfo(ImageList: HImageList; Index: Integer;
2437 var ImageInfo: TImageInfo): Bool; stdcall;
2438 function ImageList_Merge(ImageList1: HImageList; Index1: Integer;
2439 ImageList2: HImageList; Index2: Integer; DX, DY: Integer)://Bool - ERROR IN VCL
2440 HImageList; stdcall;
2442 //[LoadBmp]
2443 function LoadBmp( Instance: Integer; Rsrc: PChar; MasterObj: PObj ): HBitmap;
2458 //[BITMAPS]
2459 type
2460 tagBitmap = Windows.TBitmap;
2462 TPixelFormat = ( pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit,
2463 pf32bit, pfCustom );
2464 {* Available pixel formats. }
2465 TBitmapHandleType = ( bmDIB, bmDDB );
2466 {* Available bitmap handle types. }
2468 {++}(*TBitmap = class;*){--}
2469 PBitmap = {-}^{+}TBitmap;
2470 { ----------------------------------------------------------------------
2472 TBitmap - bitmap image
2474 ----------------------------------------------------------------------- }
2475 //[TBitmap DEFINITION]
2476 TBitmap = object( TObj )
2477 {* Bitmap incapsulation object. }
2478 protected
2479 fHeight: Integer;
2480 fWidth: Integer;
2481 fHandle: HBitmap;
2482 fCanvas: PCanvas;
2483 fScanLineSize: Integer;
2484 fBkColor: TColor;
2485 fApplyBkColor2Canvas: procedure( Sender: PBitmap );
2486 fDetachCanvas: procedure( Sender: PBitmap );
2487 fCanvasAttached : Integer;
2488 fHandleType: TBitmapHandleType;
2489 fDIBHeader: PBitmapInfo;
2490 fDIBBits: Pointer;
2491 fDIBSize: Integer;
2492 fNewPixelFormat: TPixelFormat;
2493 fFillWithBkColor: procedure( BmpObj: PBitmap; DC: HDC; oldW, oldH: Integer );
2494 //stdcall;
2495 fTransMaskBmp: PBitmap;
2496 fTransColor: TColor;
2497 fGetDIBPixels: function( Bmp: PBitmap; X, Y: Integer ): TColor;
2498 fSetDIBPixels: procedure( Bmp: PBitmap; X, Y: Integer; Value: TColor );
2499 fScanLine0: PByte;
2500 fScanLineDelta: Integer;
2501 fPixelMask: DWORD;
2502 fPixelsPerByteMask: Integer;
2503 fBytesPerPixel: Integer;
2504 fDIBAutoFree: Boolean;
2505 procedure SetHeight(const Value: Integer);
2506 procedure SetWidth(const Value: Integer);
2507 function GetEmpty: Boolean;
2508 function GetHandle: HBitmap;
2509 function GetHandleAllocated: Boolean;
2510 procedure SetHandle(const Value: HBitmap);
2511 procedure SetPixelFormat(Value: TPixelFormat);
2512 procedure FormatChanged;
2513 function GetCanvas: PCanvas;
2514 procedure CanvasChanged( Sender: PObj );
2515 function GetScanLine(Y: Integer): Pointer;
2516 function GetScanLineSize: Integer;
2517 procedure ClearData;
2518 procedure ClearTransImage;
2519 procedure SetBkColor(const Value: TColor);
2520 function GetDIBPalEntries(Idx: Integer): TColor;
2521 function GetDIBPalEntryCount: Integer;
2522 procedure SetDIBPalEntries(Idx: Integer; const Value: TColor);
2523 procedure SetHandleType(const Value: TBitmapHandleType);
2524 function GetPixelFormat: TPixelFormat;
2525 function GetPixels(X, Y: Integer): TColor;
2526 procedure SetPixels(X, Y: Integer; const Value: TColor);
2527 function GetDIBPixels(X, Y: Integer): TColor;
2528 procedure SetDIBPixels(X, Y: Integer; const Value: TColor);
2529 function GetBoundsRect: TRect;
2530 protected
2531 {++}(*public*){--}
2532 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2533 public
2534 property Width: Integer read fWidth write SetWidth;
2535 {* Width of bitmap. To make code smaller, avoid changing Width or Height
2536 after bitmap is created (using NewBitmap) or after it is loaded from
2537 file, stream of resource. }
2538 property Height: Integer read fHeight write SetHeight;
2539 {* Height of bitmap. To make code smaller, avoid changing Width or Height
2540 after bitmap is created (using NewBitmap) or after it is loaded from
2541 file, stream of resource. }
2542 property BoundsRect: TRect read GetBoundsRect;
2543 {* Returns rectangle (0,0,Width,Height). }
2544 property Empty: Boolean read GetEmpty;
2545 {* Returns True if Width or Height is 0. }
2546 procedure Clear;
2547 {* Makes bitmap empty, setting its Width and Height to 0. }
2548 procedure LoadFromFile( const Filename: String );
2549 {* Loads bitmap from file (LoadFromStream used). }
2550 function LoadFromFileEx( const Filename: String ): Boolean;
2551 {* Loads bitmap from a file. If necessary, bitmap is RLE-decoded. Code given
2552 by Vyacheslav A. Gavrik. }
2553 procedure SaveToFile( const Filename: String );
2554 {* Stores bitmap to file (SaveToStream used). }
2555 procedure LoadFromStream( Strm: PStream );
2556 {* Loads bitmap from stream. Follow loading, bitmap has DIB format (without
2557 handle allocated). It is possible to draw DIB bitmap without creating
2558 handle for it, which can economy GDI resources. }
2559 function LoadFromStreamEx( Strm: PStream ): Boolean;
2560 {* Loads bitmap from a stream. Difference is that RLE decoding supported.
2561 Code given by Vyacheslav A. Gavrik. }
2562 procedure SaveToStream( Strm: PStream );
2563 {* Saves bitmap to stream. If bitmap is not DIB, it is converted to DIB
2564 before saving. }
2565 procedure LoadFromResourceID( Inst: DWORD; ResID: Integer );
2566 {* Loads bitmap from resource using integer ID of resource. To load by name,
2567 use LoadFromResurceName. To load resource of application itself, pass
2568 hInstance as first parameter. This method also can be used to load system
2569 predefined bitmaps, if 0 is passed as Inst parameter:
2570 |<pre>
2571 OBM_BTNCORNERS OBM_REDUCE
2572 OBM_BTSIZE OBM_REDUCED
2573 OBM_CHECK OBM_RESTORE
2574 OBM_CHECKBOXES OBM_RESTORED
2575 OBM_CLOSE OBM_RGARROW
2576 OBM_COMBO OBM_RGARROWD
2577 OBM_DNARROW OBM_RGARROWI
2578 OBM_DNARROWD OBM_SIZE
2579 OBM_DNARROWI OBM_UPARROW
2580 OBM_LFARROW OBM_UPARROWD
2581 OBM_LFARROWD OBM_UPARROWI
2582 OBM_LFARROWI OBM_ZOOM
2583 OBM_MNARROW OBM_ZOOMD
2584 |</pre> }
2585 procedure LoadFromResourceName( Inst: DWORD; ResName: PChar );
2586 {* Loads bitmap from resurce (using passed name of bitmap resource. }
2587 function Assign( SrcBmp: PBitmap ): Boolean;
2588 {* Assigns bitmap from another. Returns False if not success.
2589 Note: remember, that Canvas is not assigned - only bitmap image
2590 is copied. And for DIB, handle is not allocating due this process. }
2591 property Handle: HBitmap read GetHandle write SetHandle;
2592 {* Handle of bitmap. Created whenever property accessed. To check if handle
2593 is allocated (without allocating it), use HandleAllocated property. }
2594 property HandleAllocated: Boolean read GetHandleAllocated;
2595 {* Returns True, if Handle already allocated. }
2596 function ReleaseHandle: HBitmap;
2597 {* Returns Handle and releases it, so bitmap no more know about handle.
2598 This method does not destroy bitmap image, but converts it into DIB.
2599 Returned Handle actually is a handle of copy of original bitmap. If
2600 You need not in keping it up, use Dormant method instead. }
2601 procedure Dormant;
2602 {* Releases handle from bitmap and destroys it. But image is not destroyed
2603 and its data are preserved in DIB format. Please note, that in KOL, DIB
2604 bitmaps can be drawn onto given device context without allocating of
2605 handle. So, it is very useful to call Dormant preparing it using
2606 Canvas drawing operations - to economy GDI resources. }
2607 property HandleType: TBitmapHandleType read fHandleType write SetHandleType;
2608 {* bmDIB, if DIB part of image data is filled and stored internally in
2609 TBitmap object. DIB image therefore can have Handle allocated, which
2610 require resources. Use HandleAllocated funtion to determine if handle
2611 is allocated and Dormant method to remove it, if You want to economy
2612 GDI resources. (Actually Handle needed for DIB bitmap only in case
2613 when Canvas is used to draw on bitmap surface). Please note also, that
2614 before saving bitmap to file or stream, it is converted to DIB. }
2615 property PixelFormat: TPixelFormat read GetPixelFormat write SetPixelFormat;
2616 {* Current pixel format. If format of bitmap is unknown, or bitmap is DDB,
2617 value is pfDevice. Setting PixelFormat to any other format converts
2618 bitmap to DIB, back to pfDevice converts bitmap to DDB again. Avoid
2619 such conversations for large bitmaps or for numerous bitmaps in your
2620 application to keep good performance. }
2621 function BitsPerPixel: Integer;
2622 {* Returns bits per pixel if possible. }
2623 procedure Draw( DC: HDC; X, Y: Integer );
2624 {* Draws bitmap to given device context. If bitmap is DIB, it is always
2625 drawing using SetDIBitsToDevice API call, which does not require bitmap
2626 handle (so, it is very sensible to call Dormant method to free correspondent
2627 GDI resources). }
2628 procedure StretchDraw( DC: HDC; const Rect: TRect );
2629 {* Draws bitmap onto DC, stretching it to fit given rectangle Rect. }
2630 procedure DrawTransparent( DC: HDC; X, Y: Integer; TranspColor: TColor );
2631 {* Draws bitmap onto DC transparently, using TranspColor as transparent. }
2632 procedure StretchDrawTransparent( DC: HDC; const Rect: TRect; TranspColor: TColor );
2633 {* Draws bitmap onto given rectangle of destination DC (with stretching it
2634 to fit Rect) - transparently, using TranspColor as transparent. }
2635 procedure DrawMasked( DC: HDC; X, Y: Integer; Mask: HBitmap );
2636 {* Draws bitmap to destination DC transparently by mask. It is possible
2637 to pass as a mask handle of another TBitmap, previously converted to
2638 monochrome mask using Convert2Mask method. }
2639 procedure StretchDrawMasked( DC: HDC; const Rect: TRect; Mask: HBitmap );
2640 {* Like DrawMasked, but with stretching image onto given rectangle. }
2641 procedure Convert2Mask( TranspColor: TColor );
2642 {* Converts bitmap to monochrome (mask) bitmap with TranspColor replaced
2643 to clBlack and all other ones to clWhite. Such mask bitmap can be used
2644 to draw original bitmap transparently, with given TranspColor as
2645 transparent. (To preserve original bitmap, create new instance of
2646 TBitmap and assign original bitmap to it). See also DrawTransparent and
2647 StretchDrawTransparent methods. }
2648 procedure Invert;
2649 {* Obvious. }
2650 property Canvas: PCanvas read GetCanvas;
2651 {* Canvas can be used to draw onto bitmap. Whenever it is accessed, handle
2652 is allocated for bitmap, if it is not yet (to make it possible
2653 to select bitmap to display compatible device context). }
2654 procedure RemoveCanvas;
2655 {* Call this method to destroy Canvas and free GDI resources. }
2656 property BkColor: TColor read fBkColor write SetBkColor;
2657 {* Used to fill background for Bitmap, when its width or height is increased.
2658 Although this value always synchronized with Canvas.Brush.Color, use it
2659 instead if You do not use Canvas for drawing on bitmap surface. }
2660 property Pixels[ X, Y: Integer ]: TColor read GetPixels write SetPixels;
2661 {* Allows to obtain or change certain pixels of a bitmap. This method is
2662 both for DIB and DDB bitmaps, and leads to allocate handle anyway. For
2663 DIB bitmaps, it is possible to use property DIBPixels[ ] instead,
2664 which is much faster and does not require in Handle. }
2665 property ScanLineSize: Integer read GetScanLineSize;
2666 {* Returns size of scan line in bytes. Use it to measure size of a single
2667 ScanLine. To calculate increment value from first byte of ScanLine to
2668 first byte of next ScanLine, use difference
2669 ! Integer(ScanLine[1]-ScanLine[0])
2670 (this is because bitmap can be oriented from bottom to top, so
2671 step can be negative). }
2672 property ScanLine[ Y: Integer ]: Pointer read GetScanLine;
2673 {* Use ScanLine to access DIB bitmap pixels in memory to direct access it
2674 fast. Take in attention, that for different pixel formats, different
2675 bit counts are used to represent bitmap pixels. Also do not forget, that
2676 for formats pf4bit and pf8bit, pixels actually are indices to palette
2677 entries, and for formats pf16bit, pf24bit and pf32bit are actually
2678 RGB values (for pf16bit B:5-G:6-R:5, for pf15bit B:5-G:5-R:5 (high order
2679 bit not used), for pf24bit B:8-G:8-R:8, and for pf32bit high order byte
2680 of TRGBQuad structure is not used). }
2681 property DIBPixels[ X, Y: Integer ]: TColor read GetDIBPixels write SetDIBPixels;
2682 {* Allows direct access to pixels of DIB bitmap, faster then Pixels[ ]
2683 property. Access to read is slower for pf15bit, pf16bit formats (because
2684 some conversation needed to translate packed RGB color to TColor). And
2685 for write, operation performed most slower for pf4bit, pf8bit (searching
2686 nearest color required) and fastest for pf24bit, pf32bit and pf1bit. }
2687 property DIBPalEntryCount: Integer read GetDIBPalEntryCount;
2688 {* Returns palette entries count for DIB image. Always returns 2 for pf1bit,
2689 16 for pf4bit, 256 for pf8bit and 0 for other pixel formats. }
2690 property DIBPalEntries[ Idx: Integer ]: TColor read GetDIBPalEntries write
2691 SetDIBPalEntries;
2692 {* Provides direct access to DIB palette. }
2693 function DIBPalNearestEntry( Color: TColor ): Integer;
2694 {* Returns index of entry in DIB palette with color nearest (or matching)
2695 to given one. }
2696 property DIBBits: Pointer read fDIBBits;
2697 {* This property is mainly for internal use. }
2698 property DIBSize: Integer read fDIBSize;
2699 {* Size of DIBBits array. }
2700 property DIBHeader: PBitmapInfo read fDIBHeader;
2701 {* This property is mainly for internal use. }
2702 procedure DIBDrawRect( DC: HDC; X, Y: Integer; const R: TRect );
2703 {* This procedure copies given rectangle to the target device context,
2704 but only for DIB bitmap (using SetDIBBitsToDevice API call). }
2705 procedure RotateRight;
2706 {* Rotates bitmap right (90 degree). Bitmap must be DIB. If You definitevely
2707 know format of a bitmap, use instead one of methods RotateRightMono,
2708 RotateRight4bit, RotateRight8bit, RotateRight16bit or RotateRightTrueColor
2709 - this will economy code. But if for most of formats such methods are
2710 called, this can be more economy just to call always universal method
2711 RotateRight. }
2712 procedure RotateLeft;
2713 {* Rotates bitmap left (90 degree). Bitmap must be DIB. If You definitevely
2714 know format of a bitmap, use instead one of methods RotateLeftMono,
2715 RotateLeft4bit, RotateLeft8bit, RotateLeft16bit or RotateLeftTrueColor
2716 - this will economy code. But if for most of formats such methods are
2717 called, this can be more economy just to call always universal method
2718 RotateLeft. }
2719 procedure RotateRightMono;
2720 {* Rotates bitmat right, but only if bitmap is monochrome (pf1bit). }
2721 procedure RotateLeftMono;
2722 {* Rotates bitmap left, but only if bitmap is monochrome (pf1bit). }
2723 procedure RotateRight4bit;
2724 {* Rotates bitmap right, but only if PixelFormat is pf4bit. }
2725 procedure RotateLeft4bit;
2726 {* Rotates bitmap left, but only if PixelFormat is pf4bit. }
2727 procedure RotateRight8bit;
2728 {* Rotates bitmap right, but only if PixelFormat is pf8bit. }
2729 procedure RotateLeft8bit;
2730 {* Rotates bitmap left, but only if PixelFormat is pf8bit. }
2731 procedure RotateRight16bit;
2732 {* Rotates bitmap right, but only if PixelFormat is pf16bit. }
2733 procedure RotateLeft16bit;
2734 {* Rotates bitmap left, but only if PixelFormat is pf16bit. }
2735 procedure RotateRightTrueColor;
2736 {* Rotates bitmap right, but only if PixelFormat is pf24bit or pf32bit. }
2737 procedure RotateLeftTrueColor;
2738 {* Rotates bitmap left, but only if PixelFormat is pf24bit or pf32bit. }
2739 procedure FlipVertical;
2740 {* Flips bitmap vertically }
2741 procedure FlipHorizontal;
2742 {* Flips bitmap horizontally }
2743 procedure CopyRect( const DstRect : TRect; SrcBmp : PBitmap; const SrcRect : TRect );
2744 {* It is possible to use Canvas.CopyRect for such purpose, but if You
2745 do not want use TCanvas, it is possible to copy rectangle from one
2746 bitmap to another using this function. }
2747 function CopyToClipboard: Boolean;
2748 {* Copies bitmap to clipboard. }
2749 function PasteFromClipboard: Boolean;
2750 {* Takes CF_DIB format bitmap from clipboard and assigns it to the
2751 TBitmap object. }
2752 end;
2753 //[END OF TBitmap DEFINITION]
2755 //[NewBitmap DECLARATION]
2756 function NewBitmap( W, H: Integer ): PBitmap;
2757 {* Creates bitmap object of given size. If it is possible, do not change its
2758 size (Width and Heigth) later - this can economy code a bit. See TBitmap. }
2760 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;
2761 {* Creates DIB bitmap object of given size and pixel format. If it is possible,
2762 do not change its size (Width and Heigth) later - this can economy code a bit.
2763 See TBitmap. }
2765 //[CalcScanLineSize DECLARATION]
2766 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;
2767 {* May be will be useful. }
2769 //[DefaultPixelFormat VARIABLE]
2771 //DefaultBitsPerPixel: Integer = 16;
2772 DefaultPixelFormat: TPixelFormat = pf16bit;
2774 //[Mapped bitmaps]
2776 { -- Function to load bitmap mapping some its colors. -- }
2777 function LoadMappedBitmap( hInst: THandle; BmpResID: Integer; const Map: array of TColor )
2778 : HBitmap;
2779 {* This function can be used to load bitmap and replace some it colors to
2780 desired ones. This function especially useful when loaded by the such way
2781 bitmap is used as toolbar bitmap - to replace some original colors to
2782 system default colors. To use this function properly, the bitmap shoud
2783 be prepared as 16-color bitmap, which uses only system colors. To do so,
2784 create a new 16-color bitmap with needed dimensions in Borland Image Editor
2785 and paste a bitmap image, copyed in another graphic tool, and then save it.
2786 If this is not done, bitmap will not be loaded correctly! }
2787 function LoadMappedBitmapEx( MasterObj: PObj; hInst: THandle; BmpResName: PChar; const Map: array of TColor )
2788 : HBitmap;
2789 {* Like LoadMappedBitmap, but much powerful. It uses CreateMappedBitmapEx
2790 by Alex Pravdin, so it understands any bitmap color format, including
2791 pf24bit. Also, LoadMappedBitmapEx provides auto-destroying loaded resource
2792 when MasterObj is destroyed. }
2793 function CreateMappedBitmap(Instance: THandle; Bitmap: Integer;
2794 Flags: UINT; ColorMap: PColorMap; NumMaps: Integer): HBitmap; stdcall;
2795 {* Creates mapped bitmap replacing colors correspondently to the
2796 ColorMap (each pare of colors defines color replaced and a color
2797 used for replace it in the bitmap). See also CreateMappedBitmapEx. }
2798 function CreateMappedBitmapEx(Instance: THandle; BmpRsrcName: PChar; Flags:
2799 Cardinal; ColorMap: PColorMap; NumMaps: Integer): HBitmap;
2800 {* By Alex Pravdin.
2801 Creates mapped bitmap independently from bitmap color format (works
2802 correctly with bitmaps having format deeper than 8bit per pixel). }
2815 //[ICONS]
2817 type
2818 {++}(*TIcon = class;*){--}
2819 PIcon = {-}^{+}TIcon;
2820 { ----------------------------------------------------------------------
2822 TIcon - icon image
2824 ----------------------------------------------------------------------- }
2825 //[TIcon DEFINITION]
2826 TIcon = object( TObj )
2827 {* Object type to incapsulate icon or cursor image. }
2828 protected
2829 FSize : Integer;
2830 FHandle: HIcon;
2831 FShareIcon: Boolean;
2832 procedure SetSize(const Value: Integer);
2833 procedure SetHandle(const Value: HIcon);
2834 function GetHotSpot: TPoint;
2835 function GetEmpty: Boolean;
2836 protected
2837 {++}(*public*){--}
2838 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2839 public
2840 property Size : Integer read FSize write SetSize;
2841 {* Icon dimension (width and/or height, which are equal to each other always). }
2842 property Handle : HIcon read FHandle write SetHandle;
2843 {* Windows icon object handle. }
2844 procedure Clear;
2845 {* Clears icon, freeing image and allocated GDI resource (Handle). }
2846 property Empty: Boolean read GetEmpty;
2847 {* Returns True if icon is Empty. }
2848 property ShareIcon : Boolean read FShareIcon write FShareIcon;
2849 {* True, if icon object is shared and can not be deleted when TIcon object
2850 is destroyed (set this flag is to True, if an icon is obtained from another
2851 TIcon object, for example). }
2852 property HotSpot : TPoint read GetHotSpot;
2853 {* Hot spot point - for cursors. }
2854 procedure Draw( DC : HDC; X, Y : Integer );
2855 {* Draws icon onto given device context. Icon always is drawn transparently
2856 using its transparency mask (stored internally in icon object). }
2857 procedure StretchDraw( DC : HDC; Dest : TRect );
2858 {* Draws icon onto given device context with stretching it to fit destination
2859 rectangle. See also Draw. }
2860 procedure LoadFromStream( Strm : PStream );
2861 {* Loads icon from stream. If stream contains several icons (of
2862 different dimentions), icon with the most appropriate size is loading. }
2863 procedure LoadFromFile( const FileName : String );
2864 {* Load icon from file. If file contains several icons (of
2865 different dimensions), icon with the most appropriate size is loading. }
2866 procedure LoadFromResourceID( Inst: Integer; ResID: Integer; DesiredSize: Integer );
2867 {* Loads icon from resource. To load system default icon, pass 0 as Inst and
2868 one of followin values as ResID:
2869 |<pre>
2870 IDI_APPLICATION Default application icon.
2871 IDI_ASTERISK Asterisk (used in informative messages).
2872 IDI_EXCLAMATION Exclamation point (used in warning messages).
2873 IDI_HAND Hand-shaped icon (used in serious warning messages).
2874 IDI_QUESTION Question mark (used in prompting messages).
2875 IDI_WINLOGO Windows logo.
2876 |</pre> It is also possible to load icon from resources of another module,
2877 if pass instance handle of loaded module as Inst parameter. }
2878 procedure LoadFromResourceName( Inst: Integer; ResName: PChar; DesiredSize: Integer );
2879 {* Loads icon from resource. To load own application resource, pass
2880 hInstance as Inst parameter. It is possible to load resource from
2881 another module, if pass its instance handle as Inst. }
2882 procedure LoadFromExecutable( const FileName: String; IconIdx: Integer );
2883 {* Loads icon from executable (exe or dll file). Always default sized icon
2884 is loaded. It is possible also to get know how much icons are contained
2885 in executable using gloabl function GetFileIconCount. To obtain icon of
2886 another size, try to load given executable and use LoadFromResourceID
2887 method. }
2888 procedure SaveToStream( Strm : PStream );
2889 {* Saves single icon to stream. To save icons with several different
2890 dimensions, use global procedure SaveIcons2Stream. }
2891 procedure SaveToFile( const FileName : String );
2892 {* Saves single icon to file. To save icons with several different
2893 dimensions, use global procedure SaveIcons2File. }
2894 function Convert2Bitmap( TranColor: TColor ): HBitmap;
2895 {* Converts icon to bitmap, returning Windows GDI bitmap resource as
2896 a result. It is possible later to assign returned bitmap handle to
2897 Handle property of TBitmap object to use features of TBitmap.
2898 Pass TranColor to replace transparent area of icon with given color. }
2899 end;
2900 //[END OF TIcon DEFINITION]
2902 //[Icon save functions]
2904 procedure SaveIcons2Stream( const Icons : array of PIcon; Strm : PStream );
2905 {* Saves several icons (of different dimentions) to stream. }
2906 function SaveIcons2StreamEx( const BmpHandles: array of HBitmap; Strm: PStream ): Boolean;
2907 {* Saves icons creating it from pairs of bitmaps and their masks.
2908 BmpHandles array must contain pairs of bitmap handles, each pair
2909 of color bitmap and mask bitmap of the same size. }
2910 procedure SaveIcons2File( const Icons : array of PIcon; const FileName : String );
2911 {* Saves several icons (of different dimentions) to file. (Single file
2912 with extension .ico can contain several different sized icon images
2913 to use later one with the most appropriate size). }
2915 //[NewIcon DECLARATION]
2916 function NewIcon: PIcon;
2917 {* Creates new icon object, setting its Size to 32 by default. Created icon
2918 is Empty. }
2920 //[GetFileIconCount DECLARATION]
2921 function GetFileIconCount( const FileName: String ): Integer;
2922 {* Returns number of icon resources stored in given (executable) file. }
2924 //[ICON STRUCTURES]
2925 type
2926 TIconHeader = packed record
2927 idReserved: Word; (* Always set to 0 *)
2928 idType: Word; (* Always set to 1 *)
2929 idCount: Word; (* Number of icon images *)
2930 (* immediately followed by idCount TIconDirEntries *)
2931 end;
2933 TIconDirEntry = packed record
2934 bWidth: Byte; (* Width *)
2935 bHeight: Byte; (* Height *)
2936 bColorCount: Byte; (* Nr. of colors used, see below *)
2937 bReserved: Byte; (* not used, 0 *)
2938 wPlanes: Word; (* not used, 0 *)
2939 wBitCount: Word; (* not used, 0 *)
2940 dwBytesInRes: Longint; (* total number of bytes in images *)
2941 dwImageOffset: Longint;(* location of image from the beginning of file *)
2942 end;
2944 //[LoadImgIcon DECLARATION]
2945 function LoadImgIcon( RsrcName: PChar; Size: Integer ): HIcon;
2946 {* Loads icon of specified size from the resource. }
2955 //[METAFILES]
2957 type
2958 {++}(*TMetafile = class;*){--}
2959 PMetafile = {-}^{+}TMetafile;
2960 { ----------------------------------------------------------------------
2962 TMetafile - Windows metafile and Enchanced Metafile image
2964 ----------------------------------------------------------------------- }
2965 //[TMetafile DEFINITION]
2966 TMetafile = object( TObj )
2967 {* Object type to incapsulate metafile image. }
2968 protected
2969 function GetHeight: Integer;
2970 function GetWidth: Integer;
2971 procedure SetHandle(const Value: THandle);
2972 protected
2973 fHandle: THandle;
2974 fHeader: PEnhMetaHeader;
2975 procedure RetrieveHeader;
2976 public
2977 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2978 {* }
2979 procedure Clear;
2980 {* }
2981 function Empty: Boolean;
2982 {* Returns TRUE if empty}
2983 property Handle: THandle read fHandle write SetHandle;
2984 {* Returns handle of enchanced metafile. }
2985 function LoadFromStream( Strm: PStream ): Boolean;
2986 {* Loads emf or wmf file format from stream. }
2987 function LoadFromFile( const Filename: String ): Boolean;
2988 {* Loads emf or wmf from stream. }
2989 procedure Draw( DC: HDC; X, Y: Integer );
2990 {* Draws enchanced metafile on DC. }
2991 procedure StretchDraw( DC: HDC; const R: TRect );
2992 {* Draws enchanced metafile stretched. }
2993 property Width: Integer read GetWidth;
2994 {* Native width of the metafile. }
2995 property Height: Integer read GetHeight;
2996 {* Native height of the metafile. }
2997 end;
2998 //[END OF TMetafile DEFINITION]
3000 //[NewMetafile DECLARATION]
3001 function NewMetafile: PMetafile;
3002 {* Creates metafile object. }
3004 //[Metafile CONSTANTS, STRUCTURES, ETC.]
3005 const
3006 WMFKey = Integer($9AC6CDD7);
3007 WMFWord = $CDD7;
3008 type
3009 TMetafileHeader = packed record
3010 Key: Longint;
3011 Handle: SmallInt;
3012 Box: TSmallRect;
3013 Inch: Word;
3014 Reserved: Longint;
3015 CheckSum: Word;
3016 end;
3018 function ComputeAldusChecksum(var WMF: TMetafileHeader): Word;
3020 {++}(*
3021 function SetEnhMetaFileBits(p1: UINT; p2: PChar): HENHMETAFILE; stdcall;
3022 function PlayEnhMetaFile(DC: HDC; p2: HENHMETAFILE; const p3: TRect): BOOL; stdcall;
3023 *){--}
3043 ////////////////////////////////////////////////////////////////////////////////
3044 // UNIVERSAL CONTROL OBJECT //
3045 ////////////////////////////////////////////////////////////////////////////////
3047 //[CM_XXX CONSTANTS]
3049 const
3050 CM_EXECPROC = $8FFF;
3051 CM_BASE = $B000;
3052 CM_ACTIVATE = CM_BASE + 0;
3053 CM_DEACTIVATE = CM_BASE + 1;
3054 CM_ENTER = CM_BASE + 2;
3055 CM_RELEASE = CM_BASE + 3;
3056 CM_QUIT = CM_BASE + 4;
3057 CM_COMMAND = CM_BASE + 5;
3058 CM_MEASUREITEM = CM_BASE + 6;
3059 CM_DRAWITEM = CM_BASE + 7;
3060 CM_TRAYICON = CM_BASE + 8;
3061 CM_INVALIDATE = CM_BASE + 9;
3062 CM_UPDATE = CM_BASE + 10;
3063 CM_NCUPDATE = CM_BASE + 11;
3064 CM_SIZEPOS = CM_BASE + 12;
3065 CM_SIZE = CM_BASE + 13;
3066 CM_SETFOCUS = CM_BASE + 14;
3067 CM_CBN_SELCHANGE = 15;
3069 CM_UIACTIVATE = CM_BASE + 16;
3070 CM_UIDEACTIVATE = CM_BASE + 17;
3071 CM_PROCESS = CM_BASE + 18;
3072 CM_SHOW = CM_BASE + 19;
3074 //CM_CLOSE = CM_BASE + 20;
3075 CM_MDIClientShowEdge = CM_BASE + 21;
3077 //[CN_XXX CONSTANTS]
3079 CN_BASE = $BC00;
3080 CN_CHARTOITEM = CN_BASE + WM_CHARTOITEM;
3081 CN_COMMAND = CN_BASE + WM_COMMAND;
3082 CN_COMPAREITEM = CN_BASE + WM_COMPAREITEM;
3084 CN_CTLCOLORMSGBOX = CN_BASE + WM_CTLCOLORMSGBOX;
3085 CN_CTLCOLOREDIT = CN_BASE + WM_CTLCOLOREDIT;
3086 CN_CTLCOLORLISTBOX = CN_BASE + WM_CTLCOLORLISTBOX;
3087 CN_CTLCOLORBTN = CN_BASE + WM_CTLCOLORBTN;
3088 CN_CTLCOLORDLG = CN_BASE + WM_CTLCOLORDLG;
3089 CN_CTLCOLORSCROLLBAR = CN_BASE + WM_CTLCOLORSCROLLBAR;
3090 CN_CTLCOLORSTATIC = CN_BASE + WM_CTLCOLORSTATIC;
3092 CN_DELETEITEM = CN_BASE + WM_DELETEITEM;
3093 CN_DRAWITEM = CN_BASE + WM_DRAWITEM;
3094 CN_HSCROLL = CN_BASE + WM_HSCROLL;
3095 CN_MEASUREITEM = CN_BASE + WM_MEASUREITEM;
3096 CN_PARENTNOTIFY = CN_BASE + WM_PARENTNOTIFY;
3097 CN_VKEYTOITEM = CN_BASE + WM_VKEYTOITEM;
3098 CN_VSCROLL = CN_BASE + WM_VSCROLL;
3099 CN_KEYDOWN = CN_BASE + WM_KEYDOWN;
3100 CN_KEYUP = CN_BASE + WM_KEYUP;
3101 CN_CHAR = CN_BASE + WM_CHAR;
3102 CN_SYSKEYDOWN = CN_BASE + WM_SYSKEYDOWN;
3103 CN_SYSCHAR = CN_BASE + WM_SYSCHAR;
3104 CN_NOTIFY = CN_BASE + WM_NOTIFY;
3107 //[ID_SELF DEFINED]
3108 ID_SELF: array[ 0..5 ] of Char = ( 'S','E','L','F','_',#0 );
3109 {* Identifier for window property "Self", stored directly in window, when
3110 it is created. This property is used to [fast] find TControl object,
3111 correspondent to given window handle (using API call GetProp). }
3113 //[ID_PREVPROC DEFINED]
3114 ID_PREVPROC: array[ 0..9 ] of Char = ( 'P','R','E','V','_','P','R','O','C',#0 );
3115 {* }
3117 //[MK_ALT DEFINED]
3118 MK_ALT = $20;
3120 //[RICHEDIT STRUCTURES]
3121 type
3122 TCharFormat2A = packed record
3123 cbSize: UINT;
3124 dwMask: DWORD;
3125 dwEffects: DWORD;
3126 yHeight: Longint;
3127 yOffset: Longint;
3128 crTextColor: TColorRef;
3129 bCharSet: Byte;
3130 bPitchAndFamily: Byte;
3131 szFaceName: array[0..LF_FACESIZE - 1] of AnsiChar;
3132 R2Bytes: Word;
3133 wWeight: Word; { Font weight (LOGFONT value) }
3134 sSpacing: Smallint; { Amount to space between letters }
3135 crBackColor: TColorRef; { Background color }
3136 lid: LCID; { Locale ID }
3137 dwReserved: DWORD; { Reserved. Must be 0 }
3138 sStyle: Smallint; { Style handle }
3139 wKerning: Word; { Twip size above which to kern char pair }
3140 bUnderlineType: Byte; { Underline type }
3141 bAnimation: Byte; { Animated text like marching ants }
3142 bRevAuthor: Byte; { Revision author index }
3143 bReserved1: Byte;
3144 end;
3145 TCharFormat2 = TCharFormat2A;
3147 TParaFormat2 = packed record
3148 cbSize: UINT;
3149 dwMask: DWORD;
3150 wNumbering: Word;
3151 wReserved: Word;
3152 dxStartIndent: Longint;
3153 dxRightIndent: Longint;
3154 dxOffset: Longint;
3155 wAlignment: Word;
3156 cTabCount: Smallint;
3157 rgxTabs: array [0..MAX_TAB_STOPS - 1] of Longint;
3158 dySpaceBefore: Longint; { Vertical spacing before para }
3159 dySpaceAfter: Longint; { Vertical spacing after para }
3160 dyLineSpacing: Longint; { Line spacing depending on Rule }
3161 sStyle: Smallint; { Style handle }
3162 bLineSpacingRule: Byte; { Rule for line spacing (see tom.doc) }
3163 bCRC: Byte; { Reserved for CRC for rapid searching }
3164 wShadingWeight: Word; { Shading in hundredths of a per cent }
3165 wShadingStyle: Word; { Nibble 0: style, 1: cfpat, 2: cbpat }
3166 wNumberingStart: Word; { Starting value for numbering }
3167 wNumberingStyle: Word; { Alignment, roman/arabic, (), ), ., etc. }
3168 wNumberingTab: Word; { Space bet 1st indent and 1st-line text }
3169 wBorderSpace: Word; { Space between border and text (twips) }
3170 wBorderWidth: Word; { Border pen width (twips) }
3171 wBorders: Word; { Byte 0: bits specify which borders }
3172 { Nibble 2: border style, 3: color index }
3173 end;
3175 TGetTextLengthEx = packed record
3176 flags: DWORD; { flags (see GTL_XXX defines) }
3177 codepage: UINT; { code page for translation (CP_ACP for default,
3178 1200 for Unicode }
3179 end;
3181 const
3182 PFM_SPACEBEFORE = $00000040;
3183 PFM_SPACEAFTER = $00000080;
3184 PFM_LINESPACING = $00000100;
3185 PFM_STYLE = $00000400;
3186 PFM_BORDER = $00000800; { (*) }
3187 PFM_SHADING = $00001000; { (*) }
3188 PFM_NUMBERINGSTYLE = $00002000; { (*) }
3189 PFM_NUMBERINGTAB = $00004000; { (*) }
3190 PFM_NUMBERINGSTART = $00008000; { (*) }
3192 PFM_RTLPARA = $00010000;
3193 PFM_KEEP = $00020000; { (*) }
3194 PFM_KEEPNEXT = $00040000; { (*) }
3195 PFM_PAGEBREAKBEFORE = $00080000; { (*) }
3196 PFM_NOLINENUMBER = $00100000; { (*) }
3197 PFM_NOWIDOWCONTROL = $00200000; { (*) }
3198 PFM_DONOTHYPHEN = $00400000; { (*) }
3199 PFM_SIDEBYSIDE = $00800000; { (*) }
3201 PFM_TABLE = $c0000000; { (*) }
3202 EM_REDO = WM_USER + 84;
3203 EM_AUTOURLDETECT = WM_USER + 91;
3204 EM_GETAUTOURLDETECT = WM_USER + 92;
3205 CFM_UNDERLINETYPE = $00800000; { (*) }
3206 CFM_HIDDEN = $0100; { (*) }
3207 CFM_BACKCOLOR = $04000000;
3208 CFE_AUTOBACKCOLOR = CFM_BACKCOLOR;
3209 GTL_USECRLF = 1; { compute answer using CRLFs for paragraphs }
3210 GTL_PRECISE = 2; { compute a precise answer }
3211 GTL_CLOSE = 4; { fast computation of a "close" answer }
3212 GTL_NUMCHARS = 8; { return the number of characters }
3213 GTL_NUMBYTES = 16; { return the number of _bytes_ }
3214 EM_GETTEXTLENGTHEX = WM_USER + 95;
3215 EM_SETLANGOPTIONS = WM_USER + 120;
3216 EM_GETLANGOPTIONS = WM_USER + 121;
3218 EM_SETEDITSTYLE = $400 + 204;
3219 EM_GETEDITSTYLE = $400 + 205;
3221 SES_EMULATESYSEDIT = 1;
3222 SES_BEEPONMAXTEXT = 2;
3223 SES_EXTENDBACKCOLOR = 4;
3224 SES_MAPCPS = 8;
3225 SES_EMULATE10 = 16;
3226 SES_USECRLF = 32;
3227 SES_USEAIMM = 64;
3228 SES_NOIME = 128;
3229 SES_ALLOWBEEPS = 256;
3230 SES_UPPERCASE = 512;
3231 SES_LOWERCASE = 1024;
3232 SES_NOINPUTSEQUENCECHK = 2048;
3233 SES_BIDI = 4096;
3234 SES_SCROLLONKILLFOCUS = 8192;
3235 SES_XLTCRCRLFTOCR = 16384;
3237 //[CONTROLS]
3239 type
3240 {++}(*TControl = class;*){--}
3241 PControl = {-}^{+}TControl;
3242 {* Type of pointer to TControl visual object. All
3243 |<a href="kol_pas.htm#visual_objects_constructors">
3244 constructing functions
3245 |</a>
3246 New[ControlName] are returning
3247 pointer of this type. Do not forget about some difference
3248 of using objects from using classes. Identifier Self for
3249 methods of object is not of pointer type, and to pass
3250 pointer to Self, it is necessary to pass @Self instead.
3251 At the same time, to use pointer to object in 'WITH' operator,
3252 it is necessary to apply suffix '^' to pointer to get know
3253 to compiler, what do You want. }
3255 //[TWindowFunc TYPE]
3256 TWindowFunc = function( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
3257 : Boolean;
3258 {* Event type to define custom extended message handlers (as pointers to
3259 procedure entry points). Such handlers are usually defined like add-ons,
3260 extending behaviour of certain controls and attached using AttachProc
3261 method of TControl. If the handler detects, that it is necessary to stop
3262 further message processing, it should return True. }
3265 //[Mouse TYPES]
3266 TMouseButton = ( mbNone, mbLeft, mbRight, mbMiddle );
3267 {* Available mouse buttons. mbNone is useful to get know, that
3268 there were no mouse buttons pressed. }
3270 TMouseEventData = packed Record
3271 {* Record to pass it to mouse handling routines, assigned to OnMouseXXXX
3272 events. }
3273 Button: TMouseButton;
3274 StopHandling: Boolean; // Set it to True in OnMouseXXXX event handler to
3275 // stop further processing
3276 R1, R2: Byte; // Not used
3277 Shift : DWORD; // HiWord( Shift ) = zDelta in WM_MOUSEWHEEL
3278 X, Y : SmallInt;
3279 end;
3281 TOnMouse = procedure( Sender: PControl; var Mouse: TMouseEventData ) of object;
3282 {* Common mouse handling event type. }
3284 //[Key TYPES]
3285 TOnKey = procedure( Sender: PControl; var Key: Longint; Shift: DWORD ) of object;
3286 {* Key events. Shift is a combination of flags MK_SHIFT, MK_CONTROL, MK_ALT.
3287 (See GetShiftState funtion). }
3289 TOnChar = procedure( Sender: PControl; var Key: Char; Shift: DWORD ) of object;
3290 {* Char event. Shift is a combination of flags MK_SHIFT, MK_CONTROL, MK_ALT. }
3292 TTabKey = ( tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn );
3293 {* Available tabulating key groups. }
3294 TTabKeys = Set of TTabKey;
3295 {* Set of tabulating key groups, allowed to be used in with a control
3296 (are installed by TControl.LookTabKey property). }
3298 //[Event TYPES]
3299 TOnMessage = function( var Msg: TMsg; var Rslt: Integer ): Boolean of object;
3300 {* Event type for events, which allows to extend behaviour of windowed controls
3301 descendants using add-ons. }
3303 TOnEventAccept = procedure( Sender: PObj; var Accept: Boolean ) of object;
3304 {* Event type for OnClose event. }
3305 TCloseQueryReason = ( qClose, qShutdown, qLogoff );
3306 {* Request reason type to call OnClose and OnQueryEndSession. }
3307 TWindowState = ( wsNormal, wsMinimized, wsMaximized );
3308 {* Avalable states of TControl's window object. }
3310 TOnSplit = function( Sender: PControl; NewSize1, NewSize2: Integer ): Boolean of object;
3311 {* Event type for OnSplit event handler, designed specially for splitter
3312 control. Event handler must return True to accept new size of previous
3313 (to splitter) control and new size of the rest of client area of parent. }
3315 TOnTVBeginDrag = procedure( Sender: PControl; Item: THandle ) of object;
3316 {* Event type for OnTVBeginDrag event (defined for tree view control). }
3317 TOnTVBeginEdit = function( Sender: PControl; Item: THandle ): Boolean of object;
3318 {* Event type for OnTVBeginEdit event (for tree view control). }
3319 TOnTVEndEdit = function( Sender: PControl; Item: THandle; const NewTxt: String )
3320 : Boolean of object;
3321 {* Event type for TOnTVEndEdit event. }
3322 TOnTVExpanding = function( Sender: PControl; Item: THandle; Expand: Boolean )
3323 : Boolean of object;
3324 {* Event type for TOnTVExpanding event. }
3325 TOnTVExpanded = procedure( Sender: PControl; Item: THandle; Expand: Boolean )
3326 of object;
3327 {* Event type for OnTVExpanded event. }
3328 TOnTVDelete = procedure( Sender: PControl; Item: THandle ) of object;
3329 {* Event type for OnTVDelete event. }
3331 //--------- by Sergey Shisminzev:
3332 TOnTVSelChanging = function(Sender: PControl; oldItem, newItem: THandle): Boolean //~ss
3333 of object;
3334 {* When the handler returns False, selection is not changed. }
3335 //-------------------------------
3336 TOnDrag = function( Sender: PControl; ScrX, ScrY: Integer; var CursorShape: Integer;
3337 var Stop: Boolean ): Boolean of object;
3338 {* Event, called during dragging operation (it is initiated
3339 with method Drag, where callback function of type TOnDrag is
3340 passed as a parameter). Callback function receives Stop parameter True,
3341 when operation is finishing. Otherwise, it can set it to True to force
3342 finishing the operation (in such case, returning False means cancelling
3343 drag operation, True - successful drag and in this last case callback is
3344 no more called). During the operation, when input Stop value is False,
3345 callback function can control Cursor shape, and return True, if the operation
3346 can be finished successfully at the given ScrX, ScrY position.
3347 ScrX, ScrY are screen coordinates of the mouse cursor. }
3349 //[Create Window STRUCTURES]
3350 TCreateParams = packed record
3351 {* Record to pass it through CreateSubClass method. }
3352 Caption: PChar;
3353 Style: cardinal;
3354 ExStyle: cardinal;
3355 X, Y: Integer;
3356 Width, Height: Integer;
3357 WndParent: HWnd;
3358 Param: Pointer;
3359 WindowClass: TWndClass;
3360 WinClassName: array[0..63] of Char;
3361 end;
3363 TCreateWndParams = packed Record
3364 ExStyle: DWORD;
3365 WinClassName: PChar;
3366 Caption: PChar;
3367 Style: DWORD;
3368 X, Y, Width, Height: Integer;
3369 WndParent: HWnd;
3370 Menu: HMenu;
3371 Inst: THandle;
3372 Param: Pointer;
3373 WinClsNamBuf: array[ 0..63 ] of Char;
3374 WindowClass: TWndClass;
3375 end;
3378 //[COMMAND ACTIONS TYPE FOR DIFFERENT CONTROLS]
3379 PCommandActions = ^TCommandActions;
3380 TCommandActions = packed Record
3381 aClear: procedure( Sender: PControl );
3382 aAddText: procedure( Sender: PControl; const S: String );
3383 aClick, aEnter, aLeave: WORD; aChange: SmallInt; aSelChange: SmallInt;
3384 aGetCount, aSetCount, aGetItemLength, aGetItemText, aSetItemText,
3385 aGetItemData, aSetItemData: WORD;
3386 aAddItem, aDeleteItem, aInsertItem: WORD;
3387 aFindItem, aFindPartial: WORD;
3388 aItem2Pos, aPos2Item: BYTE;
3389 aGetSelCount, aGetSelected, aGetSelRange, aExGetSelRange, aGetCurrent,
3390 aSetSelected, aSetCurrent, aSetSelRange, aExSetSelRange,
3391 aGetSelection, aReplaceSel: WORD;
3392 aTextAlignLeft, aTextAlignRight, aTextAlignCenter: WORD;
3393 aTextAlignMask: Byte;
3394 aVertAlignCenter, aVertAlignTop, aVertAlignBottom: Byte;
3395 aDir, aSetLimit: Word; aSetImgList: Word;
3396 aAutoSzX, aAutoSzY: Word;
3397 aSetBkColor: Word;
3398 aItem2XY: Word;
3399 end;
3401 //[Align TYPES]
3402 TTextAlign = ( taLeft, taRight, taCenter );
3403 {* Text alignments available. }
3404 TRichTextAlign = ( raLeft, raRight, raCenter,
3405 // all other are only set but can not be displayed:
3406 raJustify, // displayed like raLeft (though stored normally)
3407 raInterLetter, raScaled, raGlyphs, raSnapGrid );
3408 {* Text alignment styles, available for RichEdit control. }
3409 TVerticalAlign = ( vaCenter, vaTop, vaBottom );
3410 {* Vertical alignments available. }
3411 TControlAlign = ( caNone, caLeft, caTop, caRight, caBottom, caClient );
3412 {* Control alignments available. }
3414 //[BitBtn TYPES]
3415 TBitBtnOption = ( bboImageList,
3416 bboNoBorder,
3417 bboNoCaption,
3418 bboFixed );
3419 {* Options available for NewBitBtn. }
3420 TBitBtnOptions = set of TBitBtnOption;
3421 {* Set of options, available for NewBitBtn. }
3422 TGlyphLayout = ( glyphLeft, glyphTop, glyphRight, glyphBottom, glyphOver );
3423 {* Layout of glyph (for NewBitBtn). Layout glyphOver means that text is
3424 drawn over glyph. }
3425 TOnBitBtnDraw = function( Sender: PControl; BtnState: Integer ): Boolean of object;
3426 {* Event type for TControl.OnBitBtnDraw event (which is called just before
3427 drawing the BitBtn). If handler returns True, there are no drawing occure.
3428 BtnState, passed to a handler, determines current button state and can
3429 be following: 0 - not pressed, 1 - pressed, 2 - disabled, 3 - focused.
3430 Value 4 is reserved for highlight state (then mouse is over it), but
3431 highlighting is provided only if property Flat is set to True (or one
3432 of events OnMouseEnter / OnMouseLeave is assigned to something). }
3434 //[ListView TYPES]
3435 TListViewStyle = ( lvsIcon, lvsSmallIcon, lvsList, lvsDetail, lvsDetailNoHeader );
3436 {* Styles of view for ListView control (see NewListVew). }
3438 TListViewItemStates = ( lvisFocus, lvisSelect, lvisBlend, lvisHighlight );
3439 TListViewItemState = Set of TListViewItemStates;
3440 TListViewOption = (
3441 lvoIconLeft, // in lvsIcon, lvsSmallIcon plce icon left from text (rather then top)
3442 lvoAutoArrange, // keep icons auto arranged in lvsIcon and lvsSmallIcon view
3443 lvoButton, // icons look like buttons in lvsIcon view
3444 lvoEditLabel, // allows edit labels inplace (first column #0 text)
3445 lvoNoLabelWrap, // item text on a single line in lvsIcon view (by default, item text may wrap in lvsIcon view).
3446 lvoNoScroll, // obvious
3447 lvoNoSortHeader, // click on header button does not lead to sort items
3448 lvoHideSel, // hide selection when not in focus
3449 lvoMultiselect, // allow to select multiple items
3450 lvoSortAscending,
3451 lvoSortDescending,
3452 // extended styles (not documented in my Win32.hlp :( , got from VCL source:
3453 lvoGridLines,
3454 lvoSubItemImages,
3455 lvoCheckBoxes,
3456 lvoTrackSelect,
3457 lvoHeaderDragDrop,
3458 lvoRowSelect,
3459 lvoOneClickActivate,
3460 lvoTwoClickActivate,
3461 lvoFlatsb,
3462 lvoRegional,
3463 lvoInfoTip,
3464 lvoUnderlineHot,
3465 lvoMultiWorkares,
3466 // virtual list view style:
3467 lvoOwnerData,
3468 // custom draw style:
3469 lvoOwnerDrawFixed
3471 TListViewOptions = Set of TListViewOption;
3473 TOnEditLVItem = function( Sender: PControl; Idx, Col: Integer; NewText: PChar ): Boolean
3474 of object;
3475 {* Event type for OnEndEditLVItem. Return True in handler to accept new text value. }
3476 TOnDeleteLVItem = procedure( Sender: PControl; Idx: Integer ) of object;
3477 {* Event type for OnDeleteLVItem event. }
3478 TOnLVData = procedure( Sender: PControl; Idx, SubItem: Integer;
3479 var Txt: String; var ImgIdx: Integer; var State: DWORD;
3480 var Store: Boolean ) of object;
3481 {* Event type for OnLVData event. Used to provide virtual list view control
3482 (i.e. having lvoOwnerData style) with actual data on request. Use parameter
3483 Store as a flag if control should store obtained data by itself or not. }
3484 {$IFNDEF _D2}
3485 {$IFNDEF _FPC}
3486 TOnLVDataW = procedure( Sender: PControl; Idx, SubItem: Integer;
3487 var Txt: WideString; var ImgIdx: Integer; var State: DWORD;
3488 var Store: Boolean ) of object;
3489 {* Event type for OnLVDataW event (the same as OnLVData, but for unicode verion
3490 of the control OnLVDataW allows to return WideString text in the event
3491 handler). Used to provide virtual list view control
3492 (i.e. having lvoOwnerData style) with actual data on request. Use parameter
3493 Store as a flag if control should store obtained data by itself or not. }
3494 {$ENDIF _FPC}
3495 {$ENDIF _D2}
3496 TOnCompareLVItems = function( Sender: PControl; Idx1, Idx2: Integer ): Integer
3497 of object;
3498 {* Event type to compare two items of the list view (while sorting it). }
3499 TOnLVColumnClick = procedure( Sender: PControl; Idx: Integer ) of object;
3500 {* Event type for OnColumnClick event. }
3501 TOnLVStateChange = procedure( Sender: PControl; IdxFrom, IdxTo: Integer; OldState, NewState: DWORD )
3502 of object;
3503 {* Event type for OnLVStateChange event, called in responce to select/unselect
3504 a single item or items range in list view control). }
3505 TOnLVDelete = procedure( Sender: PControl; Idx: Integer ) of object;
3506 {* Event type for OnLVDelete event, called when an item is been deleting. }
3508 TDrawActions = ( odaEntire, odaFocus, odaSelect );
3509 TDrawAction = Set of TDrawActions;
3510 TDrawStates = ( odsSelected, odsGrayed, odsDisabled, odsChecked, odsFocused,
3511 odsDefault, odsHotlist, odsInactive,
3512 odsNoAccel, odsNoFocusRect,
3513 ods400reserved, ods800reserved,
3514 odsComboboxEdit,
3515 // specific for common controls:
3516 odsMarked, odsIndeterminate );
3517 {* Possible draw states.
3518 |<br>odsSelected - The menu item's status is selected.
3519 |<br>odsGrayed - The item is to be grayed. This bit is used only in a menu.
3520 |<br>odsDisabled - The item is to be drawn as disabled.
3521 |<br>odsChecked - The menu item is to be checked. This bit is used only in
3522 a menu.
3523 |<br>odsFocused - The item has the keyboard focus.
3524 |<br>odsDefault - The item is the default item.
3525 |<br>odsHotList - <b>Windows 98, Windows 2000:</b> The item is being
3526 hot-tracked, that is, the item will be highlighted when
3527 the mouse is on the item.
3528 |<br>odsInactive - <b>Windows 98, Windows 2000:</b> The item is inactive
3529 and the window associated with the menu is inactive.
3530 |<br>odsNoAccel - <b>Windows 2000:</b> The control is drawn without the
3531 keyboard accelerator cues.
3532 |<br>odsNoFocusRect - <b>Windows 2000:</b> The control is drawn without
3533 focus indicator cues.
3534 |<br>odsComboboxEdit - The drawing takes place in the selection field
3535 (edit control) of an owner-drawn combo box.
3536 |<br>odsMarked - for Common controls only. The item is marked. The meaning
3537 of this is up to the implementation.
3538 |<br>odsIndeterminate - for Common Controls only. The item is in an
3539 indeterminate state. }
3540 TDrawState = Set of TDrawStates;
3541 {* Set of possible draw states. }
3542 TOnDrawItem = function( Sender: PObj; DC: HDC; const Rect: TRect; ItemIdx: Integer;
3543 DrawAction: TDrawAction; ItemState: TDrawState ): Boolean of object;
3544 {* Event type for OnDrawItem event (applied to list box, combo box, list view). }
3545 TOnMeasureItem = function( Sender: PObj; Idx: Integer ): Integer of object;
3546 {* Event type for OnMeasureItem event. The event handler must return height of list box
3547 item as a result. }
3548 TGetLVItemPart = ( lvipBounds, lvipIcon, lvipLabel, lvupIconAndLabel );
3549 {* }
3550 TWherePosLVItem = ( lvwpOnIcon, lvwpOnLabel, lvwpOnStateIcon, lvwpOnColumn,
3551 lvwpOnItem );
3552 {* }
3554 TOnLVCustomDraw = function( Sender: PControl; DC: HDC; Stage: DWORD;
3555 ItemIdx, SubItemIdx: Integer; const Rect: TRect;
3556 ItemState: TDrawState; var TextColor, BackColor: TColor )
3557 : DWORD of object;
3558 {* Event type for OnLVCustomDraw event. }
3560 //[Paint TYPES]
3561 TOnPaint = procedure( Sender: PControl; DC: HDC ) of object;
3563 TGradientStyle = ( gsVertical, gsHorizontal, gsRectangle, gsElliptic, gsRombic );
3564 {* Gradient fill styles. See also TGradientLayout. }
3565 TGradientLayout = ( glTopLeft, glTop, glTopRight,
3566 glLeft, glCenter, glRight,
3567 glBottomLeft, glBottom, glBottomRight );
3568 {* Position of starting line / point for gradient filling. Depending on
3569 TGradientStyle, means either position of first line of first rectangle
3570 (ellipse) to be expanded in a loop to fit entire gradient panel area. }
3572 //[Edit TYPES]
3573 TEditOption = ( eoNoHScroll, eoNoVScroll, eoLowercase, eoMultiline,
3574 eoNoHideSel, eoOemConvert, eoPassword, eoReadonly,
3575 eoUpperCase, eoWantReturn, eoWantTab, eoNumber );
3576 {* Available edit options.
3577 |<br> Please note, that eoWantTab option just removes TAB key from a list
3578 of keys available to tabulate from the edit control. To provide insertion
3579 of tabulating key, do so in TControl.OnChar event handler. Sorry for
3580 inconvenience, but this is because such behaviour is not must in all cases.
3581 See also TControl.EditTabChar property. }
3582 TEditOptions = Set of TEditOption;
3583 {* Set of available edit options. }
3585 TRichFmtArea = ( raSelection, raWord, raAll );
3586 {* Characters formatting area for RichEdit. }
3587 TRETextFormat = ( reRTF, reText, rePlainRTF, reRTFNoObjs, rePlainRTFNoObjs,
3588 reTextized );
3589 {* Available formats for transfer RichEdit text using property
3590 TControl.RE_Text.
3591 |<pre>
3592 reRTF - normal rich text (no transformations)
3593 reText - plain text only (without OLE objects)
3594 reTextized - plain text with text representation of OLE objects
3595 rePlainRTF - reRTF without language-specific keywords
3596 reRTFNoObjs - reRTF without OLE objects
3597 rePlainRTFNoObjs - rePlainRTF without OLE objects
3598 |</pre> }
3599 TRichUnderline = ( ruSingle, ruWord, ruDouble, ruDotted,
3600 //all other - only for RichEditv3.0:
3601 ruDash, ruDashDot, ruDashDotDot, ruWave, ruThick, ruHairLine );
3602 {* Rich text exteded underline styles (available only for RichEdit v2.0,
3603 and even for RichEdit v2.0 additional styles can not displayed - but
3604 ruDotted under Windows2000 is working). }
3605 TRichTextSizes = ( rtsNoUseCRLF, rtsNoPrecise, rtsClose, rtsBytes );
3606 {* Options to calculate size of rich text. Available only for RichEdit2.0
3607 or higher. }
3608 TRichTextSize = set of TRichTextSizes;
3609 {* Set of all available optioins to calculate rich text size using
3610 property TControl.RE_TextSize[ options ]. }
3611 TRichNumbering = ( rnNone, rnBullets, rnArabic, rnLLetter, rnULetter,
3612 rnLRoman, rnURoman );
3613 {* Advanced numbering styles for paragraph (RichEdit).
3614 |<pre>
3615 rnNone - no numbering
3616 rnBullets - bullets only
3617 rnArabic - 1, 2, 3, 4, ...
3618 rnLLetter - a, b, c, d, ...
3619 rnULetter - A, B, C, D, ...
3620 rnLRoman - i, ii, iii, iv, ...
3621 rnURoman - I, II, III, IV, ...
3622 rnNoNumber - do not show any numbers (but numbering is taking place).
3623 |</pre> }
3624 TRichNumBrackets = ( rnbRight, rnbBoth, rnbPeriod, rnbPlain, rnbNoNumber );
3625 {* Brackets around number:
3626 |<pre>
3627 rnbRight - 1) 2) 3) - this is default !
3628 rnbBoth - (1) (2) (3)
3629 rnbPeriod - 1. 2. 3.
3630 rnbPlain - 1 2 3
3631 |</pre> }
3632 TBorderEdge = (beLeft, beTop, beRight, beBottom);
3633 {* Borders of rectangle. }
3635 TCharFormat = TCharFormat2;
3636 TParaFormat = TParaFormat2;
3638 TOnTestMouseOver = function( Sender: PControl ): Boolean of object;
3639 {* Event type for TControl.OnTestMouseOver event. The handler should
3640 return True, if it dectects, that mouse is over control. }
3642 TEdgeStyle = ( esRaised, esLowered, esNone );
3643 {* Edge styles (for panel - see NewPanel). }
3645 //[List TYPES]
3646 TListOption = ( loNoHideScroll, loNoExtendSel, loMultiColumn, loMultiSelect,
3647 loNoIntegralHeight, loNoSel, loSort, loTabstops,
3648 loNoStrings, loNoData, loOwnerDrawFixed, loOwnerDrawVariable );
3649 {* Options for ListBox (see NewListbox). }
3650 TListOptions = Set of TListOption;
3651 {* Set of available options for Listbox. }
3653 TComboOption = ( coReadOnly, coNoHScroll, coAlwaysVScroll, coLowerCase,
3654 coNoIntegralHeight, coOemConvert, coSort, coUpperCase,
3655 coOwnerDrawFixed, coOwnerDrawVariable, coSimple );
3656 {* Options for combobox. }
3657 TComboOptions = Set of TComboOption;
3658 {* Set of options available for combobox. }
3660 //[Progress TYPES]
3661 TProgressbarOption = ( pboVertical, pboSmooth );
3662 {* Options for progress bar. }
3663 TProgressbarOptions = set of TProgressbarOption;
3664 {* Set of options available for progress bar. }
3666 //[TreeView TYPES]
3667 TTreeViewOption = ( tvoNoLines, tvoLinesRoot, tvoNoButtons, tvoEditLabels, tvoHideSel,
3668 tvoDragDrop, tvoNoTooltips, tvoCheckBoxes, tvoTrackSelect,
3669 tvoSingleExpand, tvoInfoTip, tvoFullRowSelect, tvoNoScroll,
3670 tvoNonEvenHeight );
3671 {* Tree view options. }
3672 TTreeViewOptions = set of TTreeViewOption;
3673 {* Set of tree view options. }
3675 //[TabControl TYPES]
3676 TTabControlOption = ( tcoButtons, tcoFixedWidth, tcoFocusTabs,
3677 tcoIconLeft, tcoLabelLeft,
3678 tcoMultiline, tcoMultiselect, tcoFitRows, tcoScrollOpposite,
3679 tcoBottom, tcoVertical, tcoFlat, tcoHotTrack, tcoBorder,
3680 tcoOwnerDrawFixed );
3681 {* Options, available for TabControl. }
3682 TTabControlOptions = set of TTabControlOption;
3683 {* Set of options, available for TAbControl during its creation (by
3684 NewTabControl function). }
3686 //[Toolbar TYPES]
3687 TToolbarOption = ( tboTextRight, tboTextBottom, tboFlat, tboTransparent,
3688 tboWrapable, tboNoDivider, tbo3DBorder );
3689 {* Toolbar options. When tboFlat is set and toolbar is placed onto panel,
3690 set its property Transparent to TRUE to provide its correct view. }
3691 TToolbarOptions = Set of TToolbarOption;
3692 {* Set of toolbar options. }
3693 TOnToolbarButtonClick = procedure( Sender: PControl; BtnID: Integer ) of object;
3694 {* Special event type to handle separate toolbar buttons click events. }
3696 TDateTimePickerOption = ( dtpoTime, dtpoDateLong, dtpoUpDown, dtpoRightAlign,
3697 dtpoShowNone, dtpoParseInput );
3698 {* }
3699 TDateTimePickerOptions = set of TDateTimePickerOption;
3700 {* }
3701 TDTParseInputEvent = procedure(Sender: PControl; const UserString: string;
3702 var DateAndTime: TDateTime; var AllowChange: Boolean) of object;
3703 {* }
3704 TDateTimeRange = array[ 0..1 ] of TDateTime;
3705 {* }
3706 TDateTimePickerColor = ( dtpcBackground, dtpcMonthBk, dtpcText, dtpcTitleBk,
3707 dtpcTitleText, dtpcTrailingText );
3709 //[TOnDropFiles TYPE]
3710 TOnDropFiles = procedure( Sender: PControl; const FileList: String; const Pt: TPoint ) of object;
3711 {* An event type for OnDropFiles event. When the event is occur, FileList
3712 parameter contains a list of files dropped. File names in a list are
3713 separated with #13 character. This allows You to assign it to TStrList
3714 object using its property Text (for example):
3715 ! procedure TSomeObject.DropFiles( Sender: PControl; const FileList: String;
3716 ! const Pt: TPoint ); )
3717 ! var FList: PStrList;
3718 ! I: Integer;
3719 ! begin
3720 ! FList := NewStrList;
3721 ! FList.Text := FileList;
3722 ! for I := 0 to FList.Count-1 do
3723 ! begin
3724 ! // do something with FList.Items[ I ]
3725 ! end;
3726 ! FList.Free;
3727 ! end; }
3729 //[Scroll TYPES]
3730 TScrollerBar = ( sbHorizontal, sbVertical );
3731 TScrollerBars = set of TScrollerBar;
3733 TOnScroll = procedure( Sender: PControl; Bar: TScrollerBar; ScrollCmd: DWORD;
3734 ThumbPos: DWORD ) of object;
3736 //[TOnHelp EVENT TYPE]
3737 TOnHelp = procedure( var Sender: PControl; var Context: Integer; var Popup: Boolean )
3738 of object;
3740 //[ScrollBar TYPES]
3741 TOnSBBeforeScroll =
3742 procedure(
3743 Sender: PControl; OldPos, NewPos: Integer; Cmd: Word;
3744 var AllowChange: Boolean) of object;
3745 TOnSBScroll = procedure(Sender: PControl; Cmd: Word) of object;
3748 {$IFDEF USE_MHTOOLTIP}
3749 {$DEFINE pre_interface}
3750 {$I KOLMHToolTip}
3751 {$UNDEF pre_interface}
3752 {$ENDIF}
3754 { ----------------------------------------------------------------------
3756 TControl - object to implement any visual control
3758 ----------------------------------------------------------------------- }
3759 //[TControl DEFINITION]
3760 TControl = object( TObj )
3761 protected
3762 fSBMinMax: TPoint;
3763 fSBPageSize: Integer;
3764 fSBPosition: Integer;
3765 procedure SetSBMax(Value: Longint);
3766 procedure SetSBMin(Value: Longint);
3767 procedure SetSBPageSize(Value: Integer);
3768 procedure SetSBPosition(Value: Integer);
3769 procedure SetSBMinMax(const Value: TPoint);
3771 function GetDate: TDateTime;
3772 function GetTime: TDateTime;
3773 procedure SetDate(const Value: TDateTime);
3774 procedure SetTime(const Value: TDateTime);
3775 {*! TControl is the basic visual object of KOL. And now, all visual
3776 objects have the same type PControl, differing only in "constructor",
3777 which during creating of object adjusts it so it can play role of
3778 desired control. Idea of incapsulating of all visual objects having
3779 the most common set of properties, is belonging to Vladimir Kladov,
3780 (C) 2000.
3781 |<br>&nbsp;&nbsp;&nbsp;<b> Since all visual objects are represented
3782 in KOL by this single object type, not all methods, properties and
3783 events defined in TControl, are applicable to different visual objects.
3784 See also notes about certain control kinds, located together with its
3785 |<a href="kol_pas.htm#visual_objects_constructors">
3786 |constructing functions definitions</a></b>. }
3787 protected
3788 function GetHelpPath: String;
3789 procedure SetHelpPath(const Value: String);
3790 procedure SetOnQueryEndSession(const Value: TOnEventAccept);
3791 procedure SetOnMinMaxRestore(const Index: Integer; const Value: TOnEvent);
3792 procedure SetConstraint(const Index, Value: Integer);
3793 {$IFDEF F_P}
3794 function GetOnMinMaxRestore(const Index: Integer): TOnEvent;
3795 function GetConstraint(const Index: Integer): Integer;
3796 {$ENDIF F_P}
3797 procedure SetOnScroll(const Value: TOnScroll);
3798 function GetLVColalign(Idx: Integer): TTextAlign;
3799 procedure SetLVColalign(Idx: Integer; const Value: TTextAlign);
3801 procedure SetParent( Value: PControl );
3802 function GetLeft: Integer;
3803 procedure SetLeft( Value: Integer );
3804 function GetTop: Integer;
3805 procedure SetTop( Value: Integer );
3806 function GetWidth: Integer;
3807 procedure SetWidth( Value: Integer );
3808 function GetHeight: Integer;
3809 procedure SetHeight( Value: Integer );
3811 function GetPosition: TPoint;
3812 procedure Set_Position( Value: TPoint );
3814 function GetMembers(Idx: Integer): PControl;
3815 function GetFont: PGraphicTool;
3816 procedure FontChanged( Sender: PGraphicTool );
3817 function GetBrush: PGraphicTool;
3818 procedure BrushChanged( Sender: PGraphicTool );
3819 function GetClientHeight: Integer;
3820 function GetClientWidth: Integer;
3821 procedure SetClientHeight(const Value: Integer);
3822 procedure SetClientWidth(const Value: Integer);
3823 function GetHasBorder: Boolean;
3824 procedure SetHasBorder(const Value: Boolean);
3826 function GetHasCaption: Boolean;
3827 procedure SetHasCaption(const Value: Boolean);
3829 function GetCanResize: Boolean;
3830 procedure SetCanResize( const Value: Boolean );
3832 function GetStayOnTop: Boolean;
3833 procedure SetStayOnTop(const Value: Boolean);
3834 function GetChecked: Boolean;
3835 procedure Set_Checked(const Value: Boolean);
3837 function GetSelStart: Integer;
3838 procedure SetSelStart(const Value: Integer);
3839 function GetSelLength: Integer;
3840 procedure SetSelLength(const Value: Integer);
3842 function GetItems(Idx: Integer): String;
3843 procedure SetItems(Idx: Integer; const Value: String);
3845 function GetItemsCount: Integer;
3846 function GetItemSelected(ItemIdx: Integer): Boolean;
3847 procedure SetItemSelected(ItemIdx: Integer; const Value: Boolean);
3849 procedure SetCtl3D(const Value: Boolean);
3850 function GetCurIndex: Integer;
3851 procedure SetCurIndex(const Value: Integer);
3852 function GetTextAlign: TTextAlign;
3853 function GetVerticalAlign: TVerticalAlign;
3854 procedure SetTextAlign(const Value: TTextAlign);
3855 procedure SetVerticalAlign(const Value: TVerticalAlign);
3857 function GetCanvas: PCanvas;
3858 function Dc2Canvas( Sender: PCanvas ): HDC;
3859 procedure SetShadowDeep(const Value: Integer);
3860 procedure SetDoubleBuffered(const Value: Boolean);
3862 procedure SetStatusText(Index: Integer; Value: PChar);
3863 function GetStatusText( Index: Integer ): PChar;
3864 function GetStatusPanelX(Idx: Integer): Integer;
3865 procedure SetStatusPanelX(Idx: Integer; const Value: Integer);
3867 procedure SetTransparent(const Value: Boolean);
3868 function GetImgListIdx(const Index: Integer): PImageList;
3870 procedure SetImgListIdx(const Index: Integer; const Value: PImageList);
3871 function GetLVColText(Idx: Integer): String;
3872 procedure SetLVColText(Idx: Integer; const Value: String);
3873 {$IFNDEF _FPC}
3874 {$IFNDEF _D2}
3875 function GetLVColTextW(Idx: Integer): WideString;
3876 procedure SetLVColTextW(Idx: Integer; const Value: WideString);
3877 {$ENDIF _D2}
3878 {$ENDIF _FPC}
3879 function LVGetItemText(Idx, Col: Integer): String;
3880 procedure LVSetItemText(Idx, Col: Integer; const Value: String);
3881 {$IFNDEF _FPC}
3882 {$IFNDEF _D2}
3883 function LVGetItemTextW(Idx, Col: Integer): WideString;
3884 procedure LVSetItemTextW(Idx, Col: Integer; const Value: WideString);
3885 {$ENDIF _D2}
3886 {$ENDIF _FPC}
3887 procedure SetLVOptions(const Value: TListViewOptions);
3888 procedure SetLVStyle(const Value: TListViewStyle);
3889 function GetLVColEx(Idx: Integer; const Index: Integer): Integer;
3890 procedure SetLVColEx(Idx: Integer; const Index: Integer;
3891 const Value: Integer);
3893 function GetChildCount: Integer;
3895 function LVGetItemPos(Idx: Integer): TPoint;
3896 procedure LVSetItemPos(Idx: Integer; const Value: TPoint);
3897 procedure LVSetColorByIdx(const Index: Integer; const Value: TColor);
3898 {$IFDEF F_P}
3899 function LVGetColorByIdx(const Index: Integer): TColor;
3900 {$ENDIF F_P}
3901 function GetIntVal(const Index: Integer): Integer;
3902 procedure SetIntVal(const Index, Value: Integer);
3903 function GetItemVal(Item: Integer; const Index: Integer): Integer;
3904 procedure SetItemVal(Item: Integer; const Index, Value: Integer);
3905 function TBGetButtonVisible(BtnID: Integer): Boolean;
3906 procedure TBSetButtonVisible(BtnID: Integer; const Value: Boolean);
3908 function TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;
3909 procedure TBSetBtnStt(BtnID: Integer; const Index: Integer; const Value: Boolean);
3910 function TBGetButtonText(BtnID: Integer): String;
3911 function TBGetButtonRect(BtnID: Integer): TRect;
3913 function TBGetRows: Integer;
3914 procedure TBSetRows(const Value: Integer);
3915 procedure SetProgressColor(const Value: TColor);
3916 function TBGetBtnImgIdx(BtnID: Integer): Integer;
3917 procedure TBSetBtnImgIdx(BtnID: Integer; const Value: Integer);
3919 procedure TBSetButtonText(BtnID: Integer; const Value: String);
3921 function TBGetBtnWidth(BtnID: Integer): Integer;
3922 procedure TBSetBtnWidth(BtnID: Integer; const Value: Integer);
3923 procedure TBSetBtMinMaxWidth(const Idx: Integer; const Value: Integer);
3924 {$IFDEF F_P}
3925 function TBGetBtMinMaxWidth(const Idx: Integer): Integer;
3926 {$ENDIF F_P}
3927 procedure TBFreeTBevents;
3928 procedure Set_Align(const Value: TControlAlign);
3929 function GetSelection: String;
3930 procedure SetSelection(const Value: String);
3931 procedure SetTabOrder(const Value: Integer);
3932 function GetFocused: Boolean;
3933 procedure SetFocused(const Value: Boolean);
3934 function REGetFont: PGraphicTool;
3935 procedure RESetFont(Value: PGraphicTool);
3936 procedure RESetFontEx(const Index: Integer);
3937 function REGetFontEffects(const Index: Integer): Boolean;
3938 function REGetFontMask(const Index: Integer): Boolean;
3939 procedure RESetFontEffect(const Index: Integer; const Value: Boolean);
3940 function REGetFontAttr(const Index: Integer): Integer;
3941 procedure RESetFontAttr(const Index, Value: Integer);
3942 procedure RESetFontAttr1(const Index, Value: Integer);
3943 function REGetFontSizeValid: Boolean;
3944 function REGetCharformat: TCharFormat;
3945 procedure RESetCharFormat(const Value: TCharFormat);
3946 function REReadText(Format: TRETextFormat;
3947 SelectionOnly: Boolean): String;
3948 procedure REWriteText(Format: TRETextFormat; SelectionOnly: Boolean;
3949 const Value: String);
3950 function REGetFontName: String;
3951 procedure RESetFontName(const Value: String);
3952 function REGetParaFmt: TParaFormat;
3953 procedure RESetParaFmt(const Value: TParaFormat);
3954 function REGetNumbering: Boolean;
3955 function REGetParaAttr( const Index: Integer ): Integer;
3956 function REGetParaAttrValid( const Index: Integer ): Boolean;
3957 function REGetTabCount: Integer;
3958 function REGetTabs(Idx: Integer): Integer;
3959 function REGetTextAlign: TRichTextAlign;
3960 procedure RESetNumbering(const Value: Boolean);
3961 procedure RESetParaAttr(const Index, Value: Integer);
3962 procedure RESetTabCount(const Value: Integer);
3963 procedure RESetTabs(Idx: Integer; const Value: Integer);
3964 procedure RESetTextAlign(const Value: TRichTextAlign);
3965 function REGetStartIndentValid: Boolean;
3966 function REGetAutoURLDetect: Boolean;
3967 procedure RESetAutoURLDetect(const Value: Boolean);
3969 function GetMaxTextSize: DWORD;
3970 procedure SetMaxTextSize(const Value: DWORD);
3971 procedure SetOnResize(const Value: TOnEvent);
3973 procedure DoSelChange;
3975 function REGetUnderlineEx: TRichUnderline;
3976 procedure RESetUnderlineEx(const Value: TRichUnderline);
3978 function GetTextSize: Integer;
3979 function REGetTextSize(Units: TRichTextSize): Integer;
3981 function REGetNumStyle: TRichNumbering;
3982 procedure RESetNumStyle(const Value: TRichNumbering);
3983 function REGetNumBrackets: TRichNumBrackets;
3984 procedure RESetNumBrackets(const Value: TRichNumBrackets);
3985 function REGetNumTab: Integer;
3986 procedure RESetNumTab(const Value: Integer);
3987 function REGetNumStart: Integer;
3988 procedure RESetNumStart(const Value: Integer);
3989 function REGetSpacing(const Index: Integer): Integer;
3990 procedure RESetSpacing(const Index, Value: Integer);
3991 function REGetSpacingRule: Integer;
3992 procedure RESetSpacingRule(const Value: Integer);
3993 function REGetLevel: Integer;
3994 function REGetBorder(Side: TBorderEdge; const Index: Integer): Integer;
3995 procedure RESetBorder(Side: TBorderEdge; const Index: Integer;
3996 const Value: Integer);
3997 function REGetParaEffect(const Index: Integer): Boolean;
3998 procedure RESetParaEffect(const Index: Integer; const Value: Boolean);
3999 function REGetOverwite: Boolean;
4000 procedure RESetOverwrite(const Value: Boolean);
4001 procedure RESetOvrDisable(const Value: Boolean);
4002 function REGetTransparent: Boolean;
4003 procedure RESetTransparent(const Value: Boolean);
4004 procedure RESetOnURL(const Index: Integer; const Value: TOnEvent);
4005 {$IFDEF F_P}
4006 function REGetOnURL(const Index: Integer): TOnEvent;
4007 {$ENDIF F_P}
4008 function REGetLangOptions(const Index: Integer): Boolean;
4009 procedure RESetLangOptions(const Index: Integer; const Value: Boolean);
4010 function LVGetItemImgIdx(Idx: Integer): Integer;
4011 procedure LVSetItemImgIdx(Idx: Integer; const Value: Integer);
4012 procedure SetFlat(const Value: Boolean);
4013 procedure SetOnMouseEnter(const Value: TOnEvent);
4014 procedure SetOnMouseLeave(const Value: TOnEvent);
4015 procedure EdSetTransparent(const Value: Boolean);
4016 procedure SetOnTestMouseOver(const Value: TOnTestMouseOver);
4017 function GetPages(Idx: Integer): PControl;
4018 function TCGetItemText(Idx: Integer): String;
4019 procedure TCSetItemText(Idx: Integer; const Value: String);
4020 function TCGetItemImgIDx(Idx: Integer): Integer;
4021 procedure TCSetItemImgIdx(Idx: Integer; const Value: Integer);
4022 function TCGetItemRect(Idx: Integer): TRect;
4023 function TVGetItemIdx(const Index: Integer): THandle;
4024 procedure TVSetItemIdx(const Index: Integer; const Value: THandle);
4025 function TVGetItemNext(Item: THandle; const Index: Integer): THandle;
4026 function TVGetItemRect(Item: THandle; TextOnly: Boolean): TRect;
4027 function TVGetItemVisible(Item: THandle): Boolean;
4028 procedure TVSetITemVisible(Item: THandle; const Value: Boolean);
4029 function TVGetItemStateFlg(Item: THandle; const Index: Integer): Boolean;
4030 procedure TVSetItemStateFlg(Item: THandle; const Index: Integer;
4031 const Value: Boolean);
4032 function TVGetItemImage(Item: THandle; const Index: Integer): Integer;
4033 procedure TVSetItemImage(Item: THandle; const Index: Integer;
4034 const Value: Integer);
4035 function TVGetItemText(Item: THandle): String;
4036 procedure TVSetItemText(Item: THandle; const Value: String);
4037 {$IFNDEF _FPC}
4038 {$IFNDEF _D2}
4039 function TVGetItemTextW(Item: THandle): WideString;
4040 procedure TVSetItemTextW(Item: THandle; const Value: WideString);
4041 {$ENDIF _D2}
4042 {$ENDIF _FPC}
4043 function TV_GetItemHasChildren(Item: THandle): Boolean;
4044 procedure TV_SetItemHasChildren(Item: THandle; const Value: Boolean);
4045 function TV_GetItemChildCount(Item: THandle): Integer;
4046 function TVGetItemData(Item: THandle): Pointer;
4047 procedure TVSetItemData(Item: THandle; const Value: Pointer);
4049 function GetToBeVisible: Boolean;
4051 procedure SetAlphaBlend(const Value: Integer);
4052 procedure SetMaxProgress(const Index, Value: Integer);
4053 procedure SetDroppedWidth(const Value: Integer);
4054 function LVGetItemState(Idx: Integer): TListViewItemState;
4055 procedure LVSetItemState(Idx: Integer; const Value: TListViewItemState);
4056 function LVGetSttImgIdx(Idx: Integer): Integer;
4057 procedure LVSetSttImgIdx(Idx: Integer; const Value: Integer);
4058 function LVGetOvlImgIdx(Idx: Integer): Integer;
4059 procedure LVSetOvlImgIdx(Idx: Integer; const Value: Integer);
4060 function LVGetItemData(Idx: Integer): DWORD;
4061 procedure LVSetItemData(Idx: Integer; const Value: DWORD);
4062 function LVGetItemIndent(Idx: Integer): Integer;
4063 procedure LVSetItemIndent(Idx: Integer; const Value: Integer);
4064 procedure SetOnDeleteAllLVItems(const Value: TOnEvent);
4065 procedure SetOnDeleteLVItem(const Value: TOnDeleteLVItem);
4066 procedure SetOnEditLVItem(const Value: TOnEditLVItem);
4067 procedure SetOnLVData(const Value: TOnLVData);
4068 {$IFNDEF _FPC}
4069 {$IFNDEF _D2}
4070 procedure SetOnLVDataW(const Value: TOnLVDataW);
4071 {$ENDIF _D2}
4072 {$ENDIF _FPC}
4073 procedure SetOnColumnClick(const Value: TOnLVColumnClick);
4074 procedure SetOnDrawItem(const Value: TOnDrawItem);
4075 procedure SetOnMeasureItem(const Value: TOnMeasureItem);
4077 procedure SetItemsCount(const Value: Integer);
4079 function GetItemData(Idx: Integer): DWORD;
4080 procedure SetItemData(Idx: Integer; const Value: DWORD);
4081 function GetLVCurItem: Integer;
4082 procedure SetLVCurItem(const Value: Integer);
4083 procedure SetOnDropFiles(const Value: TOnDropFiles);
4084 procedure SetOnHide(const Value: TOnEvent);
4085 procedure SetOnShow(const Value: TOnEvent);
4086 procedure SetClientMargin(const Index, Value: Integer);
4087 {$IFDEF F_P}
4088 function GetClientMargin(const Index: Integer): Integer;
4089 {$ENDIF F_P}
4090 procedure SetOnPaint(const Value: TOnPaint);
4091 procedure SetOnEraseBkgnd(const Value: TOnPaint);
4092 procedure SetTVRightClickSelect(const Value: Boolean);
4093 procedure SetOnLVStateChange(const Value: TOnLVStateChange);
4094 procedure SetOnLVDelete(const Value: TOnLVDelete);
4095 procedure SetOnMove(const Value: TOnEvent);
4096 procedure SetColor1(const Value: TColor);
4097 procedure SetColor2(const Value: TColor);
4098 procedure SetGradientLayout(const Value: TGradientLayout);
4099 procedure SetGradientStyle(const Value: TGradientStyle);
4100 procedure SetDroppedDown(const Value: Boolean);
4101 function get_ClassName: String;
4102 procedure set_ClassName(const Value: String);
4103 procedure SetClsStyle( Value: DWord );
4105 procedure SetStyle( Value: DWord );
4106 procedure SetExStyle( Value: DWord );
4108 procedure SetCursor( Value: HCursor );
4110 procedure SetIcon( Value: HIcon );
4111 procedure SetMenu( Value: HMenu );
4112 function GetCaption: String;
4113 procedure SetCaption( const Value: String );
4115 procedure SetWindowState( Value: TWindowState );
4116 function GetWindowState: TWindowState;
4118 procedure ApplyFont2Wnd;
4119 procedure DoClick;
4121 function TBAddInsButtons( Idx: Integer; const Buttons: array of PChar; const BtnImgIdxArray: array
4122 of Integer ): Integer; stdcall;
4123 procedure SetBitBtnDrawMnemonic(const Value: Boolean);
4124 function GetBitBtnImgIdx: Integer;
4125 procedure SetBitBtnImgIdx(const Value: Integer);
4126 function GetBitBtnImageList: THandle;
4127 procedure SetBitBtnImageList(const Value: THandle);
4129 function GetModal: Boolean;
4130 {$IFDEF USE_SETMODALRESULT}
4131 procedure SetModalResult( const Value: Integer );
4132 {$ENDIF}
4134 protected
4135 fHandle: HWnd;
4136 fFocusHandle: HWnd;
4137 fClsStyle: DWord;
4138 fStyle: DWord;
4139 fExStyle: DWord;
4140 fCursor: HCursor;
4141 fCursorShared: Boolean;
4142 fIcon: HIcon;
4143 fIconShared: Boolean;
4144 fCaption: PChar; // it is now preferred to store Caption as PChar (null-
4145 // terminated string), dynamically allocated in memory.
4146 fIgnoreWndCaption: Boolean;
4148 fWindowState: TWindowState;
4149 fShowAction: Integer;
4150 fCanvas: PCanvas;
4151 fDefWndProc: Pointer;
4152 fNCDestroyed: Boolean;
4154 FParent: PControl;
4155 //FTag: Integer;
4156 fEnabled: Boolean; // Caution!!! fVisible must follow fEnabled! ___
4157 fVisible: Boolean; //____________________________________________//
4158 fTabstop: Boolean;
4159 fTabOrder: Integer;
4160 fTextAlign: TTextAlign;
4161 fVerticalAlign: TVerticalAlign;
4162 fWordWrap: Boolean;
4163 fPreventResize: Boolean;
4164 fAlphaBlend: Integer;
4165 FDroppedWidth: Integer;
4167 fChildren: PList;
4168 {* List of children. }
4169 fMDIClient: PControl;
4170 {* MDI client window control }
4171 fPass2DefProc: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
4172 {* MDI children list }
4173 fMDIChildren: PList;
4174 {* List of MDI children. It is filled for MDI client window. }
4175 fWndFunc: Pointer;
4176 {* Initially pointer to WndFunc. For MDI child window, points to DefMDIChildProc. }
4177 fExMsgProc: function( Applet: PControl; var Msg: TMsg ): Boolean;
4178 {* Additional message handler called directly from Applet.ProcessMessage.
4179 Used to call TranslateMDISysAccel API function for MDI application. }
4180 fMDIDestroying: Boolean;
4181 {* }
4183 fTmpBrush: HBrush;
4184 {* Brush handle to return in response to some color set messages.
4185 Intended for internal use instead of Brush.Color if possible
4186 to avoid using it. }
4187 fTmpBrushColorRGB: TColor;
4189 fMembersCount: Integer;
4190 {* Memebers count is first used in XCustomControl to separate
4191 some internal child controls from common XControl.Children
4192 and make it invisible among Children[]. }
4193 fDrawCtrl1st: PControl;
4194 {* Child control to draw it first, i.e. foreground of others. }
4195 FCreating: Boolean;
4196 {* True, when creating of object is in progress. }
4197 fDestroying: Boolean;
4198 {* True, when destroying of the window is started. Made protected to
4199 be accessible in descending classes. }
4200 fMenu: HMenu;
4201 {* Usually used to store handle of attached main menu, but sometimes
4202 is used to store control ID (for standard GUI controls only). }
4203 fMenuObj: PObj;
4204 {* PMenu pointer to TMenu object. Freed automatically with entire
4205 chain of menu objects attached to a control (or form). }
4206 {$IFNDEF NEW_MENU_ACCELL}
4207 fAccelTable: HAccel;
4208 {$ENDIF}
4209 {* Handle of accelerator table created by menu(s). }
4210 fImageList: PImageList;
4211 {* Pointer to first private image list. Control can own several image,
4212 lists, linked to a chain of image list objects. All these image lists
4213 are released automatically, when control is destroyed. }
4214 fCtlImageListSml: PImageList;
4215 {* ImageList object (with small icons 16x16) to use with a control (e.g.,
4216 with ListView control).
4217 If not set, but control has a list of image list objects, last added
4218 image list with small icons is used automatically. }
4219 fCtlImageListNormal: PImageList;
4220 {* ImageList object (with big icons 32x32) to use with a control.
4221 If not set, last added image list with big icons is used. }
4222 fCtlImgListState: PImageList;
4223 {* ImageList object to use as a state image list (for ListView control). }
4224 fIsApplet: Boolean;
4225 {* True, if the object represent application taskbar button. }
4226 fIsForm: Boolean;
4227 {* True, if the object is form. }
4228 fIsMDIChild: Boolean;
4229 {* TRUE, if the object is MDI child form. }
4230 fIsControl: Boolean;
4231 {* True, if it is a control on form. }
4232 fIsStaticControl: Boolean;
4233 {* True, if it is static control with a caption. (To prevent flickering
4234 it in DoubleBuffered mode. }
4235 fIsCommonControl: Boolean;
4236 {* True, if it is common control. }
4237 fChangedPosSz: Byte;
4238 {* Flags of changing left (1), top (2), width (4) or height (8) }
4239 fCannotDoubleBuf: Boolean;
4240 {* True, if cannot set DoubleBuffered to True (RichEdit). }
4241 fUpdRgn: HRgn;
4242 fCollectUpdRgn: HRGN;
4243 fEraseUpdRgn: Boolean;
4244 fPaintDC: HDC;
4245 fDblBufBmp: HBitmap;
4246 {* Memory bitmap, used for DoubleBuffered painting. }
4247 fDblBufW, fDblBufH: Integer;
4248 {* Dimensions of fDblBufBmp. }
4249 fDblBufPainting: Boolean;
4250 fLookTabKeys: TTabKeys;
4251 fNotUpdate: Boolean;
4252 fDynHandlers: PList;
4253 fColumn: Integer;
4254 FSupressTab: Boolean;
4255 fUpdateCount: Integer;
4256 fPaintLater: Boolean;
4257 fOnLeave: TOnEvent;
4258 fEditing: Boolean;
4259 fAutoPopupMenu: PObj;
4260 fHelpContext: Integer;
4262 // Order of following fields is important:
4263 //_______________________________________________________________________________________________
4264 fOnDynHandlers: TWindowFunc; //
4265 fWndProcKeybd: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; //
4266 fControlClick: procedure( Sender : PObj ); //
4267 fControlClassName: PChar; //
4268 fWindowed: Boolean; //
4269 {* True, if control is windowed (or is a form). Now always True, //
4270 because KOL does not yet contain Graphic controls. } //
4271 // //
4272 fCtlClsNameChg: Boolean; //
4273 {* True, if control class name changed and memory is allocated to store it. } //
4274 fWndProcResizeFlicks: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; //
4275 fGotoControl: function( Self_: PControl; Key: DWORD; CheckOnly: Boolean ): Boolean; //
4276 fCtl3Dchild: Boolean; //
4277 fCtl3D: Boolean; //
4278 fTextColor: TColor; //
4279 {* Color of text. Used instead of fFont.Color internally to //
4280 avoid usage of Font object if user is not accessing and changing it. } //
4281 fFont: PGraphicTool; //
4282 fColor: TColor; //
4283 {* Color of control background. } //
4284 fBrush: PGraphicTool; //
4285 fMargin: Integer; //
4286 fBoundsRect: TRect; //
4287 fClientTop, fClientBottom, fClientLeft, fClientRight: Integer; //
4288 {* Store adjustment factor of ClientRect for some 'idiosincrasies' windows, //
4289 such as Groupbox or Tabcontrol. } //
4290 //_____________________________________________________________________________________________//
4291 // this is the end of fiels set, which order is important
4293 fDoubleBuffered: Boolean; //
4294 fTransparent: Boolean; //
4296 fOnMessage: TOnMessage;
4297 fOldOnMessage: TOnMessage;
4299 fOnClick: TOnEvent;
4300 fRightClick: Boolean;
4301 fCurrentControl: PControl;
4302 fCreateVisible, fCreateHidden: Boolean;
4303 fRadio1st, fRadioLast : THandle;
4304 fDropDownProc: procedure( Sender : PObj );
4305 fDropped: Boolean;
4306 fCurIdxAtDrop: Integer;
4307 fPrevWndProc: Pointer;
4308 fClickDisabled: Byte;
4309 fCurItem, fCurIndex: Integer;
4310 FOnScroll: TOnScroll;
4311 FScrollLineDist: array[ 0..1 ] of Integer;
4313 fDefaultBtn: Boolean;
4314 fCancelBtn: Boolean;
4315 fDefaultBtnCtl: PControl;
4316 fCancelBtnCtl: PControl;
4317 fAllBtnReturnClick: Boolean;
4318 fIgnoreDefault: Boolean;
4320 fOnMouseDown: TOnMouse; // CAUTION!!! Order of mouse event handlers is important. ____
4321 fOnMouseUp: TOnMouse; //
4322 fOnMouseMove: TOnMouse; //
4323 fOnMouseDblClk: TOnMouse; //
4324 fOnMouseWheel: TOnMouse; //_____________________________________________________//
4326 fOldDefWndProc: Pointer;
4328 fOnChange: TOnEvent;
4329 fOnEnter: TOnEvent;
4331 FOnLVCustomDraw: TOnLVCustomDraw;
4332 FOnSBBeforeScroll: TOnSBBeforeScroll;
4333 FOnSBScroll: TOnSBScroll;
4334 protected
4335 procedure SetOnLVCustomDraw(const Value: TOnLVCustomDraw);
4336 public
4337 fCommandActions: TCommandActions;
4338 protected
4339 fOnChar: TOnChar;
4340 fOnKeyUp: TOnKey;
4341 fOnKeyDown: TOnKey;
4343 fOnPaint: TOnPaint;
4345 FMaxWidth: Integer;
4346 FMinWidth: Integer;
4347 FMaxHeight: Integer;
4348 FMinHeight: Integer;
4349 fShadowDeep: Integer;
4350 fStatusCtl: PControl;
4351 fStatusWnd: HWnd;
4352 fStatusTxt: PChar;
4353 fColor1: TColor;
4354 fColor2: TColor;
4355 fLVColCount: Integer;
4356 fLVOptions: TListViewOptions;
4357 fLVStyle: TListViewStyle;
4358 fOnEditLVITem: TOnEditLVItem;
4359 fLVTextBkColor: TColor;
4360 fLVItemHeight: Integer;
4362 fOnDropDown: TOnEvent;
4363 fOnCloseUp: TOnEvent;
4365 fModalResult: Integer;
4367 fModal: Integer;
4368 fModalForm: PControl;
4370 FAlign: TControlAlign;
4371 fNotUseAlign: Boolean;
4372 fDragCallback: TOnDrag;
4373 fDragging: Boolean;
4374 fDragStartPos: TPoint;
4375 fMouseStartPos: TPoint;
4376 fSplitStartPos: TPoint;
4377 fSplitStartPos2: TPoint;
4378 fSplitStartSize: Integer;
4379 fSplitMinSize1, fSplitMinSize2: Integer;
4380 fOnSplit: TOnSplit;
4381 fSecondControl: PControl;
4382 fOnSelChange: TOnEvent;
4383 fTmpFont: PGraphicTool;
4385 fRECharFormatRec: TCharFormat2;
4386 fREError: Integer;
4387 fREStream: PStream;
4388 fREStrLoadLen: DWORD;
4389 fREParaFmtRec: TParaFormat2;
4390 FOnResize: TOnEvent;
4391 fOnProgress: TOnEvent;
4392 fCharFmtDeltaSz: Integer;
4393 fParaFmtDeltaSz: Integer;
4394 fREOvr: Boolean;
4395 fReOvrDisable: Boolean;
4396 fOnREInsModeChg: TOnEvent;
4397 fREScrolling: Boolean;
4398 fUpdCount: Integer;
4399 fOnREOverURL: TOnEvent;
4400 fOnREURLClick: TOnEvent;
4401 fRECharArea: TRichFmtArea;
4402 fBitBtnOptions : TBitBtnOptions;
4403 fGlyphLayout : TGlyphLayout;
4404 fGlyphBitmap : HBitmap;
4405 fGlyphCount : Integer;
4406 fGlyphWidth, fGlyphHeight: Integer;
4407 fOnBitBtnDraw: TOnBitBtnDraw;
4408 fFlat: Boolean;
4409 fSizeRedraw: Boolean; {YS}
4411 fOnMouseLeave: TOnEvent;
4412 fOnMouseEnter: TOnEvent;
4413 fOnTestMouseOver: TOnTestMouseOver;
4415 fMouseInControl: Boolean;
4416 fRepeatInterval: Integer;
4417 fChecked: Boolean;
4418 fPrevFocusWnd: HWnd;
4420 fOnTVBeginDrag: TOnTVBeginDrag;
4421 fOnTVBeginEdit: TOnTVBeginEdit;
4422 fOnTVEndEdit: TOnTVEndEdit;
4423 fOnTVExpanded: TOnTVExpanded;
4424 fOnTVExpanding: TOnTVExpanding;
4425 fOnTVDelete: TOnTVDelete;
4427 fOnDeleteLVItem: TOnDeleteLVItem;
4428 fOnDeleteAllLVItems: TOnEvent;
4429 fOnLVData: TOnLVData;
4430 {$IFNDEF _FPC}
4431 {$IFNDEF _D2}
4432 fOnLVDataW: TOnLVDataW;
4433 {$ENDIF _D2}
4434 {$ENDIF _FPC}
4435 fOnCompareLVItems: TOnCompareLVItems;
4436 fOnColumnClick: TOnLVColumnClick;
4437 fOnDrawItem: TOnDrawItem;
4438 fOnMeasureItem: TOnMeasureItem;
4439 fREUrl: String;
4440 FMinimizeWnd: PControl;
4441 FFixWidth: Integer;
4442 FFixHeight: Integer;
4443 FOnDropFiles: TOnDropFiles;
4444 FOnHide: TOnEvent;
4445 FOnShow: TOnEvent;
4446 fOnEraseBkgnd: TOnPaint;
4447 fCustomData: Pointer;
4448 fCustomObj: PObj;
4449 fOnTVSelChanging: TOnTVSelChanging;
4451 fOnClose: TOnEventAccept;
4452 fOnQueryEndSession: TOnEventAccept;
4453 fCloseQueryReason: TCloseQueryReason;
4455 //----- order of following 3 events important: //
4456 fOnMinimize: TOnEvent; //
4457 fOnMaximize: TOnEvent; //
4458 fOnRestore: TOnEvent; //
4459 //---------------------------------------------//
4461 //fCreateParamsExt: procedure( Self_: PControl; var Params: TCreateParams );
4462 fCreateWndExt: procedure( Sender: PControl );
4464 fTBttCmd: PList;
4465 fTBttTxt: PStrList;
4466 fTBevents: PList; // events for TBAssignEvents
4467 fTBBtnImgWidth: Integer; // custom toolbar bitmap width
4468 FTBBtMinWidth: Integer;
4469 FTBBtMaxWidth: Integer;
4470 fGradientStyle: TGradientStyle;
4471 fGradientLayout: TGradientLayout;
4472 fVisibleWoParent: Boolean;
4475 fTVRightClickSelect: Boolean;
4476 FOnMove: TOnEvent;
4477 FOnLVStateChange: TOnLVStateChange;
4478 FOnLVDelete: TOnLVDelete;
4479 fAutoSize: procedure( Self_: PControl );
4480 fIsButton: Boolean;
4481 fSizeGrip: Boolean;
4482 fNotAvailable: Boolean;
4483 FPressedMnemonic: DWORD;
4484 FBitBtnDrawMnemonic: Boolean;
4485 FBitBtnGetCaption: function( Self_: PControl; const S: String ): String;
4486 FBitBtnExtDraw: procedure( Self_: PControl; DC: HDC; X, Y: Integer; const R: TRect;
4487 const CapText, CapTxtOrig: String; Color: TColor );
4488 FTextShiftX, FTextShiftY: Integer;
4489 fNotifyChild: procedure( Self_, Child: PControl );
4490 fScrollChildren: procedure( Self_: PControl );
4491 fOnHelp: TOnHelp;
4493 FOnDTPUserString: TDTParseInputEvent;
4495 {$IFDEF USE_MHTOOLTIP}
4496 {$DEFINE var}
4497 {$I KOLMHToolTip}
4498 {$UNDEF var}
4500 {$DEFINE function}
4501 {$I KOLMHToolTip}
4502 {$UNDEF function}
4503 {$ENDIF}
4505 procedure Init; {-}virtual;{+}{++}(*override;*){--}
4506 {* }
4507 procedure InitParented( AParent: PControl ); virtual;
4508 {* Initialization of visual object. }
4509 procedure DestroyChildren;
4510 {* Destroys children. Is called in destructor, and can be
4511 called in descending classes as earlier as needed to
4512 prevent problems of too late destroying of visuals. }
4514 function GetParentWnd( NeedHandle: Boolean ): HWnd;
4515 {* Returns handle of parent window. }
4516 function GetParentWindow: HWnd;
4517 {* }
4518 procedure SetEnabled( Value: Boolean );
4519 {* Changes Enabled property value. Overriden here to change enabling
4520 status of a window. }
4521 function GetEnabled: Boolean;
4522 {* Returns True, if Enabled. Overriden here to obtain real window
4523 state. }
4524 procedure SetVisible( Value: Boolean );
4525 {* Sets Visible property value. Overriden here to change visibility
4526 of correspondent window. }
4527 procedure Set_Visible( Value: Boolean );
4528 {* }
4529 function GetVisible: Boolean;
4530 {* Returns True, if correspondent window is Visible. Overriden
4531 to get visibility of real window, not just value stored in object. }
4532 function Get_Visible: Boolean;
4533 {* Returns True, if correspondent window is Visible, for forms and applet,
4534 or if fVisible flag is set, for controls. }
4535 procedure SetCtlColor( Value: TColor );
4536 {* Sets TControl's Color property value. }
4537 procedure SetBoundsRect( const Value: TRect );
4538 {* Sets BoudsRect property value. }
4539 function GetBoundsRect: TRect;
4540 {* Returns bounding rectangle. }
4541 function GetIcon: HIcon;
4542 {* Returns Icon property. By default, if it is not set,
4543 returns Icon property of an Applet. }
4545 procedure CreateSubclass( var Params: TCreateParams; ControlClassName: PChar );
4546 {* Can be used in descending classes to subclass window with given
4547 standard Windows ControlClassName - must be called after
4548 creating Params but before CreateWindow. Usually it is called
4549 in overriden method CreateParams after calling of the inherited one. }
4551 function UpdateWndStyles: PControl;
4552 {* Updates fStyle, fExStyle, fClsStyle from window handle }
4553 procedure SetOnChar(const Value: TOnChar);
4554 {* }
4555 procedure SetOnKeyDown(const Value: TOnKey);
4557 {* }
4558 procedure SetOnKeyUp(const Value: TOnKey);
4559 {* }
4560 procedure SetMouseDown(const Value: TOnMouse);
4561 {* }
4562 procedure SetMouseMove(const Value: TOnMouse);
4563 {* }
4564 procedure SetMouseUp(const Value: TOnMouse);
4565 {* }
4566 procedure SetMouseWheel(const Value: TOnMouse);
4567 {* }
4568 procedure SetMouseDblClk(const Value: TOnMouse);
4569 {* }
4570 procedure SetHelpContext( Value: Integer );
4571 {* }
4572 procedure SetOnTVDelete( const Value: TOnTVDelete );
4573 {* }
4574 procedure SetDefaultBtn(const Index: Integer; const Value: Boolean);
4575 {$IFDEF F_P}
4576 function GetDefaultBtn(const Index: Integer): Boolean;
4577 {$ENDIF F_P}
4578 function DefaultBtnProc( var Msg: TMsg; var Rslt: Integer ): Boolean;
4579 {* }
4581 procedure SetDateTime( Value: TDateTime );
4582 function GetDateTime: TDateTime;
4583 procedure SetDateTimeRange( Value: TDateTimeRange );
4584 function GetDateTimeRange: TDateTimeRange;
4585 procedure SetDateTimePickerColor( Index: TDateTimePickerColor; Value: TColor );
4586 function GetDateTimePickerColor( Index: TDateTimePickerColor ): TColor;
4587 procedure SetDateTimeFormat( const Value: String );
4589 public
4590 constructor CreateParented( AParent: PControl );
4591 {* Creates new instance of TControl object, calling InitParented }
4592 //FormPointer_DoNotUseItPlease_ItIsUsedByMCK: Pointer;
4593 { ^ no more needed }
4594 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
4595 {* Destroyes object. First of all, destructors for all children
4596 are called. }
4598 function GetWindowHandle: HWnd;
4599 {* Returns window handle. If window is not yet created,
4600 method CreateWindow is called. }
4601 procedure CreateChildWindows;
4602 {* Enumerates all children recursively and calls CreateWindow for all
4603 of these. }
4604 property Parent: PControl read fParent write SetParent;
4605 {* Parent of TParent object. Also must be of TParent type or derived from TParent. }
4606 //property Tag: Integer read FTag write FTag; //--------- moved to TObj --------
4607 {* User-defined pointer, which can contain any data or reference to
4608 anywhere in memory (when used as a pointer).
4610 function ChildIndex( Child: PControl ): Integer;
4611 {* Returns index of given child. }
4612 procedure MoveChild( Child: PControl; NewIdx: Integer );
4613 {* Moves given Child into new position. }
4615 property Enabled: Boolean read GetEnabled write SetEnabled;
4616 {* Enabled usually used to decide if control can get keyboard focus
4617 or been clicked by mouse. }
4618 procedure EnableChildren( Enable, Recursive: Boolean );
4619 {* Enables (Enable = TRUE) or disables (Enable = FALSE) all the children
4620 of the control. If Recursive = TRUE then all the children of all the
4621 children are enabled or disabled recursively. }
4622 property Visible: Boolean read Get_Visible write SetVisible;
4623 {* Obvious. }
4624 property ToBeVisible: Boolean read GetToBeVisible;
4625 {* Returns True, if a control is supposed to be visible when its
4626 form is showing. Thus is, True is returned if either control
4627 is Visible or hidden, but marked with flag fCreateHidden. }
4628 property CreateVisible: Boolean read fCreateVisible write fCreateVisible;
4629 {* False by default. If You want your form to be created visible and
4630 flick due creation, set it to True. This does not affect size of
4631 executable anyway. }
4632 property Align: TControlAlign read FAlign write Set_Align;
4633 {* Align style of a control. If this property is not used in your
4634 application, there are no additional code added. Aligning of
4635 controls is made in KOL like in VCL. To align controls when
4636 initially create ones, use "transparent" function SetAlign
4637 ("transparent" means that it returns @Self as a result).
4638 |<br>
4639 Note, that it is better not to align combobox caClient, caLeft or
4640 caRight (better way is to place a panel with Border = 0 and
4641 EdgeStyle = esNone, align it as desired and to place a combobox on it
4642 aligning caTop or caBottom). Otherwise, big problems could be under
4643 Win9x/Me, and some delay could occur under any other systems.
4644 |<br> Do not attempt to align some kinds of controls (like combobox or
4645 toolbar) caLeft or caRight, this can cause infinite recursion in the
4646 application. }
4647 property BoundsRect: TRect read GetBoundsRect write SetBoundsRect;
4648 {* Bounding rectangle of the visual. Coordinates are relative
4649 to top left corner of parent's ClientRect, or to top left corner
4650 of screen (for TForm). }
4651 property Left: Integer read GetLeft write SetLeft;
4652 {* Left horizontal position. }
4653 property Top: Integer read GetTop write SetTop;
4654 {* Top vertical position. }
4655 property Width: Integer read GetWidth write SetWidth;
4656 {* Width of TVisual object. }
4657 property Height: Integer read GetHeight write SetHeight;
4658 {* Height of TVisual object. }
4660 property Position: TPoint read GetPosition write Set_Position;
4661 {* Represents top left position of the object. See also BoundsRect. }
4662 property MinWidth: Integer index 0
4663 {$IFDEF F_P} read GetConstraint
4664 {$ELSE DELPHI} read FMinWidth
4665 {$ENDIF F_P/DELPHI} write SetConstraint;
4666 {* Minimal width constraint. }
4667 property MinHeight: Integer index 1
4668 {$IFDEF F_P} read GetConstraint
4669 {$ELSE DELPHI} read FMinHeight
4670 {$ENDIF F_P/DELPHI} write SetConstraint;
4671 {* Minimal height constraint. }
4672 property MaxWidth: Integer index 2
4673 {$IFDEF F_P} read GetConstraint
4674 {$ELSE DELPHI} read FMaxWidth
4675 {$ENDIF F_P/DELPHI} write SetConstraint;
4676 {* Maximal width constraint. }
4677 property MaxHeight: Integer index 3
4678 {$IFDEF F_P} read GetConstraint
4679 {$ELSE DELPHI} read FMaxHeight
4680 {$ENDIF F_P/DELPHI} write SetConstraint;
4681 {* Maximal height constraint. }
4683 function ClientRect: TRect;
4684 {* Client rectangle of TVisual. Contrary to VCL, for some
4685 classes (e.g., derived from XCustomControl, can be relative
4686 not to itself, but to top left corner of the BoundsRect
4687 rectangle. }
4688 property ClientWidth: Integer read GetClientWidth write SetClientWidth;
4689 {* Obvious. Accessing this property, program forces window latent creation. }
4690 property ClientHeight: Integer read GetClientHeight write SetClientHeight;
4691 {* Obvious. Accessing this property, program forces window latent creation. }
4693 function ControlRect: TRect;
4694 {* Absolute bounding rectangle relatively to nearest
4695 Windowed parent client rectangle (at least to a form, but usually to
4696 a Parent).
4697 Useful while drawing on device context, provided by such
4698 Windowed parent. For form itself is the same as BoundsRect. }
4699 function ControlAtPos( X, Y: Integer; IgnoreDisabled: Boolean ): PControl;
4700 {* Searches TVisual at the given position (relatively to top left
4701 corner of the ClientRect). }
4703 procedure Invalidate;
4704 {* Invalidates rectangle, occupied by the visual (but only if Showing =
4705 True). }
4707 procedure InvalidateEx;
4708 {* Invalidates the window and all its children. }
4709 procedure InvalidateNC( Recursive: Boolean );
4710 {* Invalidates the window and all its children including non-client area. }
4711 procedure Update;
4712 {* Updates control's window and calls Update for all child controls. }
4713 procedure BeginUpdate;
4714 {* |<#treeview>
4715 |<#listview>
4716 |<#richedit>
4717 |<#memo>
4718 |<#listbox>
4719 Call this method to stop visual updates of the control until correspondent
4720 EndUpdate called (pairs BeginUpdate - EndUpdate can be nested). }
4721 procedure EndUpdate;
4722 {* See BeginUpdate. }
4724 property Windowed: Boolean read fWindowed;
4725 {* Constantly returns True, if object is windowed (i.e. owns
4726 correspondent window handle). Otherwise, returns False.
4727 |<br>
4728 By now, all the controls are windowed (there are no controls in KOL, which are
4729 emulating window, acually belonging to Parent - like TGraphicControl
4730 in VCL). }
4732 function HandleAllocated: Boolean;
4733 {* Returns True, if window handle is allocated. Has no sense for
4734 non-Windowed objects (but now, the KOL has no non-Windowed controls). }
4735 property MDIClient: PControl read fMDIClient;
4736 {* For MDI forms only: returns MDI client window control, containng all MDI
4737 children. Use this window to send specific messages to rule MDI children. }
4739 property ChildCount: Integer read GetChildCount;//GetChildCountWOMembers;
4740 {* Returns number of commonly accessed child objects (without
4741 MembersCount). }
4742 property Children[ Idx: Integer ]: PControl read GetMembers;
4743 {* Child items of TVisual object. Property is reintroduced here
4744 to separate access to always visible Children[] from restricted
4745 a bit Members[]. }
4746 property MembersCount: Integer read FMembersCount;
4747 {* Returns number of "internal" child objects, which are
4748 not accessible through common Children[] property. }
4749 property Members[ Idx: Integer ]: PControl read GetMembers;
4750 {* Members and children array of the object (first from 0 to
4751 MembersCount-1 are Members[], and Children[] are followed by
4752 them. Usually You do not need to use this list. Use instead
4753 Children[0..ChildCount] property, Members[] is intended for
4754 internal needs of XCL (and in KOL by now Members and Children
4755 actually are the same properties). }
4757 procedure PaintBackground( DC: HDC; Rect: PRect );
4758 {* Is called to paint background in given rectangle. This
4759 method is filling clipped area of the Rect rectangle with
4760 Color, but only if global event Global_OnPaintBkgnd is
4761 not assigned. If assigned, this one is called instead here.
4762 |<br>&nbsp;&nbsp;&nbsp;
4763 This method made public, so it can be called directly to
4764 fill some device context's rectangle. But remember, that
4765 independantly of Rect, top left corner of background piece
4766 will be located so, if drawing is occure into ControlRect
4767 rectangle. }
4768 property WindowedParent: PControl read fParent;
4769 {* Returns nearest windowed parent, the same as Parent. }
4771 function ParentForm: PControl;
4772 {* |<#form>
4773 Returns parent form for a control (of @Self for form itself. }
4774 property ActiveControl: PControl read fCurrentControl write fCurrentControl;
4775 {* }
4776 function Client2Screen( const P: TPoint ): TPoint;
4777 {* Converts the client coordinates of a specified point to screen coordinates. }
4778 function Screen2Client( const P: TPoint ): TPoint;
4779 {* Converts screen coordinates of a specified point to client coordinates. }
4780 function CreateWindow: Boolean; virtual;
4781 {* |<#form>
4782 Creates correspondent window object. Returns True if success (if
4783 window is already created, False is returned). If applied to a form,
4784 all child controls also allocates handles that time.
4785 |<br>&nbsp;&nbsp;&nbsp;
4786 Call this method to ensure, that a hanle is allocated for a form,
4787 an application button or a control. (It is not necessary to do so in
4788 the most cases, even if You plan to work with control's handle directly.
4789 But immediately after creating the object, if You want to pass its
4790 handle to API function, this can be helpful). }
4791 procedure Close;
4792 {* |<#appbutton>
4793 |<#form>
4794 Closes window. If a window is the main form, this closes application,
4795 terminating it. Also it is possible to call Close method for Applet
4796 window to stop application. }
4798 {$IFDEF USE_MHTOOLTIP}
4799 {$DEFINE public}
4800 {$I KOLMHToolTip}
4801 {$UNDEF public}
4802 {$ENDIF}
4804 property Handle: HWnd read fHandle; //GetHandle;
4805 {* Returns descriptor of system window object. If window is not yet
4806 created, 0 is returned. To allocate handle, call CreateWindow method. }
4808 property ParentWindow: HWnd read GetParentWindow;
4809 {* Returns handle of parent window (not TControl object, but system
4810 window object handle). }
4811 property ClsStyle: DWord read fClsStyle write SetClsStyle;
4812 {* Window class style. Available styles are:
4813 |<table border=0>
4814 |&L=<tr><td valign=top><font face=Fixedsys>%1</font></td><td>
4815 |&E=</td></tr>
4816 |&N=<br>&nbsp;&nbsp;&nbsp;
4817 <L CS_BYTEALIGNCLIENT> - Aligns the window's client area on the byte boundary
4818 (in the x direction) to enhance performance during
4819 drawing operations. <E>
4820 <L CS_BYTEALIGNWINDOW> - Aligns a window on a byte boundary (in the x
4821 direction). <E>
4822 <L CS_CLASSDC> - Allocates one device context to be shared by all
4823 windows in the class. <E>
4824 <L CS_DBLCLKS> - Sends double-click messages to the window
4825 procedure when the user double-clicks the mouse while the
4826 cursor is within a window belonging to the class. <E>
4827 <L CS_GLOBALCLASS> - Allows an application to create a window of
4828 the class regardless of the value of the hInstance parameter.
4829 <N> You can create a global class by creating
4830 the window class in a dynamic-link library (DLL) and listing the
4831 name of the DLL in the registry under specific keys. <E>
4832 <L CS_HREDRAW> - Redraws the entire window if a movement or
4833 size adjustment changes the width of the client area. <E>
4834 <L CS_NOCLOSE> - Disables the Close command on the System menu. <E>
4835 <L CS_OWNDC> - Allocates a unique device context for each window
4836 in the class. <E>
4837 <L CS_PARENTDC> - Sets the clipping region of the child window to
4838 that of the parent window so that the child can draw on the parent. <E>
4839 <L CS_SAVEBITS> - Saves, as a bitmap, the portion of the screen
4840 image obscured by a window. Windows uses the saved bitmap to re-create
4841 the screen image when the window is removed. <E>
4842 <L CS_VREDRAW> - Redraws the entire window if a movement or size
4843 adjustment changes the height of the client area. <E>
4844 |</table> For more info, see Win32.hlp (keyword 'WndClass');
4847 property Style: DWord read fStyle write SetStyle;
4848 {* Window styles. Available styles are:
4849 |<table border=0>
4850 <L WS_BORDER> Creates a window that has a thin-line border. <E>
4851 <L WS_CAPTION> Creates a window that has a title bar (includes the
4852 WS_BORDER style). <E>
4853 <L WS_CHILD> Creates a child window. This style cannot be used with
4854 the WS_POPUP style. <E>
4855 <L WS_CHILDWINDOW> Same as the WS_CHILD style. <E>
4856 <L WS_CLIPCHILDREN> Excludes the area occupied by child windows
4857 when drawing occurs within the parent window. This style is used
4858 when creating the parent window. <E>
4859 <L WS_CLIPSIBLINGS> Clips child windows relative to each other;
4860 that is, when a particular child window receives a WM_PAINT message,
4861 the WS_CLIPSIBLINGS style clips all other overlapping child windows
4862 out of the region of the child window to be updated. If
4863 WS_CLIPSIBLINGS is not specified and child windows overlap, it is
4864 possible, when drawing within the client area of a child window,
4865 to draw within the client area of a neighboring child window. <E>
4866 <L WS_DISABLED> Creates a window that is initially disabled. A
4867 disabled window cannot receive input from the user. <E>
4868 <L WS_DLGFRAME> Creates a window that has a border of a style
4869 typically used with dialog boxes. A window with this style cannot
4870 have a title bar. <E>
4871 <L WS_GROUP> Specifies the first control of a group of controls.
4872 The group consists of this first control and all controls defined
4873 after it, up to the next control with the WS_GROUP style.
4874 The first control in each group usually has the WS_TABSTOP
4875 style so that the user can move from group to group. The user
4876 can subsequently change the keyboard focus from one control in
4877 the group to the next control in the group by using the direction
4878 keys. <E>
4879 <L WS_HSCROLL> Creates a window that has a horizontal scroll bar. <E>
4880 <L WS_ICONIC> Creates a window that is initially minimized. Same as
4881 the WS_MINIMIZE style. <E>
4882 <L WS_MAXIMIZE> Creates a window that is initially maximized. <E>
4883 <L WS_MAXIMIZEBOX> Creates a window that has a Maximize button.
4884 Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU
4885 style must also be specified. <E>
4886 <L WS_MINIMIZE> Creates a window that is initially minimized.
4887 Same as the WS_ICONIC style. <E>
4888 <L WS_MINIMIZEBOX> Creates a window that has a Minimize button.
4889 Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU
4890 style must also be specified. <E>
4891 <L WS_OVERLAPPED> Creates an overlapped window. An overlapped
4892 window has a title bar and a border. Same as the WS_TILED style. <E>
4893 <L WS_OVERLAPPEDWINDOW> Creates an overlapped window with the
4894 WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX,
4895 and WS_MAXIMIZEBOX styles. Same as the WS_TILEDWINDOW style. <E>
4896 <L WS_POPUP> Creates a pop-up window. This style cannot be used with
4897 the WS_CHILD style. <E>
4898 <L WS_POPUPWINDOW> Creates a pop-up window with WS_BORDER,
4899 WS_POPUP, and WS_SYSMENU styles. The WS_CAPTION and WS_POPUPWINDOW
4900 styles must be combined to make the window menu visible. <E>
4901 <L WS_SIZEBOX> Creates a window that has a sizing border. Same as the
4902 WS_THICKFRAME style. <E>
4903 <L WS_SYSMENU> Creates a window that has a window-menu on its title
4904 bar. The WS_CAPTION style must also be specified. <E>
4905 <L WS_TABSTOP> Specifies a control that can receive the keyboard focus
4906 when the user presses the TAB key. Pressing the TAB key changes
4907 the keyboard focus to the next control with the WS_TABSTOP style. <E>
4908 <L WS_THICKFRAME> Creates a window that has a sizing border.
4909 Same as the WS_SIZEBOX style. <E>
4910 <L WS_TILED> Creates an overlapped window. An overlapped window has
4911 a title bar and a border. Same as the WS_OVERLAPPED style. <E>
4912 <L WS_TILEDWINDOW> Creates an overlapped window with the
4913 WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME,
4914 WS_MINIMIZEBOX, and WS_MAXIMIZEBOX styles. Same as the
4915 WS_OVERLAPPEDWINDOW style. <E>
4916 <L WS_VISIBLE> Creates a window that is initially visible. <E>
4917 <L WS_VSCROLL> Creates a window that has a vertical scroll bar. <E>
4918 |</table>
4919 See also Win32.hlp (topic CreateWindow).
4921 property ExStyle: DWord read fExStyle write SetExStyle;
4922 {* Extra window styles. Available flags are following:
4923 |<table border=0>
4924 <L WS_EX_ACCEPTFILES> Specifies that a window created with this style
4925 accepts drag-drop files. <E>
4926 <L WS_EX_APPWINDOW> Forces a top-level window onto the taskbar
4927 when the window is minimized. <E>
4928 <L WS_EX_CLIENTEDGE> Specifies that a window has a border with a
4929 sunken edge. <E>
4930 <L WS_EX_CONTEXTHELP> Includes a question mark in the title bar of
4931 the window. When the user clicks the question mark, the cursor
4932 changes to a question mark with a pointer. If the user then clicks
4933 a child window, the child receives a WM_HELP message. The child
4934 window should pass the message to the parent window procedure,
4935 which should call the WinHelp function using the HELP_WM_HELP
4936 command. The Help application displays a pop-up window that
4937 typically contains help for the child window.WS_EX_CONTEXTHELP
4938 cannot be used with the WS_MAXIMIZEBOX or WS_MINIMIZEBOX styles. <E>
4939 <L WS_EX_CONTROLPARENT> Allows the user to navigate among the child
4940 windows of the window by using the TAB key. <E>
4941 <L WS_EX_DLGMODALFRAME> Creates a window that has a double border;
4942 the window can, optionally, be created with a title bar by
4943 specifying the WS_CAPTION style in the dwStyle parameter. <E>
4944 <L WS_EX_LEFT> Window has generic "left-aligned" properties. This
4945 is the default. <E>
4946 <L WS_EX_LEFTSCROLLBAR> If the shell language is Hebrew, Arabic, or
4947 another language that supports reading order alignment, the
4948 vertical scroll bar (if present) is to the left of the client
4949 area. For other languages, the style is ignored and not treated
4950 as an error. <E>
4951 <L WS_EX_LTRREADING> The window text is displayed using Left to
4952 Right reading-order properties. This is the default. <E>
4953 <L WS_EX_MDICHILD> Creates an MDI child window. <E>
4954 <L WS_EX_NOPARENTNOTIFY> Specifies that a child window created
4955 with this style does not send the WM_PARENTNOTIFY message to its
4956 parent window when it is created or destroyed. <E>
4957 <L WS_EX_OVERLAPPEDWINDOW> Combines the WS_EX_CLIENTEDGE and
4958 WS_EX_WINDOWEDGE styles. <E>
4959 <L WS_EX_PALETTEWINDOW> Combines the WS_EX_WINDOWEDGE,
4960 WS_EX_TOOLWINDOW, and WS_EX_TOPMOST styles. <E>
4961 <L WS_EX_RIGHT> Window has generic "right-aligned" properties.
4962 This depends on the window class. This style has an effect only
4963 if the shell language is Hebrew, Arabic, or another language that
4964 supports reading order alignment; otherwise, the style is
4965 ignored and not treated as an error. <E>
4966 <L WS_EX_RIGHTSCROLLBAR> Vertical scroll bar (if present) is to the
4967 right of the client area. This is the default. <E>
4968 <L WS_EX_RTLREADING> If the shell language is Hebrew, Arabic, or
4969 another language that supports reading order alignment, the
4970 window text is displayed using Right to Left reading-order
4971 properties. For other languages, the style is ignored and not
4972 treated as an error. <E>
4973 <L WS_EX_STATICEDGE> Creates a window with a three-dimensional
4974 border style intended to be used for items that do not accept
4975 user input. <E>
4976 <L WS_EX_TOOLWINDOW> Creates a tool window; that is, a window
4977 intended to be used as a floating toolbar. A tool window has
4978 a title bar that is shorter than a normal title bar, and the
4979 window title is drawn using a smaller font. A tool window does
4980 not appear in the taskbar or in the dialog that appears when
4981 the user presses ALT+TAB. <E>
4982 <L WS_EX_TOPMOST> Specifies that a window created with this style
4983 should be placed above all non-topmost windows and should stay
4984 above them, even when the window is deactivated. To add or remove
4985 this style, use the SetWindowPos function. <E>
4986 <L WS_EX_TRANSPARENT> Specifies that a window created with this
4987 style is to be transparent. That is, any windows that are
4988 beneath the window are not obscured by the window. A window
4989 created with this style receives WM_PAINT messages only after
4990 all sibling windows beneath it have been updated. <E>
4991 <L WS_EX_WINDOWEDGE> Specifies that a window has a border with
4992 a raised edge. <E>
4993 |</table>
4994 See also Win32.hlp (topic CreateWindowEx).
4997 property Cursor: HCursor read fCursor write SetCursor;
4998 {* Current cursor. For most of controls, sets initially to IDC_ARROW. See
4999 also ScreenCursor. }
5000 procedure CursorLoad( Inst: Integer; ResName: PChar );
5001 {* Loads Cursor from the resource. See also comments for Icon property. }
5003 property Icon: HIcon read GetIcon write SetIcon;
5004 {* |<#appbutton>
5005 |<#form>
5006 Icon. By default, icon of the Applet is used. To load icon from the
5007 resource, use IconLoad or IconLoadCursor method - this is more correct, because
5008 in such case a special flag is set to prevent attempts to destroy
5009 shared icon object in the destructor of the control. }
5011 procedure IconLoad( Inst: Integer; ResName: PChar );
5012 {* |<#appbutton>
5013 |<#form>
5014 See Icon property. }
5015 procedure IconLoadCursor( Inst: Integer; ResName: PChar );
5016 {* |<#appbutton>
5017 |<#form>
5018 Loads Icon from the cursor resource. See also Icon property. }
5021 property Menu: HMenu read fMenu write SetMenu;
5023 {* Menu (or ID of control - for standard GUI controls). }
5024 property HelpContext: Integer read fHelpContext write SetHelpContext;
5025 {* Help context. }
5026 function AssignHelpContext( Context: Integer ): PControl;
5027 {* Assigns HelpContext and returns @ Self (can be used in initialization
5028 of a control in a chain of "transparent" calls). }
5030 procedure CallHelp( Context: Integer; CtxCtl: PControl {; CtlID: Integer} );
5031 {* Method of a form or Applet. Call it to show help with the given context
5032 ID. If the Context = 0, help contents is displayed. By default,
5033 WinHelp is used. To allow using HtmlHelp, call AssignHtmlHelp global
5034 function. When WinHelp used, HelpPath variable can be assigned directly.
5035 If HelpPath variable is not assigned, application name
5036 (and path) is used, with extension replaced to '.hlp'. }
5038 property HelpPath: String read GetHelpPath write SetHelpPath;
5039 {* Property of a form or an Applet. Change it to provide custom path to
5040 WinHelp format help file. If HtmlHelp used, call global procedure
5041 AssignHtmlHelp instead. }
5043 property OnHelp: TOnHelp read fOnHelp write fOnHelp;
5044 {* An event of a form, it is called when F1 pressed or help topic requested
5045 by any other way. To prevent showing help, nullify Sender. Set Popup to
5046 TRUE to provide showing help in a pop-up window. It is also possible to
5047 change Context dynamically. }
5049 property Caption: String read GetCaption write SetCaption;
5050 {* |<#appbutton>
5051 |<#form>
5052 |<#button>
5053 |<#bitbtn>
5054 |<#label>
5055 |<#wwlabel>
5056 |<#3dlabel>
5057 Caption of a window. For standard Windows buttons, labels and so on
5058 not a caption of a window, but text of the window. }
5059 property Text: String read GetCaption write SetCaption;
5060 {* |<#edit>
5061 |<#memo>
5062 The same as Caption. To make more convenient with Edit controls. For
5063 Rich Edit control, use property RE_Text. }
5064 property SelStart: Integer read GetSelStart write SetSelStart;
5065 {* |<#edit>
5066 |<#memo>
5067 |<#richedit>
5068 |<#listbox>
5069 |<#combo>
5070 Start of selection (editbox - character position, listbox and combobox -
5071 index of [the first] selected item). }
5072 property SelLength: Integer read GetSelLength write SetSelLength;
5073 {* |<#edit>
5074 |<#memo>
5075 |<#richedit>
5076 |<#listbox>
5077 |<#listview>
5078 Length of selection (editbox - number of characters selected, multiline
5079 listbox - number of items selected). }
5081 property Selection: String read GetSelection write SetSelection;
5082 {* |<#edit>
5083 |<#memo>
5084 |<#richedit>
5085 Selected text (editbox, richedit) as string. Can be useful to replace
5086 selection. For rich edit, use RE_Text[ reText, TRUE ], if you want to
5087 read correctly characters from another locale then ANSI only. }
5088 procedure SelectAll;
5089 {* |<#edit>
5090 |<#memo>
5091 |<#richedit>
5092 Makes all the text in editbox or RichEdit, or all items in listbox
5093 selected. }
5095 procedure ReplaceSelection( const Value: String; aCanUndo: Boolean );
5096 {* |<#edit>
5097 |<#memo>
5098 |<#richedit>
5099 Replaces selection (in edit, RichEdit). Unlike assigning new value
5100 to Selection property, it is possible to specify, if operation can
5101 be undone. }
5103 procedure DeleteLines( FromLine, ToLine: Integer );
5104 {* |<#edit>
5105 |<#memo>
5106 |<#richedit>
5107 Deletes lines from FromLine to ToLine (inclusively, i.e. 0 to 0 deletes
5108 one line with index 0). Current selection is restored as possible. }
5109 property CurIndex: Integer read GetCurIndex write SetCurIndex;
5110 {* |<#listbox>
5111 |<#combo>
5112 |<#toolbar>
5113 Index of current item (for listbox, combobox) or button index pressed
5114 or dropped down (for toolbar button, and only in appropriate event
5115 handler call).
5116 |<br>
5117 You cannot use it to set or remove a selection in a multiple-selection
5118 list box, so you should set option loNoExtendSel to true.
5119 |<br>
5120 In OnClick event handler, CurIndex has not yet changed. Use OnSelChange
5121 to respond to selection changes. }
5123 property Count: Integer read GetItemsCount write SetItemsCount;
5124 {* |<#listbox>
5125 |<#combo>
5126 |<#listview>
5127 |<#treeview>
5128 |<#edit>
5129 |<#memo>
5130 |<#richedit>
5131 |<#toolbar>
5132 Number of items (listbox, combobox, listview) or lines (multiline
5133 editbox, richedit control) or buttons (toolbar). It is possible to
5134 assign a value to this property only for listbox control with loNoData
5135 style and for list view control with lvoOwnerData style (virtual list
5136 box and list view). }
5138 property Items[ Idx: Integer ]: String read GetItems write SetItems;
5139 {* |<#edit>
5140 |<#listbox>
5141 |<#combo>
5142 |<#memo>
5143 |<#richedit>
5144 Obvious. Used with editboxes, listbox, combobox. With list view, use
5145 property LVItems instead. }
5147 function Item2Pos( ItemIdx: Integer ): Integer;
5148 {* |<#edit>
5149 |<#memo>
5150 Only for edit controls: converts line index to character position. }
5151 function Pos2Item( Pos: Integer ): Integer;
5152 {* |<#edit>
5153 |<#memo>
5154 Only for edit controls: converts character position to line index. }
5156 function EditTabChar: PControl;
5157 {* |<#edit>
5158 |<#memo>
5159 Call this method (once) to provide insertion of tab character (code #9)
5160 when tab key is pressed on keyboard. }
5162 function IndexOf( const S: String ): Integer;
5163 {* |<#listbox>
5164 |<#combobox>
5165 |<#tabcontrol>
5166 Works for the most of control types, though some of those
5167 have its own methods to search given item. If a control is not
5168 list box or combobox, item is finding by enumerating all
5169 the Items one by one. See also SearchFor method. }
5170 function SearchFor( const S: String; StartAfter: Integer; Partial: Boolean ): Integer;
5171 {* |<#listbox>
5172 |<#combobox>
5173 |<#tabcontrol>
5174 Works for the most of control types, though some of those
5175 have its own methods to search given item. If a control is not
5176 list box or combobox, item is finding by enumerating all
5177 the Items one by one. See also IndexOf method. }
5180 property ItemSelected[ ItemIdx: Integer ]: Boolean read GetItemSelected write SetItemSelected;
5181 {* |<#edit>
5182 |<#memo>
5183 |<#listbox>
5184 |<#combo>
5185 Returns True, if a line (in editbox) or an item (in listbox, combobox) is
5186 selected.
5187 Can be set only for listboxes. For listboxes, which are not multiselect, and
5188 for combo lists, it is possible only to set to True, to change selection. }
5190 property ItemData[ Idx: Integer ]: DWORD read GetItemData write SetItemData;
5191 {* |<#listbox>
5192 |<#combo>
5193 Access to user-defined data, associated with the item of a list box and
5194 combo box. }
5195 property OnDropDown: TOnEvent read fOnDropDown write fOnDropDown;
5196 {* |<#combo>
5197 |<#toolbar>
5198 Is called when combobox is dropped down (or drop-down button of
5199 toolbar is pressed - see also OnTBDropDown). }
5200 property OnCloseUp: TOnEvent read fOnCloseUp write fOnCloseUp;
5201 {* |<#combo>
5202 Is called when combobox is closed up. When drop down list is closed
5203 because user pressed "Escape" key, previous selection is restored.
5204 To test if it is so, call GetKeyState( VK_ESCAPE ) and check, if
5205 negative value is returned (i.e. Escape key is pressed when event
5206 handler is calling). }
5207 property DroppedWidth: Integer read FDroppedWidth write SetDroppedWidth;
5208 {* |<#combo>
5209 Allows to change width of dropped down items list for combobox (only!)
5210 control. }
5211 property DroppedDown: Boolean read fDropped write SetDroppedDown;
5212 {* |<#combo>
5213 Dropped down state for combo box. Set it to TRUE or FALSE to change
5214 dropped down state. }
5215 procedure AddDirList( const Filemask: String; Attrs: DWORD );
5216 {* |<#listbox>
5217 |<#combo>
5218 Can be used only with listbox and combobox - to add directory list items,
5219 filtered by given Filemask (can contain wildcards) and Attrs. Following
5220 flags can be combined in Attrs:
5221 |<table border=0>
5222 |&L=<tr><td>%1</td><td>
5223 <L DDL_ARCHIVE> Include archived files. <E>
5224 <L DDL_DIRECTORY> Includes subdirectories. Subdirectory names are
5225 enclosed in square brackets ([ ]). <E>
5226 <L DDL_DRIVES> Includes drives. Drives are listed in the form [-x-],
5227 where x is the drive letter. <E>
5228 <L DDL_EXCLUSIVE> Includes only files with the specified attributes.
5229 By default, read-write files are listed even if DDL_READWRITE is
5230 not specified. Also, this flag needed to list directories only,
5231 etc. <E>
5232 <L DDL_HIDDEN> Includes hidden files. <E>
5233 <L DDL_READONLY> Includes read-only files. <E>
5234 <L DDL_READWRITE> Includes read-write files with no additional
5235 attributes. <E>
5236 <L DDL_SYSTEM> Includes system files. <E>
5237 </table>
5238 If the listbox is sorted, directory items will be sorted (alpabetically). }
5239 property OnBitBtnDraw: TOnBitBtnDraw read fOnBitBtnDraw write fOnBitBtnDraw;
5240 {* |<#bitbtn>
5241 Special event for BitBtn. Using it, it is possible to provide
5242 additional effects, such as highlighting button text (by changing
5243 its Font and other properties). If the handler returns True, it is
5244 supposed that it made all drawing and there are no further drawing
5245 occure. }
5246 property BitBtnDrawMnemonic: Boolean read FBitBtnDrawMnemonic write SetBitBtnDrawMnemonic;
5247 {* |<#bitbtn>
5248 Set this property to TRUE to provide correct drawing of bit btn control
5249 caption with '&' characters (to remove such characters, and underline
5250 follow ones). }
5251 property TextShiftX: Integer read fTextShiftX write fTextShiftX;
5252 {* |<#bitbtn>
5253 Horizontal shift for bitbtn text when the bitbtn is pressed. }
5254 property TextShiftY: Integer read fTextShiftY write fTextShiftY;
5255 {* |<#bitbtn>
5256 Vertical shift for bitbtn text when the bitbtn is pressed. }
5257 property BitBtnImgIdx: Integer read GetBitBtnImgIdx write SetBitBtnImgIdx;
5258 {* |<#bitbtn>
5259 BitBtn image index for the first image in list view, used as bitbtn
5260 image. It is used only in case when BitBtn is created with bboImageList
5261 option. }
5262 property BitBtnImgList: THandle read GetBitBtnImageList write SetBitBtnImageList;
5263 {* |<#bitbtn>
5264 BitBtn Image list. Assign image list handle to change it. }
5266 function SetButtonIcon( aIcon: HIcon ): PControl;
5267 {* |<#button>
5268 Sets up button icon image and changes its styles. Returns button itself. }
5269 function SetButtonBitmap( aBmp: HBitmap ): PControl;
5270 {* |<#button>
5271 Sets up button icon image and changes its styles. Returns button itself. }
5273 property OnMeasureItem: TOnMeasureItem read fOnMeasureItem write SetOnMeasureItem;
5274 {* |<#combo>
5275 |<#listbox>
5276 |<#listview>
5277 This event is called for owner-drawn controls, such as list box, combo box,
5278 list view with appropriate owner-drawn style. For fixed item height controls
5279 (list box with loOwnerDrawFixed style, combobox with coOwnerDrawFixed and
5280 list view with lvoOwnerDrawFixed option) this event is called once. For
5281 list box with loOwnerDrawVariable style and for combobox with coOwnerDrawVariable
5282 style this event is called for every item. }
5284 property DefaultBtn: Boolean index 13
5285 {$IFDEF F_P} read GetDefaultBtn
5286 {$ELSE DELPHI} read fDefaultBtn
5287 {$ENDIF F_P/DELPHI} write SetDefaultBtn;
5288 {* |<#button>
5289 |<#bitbtn>
5290 Set this property to true to make control clicked when ENTER key is pressed.
5291 This property uses OnMessage event of the parent form, storing it into
5292 fOldOnMessage field and calling in chain. So, assign default button
5293 after setting OnMessage event for the form. }
5294 property CancelBtn: Boolean index 27
5295 {$IFDEF F_P} read GetDefaultBtn
5296 {$ELSE DELPHI} read fCancelBtn
5297 {$ENDIF F_P/DELPHI} write SetDefaultBtn;
5298 {* |<#button>
5299 |<#bitbtn>
5300 Set this property to true to make control clicked when escape key is pressed.
5301 This property uses OnMessage event of the parent form, storing it into
5302 fOldOnMessage field and calling in chain. So, assign cancel button
5303 after setting OnMessage event for the form. }
5304 function AllBtnReturnClick: PControl;
5305 {* Call this method for a form or any its control to provide clicking
5306 a focused button when ENTER pressed. By default, a button can be clicked
5307 only by SPACE key from the keyboard, or by mouse. }
5308 property IgnoreDefault: Boolean read fIgnoreDefault write fIgnoreDefault;
5309 {* Change this property to TRUE to ignore default button reaction on
5310 press ENTER key when a focus is grabbed of the control. Default
5311 value is different for different controls. By default, DefaultBtn
5312 ignored in memo, richedit (even if read-only). }
5315 property Color: TColor read fColor write SetCtlColor;
5316 {* Property Color is one of the most common for all visual
5317 elements (like form, control etc.) Please note, that standard GUI button
5318 can not change its color and the most characteristics of the Font. Also,
5319 standard button can not become Transparent. Use bitbtn for such purposes.
5320 Also, changing Color property for some kinds of control has no effect (rich edit,
5321 list view, tree view, etc.). To solve this, use native (for such controls)
5322 color property, or call Perform method with appropriate message to set the
5323 background color. }
5324 property Font: PGraphicTool read GetFont;
5325 {* If the Font property is not accessed, correspondent TGraphicTool object
5326 is not created and its methods are not included into executable. Leaving
5327 properties Font and Brush untouched can economy executable size a lot. }
5328 property Brush: PGraphicTool read GetBrush;
5329 {* If not accessed, correspondent TGraphicTool object is not created
5330 and its methods are not referenced. See also note on Font property. }
5332 property Ctl3D: Boolean read fCtl3D write SetCtl3D;
5333 {* Inheritable from parent controls to child ones. }
5335 procedure Show;
5336 {* |<#appbutton>
5337 |<#form>
5338 Makes control visible and activates it. }
5339 function ShowModal: Integer;
5340 {* |<#form>
5341 Can be used only with a forms to show it modal. See also global function
5342 ShowMsgModal.
5343 |<br>
5344 To use a form as a modal, it is possible to make it either auto-created
5345 or dynamically created. For a first case, You (may be prefer to hide a
5346 form after showing it as a modal:
5348 ! procedure TForm1.Button1Click( Sender: PObj );
5349 ! begin
5350 ! Form2.Form.ShowModal;
5351 ! Form2.Form.Hide;
5352 ! end;
5354 Another way is to create modal form just before showing it (this economies
5355 system resources):
5357 ! procedure TForm1.Button1Click( Sender: PObj );
5358 ! begin
5359 ! NewForm2( Form2, Applet );
5360 ! Form2.Form.ShowModal;
5361 ! Form2.Form.Free; // Never call Form2.Free or Form2.Form.Close
5362 ! end; // but always Form2.Form.Free; (!)
5364 In samples above, You certainly can place any wished code before and after
5365 calling ShowModal method.
5366 |<br>
5367 Do not forget that if You have more than a single form in your project,
5368 separate Applet object should be used.
5369 |<br>
5370 See also ShowModalEx.
5372 function ShowModalParented( const AParent: PControl ): Integer;
5373 {* by Alexander Pravdin. The same as ShowModal, but with a certain
5374 form as a parent. }
5375 function ShowModalEx: Integer;
5376 {* The same as ShowModal, but all the windows of current thread are
5377 disabled while showing form modal. This is useful if KOL form from
5378 a DLL is used modally in non-KOL application. }
5379 property ModalResult: Integer read fModalResult write
5380 {$IFDEF USE_SETMODALRESULT}
5381 SetModalResult;
5382 {$ELSE}
5383 fModalResult;
5384 {$ENDIF}
5385 {* |<#form>
5386 Modal result. Set it to value<>0 to stop modal dialog. By agreement,
5387 value 1 corresponds 'OK', 2 - 'Cancel'. But it is totally by decision
5388 of yours how to interpret this value. }
5389 property Modal: Boolean read GetModal;
5390 {* |<#form>
5391 TRUE, if the form is shown modal. }
5392 property ModalForm: PControl read fModalForm write fModalForm;
5393 {* |<#form>
5394 |<#appbutton>
5395 Form currently shown modal from this form or from Applet. }
5397 procedure Hide;
5398 {* |<#appbutton>
5399 |<#form>
5400 Makes control hidden. }
5401 property OnShow: TOnEvent read FOnShow write SetOnShow;
5402 {* Is called when a control or form is to be shown. This event is not fired
5403 for a form, if its WindowState initially is set to wsMaximized or
5404 wsMinimized. This behaviour is by design (the window does not receive
5405 WM_SHOW message in such case). }
5406 property OnHide: TOnEvent read FOnHide write SetOnHide;
5407 {* Is called when a control or form becomes hidden. }
5408 property WindowState: TWindowState read GetWindowState write SetWindowState;
5409 {* |<#form>
5410 Window state. }
5412 property Canvas: PCanvas read GetCanvas;
5413 {* |<#paintbox>
5414 Placeholder for Canvas: PCanvas. But in KOL, it is possible to
5415 create applets without canvases at all. To do so, avoid using
5416 Canvas and use DC directly (which is passed in OnPaint event). }
5417 function CallDefWndProc( var Msg: TMsg ): Integer;
5418 {* Function to be called in WndProc method to redirect message handling
5419 to default window procedure. }
5420 function DoSetFocus: Boolean;
5421 {* Sets focus for Enabled window. Returns True, if success. }
5423 procedure MinimizeNormalAnimated;
5424 {* |<#form>
5425 Apply this method to a main form (not to another form or Applet,
5426 even when separate Applet control is not used and main form matches it!).
5427 This provides normal animated visual minimization for the application.
5428 It therefore has no effect, if animation during minimize/resore is
5429 turned off by user. }
5431 property OnMessage: TOnMessage read fOnMessage write fOnMessage;
5432 {* |<#appbutton>
5433 |<#form>
5434 Is called for every message processed by TControl object. And for
5435 Applet window, this event is called also for all messages, handled by
5436 all its child windows (forms). }
5438 function IsMainWindow: Boolean;
5439 {* |<#appbutton>
5440 |<#form>
5441 Returns True, if a window is the main in application (created first
5442 after the Applet, or matches the Applet). }
5443 property IsApplet: Boolean read FIsApplet;
5444 {* Returns true, if the control is created using NewApplet (or CreateApplet).
5446 property IsForm: Boolean read fIsForm;
5447 {* Returns True, if the object is form window. }
5448 property IsMDIChild: Boolean read fIsMDIChild;
5449 {* Returns TRUE, if the object is MDI child form. In such case, IsForm also
5450 returns TRUE. }
5451 property IsControl: Boolean read fIsControl;
5452 {* Returns True, is the control is control (not form or applet). }
5453 property IsButton: Boolean read fIsButton;
5454 {* Returns True, if the control is button-like or containing buttons (button,
5455 bitbtn, checkbox, radiobox, toolbar). }
5457 function ProcessMessage: Boolean;
5458 {* |<#appbutton>
5459 Processes one message. See also ProcessMessages. }
5461 procedure ProcessMessages;
5462 {* |<#appbutton>
5463 Processes pending messages during long cycle of calculation,
5464 allowing to window to be repainted if needed and to respond to other
5465 messages. But if there are no such messages, your application can be
5466 stopped until such one appear in messages queue. To prevent such
5467 situation, use method ProcessPendingMessages instead. }
5469 procedure ProcessMessagesEx;
5470 {* Version of ProcessMessages, which works always correctly, even if
5471 the application is minimized or background. }
5473 procedure ProcessPendingMessages;
5474 {* |<#appbutton>
5475 Similar to ProcessMessages, but without waiting of
5476 message in messages queue. I.e., if there are no pending
5477 messages, this method immediately returns control to your
5478 code. This method is better to call during long cycle of
5479 calculation (then ProcessMessages). }
5480 procedure ProcessPaintMessages;
5481 {* }
5482 function WndProc( var Msg: TMsg ): Integer; virtual;
5483 {* Responds to all Windows messages, posted (sended) to the
5484 window, before all other proceeding. You can override it in
5485 derived controls, but in KOL there are several other ways
5486 to control message flow of existing controls without deriving
5487 another costom controls for only such purposes. See OnMessage,
5488 AttachProc. }
5489 property HasBorder: Boolean read GetHasBorder write SetHasBorder;
5490 {* |<#form>
5491 Obvious. Form-aware. }
5493 property HasCaption: Boolean read GetHasCaption write SetHasCaption;
5494 {* |<#form>
5495 Obvious. Form-aware. }
5496 property CanResize: Boolean read GetCanResize write SetCanResize;
5497 {* |<#form>
5498 Obvious. Form-aware. }
5499 property StayOnTop: Boolean read GetStayOnTop write SetStayOnTop;
5500 {* |<#form>
5501 Obvious. Form-aware, but can be applied to controls. }
5502 property Border: Integer read fMargin write fMargin;
5503 {* |<#form>
5504 Distance between edges and child controls and between child
5505 controls by default (if methods PlaceRight, PlaceDown, PlaceUnder,
5506 ResizeParent, ResizeParentRight, ResizeParentBottom are called).
5507 |<br>
5508 Originally was named Margin, now I recommend to use the name 'Border' to
5509 avoid confusion with MarginTop, MarginBottom, MarginLeft and
5510 MarginRight properties.
5511 |<br>
5512 Initial value is always 2. Border property is used in realigning
5513 child controls (when its Align property is not caNone), and value
5514 of this property determines size of borders between edges of children
5515 and its parent and between aligned controls too.
5516 |<br>
5517 See also properties MarginLeft, MarginRight, MarginTop, MarginBottom. }
5518 function SetBorder( Value: Integer ): PControl;
5519 {* Assigns new Border value, and returns @ Self. }
5521 property Margin: Integer read fMargin write fMargin;
5522 {* |<#form>
5523 Old name for property Border. }
5525 property MarginTop: Integer index 1
5526 {$IFDEF F_P} read GetClientMargin
5527 {$ELSE DELPHI} read fClientTop
5528 {$ENDIF F_P/DELPHI} write SetClientMargin;
5529 {* Additional distance between true window client top and logical top of
5530 client rectangle. This value is added to Top of rectangle, returning
5531 by property ClientRect. Together with other margins and property Border,
5532 this property allows to change view of form for case, that Align property
5533 is used to align controls on parent (it is possible to provide some
5534 distance from child controls to its parent, and between child controls.
5535 |<br>
5536 Originally this property was introduced to compensate incorrect
5537 ClientRect property, calculated for some types of controls.
5538 |<br>
5539 See also properties Border, MarginBottom, MarginLeft, MarginRight. }
5540 property MarginBottom: Integer index 2
5541 {$IFDEF F_P} read GetClientMargin
5542 {$ELSE DELPHI} read fClientBottom
5543 {$ENDIF F_P/DELPHI} write SetClientMargin;
5544 {* The same as MarginTop, but a distance between true window Bottom of
5545 client rectangle and logical bottom one. Take in attention, that this value
5546 should be POSITIVE to make logical bottom edge located above true edge.
5547 |<br>
5548 See also properties Border, MarginTop, MarginLeft, MarginRight. }
5549 property MarginLeft: Integer index 3
5550 {$IFDEF F_P} read GetClientMargin
5551 {$ELSE DELPHI} read fClientLeft
5552 {$ENDIF F_P/DELPHI} write SetClientMargin;
5553 {* The same as MarginTop, but a distance between true window Left of
5554 client rectangle and logical left edge.
5555 |<br>
5556 See also properties Border, MarginTop, MarginRight, MarginBottom. }
5557 property MarginRight: Integer index 4
5558 {$IFDEF F_P} read GetClientMargin
5559 {$ELSE DELPHI} read fClientRight
5560 {$ENDIF F_P/DELPHI} write SetClientMargin;
5561 {* The same as MarginLeft, but a distance between true window Right of
5562 client rectangle and logical bottom one. Take in attention, that this value
5563 should be POSITIVE to make logical right edge located left of true edge.
5564 |<br>
5565 See also properties Border, MarginTop, MarginLeft, MarginBottom. }
5567 property Tabstop: Boolean read fTabstop write fTabstop;
5568 {* True, if control can be focused using tabulating between controls.
5569 Set it to False to make control unavailable for keyboard, but only
5570 for mouse. }
5572 property TabOrder: Integer read fTabOrder write SetTabOrder;
5573 {* Order of tabulating of controls. Initially, TabOrder is equal to
5574 creation order of controls. If TabOrder changed, TabOrder of
5575 all controls with not less value of one is shifted up. To place
5576 control before another, assign TabOrder of one to another.
5577 For example:
5578 ! Button1.TabOrder := EditBox1.TabOrder;
5579 In code above, Button1 is placed just before EditBox1 in tabulating
5580 order (value of TabOrder of EditBox1 is incremented, as well as
5581 for all follow controls). }
5583 property Focused: Boolean read GetFocused write SetFocused;
5584 {* True, if the control is current on form (but check also, what form
5585 itself is focused). For form it is True, if the form is active (i.e.
5586 it is foreground and capture keyboard). Set this value to True to make
5587 control current and focused (if applicable). }
5589 function BringToFront: PControl;
5590 {* Changes z-order of the control, bringing it to the topmost level. }
5591 function SendToBack: PControl;
5592 {* Changes z-order of the control, sending it to the back of siblings. }
5593 property TextAlign: TTextAlign read GetTextAlign write SetTextAlign;
5594 {* |<#label>
5595 |<#panel>
5596 |<#button>
5597 |<#bitbtn>
5598 |<#edit>
5599 |<#memo>
5600 Text horizontal alignment. Applicable to labels, buttons,
5601 multi-line edit boxes, panels. }
5602 property VerticalAlign: TVerticalAlign read GetVerticalAlign write SetVerticalAlign;
5603 {* |<#button>
5604 |<#label>
5605 |<#panel>
5606 Text vertical alignment. Applicable to buttons, labels and panels. }
5607 property WordWrap: Boolean read fWordWrap;
5608 {* TRUE, if this is a label, created using NewWordWrapLabel. }
5609 property ShadowDeep: Integer read FShadowDeep write SetShadowDeep;
5610 {* |<#3dlabel>
5611 Deep of a shadow (for label effect only, created calling NewLabelEffect). }
5613 property CannotDoubleBuf: Boolean read fCannotDoubleBuf write fCannotDoubleBuf;
5614 {* }
5615 property DoubleBuffered: Boolean read fDoubleBuffered write SetDoubleBuffered;
5616 {* Set it to true for some controls, which are flickering in repainting
5617 (like label effect). Slow, and requires additional code. This property
5618 is inherited by all child controls.
5619 |<br>&nbsp;&nbsp;&nbsp;
5620 Note: RichEdit control can not become DoubleBuffered. }
5621 //function IsSelfOrParentDblBuf: Boolean;
5622 {* Returns true, if DoubleBuffered or one of parents is DoubleBuffered. }
5623 function DblBufTopParent: PControl;
5624 {* Returns the topmost DoubleBuffered Parent control. }
5625 property Transparent: Boolean read fTransparent write SetTransparent;
5626 {* Set it to true to get special effects. Transparency also uses
5627 DoubleBuffered and inherited by child controls.
5628 |<br>&nbsp;&nbsp;&nbsp;
5629 Please note, that some controls can not be shown properly, when
5630 Transparent is set to True for it. If You want to make edit control
5631 transparent (e.g., over gradient filled panel), handle its OnChanged
5632 property and call there Invalidate to provide repainting of edit
5633 control content. Note also, that for RichEdit control property
5634 Transparent has no effect (as well as DoubleBuffered). But special
5635 property RE_Transparent is designed especially for RichEdit control
5636 (it works fine, but with great number of flicks while resizing
5637 of a control). Another note is about Edit control. To allow editing
5638 of transparent edit box, it is necessary to invalidate it for
5639 every pressed character. Or, use Ed_Transparent property instead. }
5641 property Ed_Transparent: Boolean read fTransparent write EdSetTransparent;
5642 {* |<#edit>
5643 |<#memo>
5644 Use this property for editbox to make it really Transparent. Remember,
5645 that though Transparent property is inherited by child controls from
5646 its parent, this is not so for Ed_Transparent. So, it is necessary to
5647 set Ed_Transparent to True for every edit control explicitly. }
5648 property AlphaBlend: Integer read fAlphaBlend write SetAlphaBlend;
5649 {* |<#form>
5650 If assigned to 0..254, makes window (form or control) semi-transparent
5651 (Win2K only).
5652 |<br>
5653 Depending on value assigned, it is possible to adjust transparency
5654 level ( 0 - totally transparent, 255 - totally opaque). }
5656 property LookTabKeys: TTabKeys read fLookTabKeys write fLookTabKeys;
5657 {* Set of keys which can be used as tabulation keys in a control. }
5658 procedure GotoControl( Key: DWORD );
5659 {* |<#form>
5660 Emulates tabulation key press w/o sending message to current control.
5661 Can be applied to a form or to any its control. If VK_TAB is used,
5662 state of shift kay is checked in: if it is pressed, tabulate is in
5663 backward direction. }
5664 property SubClassName: String read get_ClassName write set_ClassName;
5665 {* Name of window class - unique for every window class
5666 in every run session of a program. }
5668 property OnClose: TOnEventAccept read fOnClose write fOnClose;
5669 {* |<#form>
5670 |<#applet>
5671 Called before closing the window. It is possible to set Accept
5672 parameter to False to prevent closing the window. This event events
5673 is not called when windows session is finishing (to handle this
5674 event, handle WM_QUERYENDSESSION message, or assign OnQueryEndSession
5675 event to another or the same event handler). }
5677 property OnQueryEndSession: TOnEventAccept read fOnQueryEndSession write SetOnQueryEndSession;
5678 {* |<#form>
5679 |<#applet>
5680 Called when WM_QUERYENDSESSION message come in. It is possible to set Accept
5681 parameter to False to prevent closing the window (in such case session ending
5682 is halted). It is possible to check CloseQueryReason property to find out,
5683 why event occur. }
5684 property CloseQueryReason: TCloseQueryReason read fCloseQueryReason;
5685 {* Reason why OnClose or OnQueryEndSession called. }
5686 property OnMinimize: TOnEvent index 0
5687 {$IFDEF F_P} read GetOnMinMaxRestore
5688 {$ELSE DELPHI} read fOnMinimize
5689 {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;
5690 {* |<#form>
5691 Called when window is minimized. }
5692 property OnMaximize: TOnEvent index 8
5693 {$IFDEF F_P} read GetOnMinMaxRestore
5694 {$ELSE DELPHI} read fOnMaximize
5695 {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;
5696 {* |<#form>
5697 Called when window is maximized. }
5698 property OnRestore: TOnEvent index 16
5699 {$IFDEF F_P} read GetOnMinMaxRestore
5700 {$ELSE DELPHI} read fOnRestore
5701 {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;
5702 {* |<#form>
5703 Called when window is restored from minimized or maximized state. }
5705 property UpdateRgn: HRgn read fUpdRgn;
5706 {* A handle of update region. Valid only in OnPaint method. You
5707 can use it to improve painting (for speed), if necessary. When
5708 UpdateRgn is obtained in response to WM_PAINT message, value
5709 of the property EraseBackground is used to pass it to the API
5710 function GetUpdateRgn. If UpdateRgn = 0, this means that entire
5711 window should be repainted. Otherwise, You (e.g.) can check
5712 if the rectangle is in clipping region using API function
5713 RectInRegion. }
5715 property EraseBackground: Boolean read fEraseUpdRgn write fEraseUpdRgn;
5716 {* This value is used to pass it to the API function GetUpdateRgn,
5717 when UpadateRgn property is obtained first in responce to WM_PAINT
5718 message. If EraseBackground is set to True, system is responsible
5719 for erasing background of update region before painting. If not
5720 (default), the entire region invalidated should be painted by your
5721 event handler. }
5723 property OnPaint: TOnPaint read fOnPaint write SetOnPaint;
5724 {* Event to set to override standard control painting. Can be applied
5725 to any control (though originally was designed only for paintbox
5726 control). When an event handler is called, it is possible to use
5727 UpdateRgn to examine what parts of window require painting to
5728 improve performance of the painting operation. }
5731 property OnEraseBkgnd: TOnPaint read fOnEraseBkgnd write SetOnEraseBkgnd;
5732 {* This event allows to override erasing window background in response
5733 to WM_ERASEBKGND message. This allows to add some decorations to
5734 standard controls without overriding its painting in total.
5735 Note: When erase background, remember, that property ClientRect can
5736 return not true client rectangle of the window - use GetClientRect
5737 API function instead. For example:
5739 !var BkBmp: HBitmap;
5741 !procedure TForm1.KOLForm1FormCreate(Sender: PObj);
5742 !begin
5743 ! Toolbar1.OnEraseBkgnd := DecorateToolbar;
5744 ! BkBmp := LoadBitmap( hInstance, 'BK1' );
5745 !end;
5747 !procedure TForm1.DecorateToolbar(Sender: PControl; DC: HDC);
5748 !var CR: TRect;
5749 !begin
5750 ! GetClientRect( Sender.Handle, CR );
5751 ! Sender.Canvas.Brush.BrushBitmap := BkBmp;
5752 ! Sender.Canvas.FillRect( CR );
5753 !end;
5758 property OnClick: TOnEvent read fOnClick write fOnClick;
5759 {* |<#button>
5760 |<#checkbox>
5761 |<#radiobox>
5762 |<#toolbar>
5763 Called on click at control. For buttons, checkboxes and radioboxes
5764 is called regadless if control clicked by mouse or keyboard. For toolbar,
5765 the same event is used for all toolbar buttons and toolbar itself.
5766 To determine which toolbar button is clicked, check CurIndex property.
5767 And note, that all the buttons including separator buttons are enumerated
5768 starting from 0. Though images are stored (and prepared) only for
5769 non-separator buttons. And to determine, if toolbar button was clicked
5770 with right mouse button, check RightClick property. }
5771 property RightClick: Boolean read fRightClick;
5772 {* |<#toolbar>
5773 |<#listview>
5774 Use this property to determine which mouse button was clicked
5775 (applicable to toolbar in the OnClick event handler). }
5776 property OnEnter: TOnEvent read fOnEnter write fOnEnter;
5777 {* Called when control receives focus. }
5778 property OnLeave: TOnEvent read fOnLeave write fOnLeave;
5779 {* Called when control looses focus. }
5780 property OnChange: TOnEvent read fOnChange write fOnChange;
5781 {* |<#edit>
5782 |<#memo>
5783 |<#listbox>
5784 |<#combo>
5785 |<#tabcontrol>
5786 Called when edit control is changed, or selection in listbox or
5787 current index in combobox is changed (but if OnSelChanged assigned,
5788 the last is called for change selection). To respond to check/uncheck
5789 checkbox or radiobox events, use OnClick instead. }
5790 property OnSelChange: TOnEvent read fOnSelChange write fOnSelChange;
5791 {* |<#richedit>
5792 |<#listbox>
5793 |<#combo>
5794 |<#treeview>
5795 Called for rich edit control, listbox, combobox or treeview when current selection
5796 (range, or current item) is changed. If not assigned, but OnChange is
5797 assigned, OnChange is called instead. }
5798 property OnResize: TOnEvent read FOnResize write SetOnResize;
5799 {* Called whenever control receives message WM_SIZE (thus is, if
5800 control is resized. }
5801 property OnMove: TOnEvent read FOnMove write SetOnMove;
5802 {* Called whenever control receives message WM_MOVE (i.e. when control is
5803 moved over its parent). }
5805 property MinSizePrev: Integer read fSplitMinSize1 write fSplitMinSize1;
5806 {* |<#splitter>
5807 Minimal allowed (while dragging splitter) size of previous control
5808 for splitter (see NewSplitter). }
5809 property SplitMinSize1: Integer read fSplitMinSize1 write fSplitMinSize1;
5810 {* The same as MinSizePrev. }
5811 property MinSizeNext: Integer read fSplitMinSize2 write fSplitMinSize2;
5812 {* |<#splitter>
5813 Minimal allowed (while dragging splitter) size of the rest of parent
5814 of splitter or of SecondControl (see NewSplitter). }
5815 property SplitMinSize2: Integer read fSplitMinSize2 write fSplitMinSize2;
5816 {* The same as MinSizeNext. }
5817 property SecondControl: PControl read fSecondControl write fSecondControl;
5818 {* |<#splitter>
5819 Second control to check (while dragging splitter) if its size not less
5820 than SplitMinSize2 (see NewSplitter). By default, second control is
5821 not necessary, and needed only in rare case when SecondControl can not
5822 be determined automatically to restrict splitter right (bottom) position. }
5823 property OnSplit: TOnSplit read fOnSplit write fOnSplit;
5824 {* |<#splitter>
5825 Called when splitter control is dragging - to allow for
5826 your event handler to decide if to accept new size of
5827 left (top) control, and new size of the rest area of parent. }
5828 property Dragging: Boolean read FDragging;
5829 {* |<#splitter>
5830 True, if splitter control is dragging now by user with left
5831 mouse button. Also, this property can be used to detect if the control
5832 is dragging with mouse (after calling DragStartEx method). }
5833 procedure DragStart;
5834 {* Call this method for a form or control to drag it with left mouse button,
5835 when mouse left button is already down. Dragging is stopped when left mouse
5836 button is released. See also DragStartEx, DragStopEx. }
5837 procedure DragStartEx;
5838 {* Call this method to start dragging the form by mouse. To stop
5839 dragging, call DragStopEx method. (Tip: to detect mouse up event,
5840 use OnMouseUp event of the dragging control). This method can be used
5841 to move any control with the mouse, not only entire form. State of
5842 mouse button is not significant. Determine dragging state of the control
5843 checking its Dragging property. }
5844 procedure DragStopEx;
5845 {* Call this method to stop dragging the form (started by DragStopEx). }
5846 procedure DragItem( OnDrag: TOnDrag );
5847 {* Starts dragging something with mouse. During the process,
5848 callback function OnDrag is called, which allows to control
5849 drop target, change cursor shape, etc. }
5851 property OnKeyDown: TOnKey read fOnKeyDown write SetOnKeyDown;
5852 {* Obvious. }
5853 property OnKeyUp: TOnKey read fOnKeyUp write SetOnKeyUp;
5854 {* Obvious. }
5855 property OnChar: TOnChar read fOnChar write SetOnChar;
5856 {* Obvious. }
5858 property OnMouseDown: TOnMouse read fOnMouseDown write SetMouseDown;
5859 {* Obvious. }
5860 property OnMouseUp: TOnMouse read fOnMouseUp write SetMouseUp;
5861 {* Obvious. }
5862 property OnMouseMove: TOnMouse read fOnMouseMove write SetMouseMove;
5863 {* Obvious. }
5864 property OnMouseDblClk: TOnMouse read fOnMouseDblClk write SetMouseDblClk;
5865 {* Obvious. }
5866 property OnMouseWheel: TOnMouse read fOnMouseWheel write SetMouseWheel;
5867 {* Obvious. }
5869 property OnMouseEnter: TOnEvent read fOnMouseEnter write SetOnMouseEnter;
5870 {* Is called when mouse is entered into control. See also OnMouseLeave. }
5871 property OnMouseLeave: TOnEvent read fOnMouseLeave write SetOnMouseLeave;
5872 {* Is called when mouse is leaved control. If this event is assigned,
5873 then mouse is captured on mouse enter event to handle all other
5874 mouse events until mouse cursor leaves the control. }
5875 property OnTestMouseOver: TOnTestMouseOver read fOnTestMouseOver write SetOnTestMouseOver;
5876 {* |<#bitbtn>
5877 Special event, which allows to extend OnMouseEnter / OnMouseLeave
5878 (and also Flat property for BitBtn control). If a handler is assigned
5879 to this event, actual testing whether mouse is in control or not,
5880 is occuring in the handler. So, it is possible to simulate more
5881 careful hot tracking for controls with non-rectangular shape (such
5882 as glyphed BitBtn control). }
5884 property MouseInControl: Boolean read fMouseInControl;
5885 {* |<#bitbtn>
5886 This property can return True only if OnMouseEnter / OnMouseLeave
5887 event handlers are set for a control (or, for BitBtn, property Flat
5888 is set to True. Otherwise, False is returned always. }
5890 property Flat: Boolean read fFlat write SetFlat;
5891 {* |<#bitbtn>
5892 Set it to True for BitBtn, to provide either flat border for a button
5893 or availability of "highlighting" (correspondent to glyph index 4).
5894 |<br>
5895 Note: this can work incorrectly a bit under win95 without comctl32.dll
5896 updated. Therefore, application will launch. To enforce correct working
5897 even under Win95, use your own timer, which event handler checks for
5898 mouse over bitbtn control, e.g.:
5899 ! procedure TForm1.Timer1Timer(Sender: PObj);
5900 ! var P: TPoint;
5901 ! begin
5902 ! if not BitBtn1.MouseInControl then Exit;
5903 ! GetCursorPos( P );
5904 ! P := BitBtn1.Screen2Client( P );
5905 ! if not PtInRect( BitBtn1.ClientRect, P ) then
5906 ! begin
5907 ! BitBtn1.Flat := FALSE;
5908 ! BitBtn1.Flat := TRUE;
5909 ! end;
5910 ! end;
5912 property RepeatInterval: Integer read fRepeatInterval write fRepeatInterval;
5913 {* |<#bitbtn>
5914 If this property is set to non-zero, it is interpreted (for BitBtn
5915 only) as an interval in milliseconds between repeat button down events,
5916 which are generated after first mouse or button click and until
5917 button is released. Though, if the button is pressed with keyboard (with
5918 space key), RepeatInterval value is ignored and frequency of repeatitive
5919 clicking is determined by user keyboard settings only. }
5920 function LikeSpeedButton: PControl;
5921 {* |<#button>
5922 |<#bitbtn>
5923 Transparent method (returns control itself). Makes button not focusable. }
5925 function Add( const S: String ): Integer;
5926 {* |<#listbox>
5927 |<#combo>
5928 Only for listbox and combobox. }
5930 function Insert( Idx: Integer; const S: String ): Integer;
5931 {* |<#listbox>
5932 |<#combo>
5933 Only for listbox and combobox. }
5934 procedure Delete( Idx: Integer );
5935 {* |<#listbox>
5936 |<#combo>
5937 Only for listbox and combobox. }
5938 procedure Clear;
5939 {* Clears object content. Has different sense for different controls.
5940 E.g., for label, editbox, button and other simple controls it
5941 assigns empty string to Caption property. For listbox, combobox,
5942 listview it deletes all items. For toolbar, it deletes all buttons.
5943 Et so on. }
5945 property Progress: Integer index ((PBM_SETPOS or $8000) shl 16) or PBM_GETPOS
5946 read GetIntVal write SetIntVal;
5947 {* |<#progressbar>
5948 Only for ProgressBar. }
5949 property MaxProgress: Integer index ((PBM_SETRANGE32 or $8000) shl 16) or PBM_GETRANGE
5950 read GetIntVal write SetMaxProgress;
5951 {* |<#progressbar>
5952 Only for ProgressBar. 100 is the default value. }
5953 property ProgressColor: TColor read fTextColor write SetProgressColor;
5954 {* |<#progressbar>
5955 Only for ProgressBar. }
5956 property ProgressBkColor: TColor read fColor write SetCtlColor; //SetProgressBkColor;
5957 {* |<#progressbar>
5958 Obsolete. Now the same as Color. }
5960 property StatusText[ Idx: Integer ]: PChar read GetStatusText write SetStatusText;
5961 {* |<#form>
5962 Only for forms to set/retrieve status text to/from given status panel.
5963 Panels are enumerated from 0 to 254, 255 is to indicate simple
5964 status bar. Size grip in right bottom corner of status window is
5965 displayed only if form still CanResize.
5966 |<br>
5967 When a status text is set first time, status bar window is created
5968 (always aligned to bottom), and form is resizing to preset client height.
5969 While status bar is showing, client height value is returned without
5970 height of status bar. To remove status bar, call RemoveStatus method for
5971 a form.
5972 |<br>
5973 By default, text is left-aligned within the specified part of a status
5974 window. You can embed tab characters (#9) in the text to center or
5975 right-align it. Text to the right of a single tab character is centered,
5976 and text to the right of a second tab character is right-aligned.
5977 |<br>
5978 If You use separate status bar onto several panels, these automatically
5979 align its widths to the same value (width divided to number of panels).
5980 To adjust status panel widths for every panel, use property StatusPanelRightX.
5982 property SimpleStatusText: PChar index 255 read GetStatusText write SetStatusText;
5983 {* |<#form>
5984 Only for forms to set/retrive status text to/from simple status bar.
5985 Size grip in right bottom corner of status window is displayed only
5986 if form CanResize.
5987 |<br>
5988 When status text set first time, (simple) status bar window is created
5989 (always aligned to bottom), and form is resizing to preset client height.
5990 While status bar is showing, client height value is returned without
5991 height of status bar. To remove status bar, call RemoveStatus method for
5992 a form.
5993 |<br>
5994 By default, text is left-aligned within the specified part of a status
5995 window. You can embed tab characters (#9) in the text to center or
5996 right-align it. Text to the right of a single tab character is centered,
5997 and text to the right of a second tab character is right-aligned.
5999 property StatusCtl: PControl read fStatusCtl;
6000 {* Pointer to Status bar control. To "create" child controls on
6001 the status bar, first create it as a child of form, for instance, and
6002 then change its property Parent, e.g.:
6003 ! var Progress1: PControl;
6004 ! ...
6005 ! Progress1 := NewProgressBar( Form1 );
6006 ! Progress1.Parent := Form1.StatusCtl;
6007 (If you use MCK, code should be another a bit, and in this case it is
6008 possible to create and adjust the control at design-time, and at run-time
6009 change its parent control. E.g. (Progress1 is created at run-time here too):
6010 ! Progress1 := NewProgressBar( Form );
6011 ! Progress1.Parent := Form.StatusCtl;
6013 Do not forget to provide StatusCtl to be existing first (e.g. assign
6014 one-space string to SimpleStatusText property of the form, for MCK do
6015 so using Object Inspector).
6017 property SizeGrip: Boolean read fSizeGrip write fSizeGrip;
6018 {* Size grip for status bar. Has effect only before creating window. }
6020 procedure RemoveStatus;
6021 {* |<#form>
6022 Call it to remove status bar from a form (created in result of assigning
6023 value(s) to StatusText[], SimpleStatusText properties). When status bar is
6024 removed, form is resized to preset client height. }
6025 function StatusPanelCount: Integer;
6026 {* |<#form>
6027 Returns number of status panels defined in status bar. }
6028 property StatusPanelRightX[ Idx: Integer ]: Integer read GetStatusPanelX write SetStatusPanelX;
6029 {* |<#form>
6030 Use this property to adjust status panel right edges (if the status bar is
6031 divided onto several subpanels). If the right edge for the last panel is
6032 set to -1 (by default) it is expanded to the right edge of a form window.
6033 Otherwise, status bar can be shorter then form width. }
6034 property StatusWindow: HWND read fStatusWnd;
6035 {* |<#form>
6036 Provided for case if You want to use API direct message sending to
6037 status bar. }
6039 property Color1: TColor read fColor1 write SetColor1;
6040 {* |<#gradient>
6041 Top line color for GradientPanel. }
6042 property Color2: TColor read fColor2 write SetColor2;
6043 {* |<#gradient>
6044 |<#3Dlabel>
6045 Bottom line color for GradientPanel, or shadow color for LabelEffect.
6046 (If clNone, shadow color for LabelEffect is calculated as a mix bitween
6047 TextColor and clBlack). }
6048 property GradientStyle: TGradientStyle read FGradientStyle write SetGradientStyle;
6049 {* |<#gradient>
6050 Styles other then gsVertical and gsHorizontal has effect only for
6051 gradient panel, created by NewGradientPanelEx. }
6052 property GradientLayout: TGradientLayout read FGradientLayout write SetGradientLayout;
6053 {* |<#gradient>
6054 Has only effect for gradient panel, created by NewGradientPanelEx.
6055 Ignored for styles gsVertical and gsHorizontal. }
6057 //======== Image lists (for ListView, TreeView, ToolBar and TabControl):
6058 property ImageListSmall: PImageList index 16 read GetImgListIdx write SetImgListIdx;
6059 {* |<#listview>
6060 Image list with small icons used with List View control. If not set,
6061 last added (i.e. created with a control as an owner) image list with
6062 small icons is used. }
6063 property ImageListNormal: PImageList index 32 read GetImgListIdx write SetImgListIdx;
6064 {* |<#listview>
6065 |<#treeview>
6066 |<#tabcontrol>
6067 |<#bitbtn>
6068 Image list with normal size icons used with List View control (or with
6069 icons for BitBtn, TreeView, ToolBar or TabControl). If not set,
6070 last added (i.e. created with a control as an owner) image list is used.
6072 property ImageListState: PImageList index 0 read GetImgListIdx write SetImgListIdx;
6073 {* |<#listview>
6074 |<#treeview>
6075 Image list used as a state images list for ListView or TreeView control. }
6077 //========
6078 function SetUnicode( Unicode: Boolean ): PControl;
6079 {* |<#listview>
6080 |<#treeview>
6081 |<#tabcontrol>
6082 Sets control as Unicode or not. The control itself is returned as for
6083 other "transparent" functions. A conditional define UNICODE_CTRLS must
6084 be added to a project to provide handling unicode messages. }
6086 //======== TabControl-specific properties and methods:
6087 property Pages[ Idx: Integer ]: PControl read GetPages;
6088 {* |<#tabcontrol>
6089 Returns controls, which can be used as parent for controls, placed on
6090 different pages of a tab control. Use it like in follows example:
6091 | Label1 := NewLabel( TabControl1.Pages[ 0 ], 'Label1' );
6092 To find number of pages available, check out Count property of the tab
6093 control. Pages are enumerated from 0 to Count - 1, as usual. }
6094 property TC_Pages[ Idx: Integer ]: PControl read GetPages;
6095 {* |<#tabcontrol>
6096 The same as above. }
6097 function TC_Insert( Idx: Integer; const TabText: String; TabImgIdx: Integer ): PControl;
6098 {* |<#tabcontrol>
6099 Inserts new tab before given, returns correspondent page control
6100 (which can be used as a parent for controls to place on the page). }
6101 procedure TC_Delete( Idx: Integer );
6102 {* |<#tabcontrol>
6103 Removes tab from tab control, destroying all its child controls. }
6104 property TC_Items[ Idx: Integer ]: String read TCGetItemText write TCSetItemText;
6105 {* |<#tabcontrol>
6106 Text, displayed on tab control tabs. }
6107 property TC_Images[ Idx: Integer ]: Integer read TCGetItemImgIDx write TCSetItemImgIdx;
6108 {* |<#tabcontrol>
6109 Image index for a tab in tab control. }
6110 property TC_ItemRect[ Idx: Integer ]: TRect read TCGetItemRect;
6111 {* |<#tabcontrol>
6112 Item rectangle for a tab in tab control. }
6113 procedure TC_SetPadding( cx, cy: Integer );
6114 {* |<#tabcontrol>
6115 Sets space padding around tab text in a tab of tab control. }
6116 function TC_TabAtPos( x, y: Integer ): Integer;
6117 {* |<#tabcontrol>
6118 Returns index of tab, found at the given position (relative to
6119 a client rectangle of tab control). If no tabs found at the
6120 position, -1 is returned. }
6121 function TC_DisplayRect: TRect;
6122 {* |<#tabcontrol>
6123 Returns rectangle, occupied by a page rather then tab. }
6124 function TC_IndexOf(const S: String): Integer;
6125 {* |<#tabcontrol>
6126 By Mr Brdo. Index of page by its Caption. }
6127 function TC_SearchFor(const S: String; StartAfter: Integer; Partial: Boolean): Integer;
6128 {* |<#tabcontrol>
6129 By Mr Brdo. Index of page by its Caption. }
6131 //======== ListView style and options:
6132 property LVStyle: TListViewStyle read fLVStyle write SetLVStyle;
6133 {* |<#listview>
6134 ListView style of view. Can be changed at run time. }
6136 property LVOptions: TListViewOptions read fLVOptions write SetLVOptions;
6137 {* |<#listview>
6138 ListView options. Can be changed at run time. }
6140 property LVTextColor: TColor index LVM_GETTEXTCOLOR
6141 {$IFDEF F_P} read LVGetColorByIdx
6142 {$ELSE DELPHI} read fTextColor
6143 {$ENDIF F_P/DELPHI} write LVSetColorByIdx;
6144 {* |<#listview>
6145 ListView text color. Use it instead of TextColor. }
6146 property LVTextBkColor: TColor index LVM_GETTEXTBKCOLOR
6147 {$IFDEF F_P} read LVGetColorByIdx
6148 {$ELSE DELPHI} read fLVTextBkColor
6149 {$ENDIF F_P/DELPHI} write LVSetColorByIdx;
6150 {* |<#listview>
6151 ListView background color for text. }
6152 property LVBkColor: TColor read fColor write SetCtlColor; //LVSetBkColor;
6153 {* |<#listview>
6154 ListView background color. Use it instead of Color. }
6156 //======== List View columns handling:
6157 property LVColCount: Integer read fLVColCount;
6158 {* |<#listview>
6159 ListView (additional) column count. Value 0 means that there are
6160 no columns (single item text / icon is used). If You want
6161 to provide several columns, first call LVColAdd to "insert" column 0,
6162 i.e. to provide header text for first column (with index 0).
6163 If there are no column, nothing will be shown in lvsDetail /
6164 lvsDetailNoHeader view style. }
6165 procedure LVColAdd( const aText: String; aalign: TTextAlign; aWidth: Integer );
6166 {* |<#listview>
6167 Adds new column. Pass 'width' <= 0 to provide default column width.
6168 'text' is a column header text. }
6169 {$IFNDEF _FPC}
6170 {$IFNDEF _D2}
6171 procedure LVColAddW( const aText: WideString; aalign: TTextAlign; aWidth: Integer );
6172 {* |<#listview>
6173 Adds new column (unicode version). }
6174 {$ENDIF _D2}
6175 {$ENDIF _FPC}
6176 procedure LVColInsert( ColIdx: Integer; const aText: String; aAlign: TTextAlign; aWidth: Integer );
6177 {* |<#listview>
6178 Inserts new column at the Idx position (1-based column index). }
6179 {$IFNDEF _FPC}
6180 {$IFNDEF _D2}
6181 procedure LVColInsertW( ColIdx: Integer; const aText: WideString; aAlign: TTextAlign; aWidth: Integer );
6182 {* |<#listview>
6183 Inserts new column at the Idx position (1-based column index). }
6184 {$ENDIF _D2}
6185 {$ENDIF _FPC}
6186 procedure LVColDelete( ColIdx: Integer );
6187 {* |<#listview>
6188 Deletes column from List View }
6189 property LVColWidth[ Item: Integer ]: Integer index LVM_GETCOLUMNWIDTH
6190 read GetItemVal write SetItemVal;
6191 {* |<#listview>
6192 Retrieves or changes column width. For lvsList view style, the same width
6193 is returned for all columns (ColIdx is ignored). It is possible to use
6194 special values to assign to a property:
6195 |<br> LVSCW_AUTOSIZE - Automatically sizes the column
6196 |<br> LVSCW_AUTOSIZE_USEHEADER - Automatically sizes the column to fit
6197 the header text
6198 |<br>
6199 To set coumn width in lvsList view mode, column index must be -1
6200 (and Width to set must be in range 0..32767 always). }
6201 property LVColText[ Idx: Integer ]: String read GetLVColText write SetLVColText;
6202 {* |<#listview>
6203 Allows to get/change column header text at run time. }
6204 {$IFNDEF _FPC}
6205 {$IFNDEF _D2}
6206 property LVColTextW[ Idx: Integer ]: WideString read GetLVColTextW write SetLVColTextW;
6207 {* |<#listview>
6208 Allows to get/change column header text at run time. }
6209 {$ENDIF _D2}
6210 {$ENDIF _FPC}
6211 property LVColAlign[ Idx: Integer ]: TTextAlign read GetLVColalign write SetLVColalign;
6212 {* |<#listview>
6213 Column text aligning. }
6214 property LVColImage[ Idx: Integer ]: Integer index LVCF_IMAGE or (24 shl 16) read GetLVColEx write SetLVColEx;
6215 {* |<#listview>
6216 Only starting from comctrl32.dll of version 4.70 (IE4+). Allows to
6217 set an image for list view column itself from the ImageListSmall.
6219 property LVColOrder[ Idx: Integer ]: Integer index LVCF_ORDER or (28 shl 16) read GetLVColEx write SetLVColEx;
6220 {* |<#listview>
6221 Only starting from comctrl32.dll of version 4.70 (IE4+). Allows to
6222 set visual order of the list view column from the ImageListSmall.
6223 This value does not affect the index, by which the column is still
6224 accessible in the column array.
6227 //======== List View items handling:
6228 property LVCount: Integer read GetItemsCount write SetItemsCount;
6229 {* |<#listview>
6230 Returns item count for ListView control. It is possible to use Count
6231 property instead when obtaining of item count is needed only. But this this
6232 property allows also to set actual count of list view items when a list
6233 view is virtual. }
6235 property LVCurItem: Integer read GetLVCurItem write SetLVCurItem;
6236 {* |<#listview>
6237 Returns first selected item index in a list view. See also LVNextSelected
6238 and LVNextItem functions. }
6240 function LVNextItem( IdxPrev: Integer; Attrs: DWORD ): Integer;
6241 {* |<#listview>
6242 Returns an index of the next after IdxPrev item with given attributes in
6243 the list view. }
6244 function LVNextSelected( IdxPrev: Integer ): Integer;
6245 {* |<#listview>
6246 Returns an index of next (after IdxPrev) selected item in a list view. }
6248 function LVAdd( const aText: String; ImgIdx: Integer; State: TListViewItemState;
6249 StateImgIdx, OverlayImgIdx: Integer; Data: DWORD ): Integer;
6250 {* |<#listview>
6251 Adds new line to the end of ListView control. Only content of item itself
6252 is set (aText, ImgIdx). To change other column text and attributes of
6253 item added, use appropriate properties / methods ().
6254 |<br>
6255 Returns an index of added item.
6256 |<br>
6257 There is no Unicode version defined, use LVItemAddW instead. }
6258 function LVItemAdd( const aText: String ): Integer;
6259 {* |<#listview>
6260 Adds an item to the end of list view. Returns an index of the item added. }
6261 {$IFNDEF _FPC}
6262 {$IFNDEF _D2}
6263 function LVItemAddW( const aText: WideString ): Integer;
6264 {* |<#listview>
6265 Adds an item to the end of list view. Returns an index of the item added. }
6266 {$ENDIF _D2}
6267 {$ENDIF _FPC}
6268 function LVInsert( Idx: Integer; const aText: String; ImgIdx: Integer;
6269 State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer; Data: DWORD ): Integer;
6270 {* |<#listview>
6271 Inserts new line before line with index Idx in ListView control. Only
6272 content of item itself is set (aText, ImgIdx). To change other column
6273 text and attributes of item added, use appropriate properties / methods ().
6274 if ImgIdx = I_IMAGECALLBACK, event handler OnGetLVItemImgIdx is responsible
6275 for returning image index for an item ( /// not implemented yet /// )
6276 Pass StateImgIdx and OverlayImgIdx = 0 (ignored in that case) or 1..15 to
6277 use correspondent icon from ImageListState image list.
6278 |<br> Returns an index of item inserted.
6279 |<br> There is no unicode version of this method, use LVItemInsertW. }
6280 function LVItemInsert( Idx: Integer; const aText: String ): Integer;
6281 {* |<#listview>
6282 Inserts an item to Idx position. }
6283 {$IFNDEF _FPC}
6284 {$IFNDEF _D2}
6285 function LVItemInsertW( Idx: Integer; const aText: WideString ): Integer;
6286 {* |<#listview>
6287 Inserts an item to Idx position. }
6288 {$ENDIF _D2}
6289 {$ENDIF _FPC}
6291 procedure LVDelete( Idx: Integer );
6292 {* |<#listview>
6293 Deletes item of ListView with subitems (full row - in lvsDetail view style. }
6294 procedure LVSetItem( Idx, Col: Integer; const aText: String; ImgIdx: Integer;
6295 State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer; Data: DWORD );
6296 {* |<#listview>
6297 Use this method to set item data and item columns data for ListView control.
6298 It is possible to pass I_SKIP as ImgIdx, StateImgIdx, OverlayImgIdx values to
6299 skip setting this fields. But all other are set always. Like in LVInsert /
6300 LVAdd, ImgIdx can be I_IMAGECALLBACK to determine that image will be
6301 retrieved in OnGetItemImgIdx event handler when needed.
6302 |<br>
6303 If this method is called to set data for column > 0, parameters ImgIdx and
6304 Data are ignored anyway.
6305 |<br> There is no unicode version of this method, use other methods
6306 to set up listed properties separately using correspondent W-functions. }
6308 property LVItemState[ Idx: Integer ]: TListViewItemState read LVGetItemState write LVSetItemState;
6309 {* |<#listview>
6310 Access to list view item states set [lvisBlend, lvisHighlight, lvisFocus,
6311 lvisSelect]. When assign new value to the property, it is possible to use
6312 special index value -1 to change state for all items for a list view
6313 (but only when lvoMultiselect style is applied to the list view, otherwise
6314 index -1 is referring to the last item of the list view). }
6316 property LVItemIndent[ Idx: Integer ]: Integer read LVGetItemIndent write LVSetItemIndent;
6317 {* Item indentation. Indentation is calculated as this value multiplied to
6318 image list ImgWidth value (Image list must be applied to list view).
6319 Note: indentation supported only if IE3.0 or higher installed. }
6320 property LVItemStateImgIdx[ Idx: Integer ]: Integer read LVGetSttImgIdx write LVSetSttImgIdx;
6321 {* |<#listview>
6322 Access to state image of the item. Use index -1 to assign the same state
6323 image index to all items of the list view at once (fast).
6324 Option lvoCheckBoxes just means, that control itself creates special inner
6325 image list for two state images. Later it is possible to examine checked
6326 state for items or set checked state programmatically by changing
6327 LVItemStateImgIdx[ ] property. Value 1 corresponds to unchecked state,
6328 2 to checked. Value 0 allows to remove checkbox at all. So, to check all
6329 added items by default (e.g.), do following:
6330 ! ListView1.LVItemStateImgIdx[ -1 ] := 2;
6331 |<br>Use 1-based index of the image
6332 in image list ImageListState. Value 0 reserved to use as "no state image".
6333 Values 1..15 can be used only - this is the Windows restriction on
6334 state images. }
6335 property LVItemOverlayImgIdx[ Idx: Integer ]: Integer read LVGetOvlImgIdx write LVSetOvlImgIdx;
6336 {* |<#listview>
6337 Access to overlay image of the item. Use index -1 to assign the same
6338 overlay image to all items of the list view at once (fast). }
6339 property LVItemData[ Idx: Integer ]: DWORD read LVGetItemData write LVSetItemData;
6340 {* |<#listview>
6341 Access to user defined data, assiciated with the item of the list view. }
6342 procedure LVSelectAll;
6343 {* |<#listview>
6344 Call this method to select all the items of the list view control. }
6345 property LVSelCount: Integer read GetSelLength write SetSelLength;
6346 {* |<#listview>
6347 Returns number of items selected in listview. }
6348 property LVItemImageIndex[ Idx: Integer ]: Integer read LVGetItemImgIdx write LVSetItemImgIdx;
6349 {* |<#listview>
6350 Image index of items in listview. When an item is created (using LVItemAdd
6351 or LVItemInsert), image index 0 is set by default (not -1 like in VCL!). }
6352 property LVItems[ Idx, Col: Integer ]: String read LVGetItemText write LVSetItemText;
6353 {* |<#listview>
6354 Access to List View item text. }
6355 {$IFNDEF _FPC}
6356 {$IFNDEF _D2}
6357 property LVItemsW[ Idx, Col: Integer ]: WideString read LVGetItemTextW write LVSetItemTextW;
6358 {* |<#listview>
6359 Access to List View item text. }
6360 {$ENDIF _D2}
6361 {$ENDIF _FPC}
6362 function LVItemRect( Idx: Integer; Part: TGetLVItemPart ): TRect;
6363 {* |<#listview>
6364 Returns rectangle occupied by given item part(s) in ListView window.
6365 Empty rectangle is returned, if the item is not viewing currently. }
6366 function LVSubItemRect( Idx, ColIdx: Integer ): TRect;
6367 {* |<#listview>
6368 Returns rectangle occupied by given item's subitem in ListView window,
6369 in lvsDetail or lvsDetailNoHeader style. Empty rectangle (0,0,0,0) is
6370 returned if the item is not viewing currently. Left or/and right bounds
6371 of the rectangle returned can be outbound item rectangle if only a part
6372 of the subitem is visible or the subitem is not visible in the item,
6373 which is visible itself. }
6374 property LVItemPos[ Idx: Integer ]: TPoint read LVGetItemPos write LVSetItemPos;
6375 {* |<#listview>
6376 Position of List View item (can be changed in icon or small icon view). }
6377 function LVItemAtPos( X, Y: Integer ): Integer;
6378 {* |<#listview>
6379 Return index of item at the given position. }
6380 function LVItemAtPosEx( X, Y: Integer; var Where: TWherePosLVItem ): Integer;
6381 {* |<#listview>
6382 Retrieves index of item and sets in Where, what part of item is under
6383 given coordinates. If there are no items at the specified position,
6384 -1 is returned. }
6385 procedure LVMakeVisible( Item: Integer; PartiallyOK: Boolean );
6386 {* |<#listview>
6387 Makes listview item visible. Ignred when Item passed < 0. }
6388 procedure LVEditItemLabel( Idx: Integer );
6389 {* |<#listview>
6390 Begins in-place editing of item label (first column text). }
6391 procedure LVSort;
6392 {* |<#listview>
6393 Initiates sorting of list view items. This sorting procedure is available only
6394 for Win2K, WinNT4 with IE5, Win98 or Win95 with IE5. See also LVSortData. }
6395 procedure LVSortData;
6396 {* |<#listview>
6397 Initiates sorting of list view items. This sorting procedure is always available
6398 in Windows95/98, NT/2000. But OnCompareLVItems procedure receives not indexes of
6399 items compared but its Data field associated instead. }
6400 procedure LVSortColumn( Idx: Integer );
6401 {* |<#listview>
6402 This is a method to simplify sort by column. Just call it in your OnColumnClick
6403 event passing column index and enjoy with your list view sorted automatically
6404 when column header is clicked. Requieres Windows2000 or Winows98, not supported
6405 under WinNT 4.0 and below and under Windows95.
6406 |<br>
6407 Either lvoSortAscending or lvoSortDescending option must be set in
6408 LVOptions, otherwise no sorting is performed. }
6409 function LVIndexOf( const S: String ): Integer;
6410 {* Returns first list view item index with caption matching S.
6411 The same as LVSearchFor( S, -1, FALSE ). }
6412 {$IFNDEF _FPC}
6413 {$IFNDEF _D2}
6414 function LVIndexOfW( const S: WideString ): Integer;
6415 {* Returns first list view item index with caption matching S.
6416 The same as LVSearchForW( S, -1, FALSE ). }
6417 {$ENDIF _D2}
6418 {$ENDIF _FPC}
6419 function LVSearchFor( const S: String; StartAfter: Integer; Partial: Boolean ): Integer;
6420 {* Searches an item with Caption equal to S (or starting from S, if Partial = TRUE).
6421 Searching is started after an item specified by StartAfter parameter. }
6422 {$IFNDEF _FPC}
6423 {$IFNDEF _D2}
6424 function LVSearchForW( const S: WideString; StartAfter: Integer; Partial: Boolean ): Integer;
6425 {* Searches an item with Caption equal to S (or starting from S, if Partial = TRUE).
6426 Searching is started after an item specified by StartAfter parameter. }
6427 {$ENDIF _D2}
6428 {$ENDIF _FPC}
6430 //======== List view page:
6431 property LVTopItem: Integer index LVM_GETTOPINDEX read GetIntVal; //LVGetTopItem;
6432 {* |<#listview>
6433 Returns index of topmost visible item of ListView in lvsList view style. }
6434 property LVPerPage: Integer index LVM_GETCOUNTPERPAGE read GetIntVal; //LVGetPerPage;
6435 {* |<#listview>
6436 Returns the number of fully-visible items if successful. If the current
6437 view is icon or small icon view, the return value is the total number
6438 of items in the list view control. }
6440 //======== List View specific events:
6441 property OnEndEditLVItem: TOnEditLVItem read fOnEditLVITem write SetOnEditLVItem;
6442 {* |<#listview>
6443 Called when edit of an item label in ListView control finished. Return
6444 True to accept new label text, or false - to not accept it (item label
6445 will not be changed). If handler not set to an event, all changes are
6446 accepted. }
6448 property OnDeleteLVItem: TOnDeleteLVItem read fOnDeleteLVItem write SetOnDeleteLVItem;
6449 {* |<#listview>
6450 Called for every deleted list view item. }
6451 property OnDeleteAllLVItems: TOnEvent read fOnDeleteAllLVItems write SetOnDeleteAllLVItems;
6452 {* |<#listview>
6453 Called when all the items of the list view control are to be deleted. If after
6454 returning from this event handler event OnDeleteLVItem is yet assigned,
6455 an event OnDeleteLVItem will be called for every deleted item. }
6456 property OnLVData: TOnLVData read fOnLVData write SetOnLVData;
6457 {* |<#listview>
6458 Called to provide virtual list view with actual data. To use list view as
6459 virtaul list view, define also lvsOwnerData style and set Count property
6460 to actual row count of the list view. This manner of working with list view
6461 control can greatly improve performance of an application when working with
6462 huge data sets represented in listview control. }
6463 {$IFNDEF _FPC}
6464 {$IFNDEF _D2}
6465 property OnLVDataW: TOnLVDataW read fOnLVDataW write SetOnLVDataW;
6466 {* |<#listview>
6467 The same as OnLVData, but for unicode version of the list view allows
6468 to return WideString text in the event handler. Though for unicode list
6469 view it is still possible to use ordinary event OnLVData, it is
6470 very recommended to use this event istead. }
6471 {$ENDIF _D2}
6472 {$ENDIF _FPC}
6474 property OnCompareLVItems: TOnCompareLVItems read fOnCompareLVItems write fOnCompareLVItems;
6475 {* |<#listview>
6476 Event to compare two list view items during sort operation (initiated by
6477 LVSort method call). Do not send any messages to the list view control
6478 while it is sorting - results can be unpredictable! }
6479 property OnColumnClick: TOnLVColumnClick read fOnColumnClick write SetOnColumnClick;
6480 {* |<#listview>
6481 This event handler is called when column of the list view control is clicked.
6482 You can use this event to initiate sorting of list view items by this column. }
6483 property OnLVStateChange: TOnLVStateChange read FOnLVStateChange write SetOnLVStateChange;
6484 {* |<#listview>
6485 This event occure when an item or items range in list view control are
6486 changing its state (e.g. selected or unselected). }
6487 property OnLVDelete: TOnLVDelete read FOnLVDelete write SetOnLVDelete;
6488 {* |<#listview>
6489 This event is called when an item is deleted in the listview.
6490 Do not add, delete, or rearrange items in the list view while processing
6491 this notification. }
6492 property OnDrawItem: TOnDrawItem read fOnDrawItem write SetOnDrawItem;
6493 {* |<#listview>
6494 |<#listbox>
6495 |<#combo>
6496 This event can be used to implemet custom drawing for list view, list box, dropped
6497 list of a combobox. For a list view, custom drawing using this event is possible
6498 only in lvsDetail and lvsDetailNoHeader styles, and OnDrawItem is called to draw
6499 entire row at once only. See also OnLVCustomDraw event. }
6501 property OnLVCustomDraw: TOnLVCustomDraw read FOnLVCustomDraw write SetOnLVCustomDraw;
6502 {* |<#listview>
6503 Custom draw event for listview. For every item to be drawn, this event
6504 can be called several times during a single drawing cycle - depending on
6505 a result, returned by an event handler. Stage can have one of following
6506 values:
6507 |<pre>
6508 CDDS_PREERASE
6509 CDDS_POSTERASE
6510 CDDS_ITEMPREERASE
6511 CDDS_PREPAINT
6512 CDDS_ITEMPREPAINT
6513 CDDS_ITEM
6514 CDDS_SUBITEM + CDDS_ITEMPREPAINT
6515 CDDS_SUBITEM + CDDS_ITEMPOSTPAINT
6516 CDDS_ITEMPOSTPAINT
6517 CDDS_POSTPAINT
6518 </pre>
6519 When called, see on Stage to get know, on what stage the event is
6520 activated. And depend on the stage and on what you want to paint,
6521 return a value as a result, which instructs the system, if to use
6522 default drawing on this (and follows) stage(s) for the item, and if
6523 to notify further about different stages of drawing the item during
6524 this drawing cycle. Possible values to return are:
6525 |<pre>
6526 CDRF_DODEFAULT - perform default drawing. Do not notify further for this
6527 item (subitem) (or for entire listview, if called with
6528 flag CDDS_ITEM reset - ?);
6529 CDRF_NOTIFYITEMDRAW - return this value, when the event is called the
6530 first time in a cycle of drawing, with ItemIdx = -1 and
6531 flag CDDS_ITEM reset in Stage parameter;
6532 CDRF_NOTIFYPOSTERASE - usually can be used to provide default erasing,
6533 if you want to perform drawing immediately after that;
6534 CDRF_NOTIFYPOSTPAINT - return this value to provide calling the event
6535 after performing default drawing. Useful when you wish
6536 redraw only a part of the (sub)item;
6537 CDRF_SKIPDEFAULT - return this value to inform the system that all
6538 drawing is done and system should not peform any more
6539 drawing for the (sub)item during this drawing cycle.
6540 CDRF_NEWFONT - informs the system, that font is changed and default
6541 drawing should be performed with changed font;
6542 |</pre>
6543 If you want to get notifications for each subitem, do not use option
6544 lvoOwnerDrawFixed, because such style prevents system from notifying
6545 the application for each subitem to be drawn in the listview and only
6546 notifications will be sent about entire items.
6547 |<br>
6548 See also NM_CUSTOMDRAW in API Help.
6551 procedure Set_LVItemHeight(Value: Integer);
6552 function SetLVItemHeight(Value: Integer): PControl;
6553 property LVItemHeight: Integer read fLVItemHeight write Set_LVItemHeight;
6556 //======== TreeView specific properties and methods:
6557 function TVInsert( nParent, nAfter: THandle; const Txt: String ): THandle;
6558 {* |<#treeview>
6559 Inserts item to a tree view. If nParent is 0 or TVI_ROOT, the item is
6560 inserted at the root of tree view. It is possible to pass following special
6561 values as nAfter parameter:
6562 |<pre>
6563 TVI_FIRST Inserts the item at the beginning of the list.
6564 TVI_LAST Inserts the item at the end of the list.
6565 TVI_SORT Inserts the item into the list in alphabetical order.
6566 |</pre> }
6567 {$IFNDEF _FPC}
6568 {$IFNDEF _D2}
6569 function TVInsertW( nParent, nAfter: THandle; const Txt: WideString ): THandle;
6570 {* |<#treeview>
6571 Inserts item to a tree view. If nParent is 0 or TVI_ROOT, the item is
6572 inserted at the root of tree view. It is possible to pass following special
6573 values as nAfter parameter:
6574 |<pre>
6575 TVI_FIRST Inserts the item at the beginning of the list.
6576 TVI_LAST Inserts the item at the end of the list.
6577 TVI_SORT Inserts the item into the list in alphabetical order.
6578 |</pre><br>
6579 This version of the method is Unicode. The tree view control should be
6580 set up as unicode control calling Perform( TVM_SETUNICODEFORMAT, 1, 0 ),
6581 and conditional symbol UNICODE_CTRLS must be defined to provide event
6582 handling for such kind of tree view (and other Unicode) controls. }
6583 {$ENDIF _D2}
6584 {$ENDIF _FPC}
6585 procedure TVDelete( Item: THandle );
6586 {* |<#treeview>
6587 Removes an item from the tree view. If value TVI_ROOT is passed, all items
6588 are removed. }
6590 property TVSelected: THandle index TVGN_CARET read TVGetItemIdx write TVSetItemIdx;
6591 {* |<#treeview>
6592 Returns or sets currently selected item handle in tree view. }
6594 property TVDropHilighted: THandle index TVGN_DROPHILITE read TVGetItemIdx write TVSetItemIdx;
6595 {* |<#treeview>
6596 Returns or sets item, which is currently highlighted as a drop target. }
6597 property TVDropHilited: THandle index TVGN_DROPHILITE read TVGetItemIdx write TVSetItemIdx;
6598 {* The same as TVDropHilighted. }
6599 property TVFirstVisible: THandle index TVGN_FIRSTVISIBLE read TVGetItemIdx write TVSetItemIdx;
6600 {* |<#treeview>
6601 Returns or sets given item to top of tree view. }
6603 property TVIndent: Integer index TVM_GETINDENT read GetIntVal write SetIntVal;
6604 {* |<#treeview>
6605 The amount, in pixels, that child items are indented relative to their
6606 parent items. }
6607 property TVVisibleCount: Integer index TVM_GETVISIBLECOUNT read GetIntVal;
6608 {* |<#treeview>
6609 Returns number of fully (not partially) visible items in tree view. }
6611 property TVRoot: THandle index TVGN_ROOT read TVGetItemIdx;
6612 {* |<#treeview>
6613 Returns handle of root item in tree view (or 0, if tree is empty). }
6614 property TVItemChild[ Item: THandle ]: THandle index TVGN_CHILD read TVGetItemNext;
6615 {* |<#treeview>
6616 Returns first child item for given one. }
6617 property TVItemHasChildren[ Item: THandle ]: Boolean read TV_GetItemHasChildren write TV_SetItemHasChildren;
6618 {* |<#treeview>
6619 TRUE, if an Item has children. Set this value to true if you want to
6620 force [+] sign appearing left from the node, even if there are no
6621 subnodes added to the node yet. }
6622 property TVItemChildCount[ Item: THandle ]: Integer read TV_GetItemChildCount;
6623 {* |<#treeview>
6624 Returns number of node child items in tree view.
6626 property TVItemNext[ Item: THandle ]: THandle index TVGN_NEXT read TVGetItemNext;
6627 {* |<#treeview>
6628 Returns next sibling item handle for given one (or 0, if passed item is
6629 the last child for its parent node). }
6630 property TVItemPrevious[ Item: THandle ]: THandle index TVGN_PREVIOUS read TVGetItemNext;
6631 {* |<#treeview>
6632 Returns previous sibling item (or 0, if the is no such item). }
6633 property TVItemNextVisible[ Item: THandle ]: THandle index TVGN_NEXTVISIBLE read TVGetItemNext;
6634 {* |<#treeview>
6635 Returns next visible item (passed item must be visible too, to determine,
6636 if it is really visible, use property TVItemRect or TVItemVisible. }
6637 property TVItemPreviousVisible[ Item: THandle ]: THandle index TVGN_PREVIOUSVISIBLE read TVGetItemNext;
6638 {* |<#treeview>
6639 Returns previous visible item. }
6640 property TVItemParent[ Item: THandle ]: THandle index TVGN_PARENT read TVGetItemNext;
6641 {* |<#treeview>
6642 Returns parent item for given one (or 0 for root item). }
6644 property TVItemText[ Item: THandle ]: String read TVGetItemText write TVSetItemText;
6645 {* |<#treeview>
6646 Text of tree view item. }
6647 {$IFNDEF _FPC}
6648 {$IFNDEF _D2}
6649 property TVItemTextW[ Item: THandle ]: WideString read TVGetItemTextW write TVSetItemTextW;
6650 {* |<#treeview>
6651 Text of tree view item. }
6652 {$ENDIF _D2}
6653 {$ENDIF _FPC}
6654 function TVItemPath( Item: THandle; Delimiter: Char ): String;
6655 {* |<#treeview>
6656 Returns full path from the root item to given item. Path is calculated
6657 as a concatenation of all parent nodes text strings, separated by
6658 given delimiter character.
6659 |<br>Please note, that returned path has no trailing delimiter, this
6660 character is only separating different parts of the path.
6661 |<br>If Item is not specified ( =0 ), path is returned
6662 for Selected item. }
6663 {$IFNDEF _FPC}
6664 {$IFNDEF _D2}
6665 function TVItemPathW( Item: THandle; Delimiter: WideChar ): WideString;
6666 {* |<#treeview>
6667 Returns full path from the root item to given item. Path is calculated
6668 as a concatenation of all parent nodes text strings, separated by
6669 given delimiter character. If Item is not specified ( =0 ), path is returned
6670 for Selected item. }
6671 {$ENDIF _D2}
6672 {$ENDIF _FPC}
6674 property TVItemRect[ Item: THandle; TextOnly: Boolean ]: TRect read TVGetItemRect;
6675 {* |<#treeview>
6676 Returns rectangle, occupied by an item in tree view. }
6678 property TVItemVisible[ Item: THandle ]: Boolean read TVGetItemVisible write TVSetITemVisible;
6679 {* |<#treeview>
6680 Returs True, if item is visible in tree view. It is also possible to
6681 assign True to this property to ensure that a tree view item is visible
6682 (if False is assigned, this does nothing). }
6683 function TVItemAtPos( x, y: Integer; var Where: DWORD ): THandle;
6684 {* |<#treeview>
6685 Returns handle of item found at specified position (relative to upper left
6686 corener of client area of the tree view). If no item found, 0 is returned.
6687 Variable Where receives additional flags combination, describing more
6688 detailed, on which part of item or tree view given point is located,
6689 such as:
6690 |<pre>
6691 TVHT_ABOVE Above the client area
6692 TVHT_BELOW Below the client area
6693 TVHT_NOWHERE In the client area, but below the last item
6694 TVHT_ONITEM On the bitmap or label associated with an item
6695 TVHT_ONITEMBUTTON On the button associated with an item
6696 TVHT_ONITEMICON On the bitmap associated with an item
6697 TVHT_ONITEMINDENT In the indentation associated with an item
6698 TVHT_ONITEMLABEL On the label (string) associated with an item
6699 TVHT_ONITEMRIGHT In the area to the right of an item
6700 TVHT_ONITEMSTATEICON On the state icon for a tree-view item that is in a user-defined state
6701 TVHT_TOLEFT To the right of the client area
6702 TVHT_TORIGHT To the left of the client area
6703 |</pre> }
6705 property TVRightClickSelect: Boolean read fTVRightClickSelect write SetTVRightClickSelect;
6706 {* |<#treeview>
6707 Set this property to True to allow change selection to an item, clicked with right mouse button. }
6708 property TVEditing: Boolean read fEditing;
6709 {* |<#treeview>
6710 Returns True, if tree view control is editing its item label. }
6712 property TVItemBold[ Item: THandle ]: Boolean index TVIS_BOLD read TVGetItemStateFlg write TVSetItemStateFlg;
6713 {* |<#treeview>
6714 True, if item is bold. }
6715 property TVItemCut[ Item: THandle ]: Boolean index TVIS_CUT read TVGetITemStateFlg write TVSetItemStateFlg;
6716 {* |<#treeview>
6717 True, if item is selected as part of "cut and paste" operation. }
6718 property TVItemDropHighlighted[ Item: THandle ]: Boolean index TVIS_DROPHILITED read TVGetITemStateFlg write TVSetItemStateFlg;
6719 {* |<#treeview>
6720 True, if item is selected as drop target. }
6721 property TVItemDropHilited[ Item: THandle ]: Boolean index TVIS_DROPHILITED read TVGetITemStateFlg write TVSetItemStateFlg;
6722 {* The same as TVItemDropHighlighted. }
6723 property TVItemExpanded[ Item: THandle ]: Boolean index TVIS_EXPANDED read TVGetITemStateFlg; // write TVSetItemStateFlg;
6724 {* |<#treeview>
6725 True, if item's list of child items is currently expanded. To change
6726 expanded state, use method TVExpand. }
6727 property TVItemExpandedOnce[ Item: THandle ]: Boolean index TVIS_EXPANDEDONCE read TVGetITemStateFlg; // write TVSetItemStateFlg;
6728 {* |<#treeview>
6729 True, if item's list of child items has been expanded at least once. }
6730 property TVItemSelected[ Item: THandle ]: Boolean index TVIS_SELECTED read TVGetITemStateFlg write TVSetItemStateFlg;
6731 {* |<#treeview>
6732 True, if item is selected. }
6734 procedure TVExpand( Item: THandle; Flags: DWORD );
6735 {* |<#treeview>
6736 Call it to expand/collapse item's child nodes. Possible values for Flags
6737 parameter are:
6738 <pre>
6739 TVE_COLLAPSE Collapses the list.
6740 TVE_COLLAPSERESET Collapses the list and removes the child items. Note
6741 that TVE_COLLAPSE must also be specified.
6742 TVE_EXPAND Expands the list.
6743 TVE_TOGGLE Collapses the list if it is currently expanded or
6744 expands it if it is currently collapsed.
6745 </pre>
6747 procedure TVSort( N: THandle );
6748 {* |<#treeview>
6749 By Alex Mokrov. Sorts treeview. If N = 0, entire treeview is sorted.
6750 Otherwise, children of the given node only.
6753 property TVItemImage[ Item: THandle ]: Integer index TVIF_IMAGE read TVGetItemImage write TVSetItemImage;
6754 {* |<#treeview>
6755 Image index for an item of tree view. To tell that there are no image
6756 set, use index -2 (value -1 is reserved for callback image). }
6757 property TVItemSelImg[ Item: THandle ]: Integer index TVIF_SELECTEDIMAGE read TVGetItemImage write TVSetItemImage;
6758 {* |<#treeview>
6759 Image index for an item of tree view in selected state. Use value -2 to
6760 provide no image, -1 used for callback image. }
6761 property TVItemOverlay[ Item: THandle ]: Integer index TVIS_OVERLAYMASK or $80000
6762 read TVGetItemImage write TVSetItemImage;
6763 {* |<#treeview>
6764 Overlay image index for an item in tree view. }
6765 property TVItemStateImg[ Item: THandle ]: Integer index TVIS_STATEIMAGEMASK or $C0000
6766 read TVGetItemImage write TVSetItemImage;
6767 {* |<#treeview>
6768 State image index for an item in tree view. Use 1-based index of the image
6769 in image list ImageListState. Value 0 reserved to use as "no state image".
6770 Values 1..15 can be used only - this is the Windows restriction on
6771 state images. }
6773 property TVItemData[ Item: THandle ]: Pointer read TVGetItemData write TVSetItemData;
6774 {* |<#treeview>
6775 Stores any program-defined pointer with the item. }
6776 procedure TVEditItem( Item: THandle );
6777 {* |<#treeview>
6778 Begins editing given item label in tree view. }
6779 procedure TVStopEdit( Cancel: Boolean );
6780 {* |<#treeview>
6781 Ends editing item label, started by user or explicitly by TVEditItem method. }
6783 property OnTVBeginDrag: TOnTVBeginDrag read fOnTVBeginDrag write fOnTVBeginDrag;
6784 {* |<#treeview>
6785 Is called for tree view, when its item is to be dragging. }
6786 property OnTVBeginEdit: TOnTVBeginEdit read fOnTVBeginEdit write fOnTVBeginEdit;
6787 {* |<#treeview>
6788 Is called for tree view, when its item label is to be editing. }
6789 property OnTVEndEdit: TOnTVEndEdit read fOnTVEndEdit write fOnTVEndEdit;
6790 {* |<#treeview>
6791 Is called when item label is edited. It is possible to cancel
6792 edit, returning False as a result. }
6793 property OnTVExpanding: TOnTVExpanding read fOnTVExpanding write fOnTVExpanding;
6794 {* |<#treeview>
6795 Is called just before expanding/collapsing item. It is possible to
6796 return False to prevent expanding item. }
6797 property OnTVExpanded: TOnTVExpanded read fOnTVExpanded write fOnTVExpanded;
6798 {* |<#treeview>
6799 Is called after expanding/collapsing item children. }
6800 property OnTVDelete: TOnTVDelete read fOnTVDelete write SetOnTVDelete;
6801 {* |<#treeview>
6802 Is called just before deleting item. You may use this event to free
6803 resources, associated with an item (see TVItemData property). }
6804 //----------------- by Sergey Shisminzev:
6805 property OnTVSelChanging: TOnTVSelChanging read fOnTVSelChanging write fOnTVSelChanging;
6806 {* |<#treeview>
6807 Is called before changing the selection. The handler can return FALSE
6808 to prevent changing the selection. }
6809 //--------------------------------------
6811 //======== Toolbar specific methods:
6812 procedure TBAddBitmap( Bitmap: HBitmap );
6813 {* |<#toolbar>
6814 Adds bitmaps to a toolbar. You can pass special values as Bitmap to
6815 add one of predefined system button images bitmaps:
6816 |<br> THandle(-1) to add standard small icons,
6817 |<br> THandle(-2) to add standard large icons,
6818 |<br> THandle(-5) to add standard small view icons,
6819 |<br> THandle(-6) to add standard large view icons,
6820 |<br> THandle(-9) to add standard small view icons,
6821 |<br> THandle(-10) to add standard large view icons,
6822 (in that case use following values as indexes to the standard and view
6823 bitmaps:
6824 |<br>
6825 STD_COPY, STD_CUT, STD_DELETE, STD_FILENEW, STD_FILEOPEN, STD_FILESAVE,
6826 STD_FIND, STD_HELP, STD_PASTE, STD_PRINT, STD_PRINTPRE, STD_PROPERTIES,
6827 STD_REDO, STD_REPLACE, STD_UNDO,
6828 |<br>
6829 VIEW_LARGEICONS, VIEW_SMALLICONS,
6830 VIEW_LIST, VIEW_DETAILS, VIEW_SORTNAME, VIEW_SORTSIZE, VIEW_SORTDATE,
6831 VIEW_SORTTYPE (use it as parameters BtnImgIdxArray in TBAddButtons or
6832 TBInsertButtons methods, and in assigning value to TBButtonImage[ ]
6833 property).
6834 Added bitmaps have indeces starting from previous count of images
6835 (as these are appended to existing - if any).
6836 |<br>
6837 Note, that if You add your own (custom) bitmap, it is not transparent.
6838 Do not assume that clSilver is always equal to clBtnFace. Use API
6839 function CreateMappedBitmap to load bitmap from resource and map
6840 desired colors as you wish (e.g., convert clTeal to clBtnFace). Or,
6841 call defined in KOL function LoadMappedBitmap to do the same more easy.
6842 Unfortunately, resource identifier for bitmap to pass it to LoadMappedBitmap
6843 or to CreateMappedBitmap seems must be integer, so it is necessary to
6844 create rc-file manually and compile using Borland Resource Compiler to
6845 figure it out. }
6848 function TBAddButtons( const Buttons: array of PChar; const BtnImgIdxArray: array
6849 of Integer ): Integer;
6850 {* |<#toolbar>
6851 Adds buttons to toolbar. Last string in Buttons array *must* be empty
6852 ('' or nil), so to add buttons without text, pass ' ' string (one space
6853 char). It is not necessary to provide image indexes for all
6854 buttons (it is sufficient to assign index for first button only).
6855 But in place, correspondent to separator button (defined by string '-'),
6856 any integer must be passed to assign follow image indexes correctly.
6857 See example.
6858 |*Toolbar adding buttons sample.
6859 Code below shows how to call TBAddButtons method to add two buttons with
6860 a separator between these buttons. idxNew and idxOld are integer
6861 expressions assigning image indexes to buttons 'New' and 'Old'. This
6862 indexes are zero-based and refer to bitmap images, added earlier (either
6863 in creating toolbar by call of NewToolbar or later in call of TBAddBitmap).
6865 ! TBAddButtons( [ '&New', '-', '&Old', '' ], [ idxNew, 0, idxOld ] );
6868 To add check buttons, use prefix '+' or '-' in button definition
6869 string. If next character is '!', such buttons are grouped to a
6870 radio-group. Also, it is possible to use '^' prefix (must be first) to
6871 define button with small drop-down section (use also OnTBDropDown event
6872 to respond to clicking drop down section of such buttons).
6873 |<br>
6874 This function returns command id for first added button (other
6875 id's can be calculated incrementing the result by one for each
6876 button, except separators, which have no command id).
6877 |<br>
6878 Note: for static toolbar (single in application and created
6879 once) ids are started from value 100. }
6881 function TBInsertButtons( BeforeIdx: Integer; Buttons: array of PChar;
6882 BtnImgIdxArray: array of Integer ): Integer;
6883 {* |<#toolbar>
6884 Inserts buttons before button with given index on toolbar. Returns
6885 command identifier for first button inserted (other can be calculated
6886 incrementing returned value needed times. See also TBAddButtons. }
6888 procedure TBDeleteButton( BtnID: Integer );
6889 {* |<#toolbar>
6890 Deletes single button given by its command id. To delete separator,
6891 use TBDeleteBtnByIdx instead. }
6893 procedure TBDeleteBtnByIdx( Idx: Integer );
6894 {* |<#toolbar>
6895 Deletes single button given by its index in toolbar (not by command ID). }
6897 procedure TBAssignEvents( BtnID: Integer; Events: array of TOnToolbarButtonClick );
6898 {* |<#toolbar>
6899 Allows to assign separate OnClick events for every toolbar button.
6900 BtnID should be toolbar button ID or index of the first button to
6901 assign event. If it is an ID, events are assigned to buttons in
6902 creation order. Otherwise, events are assigned in placement order.
6903 Anyway, separator buttons are not skipped, so pass at least nil for such
6904 button as an event.
6905 |<br>
6906 Please note, that though not all buttons should exist before
6907 assigning events to it, therefore at least the first button
6908 (specified by BtnID) must be already added before calling TBAssignEvents. }
6910 procedure TBResetImgIdx( BtnID, BtnCount: Integer );
6911 {* |<#toolbar>
6912 Resets image index for BtnCount buttons starting from BtnID. }
6914 property CurItem: Integer read fCurItem;
6915 {* |<#toolbar>
6916 For toolbar, in OnClick event this property can be used to determine
6917 which button was clicked (100-based button id in toolbar). It is also
6918 possible to use CurIndex property (zero-based) for this purpose as
6919 well, but do not assume, that CurItem always equal to CurIndex+100.
6920 At least, it is possible to call TBItem2Index function to convert
6921 button ID to its index in toolbar.
6922 |<br>
6923 In case, when button (or toolbar itself) is clicked using right
6924 mouse button, CurItem and CurIndex are always set to -1. To further
6925 determine which button was clicked, get mouse coordinates on screen,
6926 apply Screen2Client method of toolbar control to it and then use
6927 TBButtonAtPos function to determine which button was under cursor.
6930 property TBButtonCount: Integer read GetItemsCount; //TBGetButtonCount;
6931 {* |<#toolbar>
6932 Returns count of buttons on toolbar. The same as Count. }
6934 property TBBtnImgWidth: Integer read fTBBtnImgWidth write fTBBtnImgWidth;
6935 {* |<#toolbar>
6936 Custom toolbar buttons width. Set it before assigning buttons bitmap.
6937 Changing this property after assigning the bitmap has no effect. }
6939 function TBItem2Index( BtnID: Integer ): Integer;
6940 {* |<#toolbar>
6941 Converts button command id to button index for tool bar. }
6943 function TBIndex2Item( Idx: Integer ): Integer;
6944 {* |<#toolbar>
6945 Converts toolbar button index to its command ID. }
6947 property TBButtonEnabled[ BtnID: Integer ]: Boolean index TB_ENABLEBUTTON
6948 read TBGetBtnStt write TBSetBtnStt;
6949 {* |<#toolbar>
6950 Obvious. }
6952 property TBButtonVisible[ BtnID: Integer ]: Boolean read TBGetButtonVisible
6953 write TBSetButtonVisible;
6954 {* |<#toolbar>
6955 Allows to hide/show some of toolbar buttons. }
6957 property TBButtonChecked[ BtnID: Integer ]: Boolean index TB_CHECKBUTTON
6958 read TBGetBtnStt write TBSetBtnStt;
6959 {* |<#toolbar>
6960 Allows to determine 'checked' state of a button (e.g., radio-button),
6961 and to check it programmatically. }
6963 property TBButtonMarked[ BtnID: Integer ]: Boolean index TB_MARKBUTTON
6964 read TBGetBtnStt write TBSetBtnStt;
6965 {* |<#toolbar>
6966 Returns True if toolbar button is marked (highlighted). Allows to
6967 highlight buttons assigning True to this value. }
6969 property TBButtonPressed[ BtnID: Integer ]: Boolean index TB_PRESSBUTTON
6970 read TBGetBtnStt write TBSetBtnStt;
6971 {* |<#toolbar>
6972 Allows to detrmine if toolbar button (given by its command ID) pressed,
6973 and press/unpress it programmatically. }
6975 property TBButtonText[ BtnID: Integer ]: String read TBGetButtonText write TBSetButtonText;
6976 {* |<#toolbar>
6977 Obtains toolbar button text and allows to change it. Be sure that text
6978 is not empty for all buttons, if You want for it to be shown (if at least
6979 one button has empty text, no text labels will be shown at all). At
6980 least set it to ' ' for buttons, which You do not want to show labels,
6981 if You want from other ones to have it. }
6983 property TBButtonImage[ BtnID: Integer ]: Integer read TBGetBtnImgIdx write TBSetBtnImgIdx;
6984 {* |<#toolbar>
6985 Allows to access/change button image. }
6987 property TBButtonRect[ BtnID: Integer ]: TRect read TBGetButtonRect;
6988 {* |<#toolbar>
6989 Obtains rectangle occupied by toolbar button in toolbar window.
6990 (It is not possible to obtain rectangle for buttons, currently
6991 not visible). }
6993 property TBButtonWidth[ BtnID: Integer ]: Integer read TBGetBtnWidth write TBSetBtnWidth;
6994 {* |<#toolbar>
6995 Allows to obtain / change toolbar button width. }
6997 property TBButtonsMinWidth: Integer index 0
6998 {$IFDEF F_P} read TBGetBtMinMaxWidth
6999 {$ELSE DELPHI} read FTBBtMinWidth
7000 {$ENDIF F_P/DELPHI} write TBSetBtMinMaxWidth;
7001 {* |<#toolbar>
7002 Allows to set minimal width for all toolbar buttons. }
7003 property TBButtonsMaxWidth: Integer index 1
7004 {$IFDEF F_P} read TBGetBtMinMaxWidth
7005 {$ELSE DELPHI} read FTBBtMaxWidth
7006 {$ENDIF F_P/DELPHI} write TBSetBtMinMaxWidth;
7007 {* |<#toolbar>
7008 Allows to set maximal width for all toolbar buttons. }
7010 function TBButtonAtPos( X, Y: Integer ): Integer;
7011 {* |<#toolbar>
7012 Returns command ID of button at the given position on toolbar,
7013 or -1, if there are no button at the position. Value 0 is returned
7014 for separators. }
7016 function TBBtnIdxAtPos( X, Y: Integer ): Integer;
7017 {* |<#toolbar>
7018 Returns index of button at the given position on toolbar.
7019 This also can be index of separator button. -1 is returned if
7020 there are no buttons found at the position. }
7022 property TBRows: Integer read TBGetRows write TBSetRows;
7023 {* |<#toolbar>
7024 Returns number of rows for toolbar and allows to try to set
7025 desired number of rows (but system can set another number of
7026 rows in some cases). This property has no effect if tboWrapable
7027 style not present in Options when toolbar is created. }
7029 procedure TBSetTooltips( BtnID1st: Integer; Tooltips: array of PChar );
7030 {* |<#toolbar>
7031 Allows to assign tooltips to several buttons. Until this procedure
7032 is not called, tooltips list is not created and no code is added
7033 to executable. This method of tooltips maintainance for toolbar buttons
7034 is useful both for static and dynamic toolbars (meaning "dynamic" -
7035 toolbars with buttons, deleted and inserted at run-time). }
7037 property OnTBDropDown: TOnEvent read fOnDropDown write fOnDropDown;
7038 {* |<#toolbar>
7039 This event is called for drop down buttons, when user click drop part
7040 of drop down button. To determine for which button event is called,
7041 look at CurItem or CurIndex property. It is also possible to use
7042 common (with combobox) property OnDropDown. }
7044 property OnTBClick: TOnEvent read fOnClick write fOnClick;
7045 {* |<#toolbar>
7046 The same as OnClick. }
7048 //================== RichEdit specific: ==================
7050 property MaxTextSize: DWORD read GetMaxTextSize write SetMaxTextSize;
7051 {* |<#richedit>
7052 This property valid also for simple edit control, not only for RichEdit.
7053 But for usual edit control, maximum text size available is 32K. For
7054 RichEdit, limit is 4Gb. By default, RichEdit is limited to
7055 32767 bytes (to set maximum size available to 2Gb, assign MaxInt value
7056 to a property). Also, to get current text size of RichEdit, use property
7057 TextSize or RE_TextSize[ ]. }
7058 property TextSize: Integer read GetTextSize;
7059 {* |<#richedit>
7060 Common for edit and rich edit controls property, which returns size of
7061 text in edit control. Also, for any other control (or form, or applet
7062 window) returns size (in characters) of Caption or Text (what is, the
7063 same property actually). }
7064 property RE_TextSize[ Units: TRichTextSize ]: Integer read REGetTextSize;
7065 {* |<#richedit>
7066 For RichEdit control, it returns text size, measured in desired units
7067 (rtsChars - characters, including OLE objects, counted as a single
7068 character; rtsBytes - presize length of text image (if it would be stored
7069 in file or stream). Please note, that for RichEdit1.0, only size in
7070 characters can be obtained. }
7071 function RE_TextSizePrecise: Integer;
7072 {* |<#richedit>
7073 By Savva. Returns length of rich edit text. }
7075 property RE_CharFmtArea: TRichFmtArea read fRECharArea write fRECharArea;
7076 {* |<#richedit>
7077 By default, this property is raSelection. Changing it, You determine in
7078 for which area characters format is applyed, when changing
7079 character formatting properties below (not paragraph formatting).
7080 |&A=<a href=#RE_CharFmtArea target=main>%0</a>
7082 property RE_CharFormat: TCharFormat read REGetCharformat write RESetCharFormat;
7083 {* |<#richedit>
7084 In differ to follow properties, which allow to control certain formatting
7085 attributes, this property provides low level access for formatting current
7086 character area (see RE_CharFmtArea). It returns TCharFormat structure,
7087 filled in with formatting attributes, and by assigning another value to
7088 this property You can change desired attributes as You wish. Even if
7089 RichEdit1.0 is used, TCharFormat2 is returned (but extended fields are
7090 ignored for RichEdit1.0). }
7091 property RE_Font: PGraphicTool read REGetFont write RESetFont;
7092 {* |<#richedit>
7093 Font of the first character in current selection (when retrieve).
7094 When set (or subproperties of RE_Font are set), all font attributes are
7095 applied to entire <A area>. To apply only needed attributes, use another
7096 properties: RE_FmtBold, RE_FmtItalic, RE_FmtStrikeout, RE_FmtUnderline,
7097 RE_FmtName, etc.
7098 |<br>
7099 Note, that font size is measured in twips, which is about 1/10 of pixel. }
7100 property RE_FmtBold: Boolean index CFM_BOLD read REGetFontEffects write RESetFontEffect;
7101 {* |<#richedit>
7102 Formatting flag. When retrieve, returns True, if fsBold style RE_Font.FontStyle
7103 is valid for a first character in the selection. When set, changes fsBold
7104 style (True - set, False - reset) for all characters in <A area>. }
7105 property RE_FmtBoldValid: Boolean index CFM_BOLD read REGetFontMask;
7106 {* }
7107 property RE_FmtItalic: Boolean index CFM_ITALIC read REGetFontEffects write RESetFontEffect;
7108 {* |<#richedit>
7109 Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsItalic
7110 style valid for the first character of the selection, and when set, changes
7111 only fsItalic style for an <A area>. }
7112 property RE_FmtItalicValid: Boolean index CFM_ITALIC read REGetFontMask;
7113 {* }
7114 property RE_FmtStrikeout: Boolean index CFM_STRIKEOUT read REGetFontEffects write RESetFontEffect;
7115 {* |<#richedit>
7116 Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsStrikeout
7117 style valid for the first selected character, and when set, changes only
7118 fsStrikeout style for an <A area>. }
7119 property RE_FmtStrikeoutValid: Boolean index CFM_STRIKEOUT read REGetFontMask;
7120 {* }
7121 property RE_FmtUnderline: Boolean index CFM_UNDERLINE read REGetFontEffects write RESetFontEffect;
7122 {* |<#richedit>
7123 Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsUnderline
7124 style valid for the first selected character, and when set, changes
7125 fsUnderline style for an <A area>. }
7126 property RE_FmtUnderlineValid: Boolean index CFM_UNDERLINE read REGetFontMask;
7127 {* }
7128 property RE_FmtUnderlineStyle: TRichUnderline
7129 read REGetUnderlineEx write RESetUnderlineEx;
7130 {* |<#richedit>
7131 Extended underline style. To check, if this property is valid for
7132 entire selection, examine RE_FmtUnderlineValid value. }
7133 property RE_FmtProtected: Boolean index CFM_PROTECTED read REGetFontEffects write RESetFontEffect;
7134 {* |<#richedit>
7135 Formatting flag. When retrieving, shows, is the first character of the selection
7136 is protected from changing it by user (True) or not (False). To get know,
7137 if retrived value is valid for entire selection, check the property
7138 RE_FmtProtectedValid. When set, makes all characters in <A area> protected (
7139 True) or not (False). }
7140 property RE_FmtProtectedValid: Boolean index CFM_PROTECTED read REGetFontMask;
7141 {* |<#richedit>
7142 True, if property RE_FmtProtected is valid for entire selection, when
7143 retrieving it. }
7144 property RE_FmtHidden: Boolean index CFM_HIDDEN read REGetFontEffects write RESetFontEffect;
7145 {* |<#richedit>
7146 For RichEdit3.0, makes text hidden (not displayed). }
7147 property RE_FmtHiddenValid: Boolean index CFM_HIDDEN read REGetFontMask;
7148 {* |<#richedit>
7149 Returns True, if RE_FmtHidden style is valid for entire selection. }
7151 property RE_FmtLink: Boolean index $20 {CFM_LINK} read REGetFontEffects write RESetFontEffect;
7152 {* |<#richedit>
7153 Returns True, if the first selected character is a part of link (URL). }
7154 // by Sergey Shisminzev
7156 property RE_FmtLinkValid: Boolean index $20 {CFM_LINK} read REGetFontMask;
7157 {* }
7158 property RE_FmtFontSize: Integer index (12 shl 16) or CFM_SIZE read REGetFontAttr write RESetFontAttr;
7159 {* |<#richedit>
7160 Formatting value: font size, in twips (1/1440 of an inch, or 1/20 of a
7161 printer's point, or about 1/10 of pixel). When retrieving, returns
7162 RE_Font.FontHeight.
7163 When set, changes font size for entire <A area> (but does not change
7164 other font attributes). }
7165 property RE_FmtFontSizeValid: Boolean read REGetFontSizeValid;
7166 {* |<#richedit>
7167 Returns True, if property RE_FmtFontSize is valid for entire selection,
7168 when retrieving it. }
7169 //property RE_FmtBackColor: Integer index (62 shl 16) or CFM_BACKCOLOR read REGetFontAttr write RESetFontAttr1;
7170 {* |<#richedit>
7171 Background color for an <A area>. }
7172 //property RE_FmtBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontEffect;
7173 {* |<#richedit>
7174 True, if RE_FmtBackColor valid for entire <A area>. }
7175 property RE_FmtAutoBackColor: Boolean index CFM_BACKCOLOR read REGetFontEffects write RESetFontEffect;
7176 {* |<#richedit>
7177 True, when automatic back color is used. }
7178 property RE_FmtAutoBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontMask;
7179 {* }
7180 property RE_FmtFontColor: Integer index (20 shl 16) or CFM_COLOR read REGetFontAttr write RESetFontAttr1;
7181 {* |<#richedit>
7182 Formatting value (font color). When retrieving, returns RE_Font.Color.
7183 When set, changes font color for entire <A area> (but does not change
7184 other font attributes). }
7185 property RE_FmtFontColorValid: Boolean index CFM_COLOR read REGetFontMask;
7186 {* |<#richedit>
7187 Returns True, if property RE_FmtFontColor valid for entire selection,
7188 when retrieving it. }
7189 property RE_FmtAutoColor: Boolean index CFM_COLOR read REGetFontEffects write RESetFontEffect;
7190 {* |<#richedit>
7191 True, when automatic text color is used (in such case, RE_FmtFontColor
7192 assignment is ignored for current area). }
7193 property RE_FmtAutoColorValid: Boolean index CFM_COLOR read REGetFontMask;
7194 {* }
7195 property RE_FmtBackColor: Integer index (64 shl 16) or CFM_BACKCOLOR read REGetFontAttr write RESetFontAttr1;
7196 {* |<#richedit>
7197 Formatting value (back color). Only available for Rich Edit 2.0 and higher.
7198 When set, changes background color for entire <A area> (but does not change
7199 other font attributes). }
7200 property RE_FmtBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontMask;
7201 {* }
7202 property RE_FmtFontOffset: Integer index (16 shl 16) or CFM_OFFSET read REGetFontAttr write RESetFontAttr;
7203 {* |<#richedit>
7204 Formatting value (font vertical offset from baseline, positive values
7205 correspond to subscript). When retrieving, returns offset for first
7206 character in the selection. When set, changes font offset for entire
7207 <A area>. To get know, is retrieved value valid for entire selction,
7208 check RE_FmtFontOffsetValid property. }
7209 property RE_FmtFontOffsetValid: Boolean index CFM_OFFSET read REGetFontMask;
7210 {* |<#richedit>
7211 Returns True, if property RE_FmtFontOffset is valid for entire selection,
7212 when retrieving it. }
7213 property RE_FmtFontCharset: Integer index (25 shl 16) or CFM_CHARSET read REGetFontAttr write RESetFontAttr;
7214 {* |<#richedit>
7215 Returns charset for first character in current selection, when retrieved
7216 (and to get know, if this value is valid for entire selection, check
7217 property RE_FmtFontCharsetValid). When set, changes charset for all
7218 characters in <A area>, but does not alter other formatting attributes. }
7219 property RE_FmtFontCharsetValid: Boolean index CFM_CHARSET read REGetFontMask;
7220 {* |<#richedit>
7221 Returns True, only if rerieved property RE_FmtFontCharset is valid for
7222 entire selection. }
7223 property RE_FmtFontName: String read REGetFontName write RESetFontName;
7224 {* |<#richedit>
7225 Returns font face name for first character in the selection, when retrieved,
7226 and sets font name for entire <A area>, wnen assigned to (without
7227 changing of other formatting attributes). To get know, if retrived
7228 font name valid for entire selection, examine property RE_FmtFontNameValid. }
7229 property RE_FmtFontNameValid: Boolean index CFM_FACE read REGetFontMask;
7230 {* |<#richedit>
7231 Returns True, only if the font name is the same for entire selection,
7232 thus is, if rerieved property value RE_FmtFontName is valid for entire
7233 selection. }
7235 property RE_ParaFmt: TParaFormat read REGetParaFmt write RESetParaFmt;
7236 {* |<#richedit>
7237 Allows to retrieve or set paragraph formatting attributes for currently
7238 selected paragraph(s) in RichEdit control. See also following properties,
7239 which allow to do the same for certain paragraph format attributes
7240 separately. }
7241 property RE_TextAlign: TRichTextAlign read REGetTextAlign write RESetTextAlign;
7242 {* |<#richedit>
7243 Returns text alignment for current selection and allows to change it
7244 (without changing other formatting attributes). }
7245 property RE_TextAlignValid: Boolean index PFM_ALIGNMENT read REGetParaAttrValid;
7246 {* |<#richedit>
7247 Returns True, if property RE_TextAlign is valid for entire selection. If
7248 False, it is concerning only start of selection. }
7249 property RE_Numbering: Boolean read REGetNumbering write RESetNumbering;
7250 {* |<#richedit>
7251 Returns True, if selected text is numbered (or has style of list with
7252 bullets). To get / change numbering style, see properties
7253 RE_NumStyle and RE_NumBrackets. }
7254 property RE_NumStyle: TRichNumbering read REGetNumStyle write RESetNumStyle;
7255 {* |<#richedit>
7256 Advanced numbering style, such as rnArabic etc. If You use it, do not
7257 change RE_Numbering property simultaneously - this can cause changing
7258 style to rnBullets only. }
7259 property RE_NumStart: Integer read REGetNumStart write RESetNumStart;
7260 {* |<#richedit>
7261 Starting number for advanced numbering style. If this property is not
7262 set, numbering is starting by default from 0. For rnLRoman and rnURoman
7263 this cause, that first item has no number to be shown (ancient Roman
7264 people did not invent '0'). }
7265 property RE_NumBrackets: TRichNumBrackets read REGetNumBrackets write RESetNumBrackets;
7266 {* |<#richedit>
7267 Brackets style for advanced numbering. rnbPlain is default
7268 brackets style, and every time, when RE_NumStyle is changed,
7269 RE_NumBrackets is reset to rnbPlain. }
7270 property RE_NumTab: Integer read REGetNumTab write RESetNumTab;
7271 {* |<#richedit>
7272 Tab between start of number and start of paragraph text. If too small too
7273 view number, number is not displayed. (Default value seems to be sufficient
7274 though). }
7275 property RE_NumberingValid: Boolean index PFM_NUMBERING read REGetParaAttrValid;
7276 {* |<#richedit>
7277 Returns True, if RE_Numbering, RE_NumStyle, RE_NumBrackets, RE_NumTab,
7278 RE_NumStart properties are valid for entire selection. }
7279 property RE_Level: Integer read REGetLevel;
7280 {* |<#richedit>
7281 Outline level (for numbering paragraphs?). Read only. }
7282 property RE_SpaceBefore: Integer index 0 or PFM_SPACEBEFORE read REGetSpacing write RESetSpacing;
7283 {* |<#richedit>
7284 Spacing before paragraph. }
7285 property RE_SpaceBeforeValid: Boolean index PFM_SPACEBEFORE read REGetParaAttrValid;
7286 {* |<#richedit>
7287 True, if RE_SpaceBefore value is valid for all selected paragraph (if
7288 False, this value is valid only for first paragraph. }
7289 property RE_SpaceAfter: Integer index 4 or PFM_SPACEAFTER read REGetSpacing write RESetSpacing;
7290 {* |<#richedit>
7291 Spacing after paragraph. }
7292 property RE_SpaceAfterValid: Boolean index PFM_SPACEAFTER read REGetParaAttrValid;
7293 {* |<#richedit>
7294 True, only if RE_SpaceAfter value is valid for all selected paragraphs. }
7295 property RE_LineSpacing: Integer index 8 or PFM_LINESPACING read REGetSpacing write RESetSpacing;
7296 {* |<#richedit>
7297 Linespacing in paragraph (this value is based on RE_SpacingRule property). }
7298 property RE_SpacingRule: Integer read REGetSpacingRule write RESetSpacingRule;
7299 {* |<#richedit>
7300 Linespacing rule. Do not know what is it. }
7301 property RE_LineSpacingValid: Boolean index PFM_LINESPACING read REGetParaAttrValid;
7302 {* |<#richedit>
7303 True, only if RE_LineSpacing and RE_SpacingRule values are valid for
7304 entire selection. }
7305 property RE_Indent: Integer index (20 shl 16) or PFM_OFFSET read REGetParaAttr write RESetParaAttr;
7306 {* |<#richedit>
7307 Returns left indentation for paragraph in current selection and allows
7308 to change it (without changing other formatting attributes). }
7309 property RE_IndentValid: Boolean index PFM_OFFSET read REGetParaAttrValid;
7310 {* |<#richedit>
7311 Returns True, if RE_Indent property is valid for entire selection. }
7312 property RE_StartIndent: Integer index (12 shl 16) or PFM_OFFSETINDENT read REGetParaAttr write RESetParaAttr;
7313 {* |<#richedit>
7314 Returns left indentation for first line in paragraph for current
7315 selection, and allows to change it (without changing other formatting
7316 attributes). }
7317 property RE_StartIndentValid: Boolean read REGetStartIndentValid;
7318 {* |<#richedit>
7319 Returns True, if property RE_StartIndent is valid for entire selection. }
7320 property RE_RightIndent: Integer index (16 shl 16) or PFM_RIGHTINDENT read REGetParaAttr write RESetParaAttr;
7321 {* |<#richedit>
7322 Returns right indent for paragraph in current selection, and allow to
7323 change it (without changing other formatting attributes). }
7324 property RE_RightIndentValid: Boolean index PFM_RIGHTINDENT read REGetParaAttrValid;
7325 {* |<#richedit>
7326 Returns True, if property RE_RightIndent is valid for entire selection only. }
7327 property RE_TabCount: Integer read REGetTabCount write RESetTabCount;
7328 {* |<#richedit>
7329 Number of tab stops in current selection. This value can not be set greater
7330 then MAX_TAB_COUNT (32). }
7331 property RE_Tabs[ Idx: Integer ]: Integer read REGetTabs write RESetTabs;
7332 {* |<#richedit>
7333 Tab stops for RichEdit control. }
7334 property RE_TabsValid: Boolean index PFM_TABSTOPS read REGetParaAttrValid;
7335 {* |<#richedit>
7336 Returns True, if properties RE_Tabs[ ] and RE_TabCount are valid for
7337 entire selection. }
7340 // following does not work now :
7341 property RE_BorderWidth[ Side: TBorderEdge ]: Integer index 2 read REGetBorder write RESetBorder;
7342 { * |<#richedit>
7343 Border width. }
7344 property RE_BorderSpace[ Side: TBorderEdge ]: Integer index 0 read REGetBorder write RESetBorder;
7345 { * |<#richedit>
7346 Border space. }
7347 property RE_BorderStyle[ Side: TBorderEdge ]: Integer index 4 read REGetBorder write RESetBorder;
7348 { * |<#richedit>
7349 Border style. }
7350 property RE_BorderValid: Boolean index PFM_BORDER read REGetParaAttrValid;
7351 { * |<#richedit>
7352 Returns True, if border style, space and width are the same for all
7353 paragraphs in selection. }
7354 property RE_Table: Boolean index $C000 read REGetParaEffect write RESetParaEffect;
7355 { * |<#richedit>
7356 True, if current paragraph is a part of table (row, cell or cell end).
7357 seems working as read only property. }
7358 // end of experiment section
7360 function RE_FmtStandard: PControl;
7361 {* |<#richedit>
7362 "Transparent" method (returns @Self as a result), which (when called)
7363 provides "standard" keyboard interface for formatting Rich text (just
7364 call this method, for example:
7365 ! RichEd1 := NewRichEdit( Panel1, [ ] ).SetAlign( caClient ).RE_FmtStandard;
7366 Following keys will be maintained additionally:
7367 |<pre>
7368 CTRL+I - switch "Italic",
7369 CTRL+B - switch "Bold",
7370 CTRL+U - switch "Underline",
7371 CTRL+SHIFT+U - swith underline type
7372 and turn underline on (note, that some of underline styles
7373 can not be shown properly in RichEdit v2.0 and lower,
7374 though RichEdit2.0 stores data successfully).
7375 CTRL+O - switch "StrikeOut",
7376 CTRL+'gray+' - increase font size,
7377 CTRL+'gray-' - decrease font size,
7378 CTRL+SHIFT+'gray+' - superscript,
7379 CTRL+SHIFT+'gray-' - subscript.
7380 CTRL+SHIFT+Z - ReDo
7381 |</pre>
7382 And, though following standard formatting keys are provided by RichEdit
7383 control itself in Windows2000, some of these are not functioning
7384 automatically in earlier Windows versions, even for RichEdit2.0. So,
7385 functionality of some of these (marked with (*) ) are added here too:
7386 |<pre>
7387 CTRL+L - align paragraph left, (*)
7388 CTRL+R - align paragraph right, (*)
7389 CTRL+E - align paragraph center, (*)
7390 CTRL+A - select all, (*)
7391 double-click on word - select word,
7392 CTRL+Right - to next word,
7393 CTRL+Left - to previous word,
7394 CTRL+Home - to the beginning of text,
7395 CTRL+End - to the end of text.
7396 CTRL+Z - UnDo
7397 |</pre>
7398 If You originally assign some (plain) text to Text property, switching "underline"
7399 can also change other font attributes, e.g., "bold" - if fsBold style is
7400 in default Font. To prevent such behavior, select entire text first (see
7401 SelectAll) and make assignment to RE_Font property, e.g.:
7402 ! RichEd1.SelectAll;
7403 ! RichEd1.RE_Font := RichEd1.RE_Font;
7404 ! RichEd1.SelLength := 0;
7405 |<br>
7406 And, some other notices about formatting. Please remember, that only True
7407 Type fonts can be succefully scaled and transformed to get desired effects
7408 (e.g., bold). By default, RichEdit uses System font face name, which can
7409 even have problems with fsBold style. Please remember also, that assigning
7410 RE_Font to RE_Font just initializying formatting attributes, making all
7411 those valid in entire text, but does not change font attributes. To use
7412 True Type font, directly assign face name You wish, e.g.:
7413 ! RichEd1.SelectAll;
7414 ! RichEd1.RE_Font := RichEd1.RE_Font;
7415 ! RichEd1.RE_Font.FontName := 'Arial';
7416 ! RichEd1.SelLength := 0;
7418 property RE_AutoKeyboard: Boolean index 1 read REGetLangOptions write RESetLangOptions;
7419 {* |<#richedit>
7420 True if autokeyboard on (lovely "feature" of automatic switching keyboard
7421 language when caret is over another language text). For older RichEdit,
7422 is 'on' always, for newest - 'off' by default. }
7424 property RE_OverwriteMode: Boolean read REGetOverwite write RESetOverwrite;
7425 {* |<#richedit>
7426 This property allows to control insert/overwrite mode. First, to examine, if
7427 insert or overwrite mode is current (but it is necessary either to
7428 access this property, at least once, immediately after creating RichEdit
7429 control, or to assign event OnRE_InsOvrMode_Change to your handler).
7430 Second, to set desired mode programmatically - by assigning value to
7431 this property (You also have to initialize monitoring procedure by either
7432 reading RE_OverwriteMode property or assigning handler to event
7433 OnRE_InsOvrMode_Change immediately following RichEdit control creation). }
7434 property OnRE_InsOvrMode_Change: TOnEvent read fOnREInsModeChg write fOnREInsModeChg;
7435 {* |<#richedit>
7436 This event is called, whenever key INSERT is pressed in control (and for
7437 RichEdit, this means, that insert mode is changed). }
7438 property RE_DisableOverwriteChange: Boolean read fReOvrDisable write RESetOvrDisable;
7439 {* |<#richedit>
7440 It is possible to disable switching between "insert" and "overwrite" mode
7441 by user (therefore, event OnRE_InsOvrMode_Change continue works, but it
7442 just called when key INSERT is pressed, though RE_OverwriteMode property
7443 is not actually changed if switching is disabled). }
7445 function RE_LoadFromStream( Stream: PStream; Length: Integer;
7446 Format: TRETextFormat; SelectionOnly: Boolean ): Boolean;
7447 {* |<#richedit>
7448 Use this method rather then assignment to RE_Text property, if
7449 source is stored in file or stream (to minimize resources during
7450 loading of RichEdit content). Data is loading starting from current
7451 position in stream and no more then Length bytes are loaded (use -1
7452 value to load to the end of stream). Loaded data replaces entire
7453 content of RichEdit control, or selection only, depending on SelectionOnly
7454 flag.
7455 |<br>&nbsp;&nbsp;&nbsp;
7456 If You want to provide progress (e.g. in form of progress bar), assign
7457 OnProgress event to your handler - and to examine current position of
7458 loading, read TSream.Position property of soiurce stream). }
7459 function RE_SaveToStream( Stream: PStream; Format: TRETextFormat; SelectionOnly: Boolean ): Boolean;
7460 {* |<#richedit>
7461 Use this method rather then RE_TextProperty to store data to file
7462 or stream (to minimize resources during saving of RichEdit content).
7463 Data is saving starting from current position in a stream (until
7464 end of RichEdit data). If SelectionOnly flag is True, only selected
7465 part of RichEdit text is saved.
7466 |<br>&nbsp;&nbsp;&nbsp;
7467 Like for RE_LoadFromStream, it is possible to assign your method to
7468 OnProgress event (but to calculate progress of save-to-stream operation,
7469 compare current stream position with RE_Size[ rsBytes ] property
7470 value). }
7472 property OnProgress: TOnEvent read fOnProgress write fOnProgress;
7473 {* |<#richedit>
7474 This event is called during RE_SaveToStream, RE_LoadFromStream (and also
7475 during RE_SaveToFile, RE_LoadFromFile and while accessing or changing
7476 RE_Text property). To calculate relative progress, it is possible to
7477 examine current position in stream/file with its total size while reading,
7478 or with rich edit text size, while writing (property RE_TextSize[ rsBytes ]).
7480 function RE_LoadFromFile( const Filename: String; Format: TRETextFormat;
7481 SelectionOnly: Boolean ): Boolean;
7482 {* |<#richedit>
7483 Use this method rather then other assignments to RE_Text property,
7484 if a source for RichEdit is the file. See also RE_LoadFromStream. }
7485 function RE_SaveToFile( const Filename: String; Format: TRETextFormat;
7486 SelectionOnly: Boolean ): Boolean;
7487 {* |<#richedit>
7488 Use this method rather then other similar, if You want to store
7489 entire content of RichEdit or selection only of RichEdit to a file. }
7491 property RE_Text[ Format: TRETextFormat; SelectionOnly: Boolean ]: String read REReadText write REWriteText;
7492 {* |<#richedit>
7493 This property allows to get / replace content of RichEdit control
7494 (entire text or selection only). Using different formats, it is
7495 possible to exclude or replace undesired formatting information
7496 (see TRETextFormat specification). To get or replace entire text
7497 in reText mode (plain text only), it is possible to use habitual
7498 for edit controls Text property.
7499 |<br>&nbsp;&nbsp;&nbsp;
7500 Note: it is possible to append text to the end of RichEdit control
7501 using method Add, but only if property RE_Text is accessed at least
7502 once:
7503 ! RichEdit1.RE_Text[ reText, True ];
7504 (This line can be written immediatelly after creating RichEdit control). }
7506 procedure RE_Append( const S: String; ACanUndo: Boolean );
7507 {* }
7508 procedure RE_InsertRTF( const S: String );
7509 {* }
7510 property RE_Error: Integer read fREError;
7511 {* |<#richedit>
7512 Contains error code, if access to RE_Text failed. }
7514 procedure RE_HideSelection( aHide: Boolean );
7515 {* |<#richedit>
7516 Allows to hide / show selection in RichEdit. }
7518 function RE_SearchText( const Value: String; MatchCase, WholeWord, ScanForward: Boolean;
7519 SearchFrom, SearchTo: Integer ): Integer;
7520 {* |<#richedit>
7521 Searches given string starting from SearchFrom position up to SearchTo
7522 position (to the end of text, if SearchTo is -1). Returns zero-based
7523 character position of the next match, or -1 if there are no more matches.
7524 To search in bacward direction, set ScanForward to False, and pass
7525 SearchFrom > SearchTo (or even SearchFrom = -1 and SearchTo = 0). }
7527 property RE_AutoURLDetect: Boolean read REGetAutoURLDetect write RESetAutoURLDetect;
7528 {* |<#richedit>
7529 If set to True, automatically detects URLs (and highlights it with
7530 blue color, applying fsItalic and fsUnderline font styles (while
7531 typing and loading). Default value is False. Note: if event OnRE_URLClick
7532 or event OnRE_OverURL are set, property RE_AutoURLDetect is set to True
7533 automatically. }
7535 property RE_URL: String read fREUrl;
7536 {* |<#richedit>
7537 Detected URL (valid in OnRE_OverURL and OnRE_URLClick event handlers). }
7538 property OnRE_OverURL: TOnEvent index 0
7539 {$IFDEF F_P} read REGetOnURL
7540 {$ELSE DELPHI} read fOnREOverURL
7541 {$ENDIF F_P/DELPHI} write RESetOnURL;
7542 {* |<#richedit>
7543 Is called when mouse is moving over URL. This can be used to set
7544 cursor, for example, depending on type of URL (to determine URL type
7545 read property RE_URL). }
7546 property OnRE_URLClick: TOnEvent index 8
7547 {$IFDEF F_P} read REGetOnURL
7548 {$ELSE DELPHI} read fOnREURLClick
7549 {$ENDIF F_P/DELPHI} write RESetOnURL;
7550 {* |<#richedit>
7551 Is called when click on URL detected. }
7553 //property RE_SelectionBar: Boolean read REGetSelectionBar write RESetSelectionBar;
7554 //{* ??? - don't know that is this... }
7555 function RE_NoOLEDragDrop: PControl;
7556 {* |<#richedit>
7557 Just prevents drop OLE objects to the rich edit control. Seems not
7558 working for some cases. }
7560 //function RE_Wyswig: PControl;
7562 function RE_Bottomless: PControl;
7563 // not finished
7565 property RE_Transparent: Boolean read REGetTransparent write RESetTransparent;
7566 {* |<#richedit>
7567 Use this property to make richedit control transparent, instead of
7568 Ed_Transparent or Transparent. But do not place such transparent
7569 richedit control directly on form - it can be draw incorrectly when
7570 form is activated and rich editr control is not current active control.
7571 Use at least panel as a parent instead.
7574 //========== both for Edit and RichEdit: =====================
7575 function CanUndo: Boolean;
7576 {* |<#richedit>
7577 |<#edit>
7578 |<#memo>
7579 Returns True, if the edit (or RichEdit) control can correctly process
7580 the EM_UNDO message. }
7581 procedure EmptyUndoBuffer;
7582 {* |<#richedit>
7583 |<#edit>
7584 |<#memo>
7585 Reset the undo flag of an edit control, preventing undoing all previous
7586 changes. }
7587 function Undo: Boolean;
7588 {* |<#richedit>
7589 |<#edit>
7590 |<#memo>
7591 For a single-line edit control, the return value is always TRUE. For a
7592 multiline edit control and RichEdit control, the return value is TRUE if
7593 the undo operation is successful, or FALSE if the undo operation fails. }
7595 function RE_Redo: Boolean;
7596 {* |<#richedit>
7597 Only for RichEdit control: Returns True if successful. }
7599 //----------------------------------------------------------------------
7600 // DateTimePicker
7601 property OnDTPUserString: TDTParseInputEvent read FOnDTPUserString
7602 write FOnDTPUserString;
7603 {* Special event to parse input from the application. Option dtpoParseInput
7604 must be set when control is created. }
7605 property DateTime: TDateTime read GetDateTime write SetDateTime;
7606 {* DateTime for DateTimePicker control only. }
7607 property Date: TDateTime read GetDate write SetDate;
7608 {* Date only for DateTimePicker control only. }
7609 property Time: TDateTime read GetTime write SetTime;
7610 {* Time only for DateTimePicker control only. }
7611 property DateTimeRange: TDateTimeRange read GetDateTimeRange
7612 write SetDateTimeRange;
7613 {* DateTimePicker range. If first date in the agrument assigned is NAN,
7614 minimum system allowed value is used as the left bound, and if the second is
7615 NAN, maximum system allowed is used as the right one. }
7616 property DateTimePickerColors[ Index: TDateTimePickerColor ]: TColor
7617 read GetDateTimePickerColor write SetDateTimePickerColor;
7618 property DateTimeFormat: String write SetDateTimeFormat;
7621 //----------------------------------------------------------------------
7623 //----------------------------------------------------------------------
7624 // ScrollBar
7625 property SBMin: Longint read fSBMinMax.X write SetSBMin;
7626 property SBMax: Longint read fSBMinMax.Y write SetSBMax;
7627 property SBMinMax: TPoint read fSBMinMax write SetSBMinMax;
7628 property SBPosition: Integer read fSBPosition write SetSBPosition;
7629 property SBPageSize: Integer read fSBPageSize write SetSBPageSize;
7631 property OnSBBeforeScroll: TOnSBBeforeScroll read FOnSBBeforeScroll write FOnSBBeforeScroll;
7632 property OnSBScroll: TOnSBScroll read FOnSBScroll write FOnSBScroll;
7634 function SBSetScrollInfo(const SI: TScrollInfo): Integer;
7635 function SBGetScrollInfo(var SI: TScrollInfo): Boolean;
7636 function GetSBMinMax: TPoint;
7637 function GetSBPageSize: Integer;
7638 function GetSBPosition: Integer;
7639 //----------------------------------------------------------------------
7642 // "Through", or "transparent" methods to simplify initial
7643 // adjustment of controls and make non-visual designing of
7644 // forms more easy. All these functions return @Self as a
7645 // result, so, it is possible to use such methods immediately
7646 // in constructing statement, concatenating it with dots, e.g.:
7648 // NewButton( MyForm, 'Click here' ).PlaceUnder.ResizeParentBottom;
7650 function PlaceRight: PControl;
7651 {* Places control right (to previously created on the same parent). }
7652 function PlaceDown: PControl;
7653 {* Places control below (to previously created on the same parent).
7654 Left position is not changed (thus is, kept equal to Parent.Margin). }
7655 function PlaceUnder: PControl;
7656 {* Places control below (to previously created one, aligning its
7657 Left position to Left position of previous control). }
7658 function SetSize( W, H: Integer ): PControl;
7660 {* Changes size of a control. If W or H less or equal to 0,
7661 correspondent size is not changed. }
7662 function Size( W, H: Integer ): PControl;
7663 {* Like SetSize, but provides automatic resizing of parent control
7664 (recursively). Especially useful for aligned controls. }
7665 function SetClientSize( W, H: Integer ): PControl;
7666 {* Like SetSize, but works setting W = ClientWidth, H = ClientHeight.
7667 Use this method for forms, which can not be resized (dialogs). }
7669 function AutoSize( AutoSzOn: Boolean ): PControl;
7671 {* Determines if to autosize control (like label, button, etc.) }
7672 function IsAutoSize: Boolean;
7673 {* TRUE, if a control is autosizing. }
7674 function AlignLeft( P: PControl ): PControl;
7675 {* assigns Left := P.Left }
7676 function AlignTop( P: PControl ): PControl;
7677 {* assigns Top := P.Top }
7678 function ResizeParent: PControl;
7679 {* Resizes parent, calling ResizeParentRight and ResizeParentBottom. }
7680 function ResizeParentRight: PControl;
7681 {* Resizes parent right edge (Margin of parent is added to right
7682 coordinate of a control). If called second time (for the same
7683 parent), resizes only for increasing of right edge of parent. }
7685 function ResizeParentBottom: PControl;
7686 {* Resizes parent bottom edge (Margin of parent is added to
7687 bottom coordinate of a control). }
7688 function CenterOnParent: PControl;
7689 {* Centers control on parent, or if applied to a form, centers
7690 form on screen. }
7692 function Shift( dX, dY : Integer ): PControl;
7693 {* Moves control respectively to current position (Left := Left + dX,
7694 Top := Top + dY). }
7695 function SetPosition( X, Y: Integer ): PControl;
7696 {* Moves control directly to the specified position. }
7698 function Tabulate: PControl;
7699 {* Call it once for form/applet to provide tabulation between controls on
7700 form/on all forms using TAB / SHIFT+TAB and arrow keys. }
7701 function TabulateEx: PControl;
7702 {* Call it once for form/applet to provide tabulation between controls on
7703 form/on all forms using TAB / SHIFT+TAB and arrow keys. Arrow keys are
7704 used more smart, allowing go to nearest control in certain direction. }
7706 function SetAlign( AAlign: TControlAlign ): PControl;
7707 {* Assigns passed value to property Align, aligning control on parent,
7708 and returns @Self (so it is "transparent" function, which can be
7709 used to adjust control at the creation, e.g.:
7710 ! MyLabel := NewLabel( MyForm, 'Label1' ).SetAlign( caBottom );
7711 See also property Align. }
7712 function PreventResizeFlicks: PControl;
7713 {* If called, prevents resizing flicks for child controls, aligned to
7714 right and bottom (but with a lot of code added to executable - about 3,5K).
7715 There is sensible to set DoubleBuffered to True also to eliminate the
7716 most of flicks.
7717 |<br>&nbsp;&nbsp;&nbsp;
7718 This method been applied to a form, prevents, resizing flicks for
7719 form and all controls on the form. If it is called for applet window,
7720 all forms are affected. And if You want, You can apply it for certain
7721 control only - in such case only given control and its children will
7722 be resizing without flicks (e.g., using splitter control). }
7724 property Checked: Boolean read GetChecked write Set_Checked;
7725 {* |<#checkbox>
7726 |<#radiobox>
7727 For checkbox and radiobox - if it is checked. Do not assign
7728 value for radiobox - use SetRadioChecked instead. }
7729 function SetChecked(const Value: Boolean): PControl;
7730 {* |<#checkbox>
7731 Use it to check/uncheck check box control or push button.
7732 Do not apply it to check radio buttons - use SetRadioChecked
7733 method below. }
7734 function SetRadioChecked : PControl;
7735 {* |<#radiobox>
7736 Use it to check radio button item correctly (unchecking all
7737 alternative ones). Actually, method Click is called, and control
7738 itself is returned. }
7739 function SetRadioCheckedOld: PControl;
7740 {* |<#radiobox>
7741 Old version of SetRadioChecked (implemented using recommended API
7742 call. It does not work properly, if control is not visible
7743 (together with its form). }
7744 procedure Click;
7745 {* |<#button>
7746 |<#checkbox>
7747 |<#radiobox>
7748 Emulates click on control programmatically, sending WM_COMMAND
7749 message with BN_CLICKED code. This method is sensible only for
7750 buttons, checkboxes and radioboxes. }
7752 function Perform( msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;
7753 {* Sends message to control's window (created if needed). }
7754 procedure AttachProc( Proc: TWindowFunc );
7755 {* It is possible to attach dynamically any message handler to window
7756 procedure using this method. Last attached procedure is called first.
7757 If procedure returns True, further processing of a message is stopped.
7758 Attached procedure can be detached using DetachProc (but do not
7759 attach/detach procedures during handling of attached procedure -
7760 this can hang application). }
7761 procedure AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );
7762 {* The same as AttachProc, but a handler is executed even after terminating
7763 the main message loop processing (i.e. after assigning true to
7764 AppletTerminated global variable. }
7765 function IsProcAttached( Proc: TWindowFunc ): Boolean;
7766 {* Returns True, if given procedure is already in chain of attached
7767 ones for given control window proc. }
7768 procedure DetachProc( Proc: TWindowFunc );
7769 {* Detaches procedure attached earlier using AttachProc. }
7771 property OnDropFiles: TOnDropFiles read FOnDropFiles write SetOnDropFiles;
7772 {* Assign this event to your handler, if You want to accept drag and drop
7773 files from other applications such as explorer onto your control. When
7774 this event is assigned to a control or form, this has effect also for
7775 all its child controls too. }
7777 property CustomData: Pointer read fCustomData write fCustomData;
7778 {* Can be used to exend the object when new type of control added. Memory,
7779 pointed by this pointer, released automatically in the destructor. }
7780 property CustomObj: PObj read fCustomObj write fCustomObj;
7781 {* Can be used to exend the object when new type of control added. Object,
7782 pointed by this pointer, released automatically in the destructor. }
7783 procedure SetAutoPopupMenu( PopupMenu: PObj );
7784 {* To assign a popup menu to the control, call SetAutoPopupMenu method of
7785 the control with popup menu object as a parameter. }
7787 function SupportMnemonics: PControl;
7788 {* This method provides supporting mnemonic keys in menus, buttons, checkboxes,
7789 toolbar buttons. }
7790 property OnScroll: TOnScroll read FOnScroll write SetOnScroll;
7791 {* }
7795 {$IFDEF USE_CONSTRUCTORS}
7796 //------------------------------------------------------------
7797 // constructors here:
7798 constructor CreateWindowed( AParent: PControl; AClassName: PChar; ACtl3D: Boolean );
7799 constructor CreateApplet( const ACaption: String );
7800 constructor CreateForm( AParent: PControl; const ACaption: String );
7801 constructor CreateControl( AParent: PControl; AClassName: PChar; AStyle: DWORD;
7802 ACtl3D: Boolean; Actions: PCommandActions );
7803 constructor CreateButton( AParent: PControl; const ACaption: String );
7804 constructor CreateBitBtn( AParent: PControl; const ACaption: String;
7805 AOptions: TBitBtnOptions; ALayout: TGlyphLayout; AGlyphBitmap: HBitmap;
7806 AGlyphCount: Integer);
7807 constructor CreateLabel( AParent: PControl; const ACaption: String );
7808 constructor CreateWordWrapLabel( AParent: PControl; const ACaption: String );
7809 constructor CreateLabelEffect( AParent: PControl; ACaption: String; AShadowDeep: Integer );
7810 constructor CreatePaintBox( AParent: PControl );
7811 constructor CreateGradientPanel( AParent: PControl; AColor1, AColor2: TColor );
7812 constructor CreateGradientPanelEx( AParent: PControl; AColor1, AColor2: TColor;
7813 AStyle: TGradientStyle; ALayout: TGradientLayout );
7814 constructor CreateGroupbox( AParent: PControl; const ACaption: String );
7815 constructor CreateCheckbox( AParent: PControl; const ACaption: String );
7816 constructor CreateRadiobox( AParent: PControl; const ACaption: String );
7817 constructor CreateEditbox( AParent: PControl; AOptions: TEditOptions );
7818 constructor CreatePanel( AParent: PControl; AStyle: TEdgeStyle );
7819 constructor CreateSplitter( AParent: PControl; AMinSizePrev, AMinSizeNext: Integer;
7820 EdgeStyle: TEdgeStyle );
7821 constructor CreateListbox( AParent: PControl; AOptions: TListOptions );
7822 constructor CreateCombobox( AParent: PControl; AOptions: TComboOptions );
7823 constructor CreateCommonControl( AParent: PControl; AClassName: PChar; AStyle: DWORD;
7824 ACtl3D: Boolean; Actions: PCommandActions );
7825 constructor CreateRichEdit( AParent: PControl; AOptions: TEditOptions );
7826 constructor CreateRichEdit1( AParent: PControl; AOptions: TEditOptions );
7827 constructor CreateProgressbar( AParent: PControl );
7828 constructor CreateProgressbarEx( AParent: PControl; AOptions: TProgressbarOptions );
7829 constructor CreateListView( AParent: PControl; AStyle: TListViewStyle; AOptions: TListViewOptions;
7830 AImageListSmall, AImageListNormal, AImageListState: PImageList );
7831 constructor CreateTreeView( AParent: PControl; AOptions: TTreeViewOptions;
7832 AImgListNormal, AImgListState: PImageList );
7833 constructor CreateTabControl( AParent: PControl; ATabs: array of String;
7834 AOptions: TTabControlOptions; AImgList: PImageList; AImgList1stIdx: Integer );
7835 constructor CreateToolbar( AParent: PControl; AAlign: TControlAlign; AOptions: TToolbarOptions;
7836 ABitmap: HBitmap; AButtons: array of PChar;
7837 ABtnImgIdxArray: array of Integer );
7838 {$ENDIF USE_CONSTRUCTORS}
7840 {$IFDEF USE_CUSTOMEXTENSIONS}
7841 {$I CUSTOM_TCONTROL_EXTENSION.inc}
7842 {$ENDIF}
7843 // If an option USE_CUSTOMEXTENSIONS is enabled (at the beginning of this
7844 // unit), You can freely extend TControl definition by your own fields,
7845 // methods and properties. This provides You with capability to extend
7846 // TControl implementing another kinds of visual controls without deriving
7847 // new descendant objects from TControl. This way is provided to avoid too
7848 // large grow of executable size. You also can derive your own controls
7849 // from TControl using standard OOP capabilities. In such case an option
7850 // USE_CONSTRUCTORS should be turned on (see it at the start of this unit).
7851 // If You choose this "flat" model of extending the TControl with your
7852 // own properties, fieds, methods, events, etc. You should provide three
7853 // inc-files: CUSTOM_TCONTROL_EXTENSION.inc, containing such definitions
7854 // for TControl, CUSTOM_KOL_EXTENSION.inc, containing needed global
7855 // declarations, and CUSTOM_CODE_EXTENSION.inc, the implementation of those
7856 // two.
7857 // Because KOL is always grow and constantly is extending by me, I also can
7858 // add my own complements for TControl. To avoid naming conflicts, I suggest
7859 // to use the same naming rule for all of You. Name your fields, properies, etc.
7860 // using a form idx_SomeName, where idx is a prefix, containing several
7861 // (at least one) letters and digits. E.g. ZK65_OnSomething.
7863 protected
7864 {$IFDEF USE_DROPDOWNCOUNT}
7865 fDropDownCount: Cardinal;
7866 {$ENDIF}
7867 public
7868 {$IFDEF USE_DROPDOWNCOUNT}
7869 property DropDownCount: Cardinal read fDropDownCount write fDropDownCount;
7870 {$ENDIF}
7871 end;
7872 //[END OF TControl DEFINITION]
7874 {$IFDEF USE_MHTOOLTIP}
7875 {$DEFINE interface}
7876 {$I KOLMHToolTip}
7877 {$UNDEF interface}
7878 {$ENDIF}
7880 //[Paint Background PROCEDURE]
7881 type
7882 TOnPaintBkgnd = procedure( Sender: PControl; DC: HDC; Rect: PRect );
7883 {* Global event definition. Used to define Global_OnPaintBackground
7884 event placeholder. }
7886 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );
7889 Global_OnPaintBkgnd: TOnPaintBkgnd = DefaultPaintBackground;
7890 {* Global event. It is assigned in XBackgounds.pas add-on to replace
7891 PaintBackground method for all TVisual objects, allowing great
7892 visualization effect: transparent controls over [animated] bitmap
7893 background. Idea:
7894 | <a href=mailto:"bw@sunv.com">Wei&nbsp;Bao</a>. Implementation:
7895 | <a href=mailto:"bonanzas@xcl.cjb.net">Kladov&nbsp;Vladimir</a>. }
7897 procedure DummyPaintProc( Sender: PControl; DC: HDC );
7899 //[GetShiftState DECLARATION]
7900 function GetShiftState: DWORD;
7902 //[WndProcXXX DECLARATIONS]
7903 function WndProcMouse( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7904 function WndProcKeybd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7905 function WndProcDummy( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7906 function WndProcBufferedDraw( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7907 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
7908 function WndProcBtnReturnClick( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7909 {$ENDIF}
7911 //[InitCommonXXXX DECLARATIONS]
7912 procedure InitCommonControlSizeNotify( Ctrl: PControl );
7913 procedure InitCommonControlCommonNotify( Ctrl: PControl );
7915 //[Buffered Draw DECLARATIONS]
7917 Global_OnBufferedDraw: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean
7918 = WndProcDummy;
7919 Global_DblBufCreateWnd: procedure( Sender: PObj ) = DummyObjProc;
7920 Global_Invalidate: procedure( Sender: PObj ) = DummyObjProc;
7921 {* Is called in TControl.Invalidate to extend it in case when DoubleBuffered
7922 painting used. }
7924 Global_TranspDrawBkgnd: procedure( DC: HDC; Sender: PControl );
7926 //Global_OnCreateWindow: procedure( Sender: PObj ) = DummyObjProc;
7927 //{* Is called when TControl object is created. }
7928 //Global_OnDestroyWindow: procedure( Sender: PObj ) = DummyObjProc;
7929 //{* Is called before destroying TControl object (after accepting it,
7930 // if event OnClose is defined). }
7931 Global_OnBeginPaint: procedure( Sender: PControl; DC: HDC ) = DummyPaintProc;
7932 {* Is called before painting a window. }
7933 Global_OnEndPaint: procedure( Sender: PControl; DC: HDC ) = DummyPaintProc;
7934 {* Is called after painting a window. }
7935 HelpFilePath: PChar;
7936 {* Path to application help file. If not assigned, application path with
7937 extension replaced to '.hlp' used. To use '.chm' file (HtmlHelp),
7938 call AssignHtmlHelp with a path to a html help file (or a name). }
7940 //[Html Help DECLARATIONS]
7941 procedure AssignHtmlHelp( const HtmlHelpPath: String );
7942 procedure HtmlHelpCommand( Wnd: HWnd; const HelpFilePath: String; Cmd, Data: Integer );
7943 {* Use this wrapper procedure to call HtmlHelp API function. }
7944 //+++++++++++ HTML HELP DEFINITIONS SECTION:
7945 // this section is from
7946 // HTML Help API Interface Unit
7947 // Copyright (c) 1999 The Helpware Group
7948 // provided for KOL by Alexey Babenko
7949 const
7950 HH_DISPLAY_TOPIC = $0000; {**}
7951 HH_HELP_FINDER = $0000; // WinHelp equivalent
7952 HH_DISPLAY_TOC = $0001; // not currently implemented
7953 HH_DISPLAY_INDEX = $0002; // not currently implemented
7954 HH_DISPLAY_SEARCH = $0003; // not currently implemented
7955 HH_SET_WIN_TYPE = $0004;
7956 HH_GET_WIN_TYPE = $0005;
7957 HH_GET_WIN_HANDLE = $0006;
7958 HH_ENUM_INFO_TYPE = $0007; // Get Info type name, call repeatedly to enumerate, -1 at end
7959 HH_SET_INFO_TYPE = $0008; // Add Info type to filter.
7960 HH_SYNC = $0009;
7961 HH_RESERVED1 = $000A;
7962 HH_RESERVED2 = $000B;
7963 HH_RESERVED3 = $000C;
7964 HH_KEYWORD_LOOKUP = $000D;
7965 HH_DISPLAY_TEXT_POPUP = $000E; // display string resource id or text in a popup window
7966 HH_HELP_CONTEXT = $000F; {**}// display mapped numeric value in dwData
7967 HH_TP_HELP_CONTEXTMENU = $0010; // text popup help, same as WinHelp HELP_CONTEXTMENU
7968 HH_TP_HELP_WM_HELP = $0011; // text popup help, same as WinHelp HELP_WM_HELP
7969 HH_CLOSE_ALL = $0012; // close all windows opened directly or indirectly by the caller
7970 HH_ALINK_LOOKUP = $0013; // ALink version of HH_KEYWORD_LOOKUP
7971 HH_GET_LAST_ERROR = $0014; // not currently implemented // See HHERROR.h
7972 HH_ENUM_CATEGORY = $0015; // Get category name, call repeatedly to enumerate, -1 at end
7973 HH_ENUM_CATEGORY_IT = $0016; // Get category info type members, call repeatedly to enumerate, -1 at end
7974 HH_RESET_IT_FILTER = $0017; // Clear the info type filter of all info types.
7975 HH_SET_INCLUSIVE_FILTER = $0018; // set inclusive filtering method for untyped topics to be included in display
7976 HH_SET_EXCLUSIVE_FILTER = $0019; // set exclusive filtering method for untyped topics to be excluded from display
7977 HH_INITIALIZE = $001C; // Initializes the help system.
7978 HH_UNINITIALIZE = $001D; // Uninitializes the help system.
7979 HH_PRETRANSLATEMESSAGE = $00fd; // Pumps messages. (NULL, NULL, MSG*).
7980 HH_SET_GLOBAL_PROPERTY = $00fc; // Set a global property. (NULL, NULL, HH_GPROP)
7982 { window properties }
7984 const
7985 HHWIN_PROP_TAB_AUTOHIDESHOW = $00000001; // (1 << 0) Automatically hide/show tri-pane window
7986 HHWIN_PROP_ONTOP = $00000002; // (1 << 1) Top-most window
7987 HHWIN_PROP_NOTITLEBAR = $00000004; // (1 << 2) no title bar
7988 HHWIN_PROP_NODEF_STYLES = $00000008; // (1 << 3) no default window styles (only HH_WINTYPE.dwStyles)
7989 HHWIN_PROP_NODEF_EXSTYLES = $00000010; // (1 << 4) no default extended window styles (only HH_WINTYPE.dwExStyles)
7990 HHWIN_PROP_TRI_PANE = $00000020; // (1 << 5) use a tri-pane window
7991 HHWIN_PROP_NOTB_TEXT = $00000040; // (1 << 6) no text on toolbar buttons
7992 HHWIN_PROP_POST_QUIT = $00000080; // (1 << 7) post WM_QUIT message when window closes
7993 HHWIN_PROP_AUTO_SYNC = $00000100; // (1 << 8) automatically ssync contents and index
7994 HHWIN_PROP_TRACKING = $00000200; // (1 << 9) send tracking notification messages
7995 HHWIN_PROP_TAB_SEARCH = $00000400; // (1 << 10) include search tab in navigation pane
7996 HHWIN_PROP_TAB_HISTORY = $00000800; // (1 << 11) include history tab in navigation pane
7997 HHWIN_PROP_TAB_FAVORITES = $00001000; // (1 << 12) include favorites tab in navigation pane
7998 HHWIN_PROP_CHANGE_TITLE = $00002000; // (1 << 13) Put current HTML title in title bar
7999 HHWIN_PROP_NAV_ONLY_WIN = $00004000; // (1 << 14) Only display the navigation window
8000 HHWIN_PROP_NO_TOOLBAR = $00008000; // (1 << 15) Don't display a toolbar
8001 HHWIN_PROP_MENU = $00010000; // (1 << 16) Menu
8002 HHWIN_PROP_TAB_ADVSEARCH = $00020000; // (1 << 17) Advanced FTS UI.
8003 HHWIN_PROP_USER_POS = $00040000; // (1 << 18) After initial creation, user controls window size/position
8004 HHWIN_PROP_TAB_CUSTOM1 = $00080000; // (1 << 19) Use custom tab #1
8005 HHWIN_PROP_TAB_CUSTOM2 = $00100000; // (1 << 20) Use custom tab #2
8006 HHWIN_PROP_TAB_CUSTOM3 = $00200000; // (1 << 21) Use custom tab #3
8007 HHWIN_PROP_TAB_CUSTOM4 = $00400000; // (1 << 22) Use custom tab #4
8008 HHWIN_PROP_TAB_CUSTOM5 = $00800000; // (1 << 23) Use custom tab #5
8009 HHWIN_PROP_TAB_CUSTOM6 = $01000000; // (1 << 24) Use custom tab #6
8010 HHWIN_PROP_TAB_CUSTOM7 = $02000000; // (1 << 25) Use custom tab #7
8011 HHWIN_PROP_TAB_CUSTOM8 = $04000000; // (1 << 26) Use custom tab #8
8012 HHWIN_PROP_TAB_CUSTOM9 = $08000000; // (1 << 27) Use custom tab #9
8013 HHWIN_TB_MARGIN = $10000000; // (1 << 28) the window type has a margin
8015 { window parameters }
8017 const
8018 HHWIN_PARAM_PROPERTIES = $00000002; // (1 << 1) valid fsWinProperties
8019 HHWIN_PARAM_STYLES = $00000004; // (1 << 2) valid dwStyles
8020 HHWIN_PARAM_EXSTYLES = $00000008; // (1 << 3) valid dwExStyles
8021 HHWIN_PARAM_RECT = $00000010; // (1 << 4) valid rcWindowPos
8022 HHWIN_PARAM_NAV_WIDTH = $00000020; // (1 << 5) valid iNavWidth
8023 HHWIN_PARAM_SHOWSTATE = $00000040; // (1 << 6) valid nShowState
8024 HHWIN_PARAM_INFOTYPES = $00000080; // (1 << 7) valid apInfoTypes
8025 HHWIN_PARAM_TB_FLAGS = $00000100; // (1 << 8) valid fsToolBarFlags
8026 HHWIN_PARAM_EXPANSION = $00000200; // (1 << 9) valid fNotExpanded
8027 HHWIN_PARAM_TABPOS = $00000400; // (1 << 10) valid tabpos
8028 HHWIN_PARAM_TABORDER = $00000800; // (1 << 11) valid taborder
8029 HHWIN_PARAM_HISTORY_COUNT = $00001000; // (1 << 12) valid cHistory
8030 HHWIN_PARAM_CUR_TAB = $00002000; // (1 << 13) valid curNavType
8032 { button constants }
8034 const
8035 HHWIN_BUTTON_EXPAND = $00000002; // (1 << 1) Expand/contract button
8036 HHWIN_BUTTON_BACK = $00000004; // (1 << 2) Back button
8037 HHWIN_BUTTON_FORWARD = $00000008; // (1 << 3) Forward button
8038 HHWIN_BUTTON_STOP = $00000010; // (1 << 4) Stop button
8039 HHWIN_BUTTON_REFRESH = $00000020; // (1 << 5) Refresh button
8040 HHWIN_BUTTON_HOME = $00000040; // (1 << 6) Home button
8041 HHWIN_BUTTON_BROWSE_FWD = $00000080; // (1 << 7) not implemented
8042 HHWIN_BUTTON_BROWSE_BCK = $00000100; // (1 << 8) not implemented
8043 HHWIN_BUTTON_NOTES = $00000200; // (1 << 9) not implemented
8044 HHWIN_BUTTON_CONTENTS = $00000400; // (1 << 10) not implemented
8045 HHWIN_BUTTON_SYNC = $00000800; // (1 << 11) Sync button
8046 HHWIN_BUTTON_OPTIONS = $00001000; // (1 << 12) Options button
8047 HHWIN_BUTTON_PRINT = $00002000; // (1 << 13) Print button
8048 HHWIN_BUTTON_INDEX = $00004000; // (1 << 14) not implemented
8049 HHWIN_BUTTON_SEARCH = $00008000; // (1 << 15) not implemented
8050 HHWIN_BUTTON_HISTORY = $00010000; // (1 << 16) not implemented
8051 HHWIN_BUTTON_FAVORITES = $00020000; // (1 << 17) not implemented
8052 HHWIN_BUTTON_JUMP1 = $00040000; // (1 << 18)
8053 HHWIN_BUTTON_JUMP2 = $00080000; // (1 << 19)
8054 HHWIN_BUTTON_ZOOM = $00100000; // (1 << 20)
8055 HHWIN_BUTTON_TOC_NEXT = $00200000; // (1 << 21)
8056 HHWIN_BUTTON_TOC_PREV = $00400000; // (1 << 22)
8058 HHWIN_DEF_BUTTONS = (HHWIN_BUTTON_EXPAND
8059 OR HHWIN_BUTTON_BACK
8060 OR HHWIN_BUTTON_OPTIONS
8061 OR HHWIN_BUTTON_PRINT);
8064 { Button IDs }
8066 const
8067 IDTB_EXPAND = 200;
8068 IDTB_CONTRACT = 201;
8069 IDTB_STOP = 202;
8070 IDTB_REFRESH = 203;
8071 IDTB_BACK = 204;
8072 IDTB_HOME = 205;
8073 IDTB_SYNC = 206;
8074 IDTB_PRINT = 207;
8075 IDTB_OPTIONS = 208;
8076 IDTB_FORWARD = 209;
8077 IDTB_NOTES = 210; // not implemented
8078 IDTB_BROWSE_FWD = 211;
8079 IDTB_BROWSE_BACK = 212;
8080 IDTB_CONTENTS = 213; // not implemented
8081 IDTB_INDEX = 214; // not implemented
8082 IDTB_SEARCH = 215; // not implemented
8083 IDTB_HISTORY = 216; // not implemented
8084 IDTB_FAVORITES = 217; // not implemented
8085 IDTB_JUMP1 = 218;
8086 IDTB_JUMP2 = 219;
8087 IDTB_CUSTOMIZE = 221;
8088 IDTB_ZOOM = 222;
8089 IDTB_TOC_NEXT = 223;
8090 IDTB_TOC_PREV = 224;
8093 { Notification codes }
8095 const
8096 HHN_FIRST = (0-860);
8097 HHN_LAST = (0-879);
8099 HHN_NAVCOMPLETE = (HHN_FIRST-0);
8100 HHN_TRACK = (HHN_FIRST-1);
8101 HHN_WINDOW_CREATE = (HHN_FIRST-2);
8104 type
8105 {*** Used by command HH_GET_LAST_ERROR
8106 NOTE: Not part of the htmlhelp.h but documented in HH Workshop help
8107 You must call SysFreeString(xx.description) to free BSTR
8109 tagHH_LAST_ERROR = packed record
8110 cbStruct: Integer; // sizeof this structure
8111 hr: Integer; // Specifies the last error code.
8112 description: PWideChar; // (BSTR) Specifies a Unicode string containing a description of the error.
8113 end;
8114 HH_LAST_ERROR = tagHH_LAST_ERROR;
8115 THHLastError = tagHH_LAST_ERROR;
8118 type
8119 {*** Notify event info for HHN_NAVCOMPLETE, HHN_WINDOW_CREATE }
8120 PHHNNotify = ^THHNNotify;
8121 tagHHN_NOTIFY = packed record
8122 hdr: TNMHdr;
8123 pszUrl: PChar; //PCSTR: Multi-byte, null-terminated string
8124 end;
8125 HHN_NOTIFY = tagHHN_NOTIFY;
8126 THHNNotify = tagHHN_NOTIFY;
8128 {** Use by command HH_DISPLAY_TEXT_POPUP}
8129 PHHPopup = ^THHPopup;
8130 tagHH_POPUP = packed record
8131 cbStruct: Integer; // sizeof this structure
8132 hinst: HINST; // instance handle for string resource
8133 idString: cardinal; // string resource id, or text id if pszFile is specified in HtmlHelp call
8134 pszText: PChar; // used if idString is zero
8135 pt: TPOINT; // top center of popup window
8136 clrForeground: COLORREF; // use -1 for default
8137 clrBackground: COLORREF; // use -1 for default
8138 rcMargins: TRect; // amount of space between edges of window and text, -1 for each member to ignore
8139 pszFont: PChar; // facename, point size, char set, BOLD ITALIC UNDERLINE
8140 end;
8141 HH_POPUP = tagHH_POPUP;
8142 THHPopup = tagHH_POPUP;
8144 {** Use by commands - HH_ALINK_LOOKUP, HH_KEYWORD_LOOKUP}
8145 PHHAKLink = ^THHAKLink;
8146 tagHH_AKLINK = packed record
8147 cbStruct: integer; // sizeof this structure
8148 fReserved: BOOL; // must be FALSE (really!)
8149 pszKeywords: PChar; // semi-colon separated keywords
8150 pszUrl: PChar; // URL to jump to if no keywords found (may be NULL)
8151 pszMsgText: PChar; // Message text to display in MessageBox if pszUrl is NULL and no keyword match
8152 pszMsgTitle: PChar; // Message text to display in MessageBox if pszUrl is NULL and no keyword match
8153 pszWindow: PChar; // Window to display URL in
8154 fIndexOnFail: BOOL; // Displays index if keyword lookup fails.
8155 end;
8156 HH_AKLINK = tagHH_AKLINK;
8157 THHAKLink = tagHH_AKLINK;
8160 const
8161 HHWIN_NAVTYPE_TOC = 0;
8162 HHWIN_NAVTYPE_INDEX = 1;
8163 HHWIN_NAVTYPE_SEARCH = 2;
8164 HHWIN_NAVTYPE_FAVORITES = 3;
8165 HHWIN_NAVTYPE_HISTORY = 4; // not implemented
8166 HHWIN_NAVTYPE_AUTHOR = 5;
8167 HHWIN_NAVTYPE_CUSTOM_FIRST = 11;
8170 const
8171 IT_INCLUSIVE = 0;
8172 IT_EXCLUSIVE = 1;
8173 IT_HIDDEN = 2;
8175 type
8176 PHHEnumIT = ^THHEnumIT;
8177 tagHH_ENUM_IT = packed record //tagHH_ENUM_IT, HH_ENUM_IT, *PHH_ENUM_IT
8178 cbStruct: Integer; // size of this structure
8179 iType: Integer; // the type of the information type ie. Inclusive, Exclusive, or Hidden
8180 pszCatName: PAnsiChar; // Set to the name of the Category to enumerate the info types in a category; else NULL
8181 pszITName: PAnsiChar; // volitile pointer to the name of the infotype. Allocated by call. Caller responsible for freeing
8182 pszITDescription: PAnsiChar; // volitile pointer to the description of the infotype.
8183 end;
8184 THHEnumIT = tagHH_ENUM_IT;
8187 type
8188 PHHEnumCat = ^THHEnumCat;
8189 tagHH_ENUM_CAT = packed record //tagHH_ENUM_CAT, HH_ENUM_CAT, *PHH_ENUM_CAT
8190 cbStruct: Integer; // size of this structure
8191 pszCatName: PAnsiChar; // volitile pointer to the category name
8192 pszCatDescription: PAnsiChar; // volitile pointer to the category description
8193 end;
8194 THHEnumCat = tagHH_ENUM_CAT;
8197 type
8198 PHHSetInfoType = ^THHSetInfoType;
8199 tagHH_SET_INFOTYPE = packed record //tagHH_SET_INFOTYPE, HH_SET_INFOTYPE, *PHH_SET_INFOTYPE
8200 cbStruct: Integer; // the size of this structure
8201 pszCatName: PAnsiChar; // the name of the category, if any, the InfoType is a member of.
8202 pszInfoTypeName: PAnsiChar; // the name of the info type to add to the filter
8203 end;
8204 THHSetInfoType = tagHH_SET_INFOTYPE;
8207 type
8208 HH_INFOTYPE = DWORD;
8209 THHInfoType = HH_INFOTYPE;
8210 PHHInfoType = ^THHInfoType; //PHH_INFOTYPE
8213 const
8214 HHWIN_NAVTAB_TOP = 0;
8215 HHWIN_NAVTAB_LEFT = 1;
8216 HHWIN_NAVTAB_BOTTOM = 2;
8218 const
8219 HH_MAX_TABS = 19; // maximum number of tabs
8220 const
8221 HH_TAB_CONTENTS = 0;
8222 HH_TAB_INDEX = 1;
8223 HH_TAB_SEARCH = 2;
8224 HH_TAB_FAVORITES = 3;
8225 HH_TAB_HISTORY = 4;
8226 HH_TAB_AUTHOR = 5;
8227 HH_TAB_CUSTOM_FIRST = 11;
8228 HH_TAB_CUSTOM_LAST = HH_MAX_TABS;
8230 HH_MAX_TABS_CUSTOM = (HH_TAB_CUSTOM_LAST - HH_TAB_CUSTOM_FIRST + 1);
8234 { HH_DISPLAY_SEARCH Command Related Structures and Constants }
8236 const
8237 HH_FTS_DEFAULT_PROXIMITY = (-1);
8239 type
8240 {** Used by command HH_DISPLAY_SEARCH}
8241 PHHFtsQuery = ^THHFtsQuery;
8242 tagHH_FTS_QUERY = packed record //tagHH_FTS_QUERY, HH_FTS_QUERY
8243 cbStruct: integer; // Sizeof structure in bytes.
8244 fUniCodeStrings: BOOL; // TRUE if all strings are unicode.
8245 pszSearchQuery: PChar; // String containing the search query.
8246 iProximity: LongInt; // Word proximity.
8247 fStemmedSearch: Bool; // TRUE for StemmedSearch only.
8248 fTitleOnly: Bool; // TRUE for Title search only.
8249 fExecute: Bool; // TRUE to initiate the search.
8250 pszWindow: PChar; // Window to display in
8251 end;
8252 THHFtsQuery = tagHH_FTS_QUERY;
8255 { HH_WINTYPE Structure }
8257 type
8258 {** Used by commands HH_GET_WIN_TYPE, HH_SET_WIN_TYPE}
8259 PHHWinType = ^THHWinType;
8260 tagHH_WINTYPE = packed record //tagHH_WINTYPE, HH_WINTYPE, *PHH_WINTYPE;
8261 cbStruct: Integer; // IN: size of this structure including all Information Types
8262 fUniCodeStrings: BOOL; // IN/OUT: TRUE if all strings are in UNICODE
8263 pszType: PChar; // IN/OUT: Name of a type of window
8264 fsValidMembers: DWORD; // IN: Bit flag of valid members (HHWIN_PARAM_)
8265 fsWinProperties: DWORD; // IN/OUT: Properties/attributes of the window (HHWIN_)
8267 pszCaption: PChar; // IN/OUT: Window title
8268 dwStyles: DWORD; // IN/OUT: Window styles
8269 dwExStyles: DWORD; // IN/OUT: Extended Window styles
8270 rcWindowPos: TRect; // IN: Starting position, OUT: current position
8271 nShowState: Integer; // IN: show state (e.g., SW_SHOW)
8273 hwndHelp: HWND; // OUT: window handle
8274 hwndCaller: HWND; // OUT: who called this window
8276 paInfoTypes: PHHInfoType; // IN: Pointer to an array of Information Types
8278 { The following members are only valid if HHWIN_PROP_TRI_PANE is set }
8280 hwndToolBar: HWND; // OUT: toolbar window in tri-pane window
8281 hwndNavigation: HWND; // OUT: navigation window in tri-pane window
8282 hwndHTML: HWND; // OUT: window displaying HTML in tri-pane window
8283 iNavWidth: Integer; // IN/OUT: width of navigation window
8284 rcHTML: TRect; // OUT: HTML window coordinates
8286 pszToc: PChar; // IN: Location of the table of contents file
8287 pszIndex: PChar; // IN: Location of the index file
8288 pszFile: PChar; // IN: Default location of the html file
8289 pszHome: PChar; // IN/OUT: html file to display when Home button is clicked
8290 fsToolBarFlags: DWORD; // IN: flags controling the appearance of the toolbar (HHWIN_BUTTON_)
8291 fNotExpanded: BOOL; // IN: TRUE/FALSE to contract or expand, OUT: current state
8292 curNavType: Integer; // IN/OUT: UI to display in the navigational pane
8293 tabpos: Integer; // IN/OUT: HHWIN_NAVTAB_TOP, HHWIN_NAVTAB_LEFT, or HHWIN_NAVTAB_BOTTOM
8294 idNotify: Integer; // IN: ID to use for WM_NOTIFY messages
8295 tabOrder: packed array[0..HH_MAX_TABS] of Byte; // IN/OUT: tab order: Contents, Index, Search, History, Favorites, Reserved 1-5, Custom tabs
8296 cHistory: Integer; // IN/OUT: number of history items to keep (default is 30)
8297 pszJump1: PChar; // Text for HHWIN_BUTTON_JUMP1
8298 pszJump2: PChar; // Text for HHWIN_BUTTON_JUMP2
8299 pszUrlJump1: PChar; // URL for HHWIN_BUTTON_JUMP1
8300 pszUrlJump2: PChar; // URL for HHWIN_BUTTON_JUMP2
8301 rcMinSize: TRect; // Minimum size for window (ignored in version 1)
8303 cbInfoTypes: Integer; // size of paInfoTypes;
8304 pszCustomTabs: PChar; // multiple zero-terminated strings
8305 end;
8306 HH_WINTYPE = tagHH_WINTYPE;
8307 THHWinType = tagHH_WINTYPE;
8309 const
8310 HHACT_TAB_CONTENTS = 0;
8311 HHACT_TAB_INDEX = 1;
8312 HHACT_TAB_SEARCH = 2;
8313 HHACT_TAB_HISTORY = 3;
8314 HHACT_TAB_FAVORITES = 4;
8316 HHACT_EXPAND = 5;
8317 HHACT_CONTRACT = 6;
8318 HHACT_BACK = 7;
8319 HHACT_FORWARD = 8;
8320 HHACT_STOP = 9;
8321 HHACT_REFRESH = 10;
8322 HHACT_HOME = 11;
8323 HHACT_SYNC = 12;
8324 HHACT_OPTIONS = 13;
8325 HHACT_PRINT = 14;
8326 HHACT_HIGHLIGHT = 15;
8327 HHACT_CUSTOMIZE = 16;
8328 HHACT_JUMP1 = 17;
8329 HHACT_JUMP2 = 18;
8330 HHACT_ZOOM = 19;
8331 HHACT_TOC_NEXT = 20;
8332 HHACT_TOC_PREV = 21;
8333 HHACT_NOTES = 22;
8335 HHACT_LAST_ENUM = 23;
8338 type
8339 {*** Notify event info for HHN_TRACK }
8340 PHHNTrack = ^THHNTrack;
8341 tagHHNTRACK = packed record //tagHHNTRACK, HHNTRACK;
8342 hdr: TNMHdr;
8343 pszCurUrl: PChar; // Multi-byte, null-terminated string
8344 idAction: Integer; // HHACT_ value
8345 phhWinType: PHHWinType; // Current window type structure
8346 end;
8347 HHNTRACK = tagHHNTRACK;
8348 THHNTrack = tagHHNTRACK;
8351 ///////////////////////////////////////////////////////////////////////////////
8353 // Global Control Properties.
8355 const
8356 HH_GPROPID_SINGLETHREAD = 1; // VARIANT_BOOL: True for single thread
8357 HH_GPROPID_TOOLBAR_MARGIN = 2; // long: Provides a left/right margin around the toolbar.
8358 HH_GPROPID_UI_LANGUAGE = 3; // long: LangId of the UI.
8359 HH_GPROPID_CURRENT_SUBSET = 4; // BSTR: Current subset.
8360 HH_GPROPID_CONTENT_LANGUAGE = 5; // long: LandId for desired content.
8362 type
8363 tagHH_GPROPID = HH_GPROPID_SINGLETHREAD..HH_GPROPID_CONTENT_LANGUAGE; //tagHH_GPROPID, HH_GPROPID
8364 HH_GPROPID = tagHH_GPROPID;
8365 THHGPropID = HH_GPROPID;
8367 ///////////////////////////////////////////////////////////////////////////////
8369 // Global Property structure
8371 {type
8372 PHHGlobalProperty = ^THHGlobalProperty;
8373 tagHH_GLOBAL_PROPERTY = record //tagHH_GLOBAL_PROPERTY, HH_GLOBAL_PROPERTY
8374 id: THHGPropID;
8375 Dummy: Integer; // Added to enforce 8-byte packing
8376 var_: VARIANT;
8377 end;
8378 HH_GLOBAL_PROPERTY = tagHH_GLOBAL_PROPERTY;
8379 THHGlobalProperty = tagHH_GLOBAL_PROPERTY;}
8380 //[END OF HTMLHELP DECLARATIONS]
8382 //[GetCtlBrush DECLARATIONS]
8383 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush; //forward;
8386 Global_GetCtlBrushHandle: function( Sender: PControl ): HBrush = SimpleGetCtlBrushHandle;
8387 {* Is called to obtain brush handle. }
8389 Global_Align: procedure( Sender: PObj ) = DummyObjProc;
8390 {* Is set to perform aligning of control, and only if property Align
8391 is changed for TControl, or SetAlign method is called for it. }
8393 //[WndFunc DECLARATION]
8394 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
8395 : Integer; stdcall;
8396 {* Global message handler for window. Redirects all messages to
8397 destination windows, obtaining target TControl object address from
8398 window itself, using GetProp API call. }
8400 //[Applet VARIABLES]
8401 var AppletRunning: Boolean;
8402 {* Is set to True while message loop is processing (in Run procedure). }
8403 AppletTerminated: Boolean;
8404 {* Is set to True when message loop is terminated. }
8405 Applet: PControl;
8406 {* Applet window object. Actually, can be set to main form if program
8407 not needed in special applet button window (useful to make applet
8408 button invisible on taskbar, or to have several forms with single
8409 applet button - crete it in that case using NewApplet). }
8410 AppButtonUsed: Boolean;
8411 {* True if special window to represent applet button (may be invisible)
8412 is used. If no, every form is represented with its own taskbar button
8413 (always visible). }
8415 //[Screen DECLARATIONS]
8416 ScreenCursor: HCursor;
8417 {* Set this global variable to override any cursor settings of current
8418 form or control. }
8420 function ScreenWidth: Integer;
8421 {* Returns screen width in pixels. }
8422 function ScreenHeight: Integer;
8423 {* Returns screen height in pixels. }
8425 //[Status DECLARATIONS]
8426 type
8427 TStatusOption = ( soNoSizeGrip, soTop );
8428 {* Options available for status bars. }
8429 TStatusOptions = Set of TStatusOption;
8430 {* Status bar options. }
8436 //[Run DECLARATION]
8437 procedure Run( var AppletWnd: PControl );
8438 {* |<#appbutton>
8439 Call this procedure to process messages loop of your program.
8440 Pass here pointer to applet button object (if You have created it
8441 - see NewApplet) or your main form object of type PControl (created
8442 using NewForm).
8443 |<br><br>
8444 |<h1 align=center><font color=#FF8040><a name="visual_objects_constructors"></a>
8445 Visual objects constructing functions
8446 |</font></h1>
8447 Following constructing functions for visual controls are available:
8448 |#control
8451 //[Applet FUNCTIONS DECLARATIONS]
8452 procedure AppletMinimize;
8453 {* Minimizes the application (Applet should be assigned to have effect). }
8454 procedure AppletHide;
8455 {* Minimizes and hides application. }
8456 procedure AppletRestore;
8457 {* Restores Applet when minimized. }
8459 //[Idle handler DECALRATIONS]
8460 {YS+}
8461 procedure RegisterIdleHandler( const OnIdle: TOnEvent );
8462 {* Registers new Idle handler. Idle handler is called each time when
8463 message queue becomes empty. }
8464 procedure UnRegisterIdleHandler( const OnIdle: TOnEvent );
8465 {* Unregisters Idle handler. }
8466 {YS-}
8470 //[InitCommonXXXX ANOTHER DECLARATIONS]
8472 {* ComCtrl32 controls initialization. }
8473 procedure InitCommonControls; stdcall;
8474 procedure DoInitCommonControls( dwICC: DWORD );
8475 {* Calls extended initialization for Common Controls (from ComCtrl32).
8476 Pass one of following constants:
8477 |<pre>
8478 ICC_LISTVIEW_CLASSES = $00000001; // listview, header
8479 ICC_TREEVIEW_CLASSES = $00000002; // treeview, tooltips
8480 ICC_BAR_CLASSES = $00000004; // toolbar, statusbar, trackbar, tooltips
8481 ICC_TAB_CLASSES = $00000008; // tab, tooltips
8482 ICC_UPDOWN_CLASS = $00000010; // updown
8483 ICC_PROGRESS_CLASS = $00000020; // progress
8484 ICC_HOTKEY_CLASS = $00000040; // hotkey
8485 ICC_ANIMATE_CLASS = $00000080; // animate
8486 ICC_WIN95_CLASSES = $000000FF;
8487 ICC_DATE_CLASSES = $00000100; // month picker, date picker, time picker, updown
8488 ICC_USEREX_CLASSES = $00000200; // comboex
8489 ICC_COOL_CLASSES = $00000400; // rebar (coolbar) control
8490 ICC_INTERNET_CLASSES = $00000800;
8491 ICC_PAGESCROLLER_CLASS = $00001000; // page scroller
8492 ICC_NATIVEFNTCTL_CLASS = $00002000; // native font control
8493 |</pre>
8496 const
8497 ICC_LISTVIEW_CLASSES = $00000001; // listview, header
8498 ICC_TREEVIEW_CLASSES = $00000002; // treeview, tooltips
8499 ICC_BAR_CLASSES = $00000004; // toolbar, statusbar, trackbar, tooltips
8500 ICC_TAB_CLASSES = $00000008; // tab, tooltips
8501 ICC_UPDOWN_CLASS = $00000010; // updown
8502 ICC_PROGRESS_CLASS = $00000020; // progress
8503 ICC_HOTKEY_CLASS = $00000040; // hotkey
8504 ICC_ANIMATE_CLASS = $00000080; // animate
8505 ICC_WIN95_CLASSES = $000000FF;
8506 ICC_DATE_CLASSES = $00000100; // month picker, date picker, time picker, updown
8507 ICC_USEREX_CLASSES = $00000200; // comboex
8508 ICC_COOL_CLASSES = $00000400; // rebar (coolbar) control
8509 ICC_INTERNET_CLASSES = $00000800;
8510 ICC_PAGESCROLLER_CLASS = $00001000; // page scroller
8511 ICC_NATIVEFNTCTL_CLASS = $00002000; // native font control
8513 //[Ole DECLARATIONS]
8514 function OleInit: Boolean;
8515 {* Calls OleInitialize (once - all other calls are simulated by incrementing
8516 call counter. Every OleInit shoud be complemented with correspondent OleUninit.
8517 (Though, it is possible to call API function OleUnInitialize once to
8518 cancel all OleInit calls). }
8519 procedure OleUnInit;
8520 {* Decrements counter and calls OleUnInitialize when it is zeroed. }
8521 var OleInitCount: Integer;
8524 function StringToOleStr(const Source: string): PWideChar;
8525 {* }
8528 function SysAllocStringLen(psz: PWideChar; len: Integer): PWideChar; stdcall;
8529 procedure SysFreeString( psz: PWideChar ); stdcall;
8540 { -- Contructors for visual controls -- }
8541 //[NewXXXX DECLARATIONS]
8543 //[_NewWindowed DECLARATION]
8544 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;
8546 //[NewApplet DECLARATION]
8547 function NewApplet( const Caption: String ): PControl;
8548 {* |<#control>
8549 Creates applet button window, which has to be parent of all other forms
8550 in your project (but this is *not must*). See also comments about NewForm.
8551 |<br>
8552 Following methods, properties and events are useful to work with applet
8553 control:
8554 |#appbutton }
8556 //[NewForm DECLARATION]
8557 function NewForm( AParent: PControl; const Caption: String ): PControl;
8558 {* |<#control>
8559 Creates form window object and returns pointer to it. If You use only one form,
8560 and You are not going to do applet button on task bar invisible, it is not
8561 necessary to create also special applet button window - just pass
8562 your (main) form object to Run procedure. In that case, it is a good
8563 idea to assign pointer to your main form object to Applet variable
8564 immediately following creating it - because some objects (e.g. TTimer)
8565 want to have Applet assigned to something.
8566 |<br>
8567 |&D=<a href="tcontrol.htm#%1" target=_top> %0 </a>
8568 Following methods, properties and events are useful to work with forms
8569 (ones common for all visual objects, such as <D Left>, <D Top>, <D Width>,
8570 <D Height>, etc. are not listed here - look TControl for it):
8571 |#form }
8573 //[_NewControl DECLARATION]
8574 function _NewControl( AParent: PControl; ControlClassName: PChar;
8575 Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;
8577 //[NewButton DECLARATION]
8578 function NewButton( AParent: PControl; const Caption: String ): PControl;
8579 {* |<#control>
8580 Creates button on given parent control or form.
8581 Please note, that in Windows, buttons can not change its <D Font> color
8582 and to be <D Transparent>.
8583 |<br> Following methods, properies and events are (especially) useful with
8584 a button:
8585 |#button }
8587 //[NewBitBtn DECLARATION]
8588 function NewBitBtn( AParent: PControl; const Caption: String;
8589 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap; GlyphCount: Integer ): PControl;
8590 {* |<#control>
8591 Creates image button (actually implemented as owner-drawn). In Options,
8592 it is possible to determine, whether bitmap or image list used to contain
8593 one or more (up to 5) images, correspondent to certain BitBtn state.
8594 |<br>&nbsp;&nbsp;&nbsp;
8595 For case of imagelist (option bboImageList), it is possible to use a
8596 number of glyphs from the image list, starting from image index given
8597 by GlyphCount parameter. Number of used glyphs is passed in that case
8598 in high word of GlyphCount parameter (if 0, one image is used therefore).
8599 For bboImageList, BitBtn can be Transparent (and in that case bboNoBorder
8600 style can be useful to draw custom buttons of non-rectangular shape).
8601 |<br>&nbsp;&nbsp;&nbsp;
8602 For case of bitmap BitBtn, image is stretched down (if too big), but can
8603 not be transparent. It is not necessary for bitmap BitBtn to pass correct
8604 GlyphCount - it is calculated on base of bitmap size, if 0 is passed.
8605 |<br>&nbsp;&nbsp;&nbsp;
8606 And, certainly, BitBtn can be without glyph image (text only). For that
8607 case, it is therefore is more flexible and power than usual Button (but
8608 requires more code). E.g., BitBtn can change its <D Font>, <D Color>,
8609 and to be totally <D Transparent>.
8610 Moreover, BitBtn can be <D Flat>, bboFixed, <D SpeedButton> and
8611 have property <D RepeatInterval>.
8612 |<br>&nbsp;&nbsp;&nbsp;
8613 Note: if You use bboFixed Style, use OnChange event instead of OnClick,
8614 because <D Checked> state is changed immediately however OnClick occure
8615 only when mouse or space key released (and can be not called at all if
8616 mouse button is released out of BitBtn bounds). Also, bboFixed defines
8617 only which glyph to show (the border if it is not turned off behaves as
8618 usual for a button, i.e. it becomes lowered and then raised again at any click).
8619 Here You can find references to other properties, events and methods
8620 applicable to BitBtn:
8621 |#bitbtn }
8623 //[NewLabel DECLARATION]
8624 function NewLabel( AParent: PControl; const Caption: String ): PControl;
8625 {* |<#control>
8626 Creates static text control (native Windows STATIC control).
8627 Use property <D Caption> at run time to change label text. Also
8628 it is possible to adjust label <D Font>, <D Brush> or <D Color>.
8629 Label can be <D Transparent>. If You want to have rotated text
8630 label, call NewLabelEffect instead and change its <D Font>.FontOrientation.
8631 Other references certain for a label:
8632 |#label }
8634 //[NewWordWrapLabel DECLARATION]
8635 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
8636 {* |<#control>
8637 Creates multiline static text control (native Windows STATIC control),
8638 which can wrap long text onto several lines. See also NewLabel.
8639 See also:
8640 |#wwlabel
8641 |#label }
8643 //[NewLabelEffect DECLARATION]
8644 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
8645 {* |<#control>
8646 Creates 3D-label with capability to rotate its text <D Caption>, which
8647 is controlled by changing <D Font>.FontOrientation property. If You want
8648 to get flat effect label (e.g. to rotate it only), pass <D ShadowDeep> = 0.
8649 Please note, that drawing procedure uses <D Canvas> property, so using of
8650 LabelEffect leads to increase size of executable.
8651 See also:
8652 |#3dlabel
8653 |#label }
8655 //[NewPaintbox DECLARATION]
8656 function NewPaintbox( AParent: PControl ): PControl;
8657 {* |<#control>
8658 Creates owner-drawn STATIC control. Set its <D OnPaint> event to
8659 perform custom painting.
8660 |#paintbox }
8662 //[NewImageShow DECLARATION]
8663 function NewImageShow( AParent: PControl; AImgList: PImageList; ImgIdx: Integer ): PControl;
8664 {* |<#control>
8665 Creates an image show control, implemented as a paintbox which is used to
8666 draw an image from the imagelist. At run-time, use property CurIndex to
8667 select another image from the imagelist, and a property ImageListNormal to
8668 use another image list. When the control is created, its size becomes
8669 equal to dimensions of imagelist (if any). }
8671 //[NewScrollBar DECLARATION]
8672 function NewScrollBar( AParent: PControl; BarSide: TScrollerBar ): PControl;
8673 { * not yet finished... }
8675 //[NewScrollBox DECLARATION]
8676 function NewScrollBox( AParent: PControl; EdgeStyle: TEdgeStyle;
8677 Bars: TScrollerBars ): PControl;
8678 {* |<#control>
8679 Creates simple scrolling box, which can be used any way you wish, e.g. to scroll
8680 certain large image. To provide automatic scrolling of a set of child controls,
8681 use advanced scroll box, created with NewScrollBoxEx. }
8683 procedure NotifyScrollBox( Self_, Child: PControl );
8686 function NewScrollBoxEx( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
8687 {* |<#control>
8688 Creates extended scrolling box control, which automatically scrolls child
8689 controls (if any). }
8691 //[NewGradientPanel DECLARATION]
8692 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
8693 {* |<#control>
8694 Creates gradient-filled STATIC control. To adjust colors at the
8695 run time, change <D Color1> and <D Color2> properties (which initially are
8696 assigned from Color1, Color2 parameters), and call <D Invalidate> method
8697 to repaint control. }
8699 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
8700 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
8701 {* |<#control>
8702 Creates gradient-filled STATIC control. To adjust colors at the
8703 run time, change <D Color1> and <D Color2> properties (which initially are
8704 assigned from Color1, Color2 parameters), and call <D Invalidate> method
8705 to repaint control. Depending on style and first line/point layout, can
8706 looking different. Idea: Vladimir Stojiljkovic. }
8708 //[NewPanel DECLARATION]
8709 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
8710 {* |<#control>
8711 Creates panel, which can be parent for other controls (though, any
8712 control can be used as a parent for other ones, but panel is specially
8713 designed for such purpose). }
8715 //[NewMDIxxx DECLARATIONS]
8716 function NewMDIClient( AParent: PControl; WindowMenu: THandle ): PControl;
8717 {* |<#control>
8718 Creates MDI client window, which is a special type of child window,
8719 containing all MDI child windows, created calling NewMDIChild function.
8720 On a form, MDI client behaves like a panel, so it can be placed and sized
8721 (or aligned) like any other controls. To minimize flick during resizing
8722 main form having another aligned controls, place MDI client window on
8723 a panel and align it caClient in the panel.
8724 |<br>Note:
8725 MDI client must be a single on the form. }
8727 function NewMDIChild( AParent: PControl; const ACaption: String ): PControl;
8728 {* |<#control>
8729 Creates MDI client window. AParent should be a MDI client window,
8730 created with NewMDIClient function. }
8732 //[NewSplitter DECLARATIONS]
8733 function NewSplitter( AParent: PControl; MinSizePrev, MinSizeNext: Integer ): PControl;
8734 {* |<#control>
8735 Creates splitter control, which will separate previous one (i.e. last
8736 created one before splitter on the same parent) from created
8737 next, allowing to user to adjust size of separated controls by dragging
8738 the splitter in desired direction. Created splitter becomes vertical
8739 or horizontal depending on Align style of previous control on the same
8740 parent (if caLeft/caRight then vertical, if caTop/caBottom then horizontal).
8741 |<br>&nbsp;&nbsp;&nbsp;
8742 Please note, what if previous control has no Align equal to caLeft/caRight
8743 or caTop/caBottom, splitter will not be able to function normally. If
8744 previous control does not exist, it is yet possible to use splitter as
8745 a resizeable panel (but set its initial Align value first - otherwise it
8746 is not set by default. Also, change Cursor property as You wish in that
8747 case, since it is not set too in case, when previous control does not
8748 exist).
8749 |<br>&nbsp;&nbsp;&nbsp;
8750 Additional parameters determine, which minimal size (width or height -
8751 correspondently to split direction) is allowed for left (top) control
8752 and to rest of client area of parent, correspondently. (It is possible
8753 later to set second control for checking its size with MinSizeNext
8754 value - using TControl.SecondControl property). If -1 passed,
8755 correspondent control size is not checked during dragging of splitter.
8756 Usually 0 is more suitable value (with this value, it is garantee, that
8757 splitter will be always available even if mouse was released far from the
8758 edge of form).
8759 |<br>&nbsp;&nbsp;&nbsp;
8760 It is possible for user to press Escape any time while dragging splitter
8761 to abort all adjustments made starting from left mouse button push and
8762 begin of drag the splitter. But remember please, that such event is
8763 controlled using timer, and therefore correspondent keyboard events
8764 are received by currently focused control. Be sure, that pressing Escape
8765 will not affect to any control on form, which could be focused, otherwise
8766 filter keyboard messages (by yourself) to prevent undesired handling of
8767 Escape key by certain controls while splitting. (Use Dragging property
8768 to check if splitter is dragging by user with mouse).
8769 |<br>&nbsp;&nbsp;&nbsp;
8770 See also:
8771 NewSplitterEx
8772 |#splitter }
8774 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
8775 EdgeStyle: TEdgeStyle ): PControl;
8776 {* |<#control>
8777 Creates splitter control. Difference from NewSplitter is what it is possible
8778 to determine if a splitter will be beveled or not. See also NewSplitter. }
8780 //[NewGroupbox DECLARATION]
8781 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
8782 {* |<#control>
8783 Creates group box control. Note, that to group radio items, group
8784 box is not necessary - any parent can play role of group for radio items.
8785 See also NewPanel. }
8787 //[NewCheckbox DECLARATION]
8788 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
8789 {* |<#control>
8790 Creates check box control. Special properties, methods, events:
8791 |#checkbox }
8793 function NewCheckBox3State( AParent: PControl; const Caption: String ): PControl;
8794 {* |<#control>
8795 Creates check box control with 3 states. Special properties, methods,
8796 events:
8797 |#checkbox }
8799 //[NewRadiobox DECLARATION]
8800 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
8801 {* |<#control>
8802 Creates radio box control. Alternative radio items must have the
8803 same parent window (regardless of its kind, either groupbox (NewGroupbox),
8804 panel (NewPanel) or form itself). Following properties, methods and events
8805 are specially for radiobox controls:
8806 |#radiobox }
8808 //[NewEditbox DECLARATION]
8809 function NewEditbox( AParent: PControl; Options: TEditOptions ): PControl;
8810 {* |<#control>
8811 Creates edit box control. To create multiline edit box, similar to
8812 TMemo in VCL, apply eoMultiline in Options. Following properties, methods,
8813 events are special for edit controls:
8814 |#edit }
8816 //[NewRichEdit DECLARATION]
8817 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
8818 {* |<#control>
8819 Creates rich text edit control. A rich edit control is a window in which
8820 the user can enter and edit text. The text can be assigned character and
8821 paragraph formatting, and can include embedded OLE objects. Rich edit
8822 controls provide a programming interface for formatting text. However, an
8823 application must implement any user interface components necessary to make
8824 formatting operations available to the user.
8825 |<br>&nbsp;&nbsp;&nbsp;
8826 Note: eoPassword, eoMultiline options have no effect for RichEdit control.
8827 Some operations are supersided with special versions of those, created
8828 especially for RichEdit, but in some cases it is necessary to use
8829 another properties and methods, specially designed for RichEdit (see
8830 methods and properties, which names are starting from RE_...).
8831 |<br>&nbsp;&nbsp;&nbsp;
8832 Following properties, methods, events are special for edit controls:
8833 |#richedit
8836 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
8837 {* |<#control>
8838 Like NewRichEdit, but to work with older RichEdit control version 1.0
8839 (window class 'RichEdit' forced to use instead of 'RichEdit20A', even
8840 if library RICHED20.DLL found and loaded successfully). One more
8841 difference - OleInit is not called, so the most of OLE capabilities
8842 of RichEdit could not working. }
8844 //[NewListbox DECLARATION]
8845 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
8846 {* |<#control>
8847 Creates list box control. Following properties, methods and events are
8848 special for Listbox:
8849 |#listbox }
8851 //[NewCombobox DECLARATION]
8852 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
8853 {* |<#control>
8854 Creates new combo box control. Note, that it is not possible to align
8855 combobox caLeft or caRight: this can cause infinit recursion in the
8856 application.
8857 |<br>Following properties, methods and events are
8858 special for Combobox:
8859 |#combo }
8861 //[_NewCommonControl DECLARATION]
8862 function _NewCommonControl( AParent: PControl; ClassName: PChar; Style: DWORD;
8863 Ctl3D: Boolean; Actions: PCommandActions ): PControl;
8865 //[NewProgressbar DECLARATION]
8866 function NewProgressbar( AParent: PControl ): PControl;
8867 {* |<#control>
8868 Creates progress bar control. Following properties are special for
8869 progress bar:
8870 |#progressbar
8871 See also NewProgressEx. }
8873 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
8874 {* |<#control>
8875 Can create progress bar with smooth style (progress is not segmented
8876 onto bricks) or/and vertical progress bar - using additional parameter.
8877 For list of properties, suitable for progress bars, see NewProgressbar. }
8879 //[NewListVew DECLARATION]
8880 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
8881 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
8882 {* |<#control>
8883 Creates list view control. It is very powerful control, which can partially
8884 compensate absence of grid controls (in lvsDetail view mode). Properties,
8885 methods and events, special for list view control are:
8886 |#listview }
8888 //[NewTreeView DECLARATION]
8889 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
8890 ImgListNormal, ImgListState: PImageList ): PControl;
8891 {* |<#control>
8892 Creates tree view control. See tree view methods and properties:
8893 |#treeview }
8895 //[NewTabControl DECLARATION]
8896 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
8897 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
8898 {* |<#control>
8899 Creates new tab control (like notebook). To place child control on a certain
8900 page of TabControl, use property Pages[ Idx ], for example:
8901 ! Label1 := NewLabel( TabControl1.Pages[ 0 ], 'Label1' );
8902 | &nbsp;&nbsp;&nbsp;
8903 To determine number of pages at run time, use property <D Count>;
8904 |<br> to determine which page is currently selected (or to change
8905 selection), use property <D CurrentIndex>;
8906 |<br> to feedback to switch between tabs assign your handler to OnSelChange
8907 event;
8908 |<br>Note, that by default, tab control is created with a border lowered to
8909 tab control's parent. To remove it, you can apply WS_EX_TRANSPARENT extended
8910 style (see TControl.ExStyle property), but painting of some child controls
8911 can be strange a bit in this case (no border drawing for edit controls was
8912 found, but not always...). You can also apply style WS_THICKFRAME (TControl.Style
8913 property) to make the border raised.
8914 |<br> Other methods and properties, suitable for tab control, are:
8915 |#tabcontrol }
8917 //[NewToolbar DECLARATION]
8918 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
8919 Bitmap: HBitmap; Buttons: array of PChar;
8920 BtnImgIdxArray: array of Integer ) : PControl;
8921 {* |<#control>
8922 Creates toolbar control. Bitmap must contain images for all buttons
8923 excluding separators (defined by string '-' in Buttons array), otherwise
8924 last buttons will no have images at all. Image width for every button
8925 is assumed to be equal to Bitmap height (if last of "squares" has
8926 insufficient width, it will not be used). To define fixed buttons, use
8927 characters '+' or '-' as a prefix for button string (even empty). To
8928 create groups of (radio-)buttons, use also '!' follow '+' or '-'. (These rules
8929 are similar used in menu creation). To define drop down button, use (as
8930 first) prefix '^'. (Do not forget to set <D OnTBDropDown> event for this
8931 case). If You want to assign images to buttons not in the same order
8932 how these are placed in Bitmap (or You use system bitmap), define for every
8933 button (in BtnImgIdxArray array) indexes for every button (excluding
8934 separator buttons). Otherwise, it is possible to define index only for first
8935 button (e.g., [0]). It is also possible to change TBImages[ ] property
8936 for such purpose, or do the same in method TBSetBtnImgIdx).
8937 |<br>
8938 Following properties, methods and event are specially designed to work with
8939 toolbar control:
8940 |#toolbar
8941 |<br>&nbsp;&nbsp;&nbsp;
8942 If your project uses Align property to align controls, this can conflict with
8943 toolbar native aligning. To solve such problem, place toolbar to parent panel,
8944 which has its own Align property assigned to desired value.
8945 |<br>
8946 To create toolbar with buttons, drawn from top to bottom, instead from left
8947 to right, combine caLeft / caRight in Align parameter and style tboWrapable
8948 when create toolbar. To adjust width of vertically aligned toolbar, it is
8949 possible to call ResizeParentLeft for it. E.g.:
8951 ! P0 := NewPanel( W, esRaised ) .SetSize( 30, 0 ) .SetAlign( caLeft );
8952 ! // ^^^^^^^^^^^^^^^^^ //////
8953 !TB := NewToolbar( P0, caLeft, [ tboNoDivider, tboWrapable ], DWORD(-1),
8954 ! // ////// ///////////
8955 ! [ ' ', ' ', ' ', '-', ' ', ' ' ],
8956 ! [ STD_FILEOPEN ] ).ResizeParentRight;
8957 !//Note, that caLeft is *must*, and tboWrapable style too. SetSize for
8958 !//parent panel is not necessary, but only if ResizeParentRight is called
8959 !//than for Toolbar.
8960 |<br><br>
8961 One more note: if You create toolbar without text labels (passing ' ' for
8962 each button You add), include also option tboTextRight to fix incorrect
8963 sizing of buttons under Windows9x.
8966 //[NewDateTimePicker DECLARATION]
8967 function NewDateTimePicker( AParent: PControl; Options: TDateTimePickerOptions )
8968 : PControl;
8969 {* |<#control>
8970 Creates date and time picker common control.
8975 { -- Constructor for Image List objet -- }
8977 //[NewImageList DECLARATION]
8978 function NewImageList( AOwner: PControl ): PImageList;
8979 {* Constructor of TImageList object. Unlike other non-visual objects, image list
8980 can be parented by TControl object (but this does not *must*), and in that
8981 case it is destroyed automatically when its parent control is destroyed.
8982 Every control can have several TImageList objects, linked to a simple list.
8983 But if any TImageList object is destroyed, all following ones are destroyed
8984 too (at least, now I implemented it so). }
9017 //[TIMER]
9018 type
9019 {++}(*TTimer = class;*){--}
9020 PTimer = {-}^{+}TTimer;
9021 { ----------------------------------------------------------------------
9023 TTimer object
9025 ----------------------------------------------------------------------- }
9026 //[TTimer DEFINITION]
9027 TTimer = object( TObj )
9028 {* Easy timer incapsulation object. Uses applet window to
9029 receive timer events. So, either assign your main form
9030 to Applet variable or create applet button object (and
9031 assign it to Applet) before enabling timer. }
9032 protected
9033 fHandle : Integer;
9034 fEnabled: Boolean;
9035 fInterval: Integer;
9036 fOnTimer: TOnEvent;
9037 procedure SetEnabled(const Value: Boolean); virtual;
9038 procedure SetInterval(const Value: Integer);
9039 protected
9040 {++}(*public*){--}
9041 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
9042 {* Destructor. }
9043 public
9044 property Handle : Integer read fHandle;
9045 {* Windows timer object handle. }
9046 property Enabled : Boolean read fEnabled write SetEnabled;
9047 {* True, is timer is on. Initially, always False. Before assigning True,
9048 make sure, that Applet global variable is assigned to applet object
9049 (NewApplet) or to form (NewForm). }
9050 property Interval : Integer read fInterval write SetInterval;
9051 {* Interval in milliseconds (1000 is default and means 1 second). }
9052 property OnTimer : TOnEvent read fOnTimer write fOnTimer;
9053 {* Event, which is called when time interval is over. }
9054 end;
9055 //[END OF TTimer DEFINITION]
9057 //[NewTimer DECLARATION]
9058 function NewTimer( Interval: Integer ): PTimer;
9059 {* Constructs initially disabled timer with interval 1000 (1 second). }
9062 //[MULTIMEDIA TIMER]
9063 type
9064 {++}(*TMMTimer = class;*){--}
9065 PMMTimer = {-}^{+}TMMTimer;
9067 //[TMMTimer DEFINITION]
9068 TMMTimer = object( TTimer )
9069 {* Multimedia timer incapsulation object. Does not require Applet or special
9070 window to handle it. System creates a thread for each high resolution
9071 timer, so using many such objects can degrade total PC performance. }
9072 protected
9073 FResolution: Integer;
9074 FPeriodic: Boolean;
9075 procedure SetEnabled(const Value: Boolean); {-}virtual;{+}{++}(*override;*){--}
9076 public
9077 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
9078 {* }
9079 property Resolution: Integer read FResolution write FResolution;
9080 {* Minimum timer resolution. The less the more accuracy (0 is exactly
9081 Interval milliseconds between timer shots). It is recommended to set
9082 this property greater to prevent entire system from reducing overhead.
9083 If you change this value, reset and then set Enabled again to apply
9084 changes. }
9085 property Periodic: Boolean read FPeriodic write FPeriodic;
9086 {* TRUE, if timer is periodic (default). Otherwise, timer is one-shot
9087 (set it Enabled every time in such case for each shot). If you change
9088 this property, reset and set Enabled property again to get effect. }
9089 end;
9090 //[END OF TMMTimer DEFINITION]
9092 //[NewMMTimer DECLARATION]
9093 function NewMMTimer( Interval: Integer ): PMMTimer;
9094 {* Creates multimedia timer object. Initially, it has Resolution = 0,
9095 Periodic = TRUE and Enabled = FALSE. Do not forget also to assign your
9096 event handler to OnTimer to do something on timer shot. }
9110 //[DIRCHANGE]
9111 type
9112 {++}(*TDirChange = class;*){--}
9113 PDirChange = {-}^{+}TDirChange;
9114 {* }
9116 TOnDirChange = procedure (Sender: PDirChange; const Path: string) of object;
9117 {* Event type to define OnChange event for folder monitoring objects. }
9119 TFileChangeFilters = (fncFileName, fncDirName, fncAttributes, fncSize,
9120 fncLastWrite, fncLastAccess, fncCreation, fncSecurity);
9121 {* Possible change monitor filters. }
9122 TFileChangeFilter = set of TFileChangeFilters;
9123 {* Set of filters to pass to a constructor of TDirChange object. }
9125 { ----------------------------------------------------------------------
9127 TDirChange object
9129 ----------------------------------------------------------------------- }
9130 //[TDirChange DEFINITION]
9131 TDirChange = object(TObj)
9132 {* Object type to monitor changes in certain folder. }
9133 protected
9134 FOnChange: TOnDirChange;
9135 FHandle: THandle;
9136 FPath: string;
9137 FMonitor: PThread;
9138 function Execute( Sender: PThread ): Integer;
9139 procedure Changed;
9140 protected
9141 {++}(*public*){--}
9142 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
9144 public
9145 property Handle: THandle read FHandle;
9146 {* Handle of file change notification object. *}
9147 property Path: String read FPath; //write SetPath;
9148 {* Path to monitored folder (to a root, if tree of folders
9149 is under monitoring). }
9150 end;
9151 //[END OF TDirChange DEFINITION]
9153 //[NewDirChangeNotifier DECLARATION]
9154 function NewDirChangeNotifier( const Path: String; Filter: TFileChangeFilter;
9155 WatchSubtree: Boolean; ChangeProc: TOnDirChange ): PDirChange;
9156 {* Creates notification object TDirChangeNotifier. If something wrong (e.g.,
9157 passed directory does not exist), nil is returned as a result. When change
9158 is notified, ChangeProc is called always in main thread context.
9159 (Please note, that ChangeProc can not be nil).
9160 If empty filter is passed, default filter is used:
9161 [fncFileName..fncLastWrite]. }
9170 { -- TTrayIcon object -- }
9171 //[TRAYICON]
9173 type
9174 TOnTrayIconMouse = procedure( Sender: PObj; Message : Word ) of object;
9175 {* Event type to be called when Applet receives a message from an icon,
9176 added to the taskbar tray. }
9178 {++}(*TTrayIcon = class;*){--}
9179 PTrayIcon = {-}^{+}TTrayIcon;
9180 { ----------------------------------------------------------------------
9182 TTrayIcon - icon in tray area of taskbar
9184 ----------------------------------------------------------------------- }
9185 //[TTrayIcon DEFINITION]
9186 TTrayIcon = object(TObj)
9187 {* Object to place (and change) a single icon onto taskbar tray. }
9188 protected
9189 FIcon: HIcon;
9190 FActive: Boolean;
9191 FTooltip: String;
9192 FOnMouse: TOnTrayIconMouse;
9193 FControl: PControl;
9194 fAutoRecreate: Boolean;
9195 FNoAutoDeactivate: Boolean;
9196 FWnd: HWnd;
9197 procedure SetIcon(const Value: HIcon);
9198 procedure SetActive(const Value: Boolean);
9199 procedure SetTrayIcon( const Value : DWORD );
9200 procedure SetTooltip(const Value: String);
9201 procedure SetAutoRecreate(const Value: Boolean);
9202 protected
9203 {++}(*public*){--}
9204 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
9205 {* Destructor. Use Free method instead (as usual). }
9206 public
9207 property Icon : HIcon read FIcon write SetIcon;
9208 {* Icon to be shown on taskbar tray. If not set, value of Active
9209 property has no effect. It is also possible to assign a value
9210 to Icon property after assigning True to Active to install
9211 icon first time or to replace icon with another one (e.g. to
9212 get animation effect).
9213 |<br>&nbsp;&nbsp;&nbsp;
9214 Previously allocated icon (if any) is not deleted using
9215 DeleteObject. This is normal for icons, loaded from resource
9216 (e.g., by LoadIcon API call). But if icon was created (e.g.) by
9217 CreateIconIndirect, your code is responsible for destroying
9218 of it). }
9219 property Active : Boolean read FActive write SetActive;
9220 {* Set it to True to show assigned Icon on taskbar tray. Default
9221 is False. Has no effect if Icon property is not assigned.
9222 TrayIcon is deactivated automatically when Applet is finishing
9223 (but only if Applet window is used as a "parent" for tray
9224 icon object). }
9225 property Tooltip : String read FTooltip write SetTooltip;
9226 {* Tooltip string, showing automatically when mouse is moving
9227 over installed icon. Though "huge string" type is used, only
9228 first 63 characters are considered. Also note, that only in
9229 most recent versions of Windows multiline tooltips are supported. }
9230 property OnMouse : TOnTrayIconMouse read FOnMouse write FOnMouse;
9231 {* Is called then mouse message is taking place concerning installed
9232 icon. Only type of message can be obtained (e.g. WM_MOUSEMOVE,
9233 WM_LBUTTONDOWN etc.) }
9234 property AutoRecreate: Boolean read fAutoRecreate write SetAutoRecreate;
9235 {* If set to TRUE, auto-recreating of tray icon is proveded in case,
9236 when Explorer is restarted for some (unpredictable) reasons. Otherwise,
9237 your tray icon is disappeared forever, and if this is the single way
9238 to communicate with your application, the user nomore can achieve it. }
9239 property NoAutoDeactivate: Boolean read FNoAutoDeactivate write FNoAutoDeactivate;
9240 {* If set to true, tray icon is not removed from tray automatically on
9241 WM_CLOSE message receive by owner control. Set Active := FALSE in
9242 your code for such case before accepting closing the form. }
9243 property Wnd: HWnd read FWnd write FWnd;
9244 {* A window to use as a base window for tray icon messages. Overrides
9245 parent Control handle is assigned. Note, that if Wnd property used,
9246 message handling is not done automatically, and you should do this in
9247 your code, or at least for one tray icon object, call AttachProc2Wnd. }
9248 procedure AttachProc2Wnd;
9249 {* Call this method for a tray icon object in case if Wnd used rather then
9250 control. It is enough to call this method once for each Wnd used, even
9251 if several other tray icons are also based on the same Wnd. See also
9252 DetachProc2Wnd method. }
9253 procedure DetachProc2Wnd;
9254 {* Call this method to detach window procedure attached via AttachProc2Wnd.
9255 Do it once for a Wnd, used as a base to handle tray icon messages.
9256 Caution! If you do not call this method before destroying Wnd, the
9257 application will not functioning normally. }
9258 end;
9259 {* When You create invisible application, which should be represented by
9260 only the tray icon, prepare a handle for the window, resposible for
9261 messages handling. Remember, that window handle is created automatically
9262 only when a window is showing first time. If window's property Visible is
9263 set to False, You should to call CreateWindow manually.
9264 <br>
9265 There is a known bug exist with similar invisible tray-iconized applications.
9266 When a menu is activated in response to tray mouse event, if there was
9267 not active window, belonging to the application, the menu is not disappeared
9268 when mouse is clicked anywhere else. This bug is occure in Windows9x/ME.
9269 To avoid it, activate first your form window. This last window shoud have
9270 status visible (but, certainly, there are no needs to place it on visible
9271 part of screen - change its position, so it will not be visible for user,
9272 if You wish).
9273 <br>
9274 Also, to make your application "invisible" but until special event is occure,
9275 use Applet separate from the main form, and make for both Visible := False.
9276 This allows for You to make your form visible any time You wish, and without
9277 making application button visible if You do not wish.
9279 {= Êîãäà Âû äåëàåòå íåâèäèìîå ïðèëîæåíèå, êîòîðîå äîëæíî áûòü ïðåäñòàâëåíî
9280 òîëüêî èêîíêîé â òðåå, îáåñïå÷üòå íåíóëåâîé Handle äëÿ îêíà, îòâå÷àþùåãî
9281 çà îáðàáîòêó ñîîáùåíèé. Ïîìíèòå, ÷òî Handle îêíà ñîçäàåòñÿ àâòîìàòè÷åñêè
9282 òîëüêî â òîò ìîìåíò, êîãäà îíî äîëæíî ïîÿâèòüñÿ â ïåðâûé ðàç. Åñëè ñâîéñòâî
9283 îêíà Visible óñòàíîâëåíî â FALSE, íåîáõîäèìî âûçâàòü CreateWindow ñàìîñòîÿòåëüíî.
9284 <br>
9285 Ñóùåñòâóåò èçâåñòíûé BUG ñ ïîäîáíûìè íåâèäèìûìè ìèíèìèçèðîâàííûìè â òðåé
9286 ïðèëîæåíèÿìè. Êîãäà â îòâåò íà ñîáûòèå ìûøè àêòèâèçèðâàíî âûïàäàþùåå ìåíþ,
9287 îíî íå èñ÷åçàåò ïî ùåë÷êó ìûøè âíå ýòîãî ìåíþ. Ïðîèñõîäèò ýòî â Windows9x/ME.
9288 ÷òîáû ðåøèòü ýòó ïðîáëåìó, ñíà÷àëà àêòèâèçèðóéòå ñâîå îêíî (ôîðìó). Ýòî îêíî
9289 äîëæíî áûòü âèäèìûì (íî, êîíå÷íî, åãî ìîæíî ðàçìåñòèòü âíå ïðåäåëîâ âèäèìîé
9290 ÷àñòè ýêðàíà, òàê ÷òî ïîëüçîâàòåëþ åãî âèäíî íå áóäåò).
9291 <br>
9292 Òàê æå, ÷òîáû ñäåëàòü ïðèëîæåíèå íåâèäèìûì, ïî êðàéíåé ìåðå, ïîêà ýòî íå
9293 ïîòðåáóåòñÿ, èñïîëüçóéòå îòäåëüíûé ïðåäñòàâèòåëü êëàññà TControl - ãëîáàëüíóþ
9294 ïåðåìåííóþ Applet, è ïðèñâîéòå FALSE åå ñâîéñòâó Visible.
9296 //[END OF TTrayIcon DEFINITION]
9298 //[NewTrayIcon DECLARATION]
9299 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;
9300 {* Constructor of TTrayIcon object. Pass main form or applet as Wnd
9301 parameter. }
9314 //[JUST ONE]
9315 { -- JustOne -- }
9317 type
9318 TOnAnotherInstance = procedure( const CmdLine: String ) of object;
9319 {* Event type to use in JustOneNotify function. }
9321 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;
9322 {* Returns True, if this is a first instance. For all other instances
9323 (application is already running), False is returned. }
9325 function JustOneNotify( Wnd: PControl; const Identifier : String;
9326 const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;
9327 {* Returns True, if this is a first instance. For all other instances
9328 (application is already running), False is returned. If handler
9329 aOnAnotherInstance passed, it is called (in first instance) every time
9330 when another instance of an application is started, receiving command
9331 line used to run it. }
9349 { -- string (mainly) utility procedures and functions. -- }
9351 //[Message Box DECLARATIONS]
9352 function MsgBox( const S: String; Flags: DWORD ): DWORD;
9353 {* Displays message box with the same title as Applet.Caption. If applet
9354 is not running, and Applet global variable is not assigned, caption
9355 'Error' is displayed (but actually this is not an error - the system
9356 does so, if nil is passed as a title).
9357 |<br>&nbsp;&nbsp;&nbsp;
9358 Returns ID_... result (correspondently to flags passed (MB_OK, MBYESNO,
9359 etc. -> ID_OK, ID_YES, ID_NO, etc.) }
9360 procedure MsgOK( const S: String );
9361 {* Displays message box with the same title as Applet.Caption (or 'Error',
9362 if Applet is not running). }
9363 function ShowMsg( const S: String; Flags: DWORD ): DWORD;
9364 {* Displays message box like MsgBox, but uses Applet.Handle as a parent
9365 (so the message has no button on a task bar). }
9366 procedure ShowMessage( const S: String );
9367 {* Like ShowMsg, but has only styles MB_OK and MB_SETFOREGROUND. }
9368 procedure ShowMsgModal( const S: String );
9369 {* This message function can be used out of a message loop (e.g., after
9370 finishing the application). It is always modal.
9371 Actually, a form with word-wrap label (decorated as borderless edit
9372 box with btnFace color) and with OK button is created and shown modal.
9373 When a dialog is called from outside message loop, caption 'Information'
9374 is always displayed.
9375 Dialog form is automatically resized vertically to fit message text
9376 (but until screen height is achieved) and shown always centered on
9377 screen. The width is fixed (400 pixels).
9378 |<br>
9379 Do not use this function outside the message loop for case, when the
9380 Applet variable is not used in an application. }
9381 function ShowQuestion( const S: String; Answers: String ): Integer;
9382 {* Modal dialog like ShowMsgModal. It is based on KOL form, so it can
9383 be called also out of message loop, e.g. after finishing the
9384 application. Also, this function *must* be used in MDI applications
9385 in place of any dialog functions, based on MessageBox.
9386 |<br>
9387 The second parameter should be empty string or several possible
9388 answers separated by '/', e.g.: 'Yes/No/Cancel'. Result is
9389 a number answered, starting from 1. For example, if 'Cancel'
9390 was pressed, 3 will be returned.
9391 |<br>
9392 User can also press ESCAPE key, or close modal dialog. In such case
9393 -1 is returned. }
9394 function ShowQuestionEx( const S: String; Answers: String; CallBack: TOnEvent ): Integer;
9395 {* Like ShowQuestion, but with CallBack function, called just before showing
9396 the dialog. }
9397 procedure SpeakerBeep( Freq: Word; Duration: DWORD );
9398 {* On Windows NT, calls Windows.Beep. On Windows 9x, produces beep on speaker
9399 of desired frequency during given duration time (in milliseconds). }
9401 {++}(*
9402 function FormatMessage(dwFlags: DWORD; lpSource: Pointer; dwMessageId: DWORD; dwLanguageId: DWORD;
9403 lpBuffer: PChar; nSize: DWORD; Arguments: Pointer): DWORD; stdcall;
9404 *){--}
9405 function SysErrorMessage(ErrorCode: Integer): string;
9406 {* Creates and returns a string containing formatted system error message.
9407 It is possible then to display this message or write it to a log
9408 file, e.g.:
9409 ! ShowMsg( SysErrorMessage( GetLastError ) );
9413 |&R=<a name="%0"></a><font color=#FF8040><h1>%0</h1></font>
9414 <R 64-bit integer numbers>
9416 //[I64 TYPE]
9417 type
9418 I64 = record
9419 {* 64 bit integer record. Use it and correspondent functions below in KOL
9420 projects to avoid dependancy from Delphi version (earlier versions of
9421 Delphi had no Int64 type). }
9422 Lo, Hi: DWORD;
9423 end;
9424 PI64 = ^I64;
9425 {* }
9429 {$IFNDEF _D4orHigher}
9430 Int64 = I64;
9431 PInt64 = PI64;
9432 {$ENDIF}
9434 function MakeInt64( Lo, Hi: DWORD ): I64;
9435 {* }
9436 function Int2Int64( X: Integer ): I64;
9437 {* }
9438 procedure IncInt64( var I64: I64; Delta: Integer );
9439 {* I64 := I64 + Delta; }
9440 procedure DecInt64( var I64: I64; Delta: Integer );
9441 {* I64 := I64 - Delta; }
9442 function Add64( const X, Y: I64 ): I64;
9443 {* Result := X + Y; }
9444 function Sub64( const X, Y: I64 ): I64;
9445 {* Result := X - Y; }
9446 function Neg64( const X: I64 ): I64;
9447 {* Result := -X; }
9448 function Mul64i( const X: I64; Mul: Integer ): I64;
9449 {* Result := X * Mul; }
9450 function Div64i( const X: I64; D: Integer ): I64;
9451 {* Result := X div D; }
9452 function Mod64i( const X: I64; D: Integer ): Integer;
9453 {* Result := X mod D; }
9454 function Sgn64( const X: I64 ): Integer;
9455 {* Result := sign( X ); i.e.:
9456 |<br>
9457 if X < 0 then -1
9458 |<br>
9459 if X = 0 then 0
9460 |<br>
9461 if X > 0 then 1 }
9462 function Cmp64( const X, Y: I64 ): Integer;
9463 {* Result := sign( X - Y ); i.e.
9464 |<br>
9465 if X < Y then -1
9466 |<br>
9467 if X = Y then 0
9468 |<br>
9469 if X > Y then 1 }
9470 function Int64_2Str( X: I64 ): String;
9471 {* }
9472 function Str2Int64( const S: String ): I64;
9473 {* }
9474 function Int64_2Double( const X: I64 ): Double;
9475 {* }
9476 function Double2Int64( D: Double ): I64;
9481 <R Floating point numbers>
9484 const
9485 NAN = 0.0 / 0.0;
9487 {++}(*const NAN = 1e-100;*){--}
9490 function IsNan(const AValue: Double): Boolean;
9491 {* Checks is an argument passed is NAN. }
9493 function IntPower(Base: Extended; Exponent: Integer): Extended;
9494 {* Result := Base ^ Exponent; }
9496 //[String<->Double DECLARATIONS]
9497 function Str2Double( const S: String ): Double;
9498 {* }
9500 function Double2Str( D: Double ): String;
9501 {* }
9502 function Extended2Str( E: Extended ): String;
9503 {* }
9505 function Double2StrEx( D: Double ): String;
9506 {* experimental, do not use }
9508 function TruncD( D: Double ): Double;
9509 {* Result := trunc( D ) as Double;
9510 |<hr>
9526 <R Small bit arrays (max 32 bits in array)>
9527 See also TBits object.
9530 //[SMALL BIT ARRAYS DECLARATIONS]
9531 function GetBits( N: DWORD; first, last: Byte ): DWord;
9532 {* Retuns bits straing from <first> and to <last> inclusively. }
9533 function GetBitsL( N: DWORD; from, len: Byte ): DWord;
9534 {* Retuns len bits starting from index <from>.
9535 |<hr>
9547 <R Arithmetics, geometry and other utility functions>
9549 See also units KolMath.pas, CplxMath.pas and Err.pas.
9551 //[MulDiv DECLARATION]
9552 {$IFNDEF FPC}
9553 function MulDiv( A, B, C: Integer ): Integer;
9554 {* Returns A * B div C. Small and fast. }
9555 {$ENDIF}
9557 //[TMethod TYPE]
9558 type
9559 ///////////////////////////////////////////
9560 {$ifndef _D6orHigher} //
9561 ///////////////////////////////////////////
9562 TMethod = packed record
9563 {* Is defined here because using of VCL classes.pas unit is
9564 not recommended in XCL. This record type is used often
9565 to set/access event handlers, referring to a procedure
9566 of object (usually to set such event to an ordinal
9567 procedure setting Data field to nil. }
9568 Code: Pointer; // Pointer to method code.
9569 {* If used to fake assigning to event handler of type 'procedure
9570 of object' with ordinal procedure pointer, use symbol '@'
9571 before method:
9572 |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font face="Courier"><b>
9573 | Method.Code := @MyProcedure;
9574 |</b></font> }
9575 Data: Pointer; // Pointer to object, owning the method.
9576 {* To fake event of type 'procedure of object' with setting it to
9577 ordinal procedure assign here NIL; }
9578 end;
9579 {* When assigning TMethod record to event handler, typecast it with
9580 desired event type, e.g.:
9581 |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font face="Courier"><b>
9582 | SomeObject.OnSomeEvent := TOnSomeEvent( Method );
9583 |</b></font><br> }
9584 ///////////////////////////////////////////
9585 {$endif} //
9586 ///////////////////////////////////////////
9587 PMethod = ^TMethod;
9588 {* }
9590 function MakeMethod( Data, Code: Pointer ): TMethod;
9591 {* Help function to construct TMethod record. Can be useful to
9592 assign regular type procedure/function as event handler for
9593 event, defined as object method (do not forget, that in that
9594 case it must have first dummy parameter to replace @Self,
9595 passed in EAX to methods of object). }
9597 //[Rectangles&Points DECLARATIONS]
9598 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;
9599 {* Use it instead of VCL Rect function }
9600 function RectsEqual( const R1, R2: TRect ): Boolean;
9601 {* Returns True if rectangles R1 and R2 have the same bounds }
9602 function RectsIntersected( const R1, R2: TRect ): Boolean;
9603 {* Returns TRUE if rectangles R1 and R2 have at least one common point.
9604 Note, that right and bottom bounds of rectangles are not their part,
9605 so, if such points are lying on that bounds, FALSE is returned. }
9606 function PointInRect( const P: TPoint; const R: TRect ): Boolean;
9607 {* Returns True if point P is located in rectangle R (including
9608 left and top bounds but without right and bottom bounds of the
9609 rectangle). }
9610 function MakePoint( X, Y: Integer ): TPoint;
9611 {* Use instead of VCL function Point }
9612 //[MakeFlags DECLARATION]
9613 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;
9614 {* }
9616 function MakeDateTimeRange( D1, D2: TDateTime ): TDateTimeRange;
9617 {* Returns TDateTimeRange from two TDateTime bounds. }
9619 //[Integer FUNCTIONS DECLARATIONS]
9620 procedure Swap( var X, Y: Integer );
9621 {* exchanging values }
9622 function Min( X, Y: Integer ): Integer;
9623 {* minimum of two integers }
9624 function Max( X, Y: Integer ): Integer;
9625 {* maximum of two integers }
9626 function Abs( X: Integer ): Integer;
9627 {* absolute value }
9628 function Sgn( X: Integer ): Integer;
9629 {* sign of X: if X < 0, -1 is returned, if > 0, then +1, otherwise 0. }
9630 function iSqrt( X: Integer ): Integer;
9631 {* square root
9632 |<hr>
9637 <R String to number and number to string conversions>
9639 //[Integer<->String DECLARATIONS]
9640 function Int2Hex( Value : DWord; Digits : Integer ) : String;
9641 {* Converts integer Value into string with hex number. Digits parameter
9642 determines minimal number of digits (will be completed by adding
9643 necessary number of leading zeroes). }
9644 function Int2Str( Value : Integer ) : String;
9645 {* Obvious. }
9646 function UInt2Str( Value: DWORD ): String;
9647 {* The same as Int2Str, but for unsigned integer value. }
9648 function Int2StrEx( Value, MinWidth: Integer ): String;
9649 {* Like Int2Str, but resulting string filled with leading spaces to provide
9650 at least MinWidth characters. }
9651 function Int2Rome( Value: Integer ): String;
9652 {* Represents number 1..8999 to Rome numer. }
9653 function Int2Ths( I : Integer ) : String;
9654 {* Converts integer into string, separating every three digits from each
9655 other by ',' character. (Convert to thousands). }
9656 function Int2Digs( Value, Digits : Integer ) : String;
9657 {* Converts integer to string, inserting necessary number of leading zeroes
9658 to provide desired length of string, given by Digits parameter. If
9659 resulting string is greater then Digits, string is not truncated anyway. }
9660 function Num2Bytes( Value : Double ) : String;
9661 {* Converts double float to string, considering it as a bytes count.
9662 If Value is sufficiently large, number is represented in kilobytes (with
9663 following letter K), or in megabytes (M), gigabytes (G) or terabytes (T).
9664 Resulting string number is truncated to two decimals (.XX) or to one (.X),
9665 if the second is 0. }
9666 function S2Int( S: PChar ): Integer;
9667 {* Converts null-terminated string to Integer. Scanning stopped when any
9668 non-digit character found. Even empty string or string not containing
9669 valid integer number silently converted to 0. }
9670 function Str2Int(const Value : String) : Integer;
9671 {* Converts string to integer. First character, which can not be
9672 recognized as a part of number, regards as a separator. Even
9673 empty string or string without number silently converted to 0. }
9674 function Hex2Int( const Value : String) : Integer;
9675 {* Converts hexadecimal number to integer. Scanning is stopped
9676 when first non-hexadicimal character is found. Leading dollar ('$')
9677 character is skept (if present). Minus ('-') is not concerning as
9678 a sign of number and also stops scanning.}
9679 function cHex2Int( const Value : String) : Integer;
9680 {* As Hex2Int, but also checks for leading '0x' and skips it. }
9681 function Octal2Int( const Value: String ) : Integer;
9682 {* Converts octal number to integer. Scanning is stopped on first
9683 non-octal digit (any char except 0..7). There are no checking if
9684 there octal numer in the parameter. If the first char is not octal
9685 digit, 0 is returned. }
9686 function Binary2Int( const Value: String ) : Integer;
9687 {* Converts binary number to integer. Like Octal2Int, but only digits
9688 0 and 1 are allowed. }
9689 {$IFNDEF _FPC}
9690 function Format( const fmt: string; params: array of const ): String;
9691 {* Uses API call to wvsprintf, so does not understand extra formats,
9692 such as floating point, date/time, currency conversions. See list of
9693 available formats in win32.hlp (topic wsprintf).
9694 |<hr>
9698 <R Working with null-terminated and ansi strings>
9700 {$ENDIF _FPC}
9701 //[String FUNCTIONS DECLARATIONS]
9702 function StrComp(const Str1, Str2: PChar): Integer;
9703 {* Compares two strings fast. -1: Str1<Str2; 0: Str1=Str2; +1: Str1>Str2 }
9704 function StrComp_NoCase(const Str1, Str2: PChar): Integer;
9705 {* Compares two strings fast without case sensitivity.
9706 Returns: -1 when Str1<Str2; 0 when Str1=Str2; +1 when Str1>Str2 }
9707 function StrLComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
9708 {* Compare two strings (fast). Terminating 0 is not considered, so if
9709 strings are equal, comparing is continued up to MaxLen bytes.
9710 Since this, pass minimum of lengths as MaxLen. }
9711 function StrLComp_NoCase(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
9712 {* Compare two strings fast without case sensitivity.
9713 Terminating 0 is not considered, so if strings are equal,
9714 comparing is continued up to MaxLen bytes.
9715 Since this, pass minimum of lengths as MaxLen. }
9716 function StrCopy( Dest, Source: PChar ): PChar;
9717 {* Copy source string to destination (fast). Pointer to Dest is returned. }
9718 function StrCat( Dest, Source: PChar ): PChar;
9719 {* Append source string to destination (fast). Pointer to Dest is returned. }
9720 function StrLen(const Str: PChar): Cardinal;
9721 {* StrLen returns the number of characters in Str, not counting the null
9722 terminator. }
9723 function StrScanLen(Str: PChar; Chr: Char; Len: Integer): PChar;
9724 {* Fast scans string Str of length Len searching character Chr.
9725 Pointer to a character next to found or to Str[Len] (if no one found)
9726 is returned. }
9727 function StrScan(Str: PChar; Chr: Char): PChar;
9728 {* Fast search of given character in a string. Pointer to found character
9729 (or nil) is returned. }
9730 function StrRScan(const Str: PChar; Chr: Char): PChar;
9731 {* StrRScan returns a pointer to the last occurrence of Chr in Str. If Chr
9732 does not occur in Str, StrRScan returns NIL. The null terminator is
9733 considered to be part of the string. }
9734 function StrIsStartingFrom( Str, Pattern: PChar ): Boolean;
9735 {* Returns True, if string Str is starting from Pattern, i.e. if
9736 Copy( Str, 1, StrLen( Pattern ) ) = Pattern. Str must not be nil! }
9737 function StrIsStartingFromNoCase( Str, Pattern: PChar ): Boolean;
9738 {* Like StrIsStartingFrom above, but without case sensitivity. }
9739 function TrimLeft(const S: string): string;
9740 {* Removes spaces, tabulations and control characters from the starting
9741 of string S. }
9742 function TrimRight(const S: string): string;
9743 {* Removes spaces, tabulates and other control characters from the
9744 end of string S. }
9745 function Trim( const S : string): string;
9746 {* Makes TrimLeft and TrimRight for given string. }
9747 function RemoveSpaces( const S: String ): String;
9748 {* Removes all characters less or equal to ' ' in S and returns it. }
9749 procedure Str2LowerCase( S: PChar );
9750 {* Converts null-terminated string to lowercase (inplace). }
9751 function LowerCase(const S: string): string;
9752 {* Obvious. }
9753 function UpperCase(const S: string): string;
9754 {* Obvious. }
9755 function AnsiUpperCase(const S: string): string;
9756 {* Obvious. }
9757 function AnsiLowerCase(const S: string): string;
9758 {* Obvious. }
9759 {$IFNDEF _D2}
9760 {$IFNDEF _FPC}
9761 function WAnsiUpperCase(const S: WideString): WideString;
9762 {* Obvious. }
9763 function WAnsiLowerCase(const S: WideString): WideString;
9764 {* Obvious. }
9765 {$ENDIF _FPC}
9766 {$ENDIF _D2}
9767 function AnsiCompareStr(const S1, S2: string): Integer;
9768 {* AnsiCompareStr compares S1 to S2, with case-sensitivity. The compare
9769 operation is controlled by the current Windows locale. The return value
9770 is the same as for CompareStr. }
9771 function _AnsiCompareStr(S1, S2: PChar): Integer;
9772 {* The same, but for PChar ANSI strings }
9773 function AnsiCompareStrNoCase(const S1, S2: string): Integer;
9774 {* AnsiCompareStr compares S1 to S2, with case-sensitivity. The compare
9775 operation is controlled by the current Windows locale. The return value
9776 is the same as for CompareStr. }
9777 function _AnsiCompareStrNoCase(S1, S2: PChar): Integer;
9778 {* The same, but for PChar ANSI strings }
9779 function AnsiCompareText( const S1, S2: String ): Integer;
9780 {* }
9782 {$IFNDEF _FPC}
9783 function LStrFromPWCharLen(Source: PWideChar; Length: Integer): String;
9784 {* from Delphi5 - because D2 does not contain it. }
9785 function LStrFromPWChar(Source: PWideChar): String;
9786 {* from Delphi5 - because D2 does not contain it. }
9787 {$ENDIF _FPC}
9789 function CopyEnd( const S : String; Idx : Integer ) : String;
9790 {* Returns copy of source string S starting from Idx up to the end of
9791 string S. Works correctly for case, when Idx > Length( S ) (returns
9792 empty string for such case). }
9793 function CopyTail( const S : String; Len : Integer ) : String;
9794 {* Returns last Len characters of the source string. If Len > Length( S ),
9795 entire string S is returned. }
9796 procedure DeleteTail( var S : String; Len : Integer );
9797 {* Deletes last Len characters from string. }
9798 function IndexOfChar( const S : String; Chr : Char ) : Integer;
9799 {* Returns index of given character (1..Length(S)), or
9800 -1 if a character not found. }
9801 function IndexOfCharsMin( const S, Chars : String ) : Integer;
9802 {* Returns index (in string S) of those character, what is taking place
9803 in Chars string and located nearest to start of S. If no such
9804 characters in string S found, -1 is returned. }
9805 {$IFNDEF _D2}
9806 {$IFNDEF _FPC}
9807 function IndexOfWideCharsMin( const S, Chars : WideString ) : Integer;
9808 {* Returns index (in wide string S) of those wide character, what
9809 is taking place in Chars wide string and located nearest to start of S.
9810 If no such characters in string S found, -1 is returned. }
9811 {$ENDIF _FPC}
9812 {$ENDIF _D2}
9814 function IndexOfStr( const S, Sub : String ) : Integer;
9815 {* Returns index of given substring in source string S. If found,
9816 1..Length(S)-Length(Sub), if not found, -1. }
9817 function Parse( var S : String; const Separators : String ) : String;
9818 {* Returns first characters of string S, separated from others by
9819 one of characters, taking place in Separators string, assigning
9820 a tail of string (after found separator) to source string. If
9821 no separator characters found, source string S is returned, and
9822 source string itself becomes empty. }
9823 {$IFNDEF _FPC}
9824 {$IFNDEF _D2}
9825 function WParse( var S : WideString; const Separators : WideString ) : WideString;
9826 {* Returns first wide characters of wide string S, separated from others
9827 by one of wide characters, taking place in Separators wide string,
9828 assigning a tail of wide string (following found separator) to the
9829 source one. If there are no separator characters found, source wide
9830 string S is returned, and source wide string itself becomes empty. }
9831 {$ENDIF _D2}
9832 {$ENDIF _FPC}
9833 function ParsePascalString( var S : String; const Separators : String ) : String;
9834 {* Returns first characters of string S, separated from others by
9835 one of characters, taking place in Separators string, assigning
9836 a tail of string (after the found separator) to source string. If
9837 there are no separator characters found, the source string S is returned,
9838 and the source string itself becomes empty. Additionally: if the first (after
9839 a blank space) is the quote "'" or '#', pascal string is assumung first
9840 and is converted to usual string (without quotas) before analizing
9841 of other separators. }
9842 function String2PascalStrExpr( const S : String ) : String;
9843 {* Converts string to Pascal-like string expression (concatenation of
9844 strings with quotas and characters with leading '#'). }
9845 function StrEq( const S1, S2 : String ) : Boolean;
9846 {* Returns True, if LowerCase(S1) = LowerCase(S2). I.e., if strings
9847 are equal to each other without caring of characters case sensitivity
9848 (ASCII only). }
9849 function AnsiEq( const S1, S2 : String ) : Boolean;
9850 {* Returns True, if AnsiLowerCase(S1) = AnsiLowerCase(S2). I.e., if ANSI
9851 stringsare equal to each other without caring of characters case
9852 sensitivity. }
9853 {$IFNDEF _D2}
9854 {$IFNDEF _FPC}
9855 function WAnsiEq( const S1, S2 : WideString ) : Boolean;
9856 {* Returns True, if AnsiLowerCase(S1) = AnsiLowerCase(S2). I.e., if ANSI
9857 stringsare equal to each other without caring of characters case
9858 sensitivity. }
9859 {$ENDIF _FPC}
9860 {$ENDIF _D2}
9862 function StrIn( const S : String; const A : array of String ) : Boolean;
9863 {* Returns True, if S is "equal" to one of strings, taking place
9864 in A array. To check equality, StrEq function is used, i.e.
9865 comaprison is taking place without case sensitivity. }
9866 {$IFNDEF _FPC}
9867 {$IFNDEF _D2}
9868 function WStrIn( const S : WideString; const A : array of WideString ) : Boolean;
9869 {* Returns True, if S is "equal" to one of strings, taking place
9870 in A array. To check equality, WAnsiEq function is used, i.e.
9871 comaprison is taking place without case sensitivity. }
9872 {$ENDIF _D2}
9873 {$ENDIF _FPC}
9874 function StrIs( const S : String; const A : array of String; var Idx: Integer ) : Boolean;
9875 {* Returns True, if S is "equal" to one of strings, taking place
9876 in A array, and in such Case Idx also is assigned to an index of A element
9877 equal to S. To check equality, StrEq function is used, i.e.
9878 comaprison is taking place without case sensitivity. }
9879 function IntIn( Value: Integer; const List: array of Integer ): Boolean;
9880 {* Returns TRUE, if Value is found in a List. }
9881 function _StrSatisfy( S, Mask : PChar ) : Boolean;
9882 {* }
9883 function _2StrSatisfy( S, Mask: PChar ): Boolean;
9884 {* }
9885 function StrSatisfy( const S, Mask : String ) : Boolean;
9886 {* Returns True, if S is satisfying to a given Mask (which can contain
9887 wildcard symbols '*' and '?' interpeted correspondently as 'any
9888 set of characters' and 'single any character'. If there are no
9889 such wildcard symbols in a Mask, result is True only if S is maching
9890 to Mask string.) }
9891 function StrReplace( var S: String; const From, ReplTo: String ): Boolean;
9892 {* Replaces first occurance of From to ReplTo in S, returns True,
9893 if pattern From was found and replaced. }
9894 {$IFNDEF _FPC}
9895 {$IFNDEF _D2}
9896 function WStrReplace( var S: WideString; const From, ReplTo: WideString ): Boolean;
9897 {* Replaces first occurance of From to ReplTo in S, returns True,
9898 if pattern From was found and replaced. See also function StrReplace.
9899 This function is not available in Delphi2 (this version of Delphi
9900 does not support WideString type). }
9901 {$ENDIF _D2}
9902 {$ENDIF _FPC}
9904 function StrRepeat( const S: String; Count: Integer ): String;
9905 {* Repeats given string Count times. E.g., StrRepeat( 'A', 5 ) gives 'AAAAA'. }
9906 {$IFNDEF _FPC}
9907 {$IFNDEF _D2}
9908 function WStrRepeat( const S: WideString; Count: Integer ): WideString;
9909 {* Repeats given wide string Count times. E.g., StrRepeat( 'A', 5 ) gives 'AAAAA'. }
9910 {$ENDIF _D2}
9911 {$ENDIF _FPC}
9913 procedure NormalizeUnixText( var S: String );
9914 {* In the string S, replaces all occurances of character #10 (without leading #13)
9915 to the character #13. }
9917 {$IFNDEF _FPC}
9918 function WStrLen( W: PWideChar ): Integer;
9919 {* Returns Length of null-terminated Unicode string. }
9920 procedure WStrCopy( Dest, Src: PWideChar );
9921 {* Copies null-terminated Unicode string (terminated null also copied). }
9922 function WStrCmp( W1, W2: PWideChar ): Integer;
9923 {* Compares two null-terminated Unicode strings. }
9924 {$ENDIF _FPC}
9926 function StrPCopy(Dest: PChar; const Source: string): PChar;
9927 {* Copyes Pascal-style string into null-terminaed one. }
9928 function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar;
9929 {* Copyes first MaxLen characters of Pascal-style string into
9930 null-terminated one. }
9932 function DelimiterLast( const Str, Delimiters: String ): Integer;
9933 {* Returns index of the last of delimiters given by same named parameter
9934 among characters of Str. If there are no delimiters found, length of
9935 Str is returned. This function is intended mainly to use in filename
9936 parsing functions. }
9937 function __DelimiterLast( Str, Delimiters: PChar ): PChar;
9938 {* Returns address of the last of delimiters given by Delimiters parameter
9939 among characters of Str. If there are no delimeters found, position of
9940 the null terminator in Str is returned. This function is intended
9941 mainly to use in filename parsing functions. }
9942 function SkipSpaces( P: PChar ): PChar;
9943 {* Skips all characters #1..' ' in a string.
9945 {$IFDEF F_P}
9946 function DummyStrFun( const S: String ): String;
9947 {$ENDIF}
9950 //[Memory FUNCTIONS DECLARATIONS]
9951 function CompareMem(P1, P2: Pointer; Length: Integer): Boolean;
9952 {* Fast compare of two memory blocks. }
9953 function AllocMem( Size : Integer ) : Pointer;
9954 {* Allocates global memory and unlocks it. }
9955 procedure DisposeMem( var Addr : Pointer );
9956 {* Locks global memory block given by pointer, and frees it.
9957 Does nothing, if the pointer is nil.
9958 |<hr>
9960 <R Text in clipboard operations>
9963 //[clipboard FUNCTIONS DECLARATIONS]
9964 function Clipboard2Text: String;
9965 {* If clipboard contains text, this function returns it for You. }
9966 {$IFNDEF _FPC}
9967 {$IFNDEF _D2}
9968 function Clipboard2WText: WideString;
9969 {* If clipboard contains text, this function returns it for You (as Unicode string). }
9970 {$ENDIF _D2}
9971 {$ENDIF _FPC}
9972 function Text2Clipboard( const S: String ): Boolean;
9973 {* Puts given string to a clipboard. }
9974 {$IFNDEF _FPC}
9975 {$IFNDEF _D2}
9976 function WText2Clipboard( const WS: WideString ): Boolean;
9977 {* Puts given Unicode string to a clipboard.
9978 |<hr>
9980 {$ENDIF _D2}
9981 {$ENDIF _FPC}
9985 //[Mnemonics FUNCTIONS DECLARATIONS]
9986 var SearchMnemonics: function ( const S: String ): String
9987 = {$IFDEF F_P} DummyStrFun {$ELSE} UpperCase {$ENDIF};
9988 MnemonicsLocale: Integer;
9990 procedure SupportAnsiMnemonics( LocaleID: Integer );
9991 {* Provides encoding to work with given locale. Call this global function to
9992 extend TControl.SupportMnemonics capability (also should be called for a form
9993 or for Applet variable).
9999 <R Date and time handling>
10001 //[TDateTime TYPE DEFINITION]
10002 type
10003 //TDateTime = Double; // well, it is already defined so in System.pas
10004 {* Basic date and time type. Integer part represents year and days (as is,
10005 i.e. 1-Jan-2000 is representing by value 730141, which is a number of
10006 days from 1-Jan-0001 to 1-Jan-2000 inclusively). Fractional part is
10007 representing hours, minutes, seconds and milliseconds of a day
10008 proportionally (like in VCL TDateTime type, e.g. 0.5 = 12:00, 0.25 = 6:00,
10009 etc.). }
10011 PDayTable = ^TDayTable;
10012 TDayTable = array[1..12] of Word;
10014 TDateFormat = ( dfShortDate, dfLongDate );
10015 {* Date formats available to use in formatting date/time to string. }
10016 TTimeFormatFlag = ( tffNoMinutes, tffNoSeconds, tffNoMarker, tffForce24 );
10017 {* Additional flags, used for formatting time. }
10018 TTimeFormatFlags = Set of TTimeFormatFlag;
10019 {* Set of flags, used for formatting time. }
10021 const
10022 MonthDays: array [Boolean] of TDayTable =
10023 ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
10024 (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));
10025 {* The MonthDays array can be used to quickly find the number of
10026 days in a month: MonthDays[IsLeapYear(Y), M]. }
10028 SecsPerDay = 24 * 60 * 60;
10029 {* Seconds per day. }
10030 MSecsPerDay = SecsPerDay * 1000;
10031 {* Milliseconds per day. }
10033 VCLDate0 = 693594;
10034 {* Value to convert VCL "date 0" to KOL "date 0" and back.
10035 This value corresponds to 30-Dec-1899, 0:00:00. So,
10036 to convert VCL date to KOL date, just subtract this
10037 value from VCL date. And to convert back from KOL date
10038 to VCL date, add this value to KOL date.}
10040 {++}(*
10041 procedure GetLocalTime(var lpSystemTime: TSystemTime); stdcall;
10042 procedure GetSystemTime(var lpSystemTime: TSystemTime); stdcall;
10043 *){--}
10045 //[Date&Time FUNCTIONS DECLARATIONS]
10046 function Now : TDateTime;
10047 {* Returns local date and time on running PC. }
10048 function Date: TDateTime;
10049 {* Returns todaylocal date. }
10050 procedure DecodeDateFully( DateTime: TDateTime; var Year, Month, Day, DayOfWeek: WORD );
10051 {* Decodes date. }
10052 procedure DecodeDate( DateTime: TDateTime; var Year, Month, Day: WORD );
10053 {* Decodes date. }
10054 function EncodeDate( Year, Month, Day: WORD; var DateTime: TDateTime ): Boolean;
10055 {* Encodes date. }
10056 function CompareSystemTime(const D1, D2 : TSystemTime) : Integer;
10057 {* Compares to TSystemTime records. Returns -1, 0, or 1 if, correspondantly,
10058 D1 < D2, D1 = D2 and D1 > D2. }
10059 procedure IncDays( var SystemTime : TSystemTime; DaysNum : Integer );
10060 {* Increases/decreases day in TSystemTime record onto given days count
10061 (can be negative). }
10062 procedure IncMonths( var SystemTime : TSystemTime; MonthsNum : Integer );
10063 {* Increases/decreases month number in TSystemTime record onto given
10064 months count (can be negative). Correct result is not garantee if
10065 day number is incorrect for newly obtained month. }
10066 function IsLeapYear(Year: Word): Boolean;
10067 {* Returns True, if given year is "leap" (i.e. has 29 days in the February). }
10068 function DayOfWeek(Date: TDateTime): Integer;
10069 {* Returns day of week (0..6) for given date. }
10070 function SystemTime2DateTime(const SystemTime : TSystemTime; var DateTime : TDateTime ) : Boolean;
10071 {* Converts TSystemTime record to XDateTime variable. }
10072 function DateTime2SystemTime(const DateTime : TDateTime; var SystemTime : TSystemTime ) : Boolean;
10073 {* Converts TDateTime variable to TSystemTime record. }
10074 function DateTime_System2Local( DTSys: TDateTime ): TDateTime;
10075 {* Converts DTSys representing system time (+0 Grinvich) to local time. }
10076 function DateTime_Local2System( DTLoc: TDateTime ): TDateTime;
10077 {* Converts DTLoc representing local time to system time (+0 Grinvich) }
10078 function CatholicEaster( nYear: Integer ): TDateTime;
10079 {* Returns date of catholic easter for given year. }
10081 procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
10082 {* Dividing of integer onto divisor with obtaining both result of division
10083 and remainder. }
10085 function SystemDate2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
10086 const DfltDateFormat : TDateFormat; const DateFormat : PChar ) : String;
10087 {* Formats date, stored in TSystemTime record into string, using given locale
10088 and date/time formatting flags. }
10089 function SystemTime2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
10090 const Flags : TTimeFormatFlags; const TimeFormat : PChar ) : String;
10091 {* Formats time, stored in TSystemTime record into string, using given locale
10092 and date/time formatting flags. }
10094 function Date2StrFmt( const Fmt: String; D: TDateTime ): String;
10095 {* Represents date as a string correspondently to Fmt formatting string.
10096 See possible pictures in definition of the function Str2DateTimeFmt
10097 (the first part). If Fmt string is empty, default system date format
10098 for short date string used. }
10099 function Time2StrFmt( const Fmt: String; D: TDateTime ): String;
10100 {* Represents time as a string correspondently to Fmt formatting string.
10101 See possible pictures in definition of the function Str2DateTimeFmt
10102 (the second part). If Fmt string is empty, default system time format
10103 for short date string used. }
10104 function DateTime2StrShort( D: TDateTime ): String;
10105 {* Formats date and time to string in short date format using current user
10106 locale. }
10107 function Str2DateTimeFmt( const sFmtStr, sS: String ): TDateTime;
10108 {* Restores date or/and time from string correspondently to a format string.
10109 Date and time formatting string can contain following pictures (case
10110 sensitive):
10111 |<pre>
10112 DATE PICTURES
10113 d Day of the month as digits without leading zeros for single digit days.
10114 dd Day of the month as digits with leading zeros for single digit days
10115 ddd Day of the week as a 3-letter abbreviation as specified by a
10116 LOCALE_SABBREVDAYNAME value.
10117 dddd Day of the week as specified by a LOCALE_SDAYNAME value.
10118 M Month as digits without leading zeros for single digit months.
10119 MM Month as digits with leading zeros for single digit months
10120 MMM Month as a three letter abbreviation as specified by a LOCALE_SABBREVMONTHNAME value.
10121 MMMM Month as specified by a LOCALE_SMONTHNAME value.
10122 y Year represented only be the last digit.
10123 yy Year represented only be the last two digits.
10124 yyyy Year represented by the full 4 digits.
10125 gg Period/era string as specified by the CAL_SERASTRING value. The gg
10126 format picture in a date string is ignored if there is no associated era
10127 string. In Enlish locales, usual values are BC or AD.
10129 TIME PICTURES
10130 h Hours without leading zeros for single-digit hours (12-hour clock).
10131 hh Hours with leading zeros for single-digit hours (12-hour clock).
10132 H Hours without leading zeros for single-digit hours (24-hour clock).
10133 HH Hours with leading zeros for single-digit hours (24-hour clock).
10134 m Minutes without leading zeros for single-digit minutes.
10135 mm Minutes with leading zeros for single-digit minutes.
10136 s Seconds without leading zeros for single-digit seconds.
10137 ss Seconds with leading zeros for single-digit seconds.
10138 t One character–time marker string (usually P or A, in English locales).
10139 tt Multicharacter–time marker string (usually PM or AM, in English locales).
10140 |</pre>
10141 E.g., 'D, yyyy/MM/dd h:mm:ss'.
10142 See also Str2DateTimeShort function.
10144 function Str2DateTimeShort( const S: String ): TDateTime;
10145 {* Restores date and time from string correspondently to current user locale. }
10146 function Str2DateTimeShortEx( const S: String ): TDateTime;
10147 {* Like Str2DateTimeShort above, but uses locale defined date and time
10148 separators to avoid recognizing time as a date in some cases.
10149 |<hr>
10152 <R File and directory routines>
10155 //[OpenFile CONSTANTS]
10156 const
10157 ofOpenRead = $80000000;
10158 {* Use this flag (in combination with others) to open file for "read" only. }
10159 ofOpenWrite = $40000000;
10160 {* Use this flag (in combination with others) to open file for "write" only. }
10161 ofOpenReadWrite = $C0000000;
10162 {* Use this flag (in combination with others) to open file for "read" and "write". }
10163 ofShareExclusive = $00;
10164 {* Use this flag (in combination with others) to open file for exclusive use. }
10165 ofShareDenyWrite = $01;
10166 {* Use this flag (in combination with others) to open file in share mode, when
10167 only attempts to open it in other process for "write" will be impossible.
10168 I.e., other processes could open this file simultaneously for read only
10169 access. }
10170 ofShareDenyRead = $02;
10171 {* Use this flag (in combination with others) to open file in share mode, when
10172 only attempts to open it for "read" in other processes will be disabled.
10173 I.e., other processes could open it for "write" only access. }
10174 ofShareDenyNone = $03;
10175 {* Use this flag (in combination with others) to open file in full sharing mode.
10176 I.e. any process will be able open this file using the same share flag. }
10177 ofCreateNew = $100;
10178 {* Default creation disposition. Use this flag for creating new file (usually
10179 for write access. }
10180 ofCreateAlways = $200;
10181 {* Use this flag (in combination with others) to open existing or creating new
10182 file. If existing file is opened, it is truncated to size 0. }
10183 ofOpenExisting = $300;
10184 {* Use this flag (in combination with others) to open existing file only. }
10185 ofOpenAlways = $400;
10186 {* Use this flag (in combination with others) to open existing or create new
10187 (if such file is not yet exists). }
10188 ofTruncateExisting = $500;
10189 {* Use this flag (in combination with others) to open existing file and truncate
10190 it to size 0. }
10192 ofAttrReadOnly = $10000;
10193 {* Use this flag to create Read-Only file (?). }
10194 ofAttrHidden = $20000;
10195 {* Use this flag to create hidden file. }
10196 ofAttrSystem = $40000;
10197 {* Use this flag to create system file. }
10198 ofAttrTemp = $1000000;
10199 {* Use this flag to create temp file. }
10200 ofAttrArchive = $200000;
10201 {* Use this flag to create archive file. }
10202 ofAttrCompressed = $8000000;
10203 {* Use this flag to create compressed file. Has effect only on NTFS, and
10204 only if ofAttrCompressed is not specified also. }
10205 ofAttrOffline = $10000000;
10206 {* Use this flag to create offline file. }
10207 //[END OF OpenFileConstants]
10209 //[File FUNCTIONS DECLARATIONS]
10210 function FileCreate(const FileName: string; OpenFlags: DWord): THandle;
10211 {* Call this function to open existing or create new file. OpenFlags
10212 parameter can be a combination of up to three flags (by one from
10213 each group:
10214 |<table border=0>
10215 |&L=<tr><td valign=top>%0</td><td valign=top>
10216 |&E=</td></tr>
10217 <L ofOpenRead, ofOpenWrite, ofOpenReadWrite> - 1st group. Here You decide
10218 wish You open file for read, write or read-and-write operations; <E>
10219 <L ofShareExclusive, ofShareDenyWrite, ofShareDenyRead, ofShareDenyNone> -2nd
10220 group - sharing. Here You can mark out sharing mode, which is used to
10221 open file. <E>
10222 <L ofCreateNew, ofCreateAlways, ofOpenExisting, ofOpenAlways, ofTruncateExisting>
10223 - 3rd group - creation disposition. Here You determine, either to create new
10224 or open existing file and if to truncate existing or not.
10225 |</table> }
10226 function FileClose(Handle: THandle): Boolean;
10227 {* Call it to close opened earlier file. }
10228 function FileExists( const FileName: String ) : Boolean;
10229 {* Returns True, if given file exists.
10230 |<br>Note (by Dod):
10231 It is not documented in a help for GetFileAttributes, but it seems that
10232 under NT-based Windows systems, FALSE is always returned for files
10233 opened for excluseve use like pagefile.sys. }
10234 function FileRead(Handle: THandle; var Buffer; Count: DWord): DWord;
10235 {* Reads bytes from current position in file to buffer. Returns number of
10236 read bytes. }
10237 function File2Str(Handle: THandle): String;
10238 {* Reads file from current position to the end and returns result as ansi string. }
10240 function FileSeek(Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
10241 {* Changes current position in file. }
10242 function FileWrite(Handle: THandle; const Buffer; Count: DWord): DWord;
10243 {* Writes bytes from buffer to file from current position, extending its
10244 size if needed. }
10245 function FileEOF( Handle: THandle ) : Boolean;
10246 {* Returns True, if EOF is achieved during read operations or last byte is
10247 overwritten or append made to extend file during last write operation. }
10248 function FileFullPath( const FileName : String ) : String;
10249 {* Returns full path name for given file. Validness of source FileName path
10250 is not checked at all. }
10251 function FileShortPath( const FileName: String ): String;
10252 {* Returns short path to the file or directory. }
10253 function FileIconSystemIdx( const Path: String ): Integer;
10254 {* Returns index of the index of the system icon correspondent to the file or
10255 directory in system icon image list. }
10256 function FileIconSysIdxOffline( const Path: String ): Integer;
10257 {* The same as FileIconSystemIdx, but an icon is calculated for the file
10258 as it were offline (it is possible to get an icon for file even if
10259 it is not existing, on base of its extension only). }
10260 procedure LogFileOutput( const filepath, str: String );
10261 {* Debug function. Use it to append given string to the end of the given file. }
10263 function StrSaveToFile( const Filename, Str: String ): Boolean;
10264 {* Saves a string to a file without any changes. If file does not exists, it is
10265 created. If it exists, it is overriden. If operation failed, FALSE is returned. }
10266 function StrLoadFromFile( const Filename: String ): String;
10267 {* Reads entire file and returns its content as a string. If operation failed,
10268 an empty strinng is returned. }
10270 function Mem2File( Filename: PChar; Mem: Pointer; Len: Integer ): Integer;
10271 {* Saves memory block to a file (if file exists it is overriden, created new if
10272 not exists). }
10273 function File2Mem( Filename: PChar; Mem: Pointer; MaxLen: Integer ): Integer;
10274 {* Loads file content to memory. }
10276 function FileSize( const Path: String ) : Integer;
10277 {* Returns file size in bytes without opening it. If file too large
10278 to represent its size as Integer, -1 is returned. }
10279 function GetUniqueFilename( PathName: string ) : String;
10280 {* If file given by PathName exists, modifies it to create unique
10281 filename in target folder and returns it. Modification is performed
10282 by incrementing last number in name (if name part of file does not
10283 represent a number, such number is generated and concatenated to
10284 it). E.g., if file aaa.aaa is already exist, the function checks
10285 names aaa1.aaa, aaa2.aaa, ..., aaa10.aaa, etc. For name abc123.ext,
10286 names abc124.ext, abc125.ext, etc. will be checked. }
10288 function FileTimeCompare( const FT1, FT2 : TFileTime ) : Integer;
10289 {* Compares time of file (createing, writing, accessing. Returns
10290 -1, 0, 1 if correspondantly FT1<FT2, FT1=FT2, FT1>FT2. }
10292 //[Directory FUNCTIONS DECLARATIONS]
10293 function GetStartDir: String;
10294 {* Returns path to directory where executable is located (regardless
10295 of current directory). }
10296 function DirectoryExists(const Name: string): Boolean;
10297 {* Returns True if given directory (folder) exists. }
10298 function DirectoryEmpty(const Name: String): Boolean;
10299 {* Returns True if given directory is not exists or empty. }
10301 function DirectorySize( const Path: String ): I64;
10302 -- moved after PDirList
10304 function DirectoryHasSubdirs( const Path: String ): Boolean;
10305 {* Returns TRUE if given directory exists and has subdirectories. }
10306 function CheckDirectoryContent( const Name: String; SubDirsOnly: Boolean; const Mask: String ): Boolean;
10307 {* Returns TRUE if directory does not contain files (or directories only)
10308 satisfying given mask. }
10310 //---------------------------------------------------------
10311 // Following functions/procedures are created by Edward Aretino:
10312 // IncludeTrailingPathDelimiter, ExcludeTrailingPathDelimiter,
10313 // ForceDirectories, CreateDir, ChangeFileExt
10314 //---------------------------------------------------------
10315 function IncludeTrailingPathDelimiter(const S: string): string;
10316 {* by Edward Aretino. Adds '\' to the end if it is not present. }
10317 function ExcludeTrailingPathDelimiter(const S: string): string;
10318 {* by Edward Aretino. Removes '\' at the end if it is present. }
10319 function ForceDirectories(Dir: String): Boolean;
10320 {* by Edward Aretino. Creates given directory if not present. All needed
10321 subdirectories are created if necessary. }
10322 function CreateDir(const Dir: string): Boolean;
10323 {* by Edward Aretino. Creates given directory. }
10324 function ChangeFileExt(FileName: String; const Extension: string): string;
10325 {* by Edward Aretino. Changes file extention. }
10327 function ExcludeTrailingChar( const S: String; C: Char ): String;
10328 {* If S is finished with character C, it is excluded. }
10329 function IncludeTrailingChar( const S: String; C: Char ): String;
10330 {* If S is not finished with character C, it is added. }
10332 function ExtractFilePath( const Path: String ) : String;
10333 {* Returns only path part from exact path to file. }
10334 function ExtractFileName( const Path: String ) : String;
10335 {* Extracts file name from exact path to file. }
10336 function ExtractFileNameWOext( const Path: String ) : String;
10337 {* Extracts file name from path to file or from filename. }
10338 function ExtractFileExt( const Path: String ) : String;
10339 {* Extracts extention from file name (returns it with dot '.' first) }
10340 function ReplaceFileExt( const Path, NewExt: String ): String;
10341 {* Returns a path with extension replaced to a given one. }
10342 function ExtractShortPathName( const Path: String ): String;
10343 {* }
10344 function FilePathShortened( const Path: String; MaxLen: Integer ): String;
10345 {* Returns shortened file path to fit MaxLen characters. }
10346 function FilePathShortenPixels( const Path: String; DC: HDC; MaxPixels: Integer ): String;
10347 {* Returns shortened file path to fit MaxPixels for a given DC. If you pass
10348 Canvas.Handle of any control or bitmap object, ensure that font is valid
10349 for it (or call TCanvas.RequiredState( FontValid ) method before. If DC passed
10350 = 0, call is equivalent to call FilePathShortened, and MaxPixels means in such
10351 case maximum number of characters. }
10352 function MinimizeName( const Path: String; DC: HDC; MaxPixels: Integer ): String;
10353 {* Exactly the same as MinimizeName in FileCtrl.pas (VCL). }
10355 function GetSystemDir: String;
10356 {* Returns path to windows system directory. }
10357 function GetWindowsDir : string;
10358 {* Returns path to Windows directory. }
10359 function GetWorkDir : string;
10360 {* Returns path to application's working directory. }
10361 function GetTempDir : string;
10362 {* Returns path to default temp folder (directory to place temporary files). }
10363 function CreateTempFile( const DirPath, Prefix: String ): String;
10364 {* Returns path to just created temporary file. }
10365 function GetFileListStr(FPath{e.g.'c:\tmp\'}, FMask{e.g.'*.*'}: string): string;
10366 {* List of files in string, separating each path from others with semicolon (';').
10367 E.g.: 'c:\tmp\unit1.dcu;c:\tmp\unit1.~pa' (for use with DeleteFile2Recycle())}
10368 function DeleteFiles( const DirPath: String ): Boolean;
10369 {* Deletes files by file mask (given with wildcards '*' and '?'). }
10370 function DeleteFile2Recycle( const Filename : String ) : Boolean;
10371 {* Deletes file to recycle bin. This operation can be very slow, when
10372 called for a single file. To delete group of files at once (fast),
10373 pass a list of paths to files to be deleted, separating each path
10374 from others with semicolon (';'). E.g.: 'unit1.dcu;unit1.~pa'
10375 |<br>
10376 FALSE is returned only in case when at least one file was not deleted
10377 successfully.
10378 |<br>
10379 Note, that files are deleted not to recycle bin, if wildcards are
10380 used or not fully qualified paths to files. }
10381 function CopyMoveFiles( const FromList, ToList: String; Move: Boolean ): Boolean;
10382 {* }
10384 function DiskFreeSpace( const Path: String ): I64; {+}
10385 {* Returns disk free space in bytes. Pass a path to root directory,
10386 e.g. 'C:\'.
10387 |<hr>
10398 <R Wrappers to registry API functions>
10400 These functions can be used independently to simplify access to Windows
10401 registry. }
10403 //[Registry FUNCTIONS DECLARATIONS]
10404 {++}(*
10405 function RegSetValueEx(hKey: HKEY; lpValueName: PChar;
10406 Reserved: DWORD; dwType: DWORD; lpData: Pointer; cbData: DWORD): Longint; stdcall;
10407 *){--}
10408 function RegKeyOpenRead( Key: HKey; const SubKey: String ): HKey;
10409 {* Opens registry key for read operations (including enumerating of subkeys).
10410 Pass either handle of opened earlier key or one of constans
10411 HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS
10412 as a first parameter. If not successful, 0 is returned. }
10413 function RegKeyOpenWrite( Key: HKey; const SubKey: String ): HKey;
10414 {* Opens registry key for write operations (including adding new values or
10415 subkeys), as well as for read operations too. See also RegKeyOpenRead. }
10416 function RegKeyOpenCreate( Key: HKey; const SubKey: String ): HKey;
10417 {* Creates and opens key. }
10418 function RegKeyGetStr( Key: HKey; const ValueName: String ): String;
10419 {* Reads key, which must have type REG_SZ (null-terminated string). If
10420 not successful, empty string is returned. This function as well as all
10421 other registry manipulation functions, does nothing, if Key passed is 0
10422 (without producing any error). }
10423 function RegKeyGetStrEx( Key: HKey; const ValueName: String ): String;
10424 {* Like RegKeyGetStr, but accepts REG_EXPAND_SZ type, expanding all
10425 environment variables in resulting string.
10426 |<br>
10427 Code provided by neuron, e-mailto:neuron@hollowtube.mine.nu }
10428 function RegKeyGetDw( Key: HKey; const ValueName: String ): DWORD;
10429 {* Reads key value, which must have type REG_DWORD. If ValueName passed
10430 is '' (empty string), unnamed (default) value is reading. If not
10431 successful, 0 is returned. }
10432 function RegKeySetStr(Key: HKey; const ValueName: String; const Value: String ): Boolean;
10433 {* Writes new key value as null-terminated string (type REG_SZ). If not
10434 successful, returns False. }
10435 function RegKeySetStrEx( Key: HKey; const ValueName: string; const Value: string;
10436 expand: boolean): Boolean;
10437 {* Writes new key value as REG_SZ or REG_EXPAND_SZ. - by neuron, e-mailto:neuron@hollowtube.mine.nu }
10438 function RegKeySetDw( Key: HKey; const ValueName: String; Value: DWORD ): Boolean;
10439 {* Writes new key value as dword (with type REG_DWORD). Returns False,
10440 if not successful. }
10441 procedure RegKeyClose( Key: HKey );
10442 {* Closes key, opened using RegKeyOpenRead or RegKeyOpenWrite. (But does
10443 nothing, if Key passed is 0). }
10444 function RegKeyDelete( Key: HKey; const SubKey: String ): Boolean;
10445 {* Deletes key. Does nothing if key passed is 0 (returns FALSE). }
10446 function RegKeyDeleteValue( Key: HKey; const SubKey: String ): Boolean;
10447 {* Deletes value. - by neuron, e-mailto:neuron@hollowtube.mine.nu }
10448 function RegKeyExists( Key: HKey; const SubKey: String ): Boolean;
10449 {* Returns TRUE, if given subkey exists under given Key. }
10450 function RegKeyValExists( Key: HKey; const ValueName: String ): Boolean;
10451 {* Returns TRUE, if given value exists under the Key.
10453 function RegKeyValueSize( Key: HKey; const ValueName: String ): Integer;
10454 {* Returns a size of value. This is a size of buffer needed to store
10455 registry key value. For string value, size returned is equal to a
10456 length of string plus 1 for terminated null character. }
10457 function RegKeyGetBinary( Key: HKey; const ValueName: String; var Buffer; Count: Integer ): Integer;
10458 {* Reads binary data from a registry, writing it to the Buffer.
10459 It is supposed that size of Buffer provided is at least Count bytes.
10460 Returned value is actul count of bytes read from the registry and written
10461 to the Buffer.
10462 |<br>
10463 This function can be used to get data of any type from the registry, not
10464 only REG_BINARY. }
10465 function RegKeySetBinary( Key: HKey; const ValueName: String; const Buffer; Count: Integer ): Boolean;
10466 {* Stores binary data in the registry. }
10467 function RegKeyGetDateTime(Key: HKey; const ValueName: String): TDateTime;
10468 {* Returns datetime variable stored in registry in binary format. }
10469 function RegKeySetDateTime(Key: HKey; const ValueName: String; DateTime: TDateTime): Boolean;
10470 {* Stores DateTime variable in the registry. }
10473 //-------------------------------------------------------
10474 // registry functions by Valerian Luft <luft@valerian.de>
10475 //-------------------------------------------------------
10476 function RegKeyGetSubKeys( const Key: HKEY; List: PStrList): Boolean;
10477 {* The function enumerates subkeys of the specified open registry key.
10478 True is returned, if successful.
10480 function RegKeyGetValueNames(const Key: HKEY; List: PStrList): Boolean;
10481 {* The function enumerates value names of the specified open registry key.
10482 True is returned, if successful.
10484 function RegKeyGetValueTyp (const Key:HKEY; const ValueName: String) : DWORD;
10485 {* The function receives the type of data stored in the specified value.
10486 |<br>
10487 If the function fails, the return value is the Key value.
10488 |<br>
10489 If the function succeeds, the return value return will be one of the following:
10490 |<br>
10491 REG_BINARY , REG_DWORD, REG_DWORD_LITTLE_ENDIAN,
10492 REG_DWORD_BIG_ENDIAN, REG_EXPAND_SZ, REG_LINK , REG_MULTI_SZ,
10493 REG_NONE, REG_RESOURCE_LIST, REG_SZ
10496 |<hr>
10516 <R Data sorting (quicksort implementation)>
10517 This part contains implementation of 'quick sort' algorithm,
10518 based on following code:
10520 |<pre>
10521 | TQSort by Mike Junkin 10/19/95.
10522 | DoQSort routine adapted from Peter Szymiczek's QSort procedure which
10523 | was presented in issue#8 of The Unofficial Delphi Newsletter.
10525 | TQSort changed by Vladimir Kladov (Mr.Bonanzas) to allow 32-bit
10526 | sorting (of big arrays with more than 64K elements).
10527 |</pre>
10529 Finally, this sort procedure is adapted to XCL (and then to KOL)
10530 requirements (no references to SysUtils, Classes etc. TQSort object
10531 is transferred to a single procedure call and DoQSort method is
10532 renamed to SortData - which is a regular procedure now). }
10534 //[Sorting TYPES]
10535 type
10536 TCompareEvent = function (const Data: Pointer; const e1,e2 : Dword) : Integer;
10537 {* Event type to define comparison function between two elements of an array.
10538 This event handler must return -1 or +1 (correspondently for cases e1<e2
10539 and e2>e2). Items are enumerated from 0 to uNElem. }
10540 TSwapEvent = procedure (const Data : Pointer; const e1,e2 : Dword);
10541 {* Event type to define swap procedure which is swapping two elements of an
10542 array. }
10544 //[SortData FUNCTIONS DECLARATIONS]
10545 procedure SortData( const Data: Pointer; const uNElem: Dword;
10546 const CompareFun: TCompareEvent;
10547 const SwapProc: TSwapEvent );
10548 {* Call it to sort any array of data of any kind, passing total
10549 number of items in an array and two defined (regular) function
10550 and procedure to perform custom compare and swap operations.
10551 First procedure parameter is to pass it to callback function
10552 CompareFun and procedure SwapProc. Items are enumerated from
10553 0 to uNElem-1. }
10555 procedure SortIntegerArray( var A : array of Integer );
10556 {* procedure to sort array of integers. }
10558 procedure SortDwordArray( var A : array of DWORD );
10559 {* Procedure to sort array of unsigned 32-bit integers.
10560 |<hr>
10575 { -- directory list object -- }
10576 //[DirList Object]
10578 type
10579 TDirItemAction = ( diSkip, diAccept, diCancel );
10580 TOnDirItem = procedure( Sender: PObj; var DirItem: TWin32FindData; var Accept: TDirItemAction )
10581 of object;
10582 TSortDirRules = ( sdrNone, sdrFoldersFirst, sdrCaseSensitive, sdrByName, sdrByExt,
10583 sdrBySize, sdrBySizeDescending, sdrByDateCreate, sdrByDateChanged,
10584 sdrByDateAccessed );
10585 {* List of rules (options) to sort directories. Rules are passed to Sort
10586 method in an array, and first placed rules are applied first. }
10588 {++}(*TDirList = class;*){--}
10589 PDirList = {-}^{+}TDirList;
10590 { ----------------------------------------------------------------------
10592 TDirList - Directory scanning
10594 ----------------------------------------------------------------------- }
10595 //[TDirList DEFINITION]
10596 TDirList = object( TObj )
10597 {* Allows easy directory scanning. This is not visual object, but
10598 storage to simplify working with directory content. }
10599 protected
10600 FList : PList;
10601 FPath: string;
10602 fFilters: PStrList;
10603 fOnItem: TOnDirItem;
10604 function Get(Idx: Integer): PWin32FindData;
10605 function GetCount: Integer;
10606 function GetNames(Idx: Integer): string;
10607 function GetIsDirectory(Idx: Integer): Boolean;
10608 protected
10609 function SatisfyFilter( FileName : PChar; FileAttr, FindAttr : DWord ) : Boolean;
10610 {++}(*public*){--}
10611 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10612 {* Destructor. As usual, call Free method to destroy an object. }
10613 public
10614 property Items[ Idx : Integer ] : PWin32FindData read Get; default;
10615 {* Full access to scanned items (files and subdirectories). }
10616 property IsDirectory[ Idx: Integer ]: Boolean read GetIsDirectory;
10617 {* Returns TRUE, if specified item represents a directory, not a file. }
10618 property Count : Integer read GetCount;
10619 {* Number of items. }
10620 property Names[ Idx : Integer ] : string read GetNames;
10621 {* Full long names of directory items. }
10622 property Path : string read FPath;
10623 {* Path of scanned directory. }
10624 procedure Clear;
10625 {* Call it to clear list of files. }
10626 procedure ScanDirectory( const DirPath, Filter : String; Attr : DWord );
10627 {* Call it to rescan directory or to scan another directory content
10628 (method Clear is called first). Pass path to directory, file filter
10629 and attributes to scan directory immediately.
10630 |<br>&nbsp;&nbsp;&nbsp;
10631 Note: Pass FILE_ATTRIBUTE_... constants or-combination as Attr
10632 parameter. If 0 passed, both files and directories are listed. }
10633 procedure ScanDirectoryEx( const DirPath, Filters : String; Attr : DWord );
10634 {* Call it to rescan directory or to scan another directory content
10635 (method Clear is called first). Pass path to directory, file filter
10636 and attributes to scan directory immediately.
10637 |<br>&nbsp;&nbsp;&nbsp;
10638 Note: Pass FILE_ATTRIBUTE_... constants or-combination as Attr
10639 parameter. }
10640 procedure Sort( Rules : array of TSortDirRules );
10641 {* Sorts directory entries. If empty rules array passed, default rules
10642 array DefSortDirRules is used. }
10643 function FileList( const Separator {e.g.: ';', or #13}: String;
10644 Dirs, FullPaths: Boolean ): String;
10645 {* Returns a string containing all names separated with Separator.
10646 If Dirs=FALSE, only files are returned. }
10647 property OnItem: TOnDirItem read fOnItem write fOnItem;
10648 {* This event is called on reading each item while scanning directory.
10649 To use it, first create PDirList object with empty path to scan, then
10650 assign OnItem event and call ScanDirectory with correct path. }
10651 end;
10652 //[END OF TDirList DEFINITION]
10654 //[NewDirList DECLARATIONS]
10655 function NewDirList( const DirPath, Filter: String; Attr: DWORD ): PDirList;
10656 {* Creates directory list object using easy one-string filter. If Attr = FILE_ATTRIBUTE_NORMAL,
10657 only files are scanned without directories. If Attr = 0, both files and
10658 directories are listed. }
10660 function NewDirListEx( const DirPath, Filters: String; Attr: DWORD ): PDirList;
10661 {* Creates directory list object using several filters, separated by ';'.
10662 Filters starting from '^' consider to be anti-filters, i.e. files,
10663 satisfying to those masks, are skept during scanning. }
10665 const DefSortDirRules : array[ 0..3 ] of TSortDirRules = ( sdrFoldersFirst,
10666 sdrByName, sdrBySize, sdrByDateCreate );
10667 {* Default rules to sort directory entries. }
10669 //[DirectorySize DECLARATION]
10671 function DirectorySize( const Path: String ): I64;
10672 {* Returns directory size in bytes as large 64 bit integer. }
10676 //[OpenSaveDialog OPTIONS]
10677 type
10678 TOpenSaveOption = ( OSCreatePrompt,
10679 OSExtensionDiffent,
10680 OSFileMustExist,
10681 OSHideReadonly,
10682 OSNoChangedir,
10683 OSNoReferenceLinks,
10684 OSAllowMultiSelect,
10685 OSNoNetworkButton,
10686 OSNoReadonlyReturn,
10687 OSOverwritePrompt,
10688 OSPathMustExist,
10689 OSReadonly,
10690 OSNoValidate
10691 //{$IFDEF OpenSaveDialog_Extended}
10693 OSTemplate,
10694 OSHook
10695 //{$ENDIF}
10697 TOpenSaveOptions = set of TOpenSaveOption;
10698 {* Options available for TOpenSaveDialog. }
10700 {++}(*TOpenSaveDialog = class;*){--}
10701 POpenSaveDialog = {-}^{+}TOpenSaveDialog;
10702 { ----------------------------------------------------------------------
10704 TOpenSaveDialog
10706 ----------------------------------------------------------------------- }
10707 //[TOpenSaveDialog DEFINITION]
10708 TOpenSaveDialog = object( TObj )
10709 {* Object to show standard Open/Save dialog. Initially provided
10710 for XCL by Carlo Kok. }
10711 protected
10712 FFilter : String;
10713 fFilterIndex : Integer;
10714 fOpenDialog : Boolean;
10715 FInitialDir : String;
10716 FDefExtension : String;
10717 FFilename : string;
10718 FTitle : string;
10719 FOptions : TOpenSaveOptions;
10720 fWnd: THandle;
10721 public
10722 {$IFDEF OpenSaveDialog_Extended}
10723 TemplateName: String;
10724 HookProc: Pointer;
10725 {$ENDIF}
10726 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10727 {* destructor }
10728 Function Execute : Boolean;
10729 {* Call it after creating to perform selecting of file by user. }
10730 property Filename : String read FFilename write FFileName;
10732 Filename is seperated by #13 when multiselect is true and the first
10733 file, is the path of the files selected.
10734 |<pre>
10735 | C:\Projects
10736 | Test1.Dpr
10737 | Test2.Dpr
10738 |</pre>
10739 If only one file is selected, it is provided as (e.g.)
10740 C:\Projects\Test1.dpr
10741 |<br> For case when OSAllowMultiselect option used, after each
10742 call initial value for a Filename containing several files prevents
10743 system from opening the dialog. To fix this, assign another initial
10744 value to Filename property in your code, when you use multiselect.
10746 property InitialDir : string read FInitialDir write FInitialDir;
10747 {* Initial directory path. If not set, current directory (usually
10748 directory when program is started) is used. }
10749 property Filter : String read FFilter write FFilter;
10750 {* A list of pairs of filter names and filter masks, separated with '|'.
10751 If a mask contains more than one mask, it should be separated with ';'.
10752 E.g.:
10753 ! 'All files|*.*|Text files|*.txt;*.1st;*.diz' }
10754 property FilterIndex : Integer read FFilterIndex write FFilterIndex;
10755 {* Index of default filter mask (0 by default, which means "first"). }
10756 property OpenDialog : Boolean read FOpenDialog write FOpenDialog;
10757 {* True, if "Open" dialog. False, if "Save" dialog. True is default. }
10758 property Title : String read Ftitle write Ftitle;
10759 {* Title for dialog. }
10760 property Options : TOpenSaveOptions read FOptions write FOptions;
10761 {* Options. }
10762 property DefExtension : String read FDefExtension write FDefExtension;
10763 {* Default extention. Set it to desired extension without leading period,
10764 e.g. 'txt', but not '.txt'. }
10765 property WndOwner: THandle read fWnd write fWnd;
10766 {* Owner window handle. If not assigned, Applet.Handle is used (whenever
10767 possible). Assign it, if your application has stay-on-top forms, and
10768 a separate Applet object is used. }
10769 end;
10770 //[END OF TOpenSaveDialog DEFINITION]
10772 //[Default OpenSaveDialog OPTIONS]
10773 const DefOpenSaveDlgOptions: TOpenSaveOptions = [ OSHideReadonly,
10774 OSOverwritePrompt, OSFileMustExist, OSPathMustExist ];
10776 //[NewOpenSaveDialog DECLARATION]
10777 function NewOpenSaveDialog( const Title, StrtDir: String;
10778 Options: TOpenSaveOptions ): POpenSaveDialog;
10779 {* Creates object, which can be used (several times) to open file(s)
10780 selecting dialog. }
10784 //[OpenDirectory Object]
10785 type
10786 {++}(*TOpenDirDialog = class;*){--}
10787 POpenDirDialog = {-}^{+}TOpenDirDialog;
10789 TOpenDirOption = ( odBrowseForComputer, odBrowseForPrinter, odDontGoBelowDomain,
10790 odOnlyFileSystemAncestors, odOnlySystemDirs, odStatusText,
10791 odBrowseIncludeFiles );
10792 {* Flags available for TOpenDirDialog object. }
10793 // odfStatusText - do not support status callback
10794 TOpenDirOptions = set of TOpenDirOption;
10795 {* Set of all flags used to control ZOpenDirDialog class. }
10797 TOnODSelChange = procedure( Sender: POpenDirDialog; NewSelDir: PChar;
10798 var EnableOK: Integer; var StatusText: String )
10799 of object;
10800 {* Event type to be called when user select another directory in OpenDirDialog.
10801 Set EnableOK to -1 to disable OK button, or to +1 to enable it.
10802 It is also possible to set new StatusText string. }
10804 { ----------------------------------------------------------------------
10806 TOpenDirDialog
10808 ----------------------------------------------------------------------- }
10809 //[TOpenDirDialog DEFINITION]
10810 TOpenDirDialog = object( TObj )
10811 {* Dialog for open directories, uses SHBrowseForFolder. }
10812 protected
10813 FTitle: String;
10814 FOptions: TOpenDirOptions;
10815 FCallBack: Pointer;
10816 FCenterProc: procedure( Wnd: HWnd );
10817 FBuf : array[ 0..MAX_PATH ] of Char;
10818 FInitialPath: String;
10819 FCenterOnScreen: Boolean;
10820 FDoSelChanged: procedure( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ); stdcall;
10821 FOnSelChanged: TOnODSelChange;
10822 FStatusText: String;
10823 FWnd: HWnd;
10824 function GetPath: String;
10825 procedure SetInitialPath(const Value: String);
10826 procedure SetCenterOnScreen(const Value: Boolean);
10827 procedure SetOnSelChanged(const Value: TOnODSelChange);
10828 function GetInitialPath: String;
10829 public
10830 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10831 {* destructor }
10832 function Execute : Boolean;
10833 {* Call it to select directory by user. Returns True, if operation was
10834 not cancelled by user. }
10835 property Title : String read FTitle write FTitle;
10836 {* Title for a dialog. }
10837 property Options : TOpenDirOptions read FOptions write FOptions;
10838 {* Option flags. }
10839 property Path : String read GetPath;
10840 {* Resulting (selected by user) path. }
10841 property InitialPath: String read GetInitialPath write SetInitialPath;
10842 {* Set this property to a path of directory to be selected initially
10843 in a dialog. }
10844 property CenterOnScreen: Boolean read FCenterOnScreen write SetCenterOnScreen;
10845 {* Set it to True to center dialog on screen. }
10846 property OnSelChanged: TOnODSelChange read FOnSelChanged write SetOnSelChanged;
10847 {* This event is called every time, when user selects another directory.
10848 It is possible to eneble/disable OK button in dialog and/or change
10849 dialog status text in responce to event. }
10850 property WndOwner: HWnd read FWnd write FWnd;
10851 {* Owner window. If you want to provide your dialog visible over stay-on-top
10852 form, fire it as a child of the form, assigning the handle of form window
10853 to this property first. }
10854 end;
10855 //[END OF TOpenDirDialog DEFINITION]
10857 //[NewOpenSaveDialog DECLARATION]
10858 function NewOpenDirDialog( const Title: String; Options: TOpenDirOptions ):
10859 POpenDirDialog;
10860 {* Creates object, which can be used (several times) to open directory
10861 selecting dialog (using SHBrowseForFolder API call). }
10871 //[Color Dialog Object]
10872 type
10873 TColorCustomOption = ( ccoFullOpen, ccoShortOpen, ccoPreventFullOpen );
10875 {++}(*TColorDialog = class;*){--}
10876 PColorDialog = {-}^{+}TColorDialog;
10877 { ----------------------------------------------------------------------
10879 TColorDialog
10881 ----------------------------------------------------------------------- }
10882 //[TColorDialog DEFINITION]
10883 TColorDialog = object( TObj )
10884 {* Color choosing dialog. }
10885 protected
10886 public
10887 OwnerWindow: HWnd;
10888 {* Owner window (can be 0). }
10889 CustomColors: array[ 1..16 ] of TColor;
10890 {* Array of stored custom colors. }
10891 ColorCustomOption: TColorCustomOption;
10892 {* Options (how to open a dialog). }
10893 Color: TColor;
10894 {* Returned color (if the result of Execute is True). }
10895 function Execute: Boolean;
10896 {* Call this method to open a dialog and wait its result. }
10897 end;
10898 //[END OF TColorDialog DEFINITION]
10900 //[NewColorDialog DECLARATION]
10901 function NewColorDialog( FullOpen: TColorCustomOption ): PColorDialog;
10902 {* Creates color choosing dialog object. }
10912 //[Ini files]
10913 type
10914 TIniFileMode = ( ifmRead, ifmWrite );
10915 {* ifmRead is default mode (means "read" data from ini-file.
10916 Set mode to ifmWrite to write data to ini-file, correspondent to
10917 TIniFile. }
10919 {++}(*TIniFile = class;*){--}
10920 PIniFile = {-}^{+}TIniFile;
10921 { ----------------------------------------------------------------------
10923 TIniFile - store/load data to ini-files
10925 ----------------------------------------------------------------------- }
10926 //[TIniFile DEFINITION]
10927 TIniFile = object( TObj )
10928 {* Ini file incapsulation. The main feature is what the same block of
10929 read-write operations could be defined (difference must be only in
10930 Mode value).
10931 |*Ini file sample.
10932 This sample shows how the same Pascal operators can be used both
10933 for read and write for the same variables, when working with TIniFile:
10934 ! procedure ReadWriteIni( Write: Boolean );
10935 ! var Ini: PIniFile;
10936 ! begin
10937 ! Ini := OpenIniFile( 'MyIniFile.ini' );
10938 ! Ini.Section := 'Main';
10939 ! if Write then // if Write, the same operators will save
10940 ! Ini.Mode := ifmWrite; // data rather then load.
10941 ! MyForm.Left := Ini.ValueInteger( 'Left', MyForm.Left );
10942 ! MyForm.Top := Ini.ValueInteger( 'Top', MyForm.Top );
10943 ! Ini.Free;
10944 ! end;
10946 |* }
10947 protected
10948 fMode: TIniFileMode;
10949 fFileName: String;
10950 fSection: String;
10951 protected
10952 public
10953 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10954 {* destructor }
10955 property Mode: TIniFileMode read fMode write fMode;
10956 {* ifmWrite, if write data to ini-file rather than read it. }
10957 property FileName: String read fFileName;
10958 {* Ini file name. }
10959 property Section: String read fSection write fSection;
10960 {* Current ini section. }
10961 function ValueInteger( const Key: String; Value: Integer ): Integer;
10962 {* Reads or writes integer data value. }
10963 function ValueString( const Key: String; const Value: String ): String;
10964 {* Reads or writes string data value. }
10965 function ValueBoolean( const Key: String; Value: Boolean ): Boolean;
10966 {* Reads or writes boolean data value. }
10967 function ValueData( const Key: String; Value: Pointer; Count: Integer ): Boolean;
10968 {* Reads or writes data from/to buffer. Returns True, if success. }
10969 procedure ClearAll;
10970 {* Clears all sections of ini-file. }
10971 procedure ClearSection;
10972 {* Clears current Section of ini-file. }
10973 procedure ClearKey( const Key: String );
10974 {* Clears given key in current section. }
10976 /////////////// + by Vyacheslav A. Gavrik:
10977 procedure GetSectionNames(Names:PStrList);
10978 {* Retrieves section names, storing it in string list passed as a parameter.
10979 String list does not cleared before processing. Section names are added
10980 to the end of the string list. }
10981 procedure SectionData(Names:PStrList);
10982 {* Read/write current section content to/from string list. (Depending on
10983 current Mode value). }
10984 ///////////////
10986 end;
10987 //[END OF TIniFile DEFINITION]
10989 //[OpenIniFile DECLARATION]
10990 function OpenIniFile( const FileName: String ): PIniFile;
10991 {* Opens ini file, creating TIniFile object instance to work with it. }
10997 //[CABINET FILES OBJECT]
10998 type
10999 {++}(*TCabFile = class;*){--}
11000 PCABFile = {-}^{+}TCABFile;
11002 TOnNextCAB = function( Sender: PCABFile ): String of object;
11003 TOnCABFile = function( Sender: PCABFile; var FileName: String ): Boolean of object;
11005 { ----------------------------------------------------------------------
11007 TCabFile - windows cabinet files
11009 ----------------------------------------------------------------------- }
11010 //[TCabFile DEFINITION]
11011 TCABFile = object( TObj )
11012 {* An object to simplify extracting files from a cabinet (.CAB) files.
11013 The only what need to use this object, setupapi.dll. It is provided
11014 with all latest versions of Windows. }
11015 protected
11016 FPaths: PStrList;
11017 FNames: PStrList;
11018 FOnNextCAB: TOnNextCAB;
11019 FOnFile: TOnCABFile;
11020 FTargetPath: String;
11021 FSetupapi: THandle;
11022 function GetNames(Idx: Integer): String;
11023 function GetCount: Integer;
11024 function GetPaths(Idx: Integer): String;
11025 function GetTargetPath: String;
11026 protected
11027 FGettingNames: Boolean;
11028 FCurCAB: Integer;
11029 public
11030 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
11031 {* }
11032 property Paths[ Idx: Integer ]: String read GetPaths;
11033 {* A list of CAB-files. It is stored, when constructing function
11034 OpenCABFile called. }
11035 property Names[ Idx: Integer ]: String read GetNames;
11036 {* A list of file names, stored in a sequence of CAB files. To get know,
11037 how many files are there, check Count property. }
11038 property Count: Integer read GetCount;
11039 {* Number of files stored in a sequence of CAB files. }
11040 function Execute: Boolean;
11041 {* Call this method to extract or enumerate files in CAB. For every
11042 file, found during executing, event OnFile is alled (if assigned).
11043 If the event handler (if any) does not provide full target path for
11044 a file to extract to, property TargetPath is applyed (also if it
11045 is assigned), or file is extracted to the default directory (usually
11046 the same directory there CAB file is located, or current directory
11047 - by a decision of the system).
11048 |<br>
11049 If a sequence of CAB files is used, and not all names for CAB files
11050 are provided (absent or represented by a string '?' ), an event
11051 OnNextCAB is called to obtain the name of the next CAB file.}
11052 property CurCAB: Integer read FCurCAB;
11053 {* Index of current CAB file in a sequence of CAB files. When OnNextCAB
11054 event is called (if any), CurCAB property is already set to the
11055 index of path, what should be provided. }
11056 property OnNextCAB: TOnNextCAB read FOnNextCAB write FOnNextCAB;
11057 {* This event is called, when a series of CAB files is needed and not
11058 all CAB file names are provided (absent or represented by '?' string).
11059 If this event is not assigned, the user is prompted to browse file. }
11060 property OnFile: TOnCABFile read FOnFile write FOnFile;
11061 {* This event is called for every file found during Execute method.
11062 In an event handler (if any assigned), it is possible to return
11063 False to skip file, or to provide another full target path for
11064 file to extract it to, then default. If the event is not assigned,
11065 all files are extracted either to default directory, or to the
11066 directory TargetPath, if it is provided. }
11067 property TargetPath: String read GetTargetPath write FTargetPath;
11068 {* Optional target directory to place there extracted files. }
11069 end;
11070 //[END OF TCABFile DEFINITION]
11072 //[OpenCABFile DECLARATION]
11073 function OpenCABFile( const APaths: array of String ): PCABFile;
11074 {* This function creates TCABFile object, passing a sequence of CAB file names
11075 (fully qualified). It is possible not to provide all names here, or pass '?'
11076 string in place of some of those. For such files, either an event OnNextCAB
11077 will be called, or (and) user will be prompted to browse file during
11078 executing (i.e. Extracting). }
11086 //[MENU OBJECT]
11088 type
11089 TMenuitemInfo = packed record
11090 cbSize: UINT;
11091 fMask: UINT;
11092 fType: UINT; { used if MIIM_TYPE}
11093 fState: UINT; { used if MIIM_STATE}
11094 wID: UINT; { used if MIIM_ID}
11095 hSubMenu: HMENU; { used if MIIM_SUBMENU}
11096 hbmpChecked: HBITMAP; { used if MIIM_CHECKMARKS}
11097 hbmpUnchecked: HBITMAP; { used if MIIM_CHECKMARKS}
11098 dwItemData: DWORD; { used if MIIM_DATA}
11099 dwTypeData: PAnsiChar; { used if MIIM_TYPE}
11100 cch: UINT; { used if MIIM_TYPE}
11101 hbmpItem: HBITMAP; { used if MIIM_BITMAP - not exists under Windows95 }
11102 end;
11104 type
11105 {++}(*TMenu = class;*){--}
11106 PMenu = {-}^{+}TMenu;
11108 TOnMenuItem = procedure( Sender : PMenu; Item : Integer ) of object;
11109 {* Event type to define OnMenuItem event. }
11111 TMenuAccelerator = packed Record
11112 {* Menu accelerator record. Use MakeAccelerator function to combine desired
11113 attributes into a record, describing the accelerator. }
11114 fVirt: Byte; // or-combination of FSHIFT, FCONTROL, FALT, FVIRTKEY, FNOINVERT
11115 Key: Word; // character or virtual key code (FVIRTKEY flag is present above)
11116 NotUsed: Byte; // not used
11117 end;
11119 // by Sergey Shisminzev:
11120 TMenuOption = (moDefault, moDisabled, moChecked,
11121 moCheckMark, moRadioMark, moSeparator, moBitmap, moSubMenu,
11122 moBreak, moBarBreak);
11123 {* Options to add menu items dynamically. }
11124 TMenuOptions = set of TMenuOption;
11125 {* Set of options for menu item to use it in TMenu.AddItem method. }
11127 TMenuBreak = ( mbrNone, mbrBreak, mbrBarBreak );
11128 {* Possible menu item break types. }
11130 { ----------------------------------------------------------------------
11132 TMenu - main, popup menu and menu item
11134 ----------------------------------------------------------------------- }
11135 //[TMenu DEFINITION]
11136 TMenu = object( TObj )
11137 {* Dynamic menu incapsulation object. Can play role of form main menu or popup
11138 menu, depending on kind of parent window (form or control) and order of
11139 creation (created first (for a form) become main menu). Does not allow
11140 merging menus, but items can be hidden. Additionally checkmark bitmaps,
11141 shortcut key accelerators and other features are available. }
11142 protected
11143 FHandle: HMenu;
11144 FId: Integer;
11145 FParent: PMenu;
11146 FControl: PControl;
11147 fNextMenu : PMenu;
11148 FRadioGroup: Integer;
11149 FIsCheckItem: Boolean;
11150 FIsSeparator: Boolean;
11151 FMenuBreak: TMenuBreak;
11152 FItems: PList;
11153 FOnMenuItem : TOnMenuItem;
11154 FOnRadioOff : TOnMenuItem;
11155 fOnPopup: TOnEvent;
11156 fByAccel: Boolean;
11157 FPopupFlags: DWORD;
11158 //fAutoPopup: Boolean;
11159 FVisible: Boolean;
11160 FSavedState: DWORD;
11161 FData: Pointer;
11162 FOwnerDraw: Boolean;
11163 FCaption: String;
11164 FBitmap: HBitmap;
11165 FBmpChecked: HBitmap;
11166 FBmpItem: HBitmap;
11167 ClearBitmapsProc: procedure( Sender: PMenu );
11168 FClearBitmaps: Boolean;
11169 FNotPopup: Boolean;
11170 FAccelerator: TMenuAccelerator;
11171 FHelpContext: Integer;
11172 FOnMeasureItem: TOnMeasureItem;
11173 FOnDrawItem: TOnDrawItem;
11174 {$IFDEF USE_MENU_CURCTL}
11175 fCurCtl: PControl;
11176 {$ENDIF USE_MENU_CURCTL}
11177 function GetItems( Id: HMenu ): PMenu;
11178 function GetCount: Integer;
11179 function GetTopParent: PMenu;
11180 function GetState( const Index: Integer ): Boolean;
11181 procedure SetState( const Index: Integer; Value: Boolean );
11182 procedure SetVisible( Value: Boolean );
11183 procedure SetData( Value: Pointer );
11184 procedure SetMenuItemCaption( const Value: String );
11185 function FillMenuItems(AHandle: HMenu; StartIdx: Integer;
11186 const Template: array of PChar): Integer;
11187 procedure SetMenuBreak( Value: TMenuBreak );
11188 function GetControl: PControl;
11189 function GetInfo( var MII: TMenuItemInfo ): Boolean;
11190 function SetInfo( var MII: TMenuItemInfo ): Boolean;
11191 function SetTypeInfo( var MII: TMenuItemInfo ): Boolean;
11192 procedure SetBitmap( Value: HBitmap );
11193 procedure SetBmpChecked( Value: HBitmap );
11194 procedure SetBmpItem( Value: HBitmap );
11195 procedure ClearBitmaps;
11196 procedure SetAccelerator( const Value: TMenuAccelerator );
11197 procedure SetHelpContext( Value: Integer );
11198 procedure SetSubmenu( Value: HMenu );
11199 procedure SetOnMeasureItem( const Value: TOnMeasureItem );
11200 procedure SetOnDrawItem( const Value: TOnDrawItem );
11201 procedure SetOwnerDraw( Value: Boolean );
11202 protected
11203 function GetItemChecked( Item : Integer ) : Boolean;
11204 procedure SetItemChecked( Item : Integer; Value : Boolean );
11205 function GetItemBitmap(Idx: Integer): HBitmap;
11206 procedure SetItemBitmap(Idx: Integer; const Value: HBitmap);
11207 function GetItemText(Idx: Integer): String;
11208 procedure SetItemText(Idx: Integer; const Value: String);
11209 function GetItemEnabled(Idx: Integer): Boolean;
11210 procedure SetItemEnabled(Idx: Integer; const Value: Boolean);
11211 function GetItemVisible(Idx: Integer): Boolean;
11212 procedure SetItemVisible(Idx: Integer; const Value: Boolean);
11213 function GetItemAccelerator(Idx: Integer): TMenuAccelerator;
11214 procedure SetItemAccelerator(Idx: Integer; const Value: TMenuAccelerator);
11215 function GetItemSubMenu( Idx: Integer ): HMenu;
11216 public
11217 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
11218 {* To release menu dynamically, call Free method instead. All (popup)
11219 menus created after this (for the same control) are destroyed in
11220 that case too.
11221 |<br>
11222 It is not necessary to release menu object manually: all menus,
11223 created with given form (or control), are automatically released,
11224 when owner form (or control) is destroyed.
11226 property Handle : HMenu read FHandle;
11227 {* Handle of Windows menu object. }
11228 property MenuId: Integer read FId;
11229 {* Id of the menu item object. If menu item has subitems, it has
11230 also submenu Handle. Top parent menu object itself has no Id.
11231 Id-s areassigned automatically starting from 4096. Do not
11232 (re)create menu items instantly, because such values are not
11233 reused, and maximum possible Id value must not exceed 65535. }
11234 property Parent: PMenu read FParent;
11235 {* Parent menu item (or parent menu). }
11236 property TopParent: PMenu read GetTopParent;
11237 {* Top parent menu, owning all nested subitems. }
11238 property Owner: PControl read GetControl;
11239 {* Parent control or form. }
11240 property Caption: String read FCaption write SetMenuItemCaption;
11241 {* Menu item caption text (including '&' indicating mnemonic characters,
11242 and keyboard accelerator representation string, usually following
11243 tabulation character). }
11244 property Items[ Id: HMenu ]: PMenu read GetItems;
11245 {* Returns menu item object by its index or by menu id. Since menu id
11246 values are starting from 4096, values from 0 to 4095 are interpreted
11247 as absolute index of menu item. Be careful accessing menu items or
11248 submenus by index, if you dynamically insert or delete items or
11249 submenus. In this version, separators are enumerating too, like
11250 all other items. Use index -1 to access object itself. The first
11251 item of a menu (or the first subitem of submenu item) has index 0.
11252 Children are enumerating before all siblings. The maximum available
11253 index is (Count - 1), when accessing menu items by index. }
11254 property Count: Integer read GetCount;
11255 {* Count of items together with all its nested subitems. }
11256 function IndexOf( Item: PMenu ): Integer;
11257 {* Returns index of an item. This index can be used to access
11258 menu item. Value -2 is returned, if the Item is not a child for menu
11259 or menu item, and has no parents, which are children for it, etc.
11260 Menu object itself always has index -1. }
11261 property OnMenuItem : TOnMenuItem read FOnMenuItem write FOnMenuItem;
11262 {* Is called when menu item is clicked. Absolute index of menu item
11263 clicked is passed as the second parameter. TopParent always is
11264 passed as a Sender parameter. }
11265 property ByAccel: Boolean read fByAccel;
11266 {* True, when OnMenuItem is called not by mouse, but by accelerator key.
11267 Check this flag for entire menu (TopParent), not for item itself.
11268 (Note, that Sender in OnMenuItem always is TopParent menu object). )
11270 property IsSeparator: Boolean read FIsSeparator;
11271 {* TRUE, if a separator menu item. }
11272 property MenuBreak: TMenuBreak read FMenuBreak write SetMenuBreak;
11273 {* Menu item break type. }
11274 property OnUncheckRadioItem : TOnMenuItem read FOnRadioOff write FOnRadioOff;
11275 {* Is called when radio item becomes unchecked in menu in result of
11276 checking another radio item of the same radio group. }
11277 property RadioGroup: Integer read FRadioGroup write FRadioGroup;
11278 {* Radio group index. Several neighbour items with the same radio group
11279 index form radio group. Only single item from the same group can be
11280 checked at a time. }
11281 property IsCheckItem: Boolean read FIsCheckItem;
11282 {* If menu item is defined as check item, it is checked automatically
11283 when clicked. }
11284 procedure RadioCheckItem;
11285 {* Call this method to check radio item. (Calling this method for
11286 an item, which is not belonging to a radio group, just sets its
11287 Checked state to TRUE). }
11288 property Checked: Boolean index MFS_CHECKED read GetState write SetState;
11289 {* Checked state of the item. }
11290 property Enabled: Boolean
11291 {$IFDEF F_P}
11292 index $80000000 or MFS_DISABLED
11293 {$ELSE DELPHI}
11294 index Integer( $80000000 or MFS_DISABLED )
11295 {$ENDIF F_P/DELPHI}
11296 read GetState write SetState;
11297 {* Enabled state of the item. Whaen assigned, Grayed state also is
11298 set to arbitrary value (i.e., when Enabled is set to true, Grayed
11299 is set to FALSE. }
11300 property DefaultItem: Boolean index MFS_DEFAULT read GetState write SetState;
11301 {* Set this property to TRUE to make menu item default. Default item
11302 is drawn with bold.
11303 |<br>If you change DefaultItem at run-time and whant
11304 to provide changing its visual state, recreate the item first resetting
11305 Visible property, then setting it again. }
11306 property Highlight: Boolean index MFS_HILITE read GetState write SetState;
11307 {* Highlight state of the item. }
11308 property Visible: Boolean read FVisible write SetVisible;
11309 {* Visibility of menu item. }
11310 property Data: Pointer read FData write SetData;
11311 {* Data pointer, associated with the menu item. }
11312 property Bitmap: HBitmap read FBitmap write SetBitmap;
11313 {* Bitmap used for unchecked state of the menu item. }
11314 property BitmapChecked: HBitmap read FBmpChecked write SetBmpChecked;
11315 {* Bitmap used for checked state of the menu item. }
11316 property BitmapItem: HBitmap read FBmpItem write SetBmpItem;
11317 {* Bitmap used for item itself. In addition, following special values
11318 are possible:
11319 HBMMENU_CALLBACK, HBMMENU_MBAR_CLOSE, HBMMENU_MBAR_CLOSE_D,
11320 HBMMENU_MBAR_MINIMIZE, HBMMENU_MBAR_MINIMIZE_D, HBMMENU_MBAR_RESTORE,
11321 HBMMENU_POPUP_CLOSE, HBMMENU_POPUP_MAXIMIZE, HBMMENU_POPUP_MINIMIZE,
11322 HBMMENU_POPUP_RESTORE, HBMMENU_SYSTEM. }
11323 property Accelerator: TMenuAccelerator read FAccelerator write SetAccelerator;
11324 {* Accelerator for menu item. }
11325 property HelpContext: Integer read FHelpContext write SetHelpContext;
11326 {* Help context for entire menu (help context can not be assigned to
11327 individual menu items). }
11329 procedure AssignEvents( StartIdx: Integer; Events: array of TOnMenuItem );
11330 {* It is possible to assign its own event handler to every menu item
11331 using this call. This procedure also is called automatically in
11332 a constructor NewMenuEx. }
11334 procedure Popup( X, Y : Integer );
11335 {* Only for popup menu - to popup it at the given position on screen. }
11336 procedure PopupEx( X, Y: Integer );
11337 {* This version of popup command is very useful, when popup menu is activated
11338 when its parent window is not visible (e.g., for a kind of applications,
11339 which always are invisible, and can be activated only using tray icon).
11340 PopupEx method provides correct tracking of menu disappearing when mouse
11341 is clicked anywhere else on screen, fixing strange menu behavior in some
11342 Windows versions (NT).
11343 |<br>
11344 Actually, when PopupEx used, parent form is shown but below of visible
11345 screen, and when menu is disappearing, previous state of the form (visibility
11346 and position) are restored. If such solvation is not satisfying You,
11347 You can do something else (e.g., use region clipping, etc.) }
11348 property OnPopup: TOnEvent read fOnPopup write fOnPopup;
11349 {* This event occurs before the popup menu is shown. }
11350 property NotPopup: Boolean read FNotPopup write FNotPopup;
11351 {* Set this property to true to prevent popup of popup menu, e.g. in
11352 OnPopup event handler. }
11353 property Flags: DWORD read FPopupFlags write FPopupFlags;
11354 {* Pop-up flags, which are used to call TrackPopupMenuEx, when Popup or
11355 PopupEx method is called. Can be a combination of following values:
11356 |<br>
11357 TPM_CENTERALIGN or TPM_LEFTALIGN or TPM_RIGHTALIGN
11358 |<br>
11359 TPM_BOTTOMALIGN or TPM_TOPALIGN or TPM_VCENTERALIGN
11360 |<br>
11361 TPM_NONOTIFY or TPM_RETURNCMD
11362 |<br>
11363 TPM_LEFTBUTTON or TPM_RIGHTBUTTON
11364 |<br>
11365 TPM_HORNEGANIMATION or TPM_HORPOSANIMATION or TPM_NOANIMATION or
11366 TPM_VERNEGANIMATION or TPM_VERPOSANIMATION
11367 |<br>
11368 TPM_HORIZONTAL or TPM_VERTICAL.
11369 |<br>
11370 By default, a combination TPM_LEFTALIGN or TPM_LEFTBUTTON is used. }
11371 function Insert(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;
11372 Options: TMenuOptions): PMenu;
11373 {* Inserts new menu item before item, given by Id (>=4096) or index
11374 value InsertBefore. Pointer to an object created is returned. }
11375 property SubMenu: HMenu read FHandle; // write SetSubMenu;
11376 {* Submenu associated with the menu item. The same as Handle. It was possible
11377 in ealier versions to change this value, replacing (removing, assigning)
11378 entire popup menu as a submenu for menu item.
11379 But in modern version of TMenu, this is not possible.
11380 Instead, entire menu object should be added or removed using
11381 InsertSubmenu or RemoveSubmenu methods. }
11382 procedure InsertSubMenu( SubMenuToInsert: PMenu; InsertBefore: Integer );
11383 {* Inserts existing menu item (together with its subitems if any present)
11384 into given position. See also RemoveSubMenu. }
11385 function RemoveSubMenu( ItemToRemove: Integer ): PMenu;
11386 {* Removes menu item from the menu, returning TMenu object, representing it,
11387 if submenu item, having its own children, detached. If an individual menu
11388 item is removed, nil is returned.
11389 This function can be useful to add or remove dynamically entire submenus
11390 (created together with its subitems). }
11391 property OnMeasureItem: TOnMeasureItem read FOnMeasureItem write SetOnMeasureItem;
11392 {* This event is called for owner-drawn menu items. Event handler should return
11393 menu item height in lower word of a result and item width (for menu) in
11394 high word of result. If either for height or for width returned value is 0,
11395 a default one is used. }
11396 property OnDrawItem: TOnDrawItem read FOnDrawItem write SetOnDrawItem;
11397 {* This event is called for owner-drawn menu items. }
11398 property OwnerDraw: Boolean read FOwnerDraw write SetOwnerDraw;
11399 {* Set this property to true for some items to make it owner-draw. }
11401 // For compatibility with old code (be sure that item with given index
11402 // actually exists):
11403 function GetMenuItemHandle( Idx : Integer ): DWORD;
11404 {* Returns Id of menu item with given index. }
11405 property ItemHandle[ Idx: Integer ]: DWORD read GetMenuItemHandle;
11406 {* Returns handle for item given by index. }
11407 property ItemChecked[ Idx : Integer ] : Boolean read GetItemChecked write SetItemChecked;
11408 {* True, if correspondent menu item is checked. }
11409 procedure RadioCheck( Idx : Integer );
11410 {* Call this method to check radio item. For radio items, do not
11411 use assignment to ItemChecked or Checked properties. }
11412 property ItemBitmap[ Idx: Integer ]: HBitmap read GetItemBitmap write SetItemBitmap;
11413 {* This property allows to assign bitmap to menu item (for unchecked state
11414 only - for checked menu items default checkmark bitmap is used). }
11415 procedure AssignBitmaps( StartIdx: Integer; Bitmaps: array of HBitmap );
11416 {* Can be used to assign bitmaps to several menu items during one call. }
11417 property ItemText[ Idx: Integer ]: String read GetItemText write SetItemText;
11418 {* This property allows to get / modify menu item text at run time. }
11419 property ItemEnabled[ Idx: Integer ]: Boolean read GetItemEnabled write SetItemEnabled;
11420 {* Controls enabling / disabling menu items. Disabled menu items are
11421 displayed (grayed) but inaccessible to click. }
11422 property ItemVisible[ Idx: Integer ]: Boolean read GetItemVisible write SetItemVisible;
11423 {* This property allows to simulate visibility of menu items (implementing
11424 it by removing or inserting again if needed. For items of submenu, which
11425 is made invisible, True is returned. If such item made Visible, entire
11426 submenu with all its parent menu items becomes visible. To release menu
11427 properly it is necessary to make before all its items visible again.
11428 This does not matter, if menu is released at the end of execution, but
11429 can be sensible if owner form is destroyed and re-created at run time
11430 dynamically. }
11431 function ParentItem( Idx: Integer ): Integer;
11432 {* Returns index of parent menu item (for submenu item). If there are no
11433 such item (Idx corresponds to root level menu item), -1 is returned. }
11434 property ItemAccelerator[ Idx: Integer ]: TMenuAccelerator read GetItemAccelerator write SetItemAccelerator;
11435 {* Allows to get / change accelerator key kodes assigned to menu items.
11436 Has no effect unless SupportMnemonics called for a form. }
11437 property ItemSubmenu[ Idx: Integer ]: HMenu read GetItemSubmenu; // write SetItemSubmenu;
11438 {* Retrieves submenu item dynamically. See also SubMenu property. }
11440 // by Sergey Shisminzev:
11441 function AddItem(ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;
11442 {* Adds menu item dynamically. Returns ID of the added item. }
11443 function InsertItem(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;
11444 {* Inserts menu item before an item with ID, given by InsertBefore parameter. }
11445 function InsertItemEx(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions;
11446 ByPosition: Boolean): Integer;
11447 {* Inserts menu item by command or by position, dependant on ByPosition parameter }
11448 procedure RedrawFormMenuBar;
11449 {* }
11451 {$IFDEF USE_MENU_CURCTL}
11452 property CurCtl: PControl read fCurCtl;
11453 {* By Alexander Pravdin. This property is assigned to a control which were
11454 initiated a pop-up, for popup menu. }
11455 {$ENDIF USE_MENU_CURCTL}
11457 end;
11458 //[END OF TMenu DEFINITION]
11460 //[MenuStructSize VARIABLE]
11461 function MenuStructSize: Integer;
11462 {* Returns 44 under Windows95, and 48 (=sizeof(TMenuItemInfo) under all other
11463 Windows versions. }
11465 //[NewMenu DECLARATION]
11466 function NewMenu( AParent : PControl; MaxCmdReserve: DWORD; const Template : array of PChar;
11467 aOnMenuItem: TOnMenuItem ): PMenu;
11468 {* Menu constructor. First created menu becomes main menu of form (if AParent
11469 is a form). All other menus becomes popup (can be activated using Popup
11470 method). To provide dynamic replacing of main menu, create all popup
11471 menus as children of any other control, not form itself.
11472 When Menu is created, pass FirstCmd integer value to set it
11473 as ID of first menu item (all other ID's obtained by incrementing this value),
11474 and Template, which is an array of PChar (usually array of string constants),
11475 containing list of menu item identifiers and/or formatting characters.
11476 |<br>&nbsp;&nbsp;&nbsp;
11477 FirstCmd value is assigned to first menu item created as its ID,
11478 all follow menu items are assigned to ID's obtained from FirstCmd incrementing
11479 it by 1. It is desirable to provide not intersected ranges of ID's for
11480 defferent menus in the applet.
11481 |<br>&nbsp;&nbsp;&nbsp;
11482 Following formatting characters can be used in menu template strings:
11483 |&L=<br><b>%1</b>
11484 <L &amp; (in identifier)> - to underline next character and use it as a shortcut character
11485 when possible;
11486 <L + (in front of identifier)> - to make item checked. If also
11487 |<b>!</b> is used before <b>
11489 |</b> than radioitem is defined;
11490 <L - (in front of identifier)> - item not checked;
11491 <L - (separate)> - separator (between two items);
11492 <L ( (separate)> - start of submenu;
11493 <L ) (separate)> - end of submenu;
11494 |<br>&nbsp;&nbsp;&nbsp;
11495 To get access to menu items, use constants 0, 1, etc. It is a good idea
11496 to create special enumerated type to index correspondent menu items
11497 using Ord( ) operator. Note in that case, that it is necessary only to
11498 define constants correspondent to identifiers (positions, correspondent
11499 to separators or submenu brackets are not identified by numbers).
11500 |<br>&nbsp;&nbsp;&nbsp;
11503 function NewMenuEx( AParent : PControl; FirstCmd : Integer; const Template : array of PChar;
11504 aOnMenuItems: array of TOnMenuItem ): PMenu;
11505 {* Creates menu, assigning its own event handler for every (enough) menu item. }
11507 //[MakeAccelerator DECLARATION]
11508 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;
11509 {* Creates accelerator item to assign it to TMenu.ItemAccelerator[ ] property
11510 easy.}
11512 //[GetAcceleratorText DECLARATION]
11513 // {YS} added 7 Aug 2004
11514 function GetAcceleratorText( const Accelerator: TMenuAccelerator ): string;
11515 {* Returns text representation of accelerator. }
11517 // NewActionList, TAction - by Yury Sidorov
11518 //[ACTIONS OBJECT]
11519 { ----------------------------------------------------------------------
11521 TAction and TActionList
11523 ----------------------------------------------------------------------- }
11524 type
11525 PControlRec = ^TControlRec;
11526 TOnUpdateCtrlEvent = procedure(Sender: PControlRec) of object;
11528 TCtrlKind = (ckControl, ckMenu, ckToolbar);
11529 TControlRec = record
11530 Ctrl: PObj;
11531 CtrlKind: TCtrlKind;
11532 ItemID: integer;
11533 UpdateProc: TOnUpdateCtrlEvent;
11534 end;
11536 {++}(* TAction = class;*){--}
11537 PAction = {-}^{+}TAction;
11539 {++}(* TActionList = class;*){--}
11540 PActionList = {-}^{+}TActionList;
11542 //[TAction DEFINITION]
11543 TAction = {-} object( TObj ) {+}{++}(*class*){--}
11544 {*! Use action objects, in conjunction with action lists, to centralize the response
11545 to user commands (actions).
11546 Use AddControl, AddMenuItem, AddToolbarButton methods to link controls to an action.
11547 See also TActionList.
11549 protected
11550 FControls: PList;
11551 FCaption: string;
11552 FChecked: boolean;
11553 FVisible: boolean;
11554 FEnabled: boolean;
11555 FHelpContext: integer;
11556 FHint: string;
11557 FOnExecute: TOnEvent;
11558 FAccelerator: TMenuAccelerator;
11559 FShortCut: string;
11560 procedure DoOnMenuItem(Sender: PMenu; Item: Integer);
11561 procedure DoOnToolbarButtonClick(Sender: PControl; BtnID: Integer);
11562 procedure DoOnControlClick(Sender: PObj);
11564 procedure SetCaption(const Value: string);
11565 procedure SetChecked(const Value: boolean);
11566 procedure SetEnabled(const Value: boolean);
11567 procedure SetHelpContext(const Value: integer);
11568 procedure SetHint(const Value: string);
11569 procedure SetVisible(const Value: boolean);
11570 procedure SetAccelerator(const Value: TMenuAccelerator);
11571 procedure UpdateControls;
11573 procedure LinkCtrl(ACtrl: PObj; ACtrlKind: TCtrlKind; AItemID: integer; AUpdateProc: TOnUpdateCtrlEvent);
11574 procedure SetOnExecute(const Value: TOnEvent);
11576 procedure UpdateCtrl(Sender: PControlRec);
11577 procedure UpdateMenu(Sender: PControlRec);
11578 procedure UpdateToolbar(Sender: PControlRec);
11580 public
11581 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
11582 procedure LinkControl(Ctrl: PControl);
11583 {* Add a link to a TControl or descendant control. }
11584 procedure LinkMenuItem(Menu: PMenu; MenuItemIdx: integer);
11585 {* Add a link to a menu item. }
11586 procedure LinkToolbarButton(Toolbar: PControl; ButtonIdx: integer);
11587 {* Add a link to a toolbar button. }
11588 procedure Execute;
11589 {* Executes a OnExecute event handler. }
11590 property Caption: string read FCaption write SetCaption;
11591 {* Text caption. }
11592 property Hint: string read FHint write SetHint;
11593 {* Hint (tooltip). Currently used for toolbar buttons only. }
11594 property Checked: boolean read FChecked write SetChecked;
11595 {* Checked state. }
11596 property Enabled: boolean read FEnabled write SetEnabled;
11597 {* Enabled state. }
11598 property Visible: boolean read FVisible write SetVisible;
11599 {* Visible state. }
11600 property HelpContext: integer read FHelpContext write SetHelpContext;
11601 {* Help context. }
11602 property Accelerator: TMenuAccelerator read FAccelerator write SetAccelerator;
11603 {* Accelerator for menu items. }
11604 property OnExecute: TOnEvent read FOnExecute write SetOnExecute;
11605 {* This event is executed when user clicks on a linked object or Execute method was called. }
11606 end;
11607 //[END OF TAction DEFINITION]
11609 //[TActionList DEFINITION]
11610 TActionList = {-} object( TObj ) {+}{++}(*class*){--}
11611 {*! TActionList maintains a list of actions used with components and controls,
11612 such as menu items and buttons.
11613 Action lists are used, in conjunction with actions, to centralize the response
11614 to user commands (actions).
11615 Write an OnUpdateActions handler to update actions state.
11616 Created using function NewActionList.
11617 See also TAction.
11619 protected
11620 FOwner: PControl;
11621 FActions: PList;
11622 FOnUpdateActions: TOnEvent;
11623 function GetActions(Idx: integer): PAction;
11624 function GetCount: integer;
11625 protected
11626 procedure DoUpdateActions(Sender: PObj);
11627 public
11628 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
11629 function Add(const ACaption, AHint: string; OnExecute: TOnEvent): PAction;
11630 {* Add a new action to the list. Returns pointer to action object. }
11631 procedure Delete(Idx: integer);
11632 {* Delete action by index from list. }
11633 procedure Clear;
11634 {* Clear all actions in the list. }
11635 property Actions[Idx: integer]: PAction read GetActions;
11636 {* Access to actions in the list. }
11637 property Count: integer read GetCount;
11638 {* Number of actions in the list.. }
11639 property OnUpdateActions: TOnEvent read FOnUpdateActions write FOnUpdateActions;
11640 {* Event handler to update actions state. This event is called each time when application
11641 goes in the idle state (no messages in the queue). }
11642 end;
11643 //[END OF TActionList DEFINITION]
11645 //[NewActionList DECLARATION]
11646 function NewActionList(AOwner: PControl): PActionList;
11647 {* Action list constructor. AOwner - owner form.
11648 |<hr>
11657 <R System functions and working with windows>
11659 //[Window FUNCTIONS DECLARATIONS]
11660 type
11661 TWindowChildKind = ( wcActive, wcFocus, wcCapture, wcMenuOwner,
11662 wcMoveSize, wcCaret );
11663 {* Type of window child kind. Used in function GetWindowChild. }
11665 function GetWindowChild( Wnd: HWnd; Kind: TWindowChildKind ): HWnd;
11666 {* Returns child of given top-level window, having given characteristics.
11667 For example, it is possible to get know for foreground window,
11668 which of its child window has focus. This function does not work in old
11669 Windows 95 (returns Wnd in that case). But for Windows 98, Windows NT/2000
11670 this function works fine. To obtain focused child of the window,
11671 use GetFocusedWindow, which is independant from Windows version. }
11673 function GetFocusedChild( Wnd: HWnd ): HWnd;
11674 {* Returns focused child of given window (which should be foreground
11675 and active, certainly). 0 is returned either if Wnd is not active
11676 or Wnd has no focused child window. }
11678 function Stroke2Window( Wnd: HWnd; const S: String ): Boolean;
11679 {* Posts characters from string S to those child window of Wnd, which
11680 has focus now (top-level window Wnd must be foreground, and have
11681 focused edit-aware control to receive the stroke).
11682 |<br>
11683 This function allows only to post typeable characters (including
11684 such special symbols as #13 (Enter), #9 (Tab), #8 (BackSpace), etc.
11685 |<br>
11686 See also function Stroke2WindowEx, which allows to post any key down
11687 and up events, simulating keyboard for given (automated) application. }
11689 function Stroke2WindowEx( Wnd: HWnd; const S: String; Wait: Boolean ): Boolean;
11690 {* In addition to function Stroke2Window, this one can send special keys
11691 to given window, including functional keys and navigation keys. To
11692 post special key to target window, place a combination of names of
11693 such key together with keys, which should be passed simultaneously,
11694 between square or figure brackets. For example, [Ctrl F1], [Alt Shift Home],
11695 [Ctrl E]. For letters and usual characters, it is not necessary to
11696 simulate pressing it with determining all Shift combinations and it is
11697 sufficient to pass characters as is. (E.g., not '[Shift 1]', but '!'). }
11699 function FindWindowByThreadID( ThreadID : DWORD ) : HWnd;
11700 {* Searches for window, belonging to a given thread. }
11702 function GetDesktopRect : TRect;
11703 {* Returns rectangle of screen, free of taskbar and other
11704 similar app-bars, which reduces size of available desktop
11705 when created. }
11706 function GetWorkArea: TRect;
11707 {* The same as GetDesktopRect, but obtained calling SystemParametersInfo. }
11709 function ExecuteWait( const AppPath, CmdLine, DfltDirectory: String;
11710 Show: DWORD; TimeOut: DWORD; ProcID: PDWORD ): Boolean;
11711 {* Allows to execute an application and wait when it is finished. Pass
11712 INFINITE constant as TimeOut, if You sure that application is finished
11713 anyway. If another value passed as a TimeOut (in milliseconds), and
11714 application was not finished for that time, ExecuteWait is returning
11715 FALSE, and if ProcID is not nil, than ProcID^ contains started process
11716 handle (it can be used to wait it more, or to terminate it using
11717 TerminateProcess API function).
11718 |<br>
11719 Launching application can be console or GUI - it does not matter.
11720 Pass SW_SHOW, SW_HIDE or other SW_XXX constant as Show parameter
11721 as appropriate.
11722 |<br>
11723 Trie is returned only in case when application specified was launched
11724 successfully and finished for TimeOut specified. Otherwise, check
11725 ProcID^ variable: if it is 0, process could not be launched (and it
11726 is possible to get information about error using GetLastError API
11727 function in a such case). You can freely pass nil in place of ProcID
11728 parameter, but this is acually correct only when TimeOut is INFINITE. }
11729 function ExecuteIORedirect( const AppPath, CmdLine, DfltDirectory: String;
11730 Show: DWORD; ProcID: PDWORD; InPipe, OutPipeWr, OutPipeRd: PHandle ): Boolean;
11731 {* Executes an application with its console input and output redirection.
11732 Terminating of the application is not waiting, but if ProcID pointer
11733 is defined, it receives process Id launched, so it is possible to
11734 call WaitForSingleObject for it. InPipe is a pointer to THandle variable
11735 which receives a handle to input pipe of the console redirected. The same
11736 is for OutPipeWr and OutPipeRd, but for output of the console redirected.
11737 Before reading from OutPipeRd^, first close OutPipeWr^. If you run
11738 simple console application, for which you want to read results after its
11739 termination, you can use ExecuteConsoleAppIORedirect instead.
11740 |<br>&nbsp;&nbsp;&nbsp;
11741 Notes: if your application is not console and it does not create console
11742 using AllocConsole, this function will fail to redirect input-output. }
11743 function ExecuteConsoleAppIORedirect( const AppPath, CmdLine, DfltDirectory: String;
11744 Show: DWORD; const InStr: String; var OutStr: String; WaitTimeout: DWORD )
11745 : Boolean;
11746 {* Executes an application, redirecting its console input and output.
11747 After redirecting input and output and launching the application,
11748 content of InStr is written to input stream of the application, then
11749 the application is waiting for its termination (WaitTimeout milliseconds
11750 or INFINITE, as passed) and console output of the application is read to
11751 OutStr. TRUE is returned only in case, when all these tasks are
11752 completed successfully.
11753 |<br>&nbsp;&nbsp;&nbsp;
11754 Notes: if your application is not console and it does not create console
11755 using AllocConsole, this function will fail to redirect input-output. }
11758 function WindowsShutdown( const Machine : String; Force, Reboot : Boolean ) : Boolean;
11759 {* Shut down of Windows NT. Pass Machine = '' to shutdown this PC.
11760 Pass Reboot = True to reboot immediatelly after shut down. }
11762 type
11763 TWindowsVersion = ( wv31, wv95, wv98, wvNT, wvY2K, wvXP, wvLongHorn );
11764 {* Windows versions constants. }
11765 TWindowsVersions = Set of TWindowsVersion;
11766 {* Set of Windows version (e.g. to define a range of versions supported by the
11767 application). }
11769 function WinVer : TWindowsVersion;
11770 {* Returns Windows version. }
11771 function IsWinVer( Ver : TWindowsVersions ) : Boolean;
11772 {* Returns True if Windows version is in given range of values. }
11774 //[Parameters FUNCTIONS DECLARATIONS]
11775 function ParamStr( Idx: Integer ): String;
11776 {* Returns command-line parameter by index. This function supersides
11777 standard ParamStr function. }
11778 function ParamCount: Integer;
11779 {* Returns number of parameters in command line.
11780 |<hr>
11784 //{$DEFINE CHK_BITBLT}
11785 procedure Chk_BitBlt;
11786 {$IFDEF ASM_VERSION}
11787 procedure StartDC;
11788 procedure FinishDC;
11789 {$ENDIF ASM_VERSION}
11791 //[WndProcXXX OTHER DECLARATIONS]
11792 function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
11793 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
11795 var CreatingWindow: PControl;
11796 //ActiveWindow: HWnd;
11798 //[Assert OPERATOR DECLARATION]
11800 {$IFDEF _D2}
11801 // Assert operator was not available in Delphi2. Provide here easy Assert
11802 // procedure for Delphi2.
11803 procedure Assert( Cond: Boolean; const Msg: String );
11805 var AssertErrorProc: procedure( const Message, Filename: AnsiString; LineNumber: Integer );
11806 {$ENDIF}
11810 //[CUSTOM EXTENSIONS]
11811 {$IFDEF USE_CUSTOMEXTENSIONS}
11812 {$I CUSTOM_KOL_EXTENSION.inc} // See comments in TControl
11813 {$ENDIF}
11816 {$IFDEF DEBUG_ENDSESSION}
11817 var EndSession_Initiated: Boolean;
11818 {$ENDIF}
11820 //[FMMNotify VARIABLE]
11822 FMMNotify: procedure( var Msg: TMsg );
11824 //[procedure ClearText forward declaration]
11825 procedure ClearText( Sender: PControl );
11826 //[procedure ClearListbox forward declaration]
11827 procedure ClearListbox( Sender: PControl );
11828 //[procedure ClearCombobox forward declaration]
11829 procedure ClearCombobox( Sender: PControl );
11830 //[procedure ClearListView forward declaration]
11831 procedure ClearListView( Sender: PControl );
11832 //[procedure ClearTreeView forward declaration]
11833 procedure ClearTreeView( TV: PControl );
11835 //[START OF ACTIONS]
11836 const
11837 ButtonActions: TCommandActions = (
11838 aClear: ClearText;
11839 aAddText: nil;
11840 aClick: BN_CLICKED;
11841 aEnter: BN_SETFOCUS;
11842 aLeave: BN_KILLFOCUS;
11843 aChange: 0; //BN_CLICKED;
11844 aSelChange: 0;
11845 aGetCount: 0;
11846 aSetCount: 0;
11847 aGetItemLength: 0;
11848 aGetItemText: 0;
11849 aSetItemText: 0;
11850 aGetItemData: 0;
11851 aSetItemData: 0;
11852 aAddItem: 0;
11853 aDeleteItem: 0;
11854 aInsertItem: 0;
11855 aFindItem: 0;
11856 aFindPartial: 0;
11857 aItem2Pos: 0;
11858 aPos2Item: 0;
11859 aGetSelCount: 0;
11860 aGetSelected: 0;
11861 aGetSelRange: 0;
11862 aExGetSelRange: 0;
11863 aGetCurrent: 0;
11864 aSetSelected: 0;
11865 aSetCurrent: 0;
11866 aSetSelRange: 0;
11867 aExSetSelRange: 0;
11868 aGetSelection: 0;
11869 aReplaceSel: 0;
11870 aTextAlignLeft: BS_LEFT;
11871 aTextAlignRight: BS_RIGHT;
11872 aTextAlignCenter: BS_CENTER;
11873 aTextAlignMask: 0;
11874 aVertAlignCenter: BS_VCENTER shr 8;
11875 aVertAlignTop: BS_TOP shr 8;
11876 aVertAlignBottom: BS_BOTTOM shr 8;
11877 aDir: 0;
11878 aSetLimit: 0;
11879 aSetImgList: 0;
11880 aAutoSzX: 14;
11881 aAutoSzY: 0;
11882 aSetBkColor: 0;
11885 const
11886 LabelActions: TCommandActions = (
11887 aClear: ClearText;
11888 aAddText: nil;
11889 aClick: 0;
11890 aEnter: 0;
11891 aLeave: 0;
11892 aChange: 0;
11893 aSelChange: 0;
11894 aGetCount: 0;
11895 aSetCount: 0;
11896 aGetItemLength: 0;
11897 aGetItemText: 0;
11898 aSetItemText: 0;
11899 aGetItemData: 0;
11900 aSetItemData: 0;
11901 aAddItem: 0;
11902 aDeleteItem: 0;
11903 aInsertItem: 0;
11904 aFindItem: 0;
11905 aFindPartial: 0;
11906 aItem2Pos: 0;
11907 aPos2Item: 0;
11908 aGetSelCount: 0;
11909 aGetSelected: 0;
11910 aGetSelRange: 0;
11911 aExGetSelRange: 0;
11912 aGetCurrent: 0;
11913 aSetSelected: 0;
11914 aSetCurrent: 0;
11915 aSetSelRange: 0;
11916 aExSetSelRange: 0;
11917 aGetSelection: 0;
11918 aReplaceSel: 0;
11919 aTextAlignLeft: SS_LEFT;
11920 aTextAlignRight: SS_RIGHT;
11921 aTextAlignCenter: SS_CENTER;
11922 aTextAlignMask: SS_LEFTNOWORDWRAP;
11923 aVertAlignCenter: SS_CENTERIMAGE shr 8;
11924 aVertAlignTop: 0;
11925 aVertAlignBottom: 0;
11926 aDir: 0;
11927 aSetLimit: 0;
11928 aSetImgList: 0;
11929 aAutoSzX: 1;
11930 aAutoSzY: 1;
11931 aSetBkColor: 0;
11934 const
11935 EN_LINK = $070b;
11936 EditActions: TCommandActions = (
11937 aClear: ClearText;
11938 aAddText: nil;
11939 aClick: 0;
11940 aEnter: EN_SETFOCUS;
11941 aLeave: EN_KILLFOCUS;
11942 aChange: EN_CHANGE;
11943 aSelChange: 0;
11944 aGetCount: EM_GETLINECOUNT;
11945 aSetCount: 0;
11946 aGetItemLength: EM_LINELENGTH;
11947 aGetItemText: EM_GETLINE;
11948 aSetItemText: EM_REPLACESEL;
11949 aGetItemData: 0;
11950 aSetItemData: 0;
11951 aAddItem: 0;
11952 aDeleteItem: 0;
11953 aInsertItem: 0;
11954 aFindItem: 0;
11955 aFindPartial: 0;
11956 aItem2Pos: EM_LINEINDEX;
11957 aPos2Item: EM_LINEFROMCHAR;
11958 aGetSelCount: EM_GETSEL;
11959 aGetSelected: 0;
11960 aGetSelRange: EM_GETSEL;
11961 aExGetSelRange: 0;
11962 aGetCurrent: EM_LINEINDEX;
11963 aSetSelected: 0;
11964 aSetCurrent: 0;
11965 aSetSelRange: EM_SETSEL;
11966 aExSetSelRange: 0;
11967 aGetSelection: 0;
11968 aReplaceSel: EM_REPLACESEL;
11969 aTextAlignLeft: ES_LEFT;
11970 aTextAlignRight: ES_RIGHT;
11971 aTextAlignCenter: ES_CENTER;
11972 aTextAlignMask: 0;
11973 aVertAlignCenter: 0;
11974 aVertAlignTop: 0;
11975 aVertAlignBottom: 0;
11976 aDir: 0;
11977 aSetLimit: EM_SETLIMITTEXT;
11978 aSetImgList: 0;
11979 aAutoSzX: 0;
11980 aAutoSzY: 6;
11981 aSetBkColor: 0;
11982 aItem2XY: EM_POSFROMCHAR;
11985 const
11986 ListActions: TCommandActions = (
11987 aClear: ClearListbox;
11988 aAddText: nil;
11989 aClick: LBN_DBLCLK;
11990 aEnter: LBN_SETFOCUS;
11991 aLeave: LBN_KILLFOCUS;
11992 aChange: 0;
11993 aSelChange: LBN_SELCHANGE;
11994 aGetCount: LB_GETCOUNT;
11995 aSetCount: LB_SETCOUNT;
11996 aGetItemLength: LB_GETTEXTLEN;
11997 aGetItemText: LB_GETTEXT;
11998 aSetItemText: 0;
11999 aGetItemData: LB_GETITEMDATA;
12000 aSetItemData: LB_SETITEMDATA;
12001 aAddItem: LB_ADDSTRING;
12002 aDeleteItem: LB_DELETESTRING;
12003 aInsertItem: LB_INSERTSTRING;
12004 aFindItem: LB_FINDSTRINGEXACT;
12005 aFindPartial: LB_FINDSTRING;
12006 aItem2Pos: 0;
12007 aPos2Item: 0;
12008 aGetSelCount: LB_GETSELCOUNT;
12009 aGetSelected: LB_GETSEL;
12010 aGetSelRange: 0;
12011 aExGetSelRange: 0;
12012 aGetCurrent: LB_GETCURSEL;
12013 aSetSelected: LB_SETSEL;
12014 aSetCurrent: LB_SETCURSEL;
12015 aSetSelRange: 0;
12016 aExSetSelRange: 0;
12017 aGetSelection: 0;
12018 aReplaceSel: 0;
12019 aTextAlignLeft: 0;
12020 aTextAlignRight: 0;
12021 aTextAlignCenter: 0;
12022 aTextAlignMask: 0;
12023 aVertAlignCenter: 0;
12024 aVertAlignTop: 0;
12025 aVertAlignBottom: 0;
12026 aDir: LB_DIR;
12027 aSetLimit: 0;
12028 aSetImgList: 0;
12029 aAutoSzX: 0;
12030 aAutoSzY: 0;
12031 aSetBkColor: 0;
12032 aItem2XY: LB_GETITEMRECT;
12035 const
12036 ComboActions: TCommandActions = (
12037 aClear: ClearCombobox;
12038 aAddText: nil;
12039 aClick: CBN_DBLCLK;
12040 aEnter: CBN_SETFOCUS;
12041 aLeave: CBN_KILLFOCUS;
12042 aChange: CBN_EDITCHANGE;
12043 aSelChange: CM_CBN_SELCHANGE; // CBN_SELCHANGE;
12044 aGetCount: CB_GETCOUNT;
12045 aSetCount: 0;
12046 aGetItemLength: CB_GETLBTEXTLEN;
12047 aGetItemText: CB_GETLBTEXT;
12048 aSetItemText: 0;
12049 aGetItemData: CB_GETITEMDATA;
12050 aSetItemData: CB_SETITEMDATA;
12051 aAddItem: CB_ADDSTRING;
12052 aDeleteItem: CB_DELETESTRING;
12053 aInsertItem: CB_INSERTSTRING;
12054 aFindItem: CB_FINDSTRINGEXACT;
12055 aFindPartial: CB_FINDSTRING;
12056 aItem2Pos: 0;
12057 aPos2Item: 0;
12058 aGetSelCount: 0;
12059 aGetSelected: CB_GETCURSEL;
12060 aGetSelRange: 0;
12061 aExGetSelRange: 0;
12062 aGetCurrent: CB_GETCURSEL;
12063 aSetSelected: 0;
12064 aSetCurrent: CB_SETCURSEL;
12065 aSetSelRange: 0;
12066 aExSetSelRange: 0;
12067 aGetSelection: 0;
12068 aReplaceSel: 0;
12069 aTextAlignLeft: 0; //ES_LEFT;
12070 aTextAlignRight: 0; //ES_RIGHT;
12071 aTextAlignCenter: 0; //ES_CENTER;
12072 aTextAlignMask: 0;
12073 aVertAlignCenter: 0;
12074 aVertAlignTop: 0;
12075 aVertAlignBottom: 0;
12076 aDir: CB_DIR;
12077 aSetLimit: 0;
12078 aSetImgList: 0;
12079 aAutoSzX: 0;
12080 aAutoSzY: 6;
12081 aSetBkColor: 0;
12084 const
12085 ListViewActions: TCommandActions = (
12086 aClear: ClearListView;
12087 aAddText: nil;
12088 aClick: 0;
12089 aEnter: 0;
12090 aLeave: 0;
12091 aChange: LVN_ITEMCHANGED;
12092 aSelChange: 0;
12093 aGetCount: LVM_GETITEMCOUNT;
12094 aSetCount: LVM_SETITEMCOUNT;
12095 aGetItemLength: 0;
12096 aGetItemText: 0;
12097 aSetItemText: 0;
12098 aGetItemData: 0;
12099 aSetItemData: 0;
12100 aAddItem: 0;
12101 aDeleteItem: 0;
12102 aInsertItem: 0;
12103 aFindItem: 0;
12104 aFindPartial: 0;
12105 aItem2Pos: 0;
12106 aPos2Item: 0;
12107 aGetSelCount: $8000 or LVM_GETSELECTEDCOUNT;
12108 aGetSelected: 0;
12109 aGetSelRange: 0;
12110 aExGetSelRange: 0;
12111 aGetCurrent: LVM_GETNEXTITEM;
12112 aSetSelected: 0;
12113 aSetCurrent: 0;
12114 aSetSelRange: 0;
12115 aExSetSelRange: 0;
12116 aGetSelection: 0;
12117 aReplaceSel: 0;
12118 aTextAlignLeft: 0;
12119 aTextAlignRight: 0;
12120 aTextAlignCenter: 0;
12121 aTextAlignMask: 0;
12122 aVertAlignCenter: 0;
12123 aVertAlignTop: 0;
12124 aVertAlignBottom: 0;
12125 aDir: 0;
12126 aSetLimit: 0;
12127 aSetImgList: LVM_SETIMAGELIST;
12128 aAutoSzX: 0;
12129 aAutoSzY: 0;
12130 aSetBkColor: LVM_SETBKCOLOR;
12131 aItem2XY: LVM_GETITEMRECT;
12134 const
12135 TreeViewActions: TCommandActions = (
12136 aClear: ClearTreeView;
12137 aAddText: nil;
12138 aClick: 0;
12139 aEnter: 0;
12140 aLeave: 0;
12141 aChange: TVN_ENDLABELEDIT;
12142 aSelChange: TVN_SELCHANGED;
12143 aGetCount: TVM_GETCOUNT;
12144 aSetCount: 0;
12145 aGetItemLength: 0;
12146 aGetItemText: 0;
12147 aSetItemText: 0;
12148 aGetItemData: 0;
12149 aSetItemData: 0;
12150 aAddItem: 0;
12151 aDeleteItem: 0;
12152 aInsertItem: 0;
12153 aFindItem: 0;
12154 aFindPartial: 0;
12155 aItem2Pos: 0;
12156 aPos2Item: 0;
12157 aGetSelCount: 0;
12158 aGetSelected: 0;
12159 aGetSelRange: 0;
12160 aExGetSelRange: 0;
12161 aGetCurrent: 0;
12162 aSetSelected: 0;
12163 aSetCurrent: 0;
12164 aSetSelRange: 0;
12165 aExSetSelRange: 0;
12166 aGetSelection: 0;
12167 aReplaceSel: 0;
12168 aTextAlignLeft: 0;
12169 aTextAlignRight: 0;
12170 aTextAlignCenter: 0;
12171 aTextAlignMask: 0;
12172 aVertAlignCenter: 0;
12173 aVertAlignTop: 0;
12174 aVertAlignBottom: 0;
12175 aDir: CB_DIR;
12176 aSetLimit: 0;
12177 aSetImgList: TVM_SETIMAGELIST;
12178 aAutoSzX: 0;
12179 aAutoSzY: 0;
12180 aSetBkColor: TVM_SETBKCOLOR;
12181 aItem2XY: TVM_GETITEMRECT;
12184 const
12185 TabControlActions: TCommandActions = (
12186 aClear: ClearText;
12187 aAddText: nil;
12188 aClick: 0;
12189 aEnter: 0;
12190 aLeave: 0;
12191 aChange: TCN_SELCHANGE;
12192 aSelChange: TCN_SELCHANGE;
12193 aGetCount: TCM_GETITEMCOUNT;
12194 aSetCount: 0;
12195 aGetItemLength: 0;
12196 aGetItemText: 0;
12197 aSetItemText: 0;
12198 aGetItemData: 0;
12199 aSetItemData: 0;
12200 aAddItem: 0;
12201 aDeleteItem: 0;
12202 aInsertItem: 0;
12203 aFindItem: 0;
12204 aFindPartial: 0;
12205 aItem2Pos: 0;
12206 aPos2Item: 0;
12207 aGetSelCount: 0;
12208 aGetSelected: 0;
12209 aGetSelRange: 0;
12210 aExGetSelRange: 0;
12211 aGetCurrent: TCM_GETCURSEL;
12212 aSetSelected: 0;
12213 aSetCurrent: TCM_SETCURSEL; //TCM_SETCURFOCUS;
12214 aSetSelRange: 0;
12215 aExSetSelRange: 0;
12216 aGetSelection: 0;
12217 aReplaceSel: 0;
12218 aTextAlignLeft: 0;
12219 aTextAlignRight: 0;
12220 aTextAlignCenter: 0;
12221 aTextAlignMask: 0;
12222 aVertAlignCenter: 0;
12223 aVertAlignTop: 0;
12224 aVertAlignBottom: 0;
12225 aDir: CB_DIR;
12226 aSetLimit: 0;
12227 aSetImgList: TCM_SETIMAGELIST;
12228 aAutoSzX: 0;
12229 aAutoSzY: 0;
12230 aSetBkColor: 0;
12231 aItem2XY: TCM_GETITEMRECT;
12234 const
12235 RichEditActions: TCommandActions = (
12236 aClear: ClearText;
12237 aAddText: nil;
12238 aClick: 0;
12239 aEnter: EN_SETFOCUS;
12240 aLeave: EN_KILLFOCUS;
12241 aChange: EN_CHANGE;
12242 aSelChange: EN_SELCHANGE;
12243 aGetCount: EM_GETLINECOUNT;
12244 aSetCount: 0;
12245 aGetItemLength: EM_LINELENGTH;
12246 aGetItemText: EM_GETLINE;
12247 aSetItemText: EM_REPLACESEL;
12248 aGetItemData: 0;
12249 aSetItemData: 0;
12250 aAddItem: 0;
12251 aDeleteItem: 0;
12252 aInsertItem: 0;
12253 aFindItem: 0;
12254 aFindPartial: 0;
12255 aItem2Pos: EM_LINEINDEX;
12256 aPos2Item: EM_LINEFROMCHAR;
12257 aGetSelCount: 0; //EM_EXGETSEL;
12258 aGetSelected: 0;
12259 aGetSelRange: 0;
12260 aExGetSelRange: EM_EXGETSEL;
12261 aGetCurrent: EM_LINEINDEX;
12262 aSetSelected: 0;
12263 aSetCurrent: 0;
12264 aSetSelRange: 0;
12265 aExSetSelRange: EM_EXSETSEL;
12266 aGetSelection: EM_GETSELTEXT;
12267 aReplaceSel: EM_REPLACESEL;
12268 aTextAlignLeft: ES_LEFT;
12269 aTextAlignRight: ES_RIGHT;
12270 aTextAlignCenter: ES_CENTER;
12271 aTextAlignMask: 0;
12272 aVertAlignCenter: 0;
12273 aVertAlignTop: 0;
12274 aVertAlignBottom: 0;
12275 aDir: 0;
12276 aSetLimit: EM_EXLIMITTEXT;
12277 aSetImgList: 0;
12278 aAutoSzX: 0;
12279 aAutoSzY: 0;
12280 aSetBkColor: EM_SETBKGNDCOLOR;
12281 aItem2XY: EM_POSFROMCHAR;
12284 //[IMPLEMENTATION]
12285 implementation
12287 //[USES-2]
12288 uses
12289 ShellAPI,
12290 commdlg
12291 ; //, commctrl;
12292 // in Delphi3, including of commctrl.pas increases executable
12293 // onto about 30K. So, all needed definitions are copied here
12294 // (see commctrl.inc).
12295 //[END OF USES-2]
12297 {$IFDEF _D2orD3}
12298 const
12299 OFN_ENABLESIZING = $00800000;
12300 {$ENDIF}
12302 //[procedure Chk_BitBlt_ShowError]
12303 procedure Chk_BitBlt_ShowError;
12304 var Rslt: Integer;
12305 begin
12306 Rslt := GetLastError;
12307 ShowMessage( 'BitBlt ERROR: ' + Int2Str( Rslt )
12308 + ' ' + SysErrorMessage( Rslt ) );
12309 end;
12310 //[ENDe Chk_BitBlt_ShowError]
12312 //[procedure Chk_BitBlt]
12313 procedure Chk_BitBlt;
12314 var Rslt: Integer;
12315 begin
12317 MOV Rslt, EAX
12318 end;
12319 if Rslt = 0 then
12320 begin
12321 Chk_BitBlt_ShowError;
12323 int 3;
12324 end;
12325 end;
12326 end;
12327 //[ENDe Chk_BitBlt]
12329 //[FUNCTION MulDiv]
12330 {$IFNDEF FPC}
12331 function MulDiv( A, B, C: Integer ): Integer;
12333 IMUL EDX
12334 IDIV ECX
12335 end;
12336 {$ENDIF}
12337 //[END MulDiv]
12340 {$ifdef _D2}
12342 //[PROCEDURE Assert]
12343 procedure Assert( Cond: Boolean; const Msg: String );
12344 begin
12345 if not Cond then
12346 begin
12347 AssertErrorProc( Msg, '', 0 );
12348 //MsgOK( Msg );
12350 int 3;
12351 end;
12352 end;
12353 end;
12355 //[API CreateDIBSection]
12356 function CreateDIBSection(DC: HDC; const p2: TBitmapInfo; p3: UINT;
12357 var p4: Pointer; p5: THandle; p6: DWORD): HBITMAP; stdcall;
12358 external gdi32 name 'CreateDIBSection';
12361 //[PROCEDURE _LStrFromPCharLen]
12362 procedure _LStrFromPCharLen(var Dest: AnsiString; Source: PAnsiChar; Length: Integer);
12364 { -> EAX pointer to dest }
12365 { EDX source }
12366 { ECX length }
12368 PUSH EBX
12369 PUSH ESI
12370 PUSH EDI
12372 MOV EBX,EAX
12373 MOV ESI,EDX
12374 MOV EDI,ECX
12376 { allocate new string }
12378 MOV EAX,EDI
12380 CALL System.@NewAnsiString
12381 MOV ECX,EDI
12382 MOV EDI,EAX
12384 TEST ESI,ESI
12385 JE @@noMove
12387 MOV EDX,EAX
12388 MOV EAX,ESI
12389 CALL Move
12391 { assign the result to dest }
12393 @@noMove:
12394 MOV EAX,EBX
12395 CALL System.@LStrClr
12396 MOV [EBX],EDI
12398 POP EDI
12399 POP ESI
12400 POP EBX
12401 end;
12402 {$endif}
12405 //[API InitCommonControls]
12406 procedure InitCommonControls; external cctrl name 'InitCommonControls';
12408 type
12409 TInitCommonControlsEx = packed record
12410 dwSize: DWORD;
12411 dwICC: DWORD;
12412 end;
12413 PInitCommonControlsEx = ^TInitCommonControlsEx;
12415 var ComCtl32_Module: HModule;
12416 //[procedure DoInitCommonControls]
12417 procedure DoInitCommonControls( dwICC: DWORD );
12418 var Proc: procedure( ICC: PInitCommonControlsEx ); stdcall;
12419 ICC: TInitCommonControlsEx;
12420 begin
12421 InitCommonControls;
12422 if ComCtl32_Module = 0 then
12423 ComCtl32_Module := LoadLibrary( 'comctl32.dll' );
12424 @ Proc := GetProcAddress( ComCtl32_Module, 'InitCommonControlsEx' );
12425 if Assigned( Proc ) then
12426 begin
12427 ICC.dwSize := Sizeof( ICC );
12428 ICC.dwICC := dwICC;
12429 Proc( @ ICC );
12430 end;
12431 end;
12432 //[END DoInitCommonControls]
12434 const size_TRect = 16; // used often in assembler versions of code
12437 {$IFDEF ASM_VERSION}
12438 const
12439 EmptyString: String = '';
12441 //[PROCEDURE EAX2PChar]
12442 procedure EAX2PChar;
12444 TEST EAX, EAX
12445 JNZ @@exit
12446 MOV EAX, offset[EmptyString]
12447 @@exit:
12448 end;
12450 //[PROCEDURE EDX2PChar]
12451 procedure EDX2PChar;
12453 TEST EDX, EDX
12454 JNZ @@exit
12455 MOV EDX, offset[EmptyString]
12456 @@exit:
12457 end;
12459 //[PROCEDURE ECX2PChar]
12460 procedure ECX2PChar;
12462 JECXZ @@convert
12464 @@convert:
12465 MOV ECX, offset[EmptyString]
12466 @@exit:
12467 end;
12469 //[PROCEDURE RemoveStr]
12470 procedure RemoveStr;
12472 { <- [ESP+4] = string to remove
12473 -> ESP := ESP + 4
12474 EAX = 0
12476 POP EAX
12477 XCHG EAX, [ESP]
12478 PUSH EAX
12479 MOV EAX, ESP
12480 CALL System.@LStrClr
12481 POP EAX
12482 end;
12483 {$ELSE ASM_VERSION}
12484 {$ENDIF ASM_VERSION}
12487 //[PROCEDURE MsgOK]
12488 procedure MsgOK( const S: String );
12489 begin
12490 MsgBox( S, MB_OK );
12491 end;
12493 {$IFDEF ASM_VERSION}
12494 //[function MsgBox]
12495 function MsgBox( const S: String; Flags: DWORD ): DWORD;
12497 PUSH EDX
12498 PUSH EAX
12500 MOV ECX, [Applet]
12501 XOR EAX, EAX
12502 JECXZ @@1
12503 MOV EAX, [ECX].TControl.fCaption
12504 @@1:
12505 XCHG EAX, [ESP]
12506 PUSH EAX
12507 PUSH 0
12508 CALL MessageBox
12509 end;
12510 {$ELSE ASM_VERSION} //Pascal
12511 function MsgBox( const S: String; Flags: DWORD ): DWORD;
12512 var Title: PChar;
12513 begin
12514 Title := nil;
12515 if assigned( Applet ) then
12516 begin
12517 Title := PChar( Applet.fCaption );
12518 end;
12519 Result := MessageBox( 0 {Wnd}, PChar( S ), Title, Flags );
12520 end;
12521 //[END MsgBox]
12522 {$ENDIF ASM_VERSION}
12524 //[function ShowMsg]
12525 function ShowMsg( const S: String; Flags: DWORD ): DWORD;
12526 var Title: PChar;
12527 Wnd: HWnd;
12528 begin
12529 Title := nil;
12530 Wnd := 0;
12531 if assigned( Applet ) then
12532 begin
12533 Title := PChar( Applet.fCaption );
12534 Wnd := Applet.Handle;
12535 end;
12536 Result := MessageBox( Wnd, PChar( S ), Title, Flags );
12537 end;
12538 //[END ShowMsg]
12540 //[procedure ShowMessage]
12541 procedure ShowMessage( const S: String );
12542 begin
12543 ShowMsg( S, MB_OK or MB_SETFOREGROUND );
12544 end;
12545 //[ENDe ShowMessage]
12547 //[procedure OKClick]
12548 procedure OKClick( Dialog, Btn: PControl );
12549 var Rslt: Integer;
12550 begin
12551 Rslt := -1;
12552 if Btn <> nil then
12553 Rslt := Btn.Tag;
12554 Dialog.ModalResult := Rslt;
12555 Dialog.Close;
12556 end;
12557 //[END OKClick]
12559 //[procedure KeyClick]
12560 procedure KeyClick( Dialog, Btn: PControl; var Key: Longint; Shift: DWORD );
12561 begin
12562 if (Key = VK_RETURN) or (Key = VK_ESCAPE) then
12563 begin
12564 if Key = VK_ESCAPE then
12565 Btn := nil;
12566 OKClick( Dialog, Btn );
12567 end;
12568 end;
12569 //[ENDe KeyClick]
12571 //[procedure CloseMsg]
12572 procedure CloseMsg( Dummy, Dialog: PControl; var Accept: Boolean );
12573 begin
12574 Accept := FALSE;
12575 Dialog.ModalResult := -1;
12576 end;
12577 //[ENDe CloseMsg]
12579 //[function ShowQuestionEx]
12580 function ShowQuestionEx( const S: String; Answers: String; CallBack: TOnEvent ): Integer;
12581 {$IFDEF F_P105ORBELOW}
12582 type POnEvent = ^TOnEvent;
12583 PONKey = ^TOnKey;
12584 var M: TMethod;
12585 {$ENDIF F_P105ORBELOW}
12586 var Dialog: PControl;
12587 Buttons: PList;
12588 Btn: PControl;
12589 AppTermFlag: Boolean;
12590 Lab: PControl;
12591 Y, W, I: Integer;
12592 Title: String;
12593 DlgWnd: HWnd;
12594 AppCtl: PControl;
12595 begin
12596 AppTermFlag := AppletTerminated;
12597 AppCtl := Applet;
12598 AppletTerminated := FALSE;
12599 Title := 'Information';
12600 if pos( '/', Answers ) > 0 then
12601 Title := 'Question';
12602 if Applet <> nil then
12603 Title := Applet.Caption;
12604 Dialog := NewForm( Applet, Title ).SetSize( 300, 40 );
12605 Dialog.Style := Dialog.Style and not (WS_MINIMIZEBOX or WS_MAXIMIZEBOX);
12606 Dialog.OnClose := TOnEventAccept( MakeMethod( Dialog, @CloseMsg ) );
12607 Dialog.Margin := 8;
12608 Lab := NewEditbox( Dialog, [ eoMultiline, eoReadonly, eoNoHScroll, eoNoVScroll ] ).SetSize( 278, 20 );
12609 Lab.HasBorder := FALSE;
12610 Lab.Color := clBtnFace;
12611 Lab.Caption := S;
12612 Lab.Style := Lab.Style and not WS_TABSTOP;
12613 Lab.TabStop := FALSE;
12614 //Lab.LikeSpeedButton;
12616 //Lab.CreateWindow; //virtual!!! -- not needed, window created in Perform
12617 while TRUE do
12618 begin
12619 Y := HiWord( Lab.Perform( EM_POSFROMCHAR, Length( S ) - 1, 0 ) );
12620 if Y < Lab.Height - 20 then break;
12621 Lab.Height := Lab.Height + 4;
12622 if Lab.Height + 40 > GetSystemMetrics( SM_CYSCREEN ) then break;
12623 end;
12625 Buttons := NewList;
12626 W := 0;
12627 if Answers = '' then
12628 begin
12629 Btn := NewButton( Dialog, ' OK ' ).PlaceUnder;
12630 W := Btn.Width;
12631 Buttons.Add( Btn );
12633 else
12634 while Answers <> '' do
12635 begin
12636 Btn := NewButton( Dialog, ' ' + Parse( Answers, '/' ) + ' ' );
12637 Buttons.Add( Btn );
12638 if W = 0 then
12639 Btn.PlaceUnder
12640 else
12641 Btn.PlaceRight;
12642 Btn.AutoSize( TRUE );
12643 if W > 0 then
12644 begin
12645 //Inc( W, 6 );
12646 Btn.Left := Btn.Left + 6;
12647 end;
12648 W := Btn.BoundsRect.Right + 12;
12649 end;
12650 if Dialog.ClientWidth < W then
12651 Dialog.ClientWidth := W;
12652 W := (Dialog.ClientWidth - W) div 2;
12653 for I := 0 to Buttons.Count-1 do
12654 begin
12655 Btn := Buttons.Items[ I ];
12656 Btn.Tag := I + 1;
12657 {$IFDEF F_P105ORBELOW}
12658 M := MakeMethod( Dialog, @OKClick );
12659 Btn.OnClick := POnEvent( @ M )^;
12660 M := MakeMethod( Dialog, @KeyClick );
12661 Btn.OnKeyDown := POnKey( @ M )^;
12662 {$ELSE}
12663 Btn.OnClick := TOnEvent( MakeMethod( Dialog, @OKClick ) );
12664 Btn.OnKeyDown := TOnKey( MakeMethod( Dialog, @KeyClick ) );
12665 {$ENDIF}
12666 Btn.Left := Btn.Left + W;
12667 if I = 0 then
12668 begin
12669 Btn.ResizeParentBottom;
12670 Dialog.ActiveControl := Btn;
12671 end;
12672 end;
12673 Dialog.CenterOnParent.Tabulate.CanResize := FALSE;
12674 Buttons.Free;
12676 if Assigned( CallBack ) then
12677 CallBack( Dialog );
12678 Dialog.CreateWindow; // virtual!!!
12680 if (Applet <> nil) and Applet.IsApplet then
12681 begin
12682 Dialog.ShowModal;
12683 Result := Dialog.ModalResult;
12684 Dialog.Free;
12686 else
12687 begin
12688 DlgWnd := Dialog.Handle;
12689 while IsWindow( DlgWnd ) and (Dialog.ModalResult = 0) do
12690 Dialog.ProcessMessage;
12691 Result := Dialog.ModalResult;
12692 Dialog.Free;
12693 CreatingWindow := nil;
12694 Applet := AppCtl;
12695 end;
12697 AppletTerminated := AppTermFlag;
12698 end;
12699 //[END ShowQuestionEx]
12701 //[function ShowQuestion]
12702 function ShowQuestion( const S: String; Answers: String ): Integer;
12703 begin
12704 Result := ShowQuestionEx( S, Answers, nil );
12705 end;
12706 //[END ShowQuestion]
12708 //[procedure ShowMsgModal]
12709 procedure ShowMsgModal( const S: String );
12710 begin
12711 ShowQuestion( S, '' );
12712 end;
12713 //[ENDe ShowMsgModal]
12715 //[procedure SpeakerBeep]
12716 procedure SpeakerBeep( Freq: Word; Duration: DWORD );
12717 begin
12718 if WinVer >= wvNT then
12719 Windows.Beep( Freq, Duration )
12720 else
12721 begin
12722 if Freq < 18 then Exit;
12723 Freq := 1193181 div Freq;
12724 if Freq = 0 then Exit;
12726 mov al,0b6H
12727 out 43H,al
12728 mov ax,Freq
12729 //xchg al, ah
12730 out 42h,al
12731 xchg al, ah
12732 out 42h,al
12733 in al,61H
12734 or al,03H
12735 out 61H,al
12736 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF} ;
12737 Sleep(Duration);
12739 in al,61H
12740 and al,0fcH
12741 out 61H,al
12742 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF} ;
12743 end;
12744 end;
12745 //[ENDe SpeakerBeep]
12747 {++}(*
12748 //[API FormatMessage]
12749 function FormatMessage; external kernel32 name 'FormatMessageA';
12750 *){--}
12752 //[FUNCTION SysErrorMessage]
12753 function SysErrorMessage(ErrorCode: Integer): string;
12755 Len: Integer;
12756 Buffer: array[0..255] of Char;
12757 begin
12758 Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
12759 FORMAT_MESSAGE_ARGUMENT_ARRAY, nil, ErrorCode, 0, Buffer,
12760 SizeOf(Buffer), nil);
12761 while (Len > 0) and (Buffer[Len - 1] in [#0..#32 {, '.'}]) do Dec(Len);
12762 SetString(Result, Buffer, Len);
12763 end;
12764 //[END SysErrorMessage]
12766 //[function MakeMethod]
12767 function MakeMethod( Data, Code: Pointer ): TMethod;
12768 begin
12769 Result.Data := Data;
12770 Result.Code := Code;
12771 end;
12772 //[END MakeMethod]
12774 //[function GetShiftState]
12775 function GetShiftState: DWORD;
12776 begin
12777 Result := 0;
12778 if GetKeyState( VK_SHIFT ) < 0 then
12779 Result := Result or MK_SHIFT;
12780 if GetKeyState( VK_CONTROL ) < 0 then
12781 Result := Result or MK_CONTROL;
12782 //if LONGBOOL(Msg.lParam and $20000000) then
12783 if GetKeyState( VK_MENU ) < 0 then
12784 Result := Result or MK_ALT;
12785 end;
12786 //[END GetShiftState]
12788 //[FUNCTION MakeRect]
12789 {$IFDEF ASM_VERSION}
12790 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;
12792 PUSH ESI
12793 PUSH EDI
12795 MOV EDI, @Result
12796 LEA ESI, [Left]
12798 MOVSD
12799 MOVSD
12800 MOVSD
12801 MOVSD
12803 POP EDI
12804 POP ESI
12805 end;
12806 {$ELSE ASM_VERSION} //Pascal
12807 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;
12808 begin
12809 Result.Left := Left;
12810 Result.Top := Top;
12811 Result.Right:= Right;
12812 Result.Bottom := Bottom;
12813 end;
12814 {$ENDIF ASM_VERSION}
12815 //[END MakeRect]
12817 //[FUNCTION RectsEqual]
12818 {$IFDEF ASM_VERSION}
12819 function RectsEqual( const R1, R2: TRect ): Boolean;
12821 //LEA EAX, [R1]
12822 //LEA EDX, [R2]
12823 MOV ECX, size_TRect
12824 CALL CompareMem
12825 end;
12826 {$ELSE ASM_VERSION} //Pascal
12827 function RectsEqual( const R1, R2: TRect ): Boolean;
12828 begin
12829 Result := CompareMem( @R1, @R2, Sizeof( TRect ) );
12830 end;
12831 {$ENDIF ASM_VERSION}
12832 //[END RectsEqual]
12834 //[function RectsIntersected]
12835 function RectsIntersected( const R1, R2: TRect ): Boolean;
12836 begin
12837 Result := ((R1.Left <= R2.Left) and (R1.Right > R2.Left ) or
12838 (R1.Left <= R2.Right) and (R1.Right >= R2.Right) or
12839 (R1.Left >= R2.Left) and (R1.Right <= R2.Right))
12841 ((R1.Top <= R2.Top) and (R1.Bottom > R2.Top) or
12842 (R1.Top <= R2.Bottom) and (R1.Bottom >= R2.Bottom) or
12843 (R1.Top >= R2.Top) and (R1.Bottom <= R2.Bottom)) ;
12844 end;
12845 //[END RectsIntersected]
12848 //[FUNCTION PointInRect]
12849 {$IFDEF ASM_VERSION}
12850 function PointInRect( const P: TPoint; const R: TRect ): Boolean;
12852 PUSH ESI
12853 MOV ECX, EAX
12854 MOV ESI, EDX
12855 LODSD
12856 CMP EAX, [ECX]
12857 JG @@fail
12858 LODSD
12859 CMP EAX, [ECX+4]
12860 JG @@fail
12861 LODSD
12862 CMP [ECX], EAX
12863 JG @@fail
12864 LODSD
12865 CMP [ECX+4], EAX
12866 @@fail: SETLE AL
12867 POP ESI
12868 end;
12869 {$ELSE ASM_VERSION} //Pascal
12870 function PointInRect( const P: TPoint; const R: TRect ): Boolean;
12871 begin
12872 Result := (P.x >= R.Left) and (P.x < R.Right)
12873 and (P.y >= R.Top) and (P.y < R.Bottom);
12874 end;
12875 {$ENDIF ASM_VERSION}
12876 //[END PointInRect]
12878 //[FUNCTION MakePoint]
12879 {$IFDEF ASM_VERSION}
12880 function MakePoint( X, Y: Integer ): TPoint;
12882 MOV ECX, @Result
12883 MOV [ECX].TPoint.x, EAX
12884 MOV [ECX].TPoint.y, EDX
12885 end;
12886 {$ELSE ASM_VERSION} //Pascal
12887 function MakePoint( X, Y: Integer ): TPoint;
12888 begin
12889 Result.x := X;
12890 Result.y := Y;
12891 end;
12892 {$ENDIF ASM_VERSION}
12893 //[END MakePoint]
12895 //[FUNCTION MakeFlags]
12896 {$IFDEF ASM_VERSION}
12897 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;
12899 PUSH EBX
12900 PUSH ESI
12901 MOV EBX, [EAX]
12902 MOV ESI, EDX
12903 XOR EDX, EDX
12904 INC ECX
12905 JZ @@exit
12906 @@loo:
12907 LODSD
12908 TEST EAX, EAX
12909 JGE @@ge
12910 NOT EAX
12911 TEST BL, 1
12912 JZ @@or
12913 DEC EBX
12914 @@ge:
12915 TEST BL, 1
12916 JZ @@nx
12917 @@or:
12918 OR EDX, EAX
12919 @@nx:
12920 SHR EBX, 1
12921 LOOP @@loo
12923 @@exit:
12924 XCHG EAX, EDX
12925 POP ESI
12926 POP EBX
12927 end;
12928 {$ELSE ASM_VERSION} //Pascal
12929 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;
12930 var I : Integer;
12931 Mask : DWORD;
12932 begin
12933 Result := 0;
12934 Mask := FlgSet^;
12935 for I := 0 to High( FlgArray ) do
12936 begin
12937 if (FlgArray[ I ] < 0) and not LongBool( Mask and 1 ) then
12938 Result := Result or not FlgArray[ I ]
12939 else
12940 if (FlgArray[ I ] >= 0) and LongBool( Mask and 1 ) then
12941 Result := Result or FlgArray[ I ];
12942 Mask := Mask shr 1;
12943 end;
12944 end;
12945 {$ENDIF ASM_VERSION}
12946 //[END MakeFlags]
12948 //[procedure HelpFastIncNum2Els]
12949 procedure HelpFastIncNum2Els( DataArray: Pointer; Value, Count: Integer );
12951 PUSH ESI
12952 PUSH EDI
12953 {$IFDEF F_P}
12954 MOV ESI, [DataArray]
12955 MOV EDX, [Value]
12956 MOV ECX, [Count]
12957 {$ELSE DELPHI}
12958 MOV ESI, EAX
12959 {$ENDIF F_P/DELPHI}
12960 MOV EDI, ESI
12963 @@1:
12964 LODSD
12965 ADD EAX, EDX
12966 STOSD
12967 LOOP @@1
12969 POP EDI
12970 POP ESI
12971 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
12972 //[ENDe HelpFastIncNum2Els]
12974 //[procedure Swap]
12975 procedure Swap( var X, Y: Integer );
12976 {$IFDEF F_P}
12977 var Tmp: Integer;
12978 begin
12979 Tmp := X;
12980 X := Y;
12981 Y := Tmp;
12982 end;
12983 {$ELSE DELPHI}
12985 MOV ECX, [EDX]
12986 XCHG ECX, [EAX]
12987 MOV [EDX], ECX
12988 end;
12989 //[ENDe Swap]
12990 {$ENDIF F_P/DELPHI}
12992 //[function Min]
12993 function Min( X, Y: Integer ): Integer;
12995 {$IFDEF F_P}
12996 MOV EAX, [X]
12997 MOV EDX, [Y]
12998 {$ENDIF F_P}
12999 {$IFDEF USE_CMOV}
13000 CMP EAX, EDX
13001 CMOVG EAX, EDX
13002 {$ELSE}
13003 CMP EAX, EDX
13004 JLE @@exit
13005 MOV EAX, EDX
13006 @@exit:
13007 {$ENDIF}
13008 end {$IFDEF F_P} [ 'EAX', 'EDX' ] {$ENDIF};
13009 //[END Min]
13011 //[function Max]
13012 function Max( X, Y: Integer ): Integer;
13014 {$IFDEF F_P}
13015 MOV EAX, [X]
13016 MOV EDX, [Y]
13017 {$ENDIF F_P}
13018 {$IFDEF USE_CMOV}
13019 CMP EAX, EDX
13020 CMOVL EAX, EDX
13021 {$ELSE}
13022 CMP EAX, EDX
13023 JGE @@exit
13024 MOV EAX, EDX
13025 @@exit:
13026 {$ENDIF}
13027 end {$IFDEF F_P} [ 'EAX', 'EDX' ] {$ENDIF};
13028 //[END Max]
13030 //[function Abs]
13031 function Abs( X: Integer ): Integer;
13033 {$IFDEF F_P}
13034 MOV EAX, [X]
13035 {$ENDIF F_P}
13036 TEST EAX, EAX
13037 JGE @@1
13038 NEG EAX
13039 @@1:
13040 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};
13041 //[END Abs]
13043 //[function Sgn]
13044 function Sgn( X: Integer ): Integer;
13046 CMP EAX, 0
13047 {$IFDEF USE_CMOV}
13048 MOV EDX, -1
13049 CMOVL EAX, EDX
13050 MOV EDX, 1
13051 CMOVG EAX, EDX
13052 {$ELSE}
13053 JZ @@exit
13054 MOV EAX, 1
13055 JG @@exit
13056 MOV EAX, -1
13057 @@exit:
13058 {$ENDIF}
13059 end;
13060 //[END Sgn]
13062 //[function iSqrt]
13063 function iSQRT( X: Integer ): Integer;
13064 var I, N: Integer;
13065 begin
13066 Result := 0;
13067 while Result < X do
13068 begin
13069 I := 1;
13070 while I > 0 do
13071 begin
13072 N := (Result + I) * (Result + I);
13073 if N > X then
13074 begin
13075 I := I shr 1;
13076 break;
13078 else
13079 if N = X then
13080 begin
13081 Result := Result + I;
13082 Exit;
13083 end;
13084 I := I shl 1;
13085 end;
13086 if I <= 0 then Exit;
13087 Result := Result + I;
13088 end;
13089 end;
13090 //[END iSqrt]
13092 {$IFDEF ASM_VERSION}
13093 //[PROCEDURE StartDC]
13094 procedure StartDC;
13096 { <- EBX : PBitmap
13097 -> EAX = dc
13098 [ESP+8] = var dc
13099 [ESP+4] = var SaveBmp
13101 PUSH 0
13102 CALL CreateCompatibleDC
13103 POP EDX
13104 PUSH EAX
13105 PUSH EDX
13106 MOV EAX, EBX
13107 CALL [EBX].TBitmap.fDetachCanvas
13108 MOV EAX, EBX
13109 CALL TBitmap.GetHandle
13110 PUSH EAX
13111 PUSH dword ptr [ESP+8]
13112 CALL SelectObject
13113 POP EDX
13114 PUSH EAX
13115 PUSH EDX
13116 MOV EAX, [ESP+8]
13117 end;
13118 //[END StartDC]
13120 //[procedure FinishDC]
13121 procedure FinishDC;
13123 POP ECX
13124 POP EAX
13125 POP EDX
13126 PUSH ECX
13127 PUSH EDX
13128 PUSH EAX
13129 PUSH EDX
13130 CALL SelectObject
13131 CALL DeleteDC
13132 end;
13133 //[ENDe FinishDC]
13134 {$ELSE ASM_VERSION}
13135 {$ENDIF ASM_VERSION}
13137 //[procedure FastIncNum2Elements]
13138 procedure FastIncNum2Elements( List: TList; FromIdx, Count, Value: Integer );
13139 begin
13140 HelpFastIncNum2Els( @List.fItems[ FromIdx ], Value, Count );
13141 end;
13143 //[function EnumDynHandlers FORWARD DECLARATION]
13144 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
13145 forward;
13147 //[procedure DummyObjProc]
13148 procedure DummyObjProc( Sender: PObj );
13149 begin
13150 end;
13152 //[procedure DummyObjProcParam]
13153 procedure DummyObjProcParam( Sender: PObj; Param: Pointer );
13154 begin
13155 end;
13157 //[procedure DummyPaintProc]
13158 procedure DummyPaintProc( Sender: PControl; DC: HDC );
13159 begin
13160 end;
13162 //[procedure Free_And_Nil]
13163 procedure Free_And_Nil( var Obj );
13164 var Obj1: PObj;
13165 begin
13166 Obj1 := PObj( Obj );
13167 Pointer( Obj ) := nil;
13168 Obj1.Free;
13169 end;
13170 //[ENDe Free_And_Nil]
13179 { _TObj }
13181 //[procedure _TObj.Init]
13182 procedure _TObj.Init;
13183 begin
13184 {$IFDEF _D2orD3}
13185 FillChar( Pointer( Integer(@Self) + 4 )^, Sizeof( Self ) - 4, 0 );
13186 {$ENDIF}
13187 end;
13190 //[function _TObj.VmtAddr]
13191 function _TObj.VmtAddr: Pointer;
13193 MOV EAX, [EAX]
13194 end;
13196 { TObj }
13198 class function TObj.AncestorOfObject(Obj: Pointer): Boolean;
13200 MOV ECX, [EAX]
13201 MOV EAX, EDX
13202 JMP @@loop1
13203 @@loop:
13204 MOV EAX,[EAX]
13205 @@loop1:
13206 TEST EAX,EAX
13207 JE @@exit
13208 CMP EAX,ECX
13209 JNE @@loop
13210 @@success:
13211 MOV AL,1
13212 @@exit:
13213 end;
13217 {$IFDEF ASM_VERSION}
13218 constructor TObj.Create;
13220 //CALL System.@ObjSetup - Generated always by compiler
13221 //JZ @@exit
13223 PUSH EAX
13224 MOV EDX, [EAX]
13225 CALL dword ptr [EDX]
13226 POP EAX
13228 @@exit:
13229 end;
13230 {$ELSE ASM_VERSION} //Pascal
13231 constructor TObj.Create;
13232 begin
13233 Init;
13234 {++}(* inherited; *){--}
13235 end;
13236 {$ENDIF ASM_VERSION}
13238 {$IFDEF ASM_VERSION}
13239 //[procedure TObj.DoDestroy]
13240 procedure TObj.DoDestroy;
13242 MOV EDX, [EAX].fRefCount
13243 SAR EDX, 1
13244 JZ @@1
13245 JC @@exit
13246 DEC [EAX].fRefCount
13249 @@1: JC @@exit
13250 MOV EDX, [EAX]
13251 CALL dword ptr [EDX + 4]
13252 @@exit:
13253 end;
13254 {$ELSE ASM_VERSION} //Pascal
13255 procedure TObj.DoDestroy;
13256 begin
13257 if fRefCount <> 0 then
13258 begin
13259 if not LongBool( fRefCount and 1) then
13260 Dec( fRefCount );
13262 else
13263 Destroy;
13264 end;
13265 {$ENDIF ASM_VERSION}
13267 {$IFDEF ASM_VERSION}
13268 //[procedure TObj.RefDec]
13269 procedure TObj.RefDec;
13271 SUB [EAX].fRefCount, 2
13272 JGE @@exit
13273 TEST [EAX].fRefCount, 1
13274 JZ @@exit
13275 MOV EDX, [EAX]
13276 PUSH dword ptr [EDX+4]
13277 @@exit:
13278 end;
13279 {$ELSE ASM_VERSION} //Pascal
13280 procedure TObj.RefDec;
13281 begin
13282 Dec( fRefCount, 2 );
13283 if (fRefCount < 0) and LongBool(fRefCount and 1) then
13284 Destroy;
13285 end;
13286 {$ENDIF ASM_VERSION}
13288 //[procedure TObj.RefInc]
13289 procedure TObj.RefInc;
13290 begin
13291 Inc( fRefCount, 2 );
13292 end;
13295 //[function TObj.VmtAddr]
13296 function TObj.VmtAddr: Pointer;
13298 MOV EAX, [EAX - 4]
13299 end;
13301 //[function TObj.InstanceSize]
13302 function TObj.InstanceSize: Integer;
13304 MOV EAX, [EAX]
13305 MOV EAX,[EAX-4]
13306 end;
13309 //[procedure TObj.Free]
13310 procedure TObj.Free;
13311 {$IFDEF F_P}
13312 begin
13313 if Self <> nil then
13314 DoDestroy;
13315 end;
13316 {$ELSE DELPHI}
13318 TEST EAX,EAX
13319 JNE DoDestroy
13320 end;
13321 {$ENDIF F_P/DELPHI}
13323 {$IFDEF ASM_VERSION}
13324 destructor TObj.Destroy;
13326 PUSH EAX
13327 CALL Final
13328 POP EAX
13329 XOR EDX, EDX
13330 CALL System.@FreeMem
13331 //CALL System.@Dispose
13332 end;
13333 {$ELSE ASM_VERSION} //Pascal
13334 destructor TObj.Destroy;
13335 begin
13336 Final;
13337 {$IFDEF DEBUG_ENDSESSION}
13338 if EndSession_Initiated then
13339 LogFileOutput( GetStartDir + 'es_debug.txt',
13340 'FINALLED: ' + Int2Hex( DWORD( @ Self ), 8 ) );
13341 {$ENDIF}
13343 Dispose( @Self );
13344 {+} {++}(*
13345 inherited; *){--}
13346 end;
13347 {$ENDIF ASM_VERSION}
13349 {++}(*
13350 //[procedure TObj.Init]
13351 procedure TObj.Init;
13352 begin
13354 end;
13355 *){--}
13357 {$IFDEF ASM_VERSION}
13358 //[procedure TObj.Final]
13359 procedure TObj.Final;
13360 asm //cmd //opd
13361 XOR ECX, ECX
13362 XCHG ECX, [EAX].fOnDestroy.TMethod.Code
13363 JECXZ @@doAutoFree
13364 PUSH EAX
13365 XCHG EDX, EAX
13366 MOV EAX, [EDX].fOnDestroy.TMethod.Data
13367 CALL ECX
13368 POP EAX
13369 @@doAutoFree:
13370 XOR ECX, ECX
13371 XCHG ECX, [EAX].fAutoFree
13372 JECXZ @@exit
13373 PUSH ESI
13374 PUSH ECX
13375 MOV ESI, [ECX].TList.fItems
13376 MOV ECX, [ECX].TList.fCount
13377 @@freeloop:
13378 LODSD
13379 XCHG EDX, EAX
13380 LODSD
13381 PUSH ECX
13382 CALL EDX
13383 POP ECX
13384 DEC ECX
13385 LOOP @@freeloop
13386 POP EAX
13387 CALL TObj.Free
13388 POP ESI
13389 @@exit:
13390 end;
13391 {$ELSE ASM_VERSION} //Pascal
13392 procedure TObj.Final;
13393 var I: Integer;
13394 ProcMethod: TMethod;
13395 Proc: TObjectMethod Absolute ProcMethod;
13396 begin
13397 if Assigned( fOnDestroy ) then
13398 begin
13399 fOnDestroy( @Self );
13400 fOnDestroy := nil;
13401 end;
13402 if fAutoFree <> nil then
13403 begin
13404 for I := 0 to fAutoFree.fCount div 2 - 1 do
13405 begin
13406 ProcMethod.Code := fAutoFree.fItems[ I * 2 ];
13407 ProcMethod.Data := fAutoFree.fItems[ I * 2 + 1 ];
13409 Proc;
13410 {+}{++}(*
13412 MOV EAX, [ProcMethod.Data]
13413 {$IFDEF F_P}
13414 PUSH EAX
13415 {$ENDIF F_P}
13416 MOV ECX, [ProcMethod.Code]
13417 CALL ECX
13418 end {$IFDEF F_P}[ 'EAX', 'EDX', 'ECX' ]{$ENDIF};
13419 *){--}
13420 end;
13421 fAutoFree.Free;
13422 fAutoFree := nil;
13423 end;
13424 end;
13425 {$ENDIF ASM_VERSION}
13427 {$IFDEF ASM_VERSION}
13428 //[procedure TObj.Add2AutoFree]
13429 procedure TObj.Add2AutoFree(Obj: PObj);
13430 asm //cmd //opd
13431 PUSH EBX
13432 PUSH EDX
13433 XCHG EBX, EAX
13434 MOV EAX, [EBX].fAutoFree
13435 TEST EAX, EAX
13436 JNZ @@1
13437 CALL NewList
13438 MOV [EBX].fAutoFree, EAX
13439 @@1: MOV EBX, EAX
13440 XOR EDX, EDX
13441 POP ECX
13442 CALL TList.Insert
13443 XCHG EAX, EBX
13444 XOR EDX, EDX
13445 MOV ECX, offset TObj.Free
13446 //XOR ECX, ECX
13447 CALL TList.Insert
13448 POP EBX
13449 end;
13450 {$ELSE ASM_VERSION} //Pascal
13451 procedure TObj.Add2AutoFree(Obj: PObj);
13452 begin
13453 if fAutoFree = nil then
13454 fAutoFree := NewList;
13455 fAutoFree.Insert( 0, Obj );
13456 fAutoFree.Insert( 0, Pointer( @TObj.Free ) );
13457 end;
13458 {$ENDIF ASM_VERSION}
13460 {$IFDEF ASM_VERSION}
13461 //[procedure TObj.Add2AutoFreeEx]
13462 procedure TObj.Add2AutoFreeEx( Proc: TObjectMethod );
13463 asm //cmd //opd
13464 PUSH EBX
13465 XCHG EAX, EBX
13466 MOV EAX, [EBX].fAutoFree
13467 TEST EAX, EAX
13468 JNZ @@1
13469 CALL NewList
13470 MOV [EBX].fAutoFree, EAX
13471 @@1: XOR EDX, EDX
13472 MOV ECX, [EBP+12] // Data
13473 MOV EBX, EAX
13474 CALL TList.Insert
13475 XCHG EAX, EBX
13476 XOR EDX, EDX
13477 MOV ECX, [EBP+8] // Code
13478 CALL TList.Insert
13479 POP EBX
13480 end;
13481 {$ELSE ASM_VERSION} //Pascal
13482 procedure TObj.Add2AutoFreeEx( Proc: TObjectMethod );
13483 {$IFDEF F_P}
13484 var Ptr1, Ptr2: Pointer;
13485 {$ENDIF F_P}
13486 begin
13487 if fAutoFree = nil then
13488 fAutoFree := NewList;
13489 {$IFDEF F_P}
13491 MOV EAX, [Proc]
13492 MOV [Ptr1], EAX
13493 MOV EAX, [Proc+4]
13494 MOV [Ptr2], EAX
13495 end [ 'EAX' ];
13496 fAutoFree.Insert( 0, Ptr2 );
13497 fAutoFree.Insert( 0, Ptr1 );
13498 {$ELSE DELPHI}
13499 fAutoFree.Insert( 0, Pointer( TMethod( Proc ).Data ) );
13500 fAutoFree.Insert( 0, Pointer( TMethod( Proc ).Code ) );
13501 {$ENDIF}
13502 end;
13503 {$ENDIF ASM_VERSION}
13519 { TList }
13521 {$IFDEF USE_CONSTRUCTORS}
13522 //[function NewList]
13523 function NewList: PList;
13524 begin
13525 New( Result, Create );
13526 //Result.fAddBy := 4;
13527 end;
13528 //[END NewList]
13530 //[procedure TList.Init]
13531 procedure TList.Init;
13532 begin
13533 inherited;
13534 fAddBy := 4;
13535 end;
13536 {$ELSE not_USE_CONSTRUCTORS}
13537 //[function NewList]
13538 function NewList: PList;
13539 begin
13541 New( Result, Create );
13542 {+} {++}(* Result := PList.Create; *){--}
13543 //Result.fAddBy := 4;
13544 end;
13545 //[END NewList]
13546 {$ENDIF USE_CONSTRUCTORS}
13548 {$IFDEF ASM_VERSION}
13549 destructor TList.Destroy;
13551 PUSH EAX
13552 CALL TList.Clear
13553 POP EAX
13554 CALL TObj.Destroy
13555 end;
13556 {$ELSE ASM_VERSION} //Pascal
13557 destructor TList.Destroy;
13558 begin
13559 Clear;
13560 inherited;
13561 end;
13562 {$ENDIF ASM_VERSION}
13564 {$IFDEF ASM_VERSION}
13565 //[procedure TList.Release]
13566 procedure TList.Release;
13568 TEST EAX, EAX
13569 JZ @@e
13570 MOV ECX, [EAX].fCount
13571 JECXZ @@e
13572 MOV EDX, [EAX].fItems
13573 PUSH EAX
13574 @@1:
13575 MOV EAX, [EDX+ECX*4-4]
13576 TEST EAX, EAX
13577 JZ @@2
13578 PUSH EDX
13579 PUSH ECX
13580 CALL System.@FreeMem
13581 POP ECX
13582 POP EDX
13583 @@2: LOOP @@1
13584 POP EAX
13585 @@e: CALL TObj.Free
13586 end;
13587 {$ELSE ASM_VERSION} //Pascal
13588 procedure TList.Release;
13589 var I: Integer;
13590 begin
13591 if @ Self = nil then Exit;
13592 for I := 0 to fCount - 1 do
13593 if fItems[ I ] <> nil then
13594 FreeMem( fItems[ I ] );
13595 Free;
13596 end;
13597 {$ENDIF ASM_VERSION}
13599 //[procedure TList.ReleaseObjects]
13600 procedure TList.ReleaseObjects;
13601 var I: Integer;
13602 begin
13603 if @ Self = nil then Exit;
13604 for I := fCount-1 downto 0 do
13605 PObj( fItems[ I ] ).Free;
13606 Free;
13607 end;
13609 {$IFDEF ASM_VERSION}
13610 //[procedure TList.SetCapacity]
13611 procedure TList.SetCapacity( Value: Integer );
13613 CMP EDX, [EAX].fCount
13614 {$IFDEF USE_CMOV}
13615 CMOVL EDX, [EAX].fCount
13616 {$ELSE}
13617 JGE @@1
13618 MOV EDX, [EAX].fCount
13619 @@1: {$ENDIF}
13620 CMP EDX, [EAX].fCapacity
13621 JE @@exit
13623 MOV [EAX].fCapacity, EDX
13624 SAL EDX, 2
13625 LEA EAX, [EAX].fItems
13626 CALL System.@ReallocMem
13627 @@exit:
13628 end;
13629 {$ELSE ASM_VERSION} //Pascal
13630 //var NewItems: PPointerList;
13631 procedure TList.SetCapacity( Value: Integer );
13632 begin
13633 if Value < Count then
13634 Value := Count;
13635 if Value = fCapacity then Exit;
13636 ReallocMem( fItems, Value * Sizeof( Pointer ) );
13637 fCapacity := Value;
13638 end;
13639 {$ENDIF ASM_VERSION}
13641 {$IFDEF ASM_VERSION}
13642 //[procedure TList.Clear]
13643 procedure TList.Clear;
13645 PUSH [EAX].fItems
13646 XOR EDX, EDX
13647 MOV [EAX].fItems, EDX
13648 MOV [EAX].fCount, EDX
13649 MOV [EAX].fCapacity, EDX
13650 POP EAX
13651 CALL System.@FreeMem
13652 end;
13653 {$ELSE ASM_VERSION} //Pascal
13654 procedure TList.Clear;
13655 begin
13656 if fItems <> nil then
13657 FreeMem( fItems );
13658 fItems := nil;
13659 fCount := 0;
13660 fCapacity := 0;
13661 end;
13662 {$ENDIF ASM_VERSION}
13664 //[procedure TList.SetAddBy]
13665 procedure TList.SetAddBy(Value: Integer);
13666 begin
13667 if Value < 1 then Value := 1;
13668 fAddBy := Value;
13669 end;
13671 {$IFDEF ASM_VERSION}
13672 //[procedure TList.Add]
13673 procedure TList.Add( Value: Pointer );
13675 PUSH EDX
13676 LEA ECX, [EAX].fCount
13677 MOV EDX, [ECX]
13678 INC dword ptr [ECX]
13679 PUSH EDX
13680 CMP EDX, [EAX].fCapacity
13681 PUSH EAX
13682 JL @@ok
13684 MOV ECX, [EAX].fAddBy
13685 TEST ECX, ECX
13686 JNZ @@add
13687 MOV ECX, EDX
13688 SHR ECX, 2
13689 INC ECX
13690 @@add:
13691 ADD EDX, ECX
13692 CALL TList.SetCapacity
13693 @@ok:
13694 POP ECX // ECX = Self
13695 POP EAX // EAX = fCount -> Result (for TList.Insert)
13696 POP EDX // EDX = Value
13698 MOV ECX, [ECX].fItems
13699 MOV [ECX + EAX*4], EDX
13700 end;
13701 {$ELSE ASM_VERSION} //Pascal
13702 procedure TList.Add( Value: Pointer );
13703 begin
13704 //if fAddBy <= 0 then fAddBy := 4;
13705 if fCapacity <= Count then
13706 begin
13707 if fAddBy <= 0 then
13708 Capacity := Count + Min( 1000, Count div 4 + 1 )
13709 else
13710 Capacity := Count + fAddBy;
13711 end;
13712 fItems[ fCount ] := Value;
13713 Inc( fCount );
13714 end;
13715 {$ENDIF ASM_VERSION}
13717 //[procedure TList.Delete]
13718 procedure TList.Delete( Idx: Integer );
13719 begin
13720 {Assert( (Idx >= 0) and (Idx < fCount), 'TList.Delete: index out of bounds' );
13721 Move( fItems[ Idx + 1 ], fItems[ Idx ], Sizeof( Pointer ) * (Count - Idx - 1) );
13722 Dec( fCount );}
13723 DeleteRange( Idx, 1 );
13724 end;
13726 {$IFDEF ASM_VERSION}
13727 //[procedure TList.DeleteRange]
13728 procedure TList.DeleteRange(Idx, Len: Integer);
13729 asm //cmd //opd
13730 TEST ECX, ECX
13731 JLE @@exit
13732 CMP EDX, [EAX].fCount
13733 JGE @@exit
13734 PUSH EBX
13735 XCHG EBX, EAX
13736 LEA EAX, [EDX+ECX]
13737 CMP EAX, [EBX].fCount
13738 JBE @@1
13739 MOV ECX, [EBX].fCount
13740 SUB ECX, EDX
13741 @@1:
13742 MOV EAX, [EBX].fItems
13743 PUSH [EBX].fCount
13744 SUB [EBX].fCount, ECX
13745 MOV EBX, EDX
13746 LEA EDX, [EAX+EDX*4]
13747 LEA EAX, [EDX+ECX*4]
13748 ADD EBX, ECX
13749 POP ECX
13750 SUB ECX, EBX
13751 SHL ECX, 2
13752 CALL System.Move
13753 POP EBX
13754 @@exit:
13755 end;
13756 {$ELSE ASM_VERSION} //Pascal
13757 procedure TList.DeleteRange(Idx, Len: Integer);
13758 begin
13759 if Len <= 0 then Exit;
13760 if Idx >= Count then Exit;
13761 Assert( (Idx >= 0), 'TList.DeleteRange: index out of bounds' );
13762 if DWORD( Idx + Len ) > DWORD( Count ) then
13763 Len := Count - Idx;
13764 Move( fItems[ Idx + Len ], fItems[ Idx ], Sizeof( Pointer ) * (Count - Idx - Len) );
13765 Dec( fCount, Len );
13766 end;
13767 {$ENDIF ASM_VERSION}
13769 //[procedure TList.Remove]
13770 procedure TList.Remove(Value: Pointer);
13771 var I: Integer;
13772 begin
13773 I := IndexOf( Value );
13774 if I >= 0 then
13775 Delete( I );
13776 end;
13778 //[procedure TList.Put]
13779 procedure TList.Put( Idx: Integer; Value: Pointer );
13780 begin
13781 if Idx < 0 then Exit;
13782 if Idx >= Count then Exit;
13783 //Assert( (Idx >= 0) and (Idx < fCount), 'TList.Put: index out of bounds' );
13784 fItems[ Idx ] := Value;
13785 end;
13787 //[function TList.Get]
13788 function TList.Get( Idx: Integer ): Pointer;
13789 begin
13790 Result := nil;
13791 if Idx < 0 then Exit;
13792 if Idx >= fCount then Exit;
13793 //Assert( (Idx >= 0) and (Idx < fCount), 'TList.Get: index out of bounds' );
13794 Result := fItems[ Idx ];
13795 end;
13797 {$IFDEF ASM_VERSION}
13798 //[function TList.IndexOf]
13799 function TList.IndexOf( Value: Pointer ): Integer;
13801 PUSH EDI
13803 MOV EDI, [EAX].fItems
13804 MOV ECX, [EAX].fCount
13805 PUSH EDI
13806 DEC EAX // make "NZ" - EAX always <> 1
13807 MOV EAX, EDX
13808 REPNZ SCASD
13809 POP EDX
13810 {$IFDEF USE_CMOV}
13811 CMOVNZ EDI, EDX
13812 {$ELSE}
13813 JZ @@succ
13814 MOV EDI, EDX
13815 @@succ: {$ENDIF}
13817 MOV EAX, EDI
13819 SBB EAX, EDX
13820 SAR EAX, 2
13822 POP EDI
13823 end;
13824 {$ELSE ASM_VERSION} //Pascal
13825 function TList.IndexOf( Value: Pointer ): Integer;
13826 var I: Integer;
13827 begin
13828 Result := -1;
13829 for I := 0 to Count - 1 do
13830 begin
13831 if fItems[ I ] = Value then
13832 begin
13833 Result := I;
13834 break;
13835 end;
13836 end;
13837 end;
13838 {$ENDIF ASM_VERSION}
13840 {$IFDEF ASM_VERSION}
13841 //[procedure TList.Insert]
13842 procedure TList.Insert(Idx: Integer; Value: Pointer);
13844 PUSH ECX
13845 PUSH EAX
13846 PUSH [EAX].fCount
13847 PUSH EDX
13848 CALL TList.Add // don't matter what to add
13849 POP EDX // EDX = Idx, Eax = Count-1
13850 POP EAX
13851 SUB EAX, EDX
13853 SAL EAX, 2
13854 MOV ECX, EAX // ECX = (Count - Idx - 1) * 4
13855 POP EAX
13856 MOV EAX, [EAX].fItems
13857 LEA EAX, [EAX + EDX*4]
13858 JL @@1
13859 PUSH EAX
13860 LEA EDX, [EAX + 4]
13861 CALL System.Move
13863 POP EAX // EAX = @fItems[ Idx ]
13864 @@1:
13865 POP ECX // ECX = Value
13866 MOV [EAX], ECX
13867 end;
13868 {$ELSE ASM_VERSION} //Pascal
13869 procedure TList.Insert(Idx: Integer; Value: Pointer);
13870 begin
13871 Assert( (Idx >= 0) and (Idx <= Count), 'List index out of bounds' );
13872 Add( nil );
13873 if fCount > Idx then
13874 Move( FItems[ Idx ], FItems[ Idx + 1 ], (fCount - Idx - 1) * Sizeof( Pointer ) );
13875 FItems[ Idx ] := Value;
13876 end;
13877 {$ENDIF ASM_VERSION}
13879 {$IFDEF ASM_VERSION}
13880 //[procedure TList.MoveItem]
13881 procedure TList.MoveItem(OldIdx, NewIdx: Integer);
13883 CMP EDX, ECX
13884 JE @@exit
13886 CMP ECX, [EAX].fCount
13887 JGE @@exit
13889 PUSH EDI
13891 MOV EDI, [EAX].fItems
13892 PUSH dword ptr [EDI + EDX*4]
13893 PUSH ECX
13894 PUSH EAX
13895 CALL TList.Delete
13896 POP EAX
13897 POP EDX
13898 POP ECX
13900 POP EDI
13901 CALL TList.Insert
13902 @@exit:
13903 end;
13904 {$ELSE ASM_VERSION} //Pascal
13905 procedure TList.MoveItem(OldIdx, NewIdx: Integer);
13906 var Item: Pointer;
13907 //I: Integer;
13908 begin
13909 if OldIdx = NewIdx then Exit;
13910 if NewIdx >= Count then Exit;
13911 Item := Items[ OldIdx ];
13912 Delete( OldIdx );
13913 Insert( NewIdx, Item );
13914 end;
13915 {$ENDIF ASM_VERSION}
13917 {$IFDEF ASM_VERSION}
13918 //[function TList.Last]
13919 function TList.Last: Pointer;
13920 asm //cmd //opd
13921 MOV ECX, [EAX].fCount
13922 JECXZ @@0
13923 MOV EAX, [EAX].fItems
13924 DEC ECX
13925 MOV ECX, [EAX + ECX*4]
13926 @@0: XCHG EAX, ECX
13927 end;
13928 {$ELSE ASM_VERSION} //Pascal
13929 function TList.Last: Pointer;
13930 begin
13931 if Count = 0 then
13932 Result := nil
13933 else
13934 Result := Items[ Count-1 ];
13935 end;
13936 {$ENDIF ASM_VERSION}
13938 {$IFDEF ASM_VERSION}
13939 //[procedure TList.Swap]
13940 procedure TList.Swap(Idx1, Idx2: Integer);
13942 MOV EAX, [EAX].fItems
13943 PUSH dword ptr [EAX + EDX*4]
13944 PUSH ECX
13945 MOV ECX, [EAX + ECX*4]
13946 MOV [EAX + EDX*4], ECX
13947 POP ECX
13948 POP EDX
13949 MOV [EAX + ECX*4], EDX
13950 end;
13951 {$ELSE ASM_VERSION} //Pascal
13952 procedure TList.Swap(Idx1, Idx2: Integer);
13953 var Tmp: Pointer;
13954 begin
13955 Tmp := FItems[ Idx1 ];
13956 FItems[ Idx1 ] := FItems[ Idx2 ];
13957 FItems[ Idx2 ] := Tmp;
13958 end;
13959 {$ENDIF ASM_VERSION}
13961 //[procedure TList.SetCount]
13962 procedure TList.SetCount(const Value: Integer);
13963 begin
13964 if Value >= Count then exit;
13965 fCount := Value;
13966 end;
13968 //[procedure TList.Assign]
13969 procedure TList.Assign(SrcList: PList);
13970 begin
13971 Clear;
13972 if SrcList.fCount > 0 then
13973 begin
13974 Capacity := SrcList.fCount;
13975 fCount := SrcList.fCount;
13976 Move( SrcList.FItems[ 0 ], FItems[ 0 ], Sizeof( Pointer ) * fCount );
13977 end;
13978 end;
13980 { TListEx }
13982 //[function NewListEx]
13983 function NewListEx: PListEx;
13984 begin
13986 new( Result, Create );
13987 {+}{++}(*Result := PListEx.Create;*){--}
13988 Result.fList := NewList;
13989 Result.fObjects := NewList;
13990 end;
13991 //[END NewListEx]
13993 //[procedure TListEx.Add]
13994 procedure TListEx.Add(Value: Pointer);
13995 begin
13996 AddObj( Value, nil );
13997 end;
13999 //[procedure TListEx.AddObj]
14000 procedure TListEx.AddObj(Value, Obj: Pointer);
14001 var C: Integer;
14002 begin
14003 C := Count;
14004 fList.Add( Value );
14005 fObjects.Insert( C, Obj );
14006 end;
14008 //[procedure TListEx.Clear]
14009 procedure TListEx.Clear;
14010 begin
14011 fList.Clear;
14012 fObjects.Clear;
14013 end;
14015 //[procedure TListEx.Delete]
14016 procedure TListEx.Delete(Idx: Integer);
14017 begin
14018 DeleteRange( Idx, 1 );
14019 end;
14021 //[procedure TListEx.DeleteRange]
14022 procedure TListEx.DeleteRange(Idx, Len: Integer);
14023 begin
14024 fList.DeleteRange( Idx, Len );
14025 fObjects.DeleteRange( Idx, Len );
14026 end;
14028 //[destructor TListEx.Destroy]
14029 destructor TListEx.Destroy;
14030 begin
14031 fList.Free;
14032 fObjects.Free;
14033 inherited;
14034 end;
14036 //[function TListEx.GetAddBy]
14037 function TListEx.GetAddBy: Integer;
14038 begin
14039 Result := fList.AddBy;
14040 end;
14042 //[function TListEx.GetCount]
14043 function TListEx.GetCount: Integer;
14044 begin
14045 Result := fList.Count;
14046 end;
14048 //[function TListEx.GetEx]
14049 function TListEx.GetEx(Idx: Integer): Pointer;
14050 begin
14051 Result := fList.Items[ Idx ];
14052 end;
14054 //[function TListEx.IndexOf]
14055 function TListEx.IndexOf(Value: Pointer): Integer;
14056 begin
14057 Result := fList.IndexOf( Value );
14058 end;
14060 //[function TListEx.IndexOfObj]
14061 function TListEx.IndexOfObj(Obj: Pointer): Integer;
14062 begin
14063 Result := fObjects.IndexOf( Obj );
14064 end;
14066 //[procedure TListEx.Insert]
14067 procedure TListEx.Insert(Idx: Integer; Value: Pointer);
14068 begin
14069 InsertObj( Idx, Value, nil );
14070 end;
14072 //[procedure TListEx.InsertObj]
14073 procedure TListEx.InsertObj(Idx: Integer; Value, Obj: Pointer);
14074 begin
14075 fList.Insert( Idx, Value );
14076 fObjects.Insert( Idx, Obj );
14077 end;
14079 //[function TListEx.Last]
14080 function TListEx.Last: Pointer;
14081 begin
14082 Result := fList.Last;
14083 end;
14085 //[function TListEx.LastObj]
14086 function TListEx.LastObj: Pointer;
14087 begin
14088 Result := fObjects.Last;
14089 end;
14091 //[procedure TListEx.MoveItem]
14092 procedure TListEx.MoveItem(OldIdx, NewIdx: Integer);
14093 begin
14094 fList.MoveItem( OldIdx, NewIdx );
14095 fObjects.MoveItem( OldIdx, NewIdx );
14096 end;
14098 //[procedure TListEx.PutEx]
14099 procedure TListEx.PutEx(Idx: Integer; const Value: Pointer);
14100 begin
14101 fList.Items[ Idx ] := Value;
14102 end;
14104 //[procedure TListEx.Set_AddBy]
14105 procedure TListEx.Set_AddBy(const Value: Integer);
14106 begin
14107 fList.AddBy := Value;
14108 fObjects.AddBy := Value;
14109 end;
14111 //[procedure TListEx.Swap]
14112 procedure TListEx.Swap(Idx1, Idx2: Integer);
14113 begin
14114 fList.Swap( Idx1, Idx2 );
14115 fObjects.Swap( Idx1, Idx2 );
14116 end;
14135 { -- Window procedure -- }
14137 {$IFDEF ASM_VERSION} //!!//!!
14138 //[FUNCTION CallCtlWndProc]
14139 function CallCtlWndProc( Ctl: PControl; var Msg: TMsg ): Integer;
14140 begin
14141 Result := Ctl.WndProc( Msg );
14142 end;
14143 //[END CallCtlWndProc]
14145 //[function WndFunc]
14146 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
14147 : Integer; stdcall;
14148 const size_TMsg = sizeof( TMsg );
14150 ADD ESP, -size_TMsg
14151 MOV EDX, ESP
14153 PUSH ESI
14154 PUSH EDI
14156 MOV EDI, EDX
14157 LEA ESI, [W]
14159 MOVSD
14160 MOVSD
14161 MOVSD
14162 MOVSD
14164 MOV EDI, EDX
14165 MOV EAX, [EDI]
14166 TEST EAX, EAX
14167 JZ @@self_is_nil
14169 MOV ECX, [CreatingWindow]
14170 JECXZ @@get_self_prop
14172 MOV [ECX].TControl.fHandle, EAX
14174 //set_self_prop:
14175 PUSH ECX
14176 PUSH ECX
14177 PUSH Offset[ID_SELF]
14178 PUSH EAX
14179 CALL SetProp
14181 XOR EAX, EAX
14182 MOV [CreatingWindow], EAX
14183 POP EAX // EAX = self_
14184 JMP @@self_got
14186 @@get_self_prop:
14187 PUSH Offset[ID_SELF]
14188 PUSH EAX
14189 CALL GetProp
14190 TEST EAX, EAX
14191 JNZ @@self_got
14193 @@self_is_nil:
14194 OR EAX, [ Applet ]
14195 JNZ @@self_got
14197 //try_defwndproc:
14198 POP EDI
14199 POP ESI
14200 MOV ESP, EBP
14201 POP EBP
14202 JMP DefWindowProc
14204 //@@id_self:
14205 // DB 'SELF_',0
14207 @@self_got:
14208 MOV EDX, EDI
14209 //CALL TControl.WndProc
14210 CALL CallCtlWndProc
14212 POP EDI
14213 POP ESI
14215 MOV ESP, EBP
14216 end;
14217 {$ELSE ASM_VERSION} //Pascal
14218 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
14219 : Integer; stdcall;
14220 var M: TMsg;
14221 self_: PControl;
14222 begin
14223 M.hwnd := W;
14224 M.message := Msg;
14225 M.wParam := wParam;
14226 M.lParam := lParam;
14228 {$IFDEF DEBUG_ENDSESSION}
14229 if EndSession_Initiated then
14230 begin
14231 LogFileOutput( GetStartDir + 'es_debug.txt',
14232 'HWND:' + Int2Str( W ) + ' MSG:$' + Int2Hex( Msg, 4 ) +
14233 ' WParam: ' + Int2Str( wParam ) + '($' + Int2Hex( wParam, 8 ) + ')' +
14234 ' LParam: ' + Int2Str( lParam ) + '($' + Int2Hex( lParam, 8 ) + ')' );
14235 end;
14236 {$ENDIF}
14238 self_ := nil;
14239 if W <> 0 then
14240 begin
14241 if CreatingWindow <> nil then
14242 begin
14243 {$IFDEF DEBUG_CREATEWINDOW}
14244 LogFileOutput( GetStartDir + 'Session.log',
14245 'WndFunc: Creating window = ' + Int2Hex( Integer( CreatingWindow ), 4 ) +
14246 ' hwnd=' + Int2Str( M.hwnd ) +
14247 ' message=' + Int2Hex( M.message, 4 ) +
14248 ' wParam=' + Int2Str( M.wParam ) + '=$' + Int2Hex( M.wParam, 4 ) +
14249 ' lParam=' + Int2Str( M.lParam ) + '=$' + Int2Hex( M.lParam, 4 )
14251 {$ENDIF DEBUG_CREATEWINDOW}
14252 self_ := CreatingWindow;
14253 CreatingWindow.fHandle := W;
14254 SetProp( W, ID_SELF, THandle( CreatingWindow ) );
14255 CreatingWindow := nil;
14257 else
14258 self_ := Pointer( GetProp( W, ID_SELF ) );
14259 end;
14261 if self_ <> nil then
14262 Result := self_.WndProc( M )
14263 else
14264 if Assigned( Applet ) then
14265 Result := Applet.WndProc( M )
14266 else
14267 Result := DefWindowProc( W, Msg, wParam, lParam );
14268 {$IFDEF DEBUG_ENDSESSION}
14269 if EndSession_Initiated then
14270 begin
14271 LogFileOutput( GetStartDir + 'es_debug.txt',
14272 'HWND:' + Int2Str( W ) + ' MSG:$' + Int2Hex( Msg, 4 ) +
14273 ' Result: ' + Int2Str( Result ) + '($' + Int2Hex( Result, 8 ) + ')' );
14274 end;
14275 {$ENDIF}
14276 end;
14277 //[END WndFunc]
14278 {$ENDIF ASM_VERSION}
14281 IdleHandlers: PList;
14282 ProcessIdle: procedure ( Sender: PObj ) = DummyObjProc;
14284 //[procedure ProcessIdleProc]
14285 procedure ProcessIdleProc( Sender: PObj );
14287 i: integer;
14288 m: TMethod;
14289 begin
14290 if AppletTerminated then exit; // YS +
14291 i := 0;
14292 with IdleHandlers{-}^{+} do
14293 while i < Count do begin
14294 m.Code:=Items[i];
14295 Inc(i);
14296 m.Data:=Items[i];
14297 Inc(i);
14298 TOnEvent(m)(Sender);
14299 end;
14300 end;
14302 //[function FindIdleHandler]
14303 function FindIdleHandler( const OnIdle: TOnEvent ): integer;
14305 i: integer;
14306 begin
14307 i := 0;
14308 if not AppletTerminated then //+ {Maxim Pushkar}
14309 with TMethod(OnIdle), IdleHandlers{-}^{+} do
14310 while i < Count do begin
14311 if (Items[i] = Code) and (Items[i + 1] = Data) then
14312 begin
14313 Result := i;
14314 exit;
14315 end;
14316 Inc(i, 2);
14317 end;
14318 Result := -1;
14319 end;
14320 //[END FindIdleHandler]
14322 //[procedure RegisterIdleHandler]
14323 procedure RegisterIdleHandler( const OnIdle: TOnEvent );
14324 begin
14325 if IdleHandlers = nil then begin
14326 IdleHandlers := NewList;
14327 if Applet <> nil then
14328 Applet.Add2AutoFree(IdleHandlers);
14329 end;
14330 with TMethod(OnIdle) do
14331 begin
14332 IdleHandlers.Add(Code);
14333 IdleHandlers.Add(Data);
14334 end;
14335 ProcessIdle := @ProcessIdleProc;
14336 end;
14338 //[procedure UnRegisterIdleHandler]
14339 procedure UnRegisterIdleHandler( const OnIdle: TOnEvent );
14341 i: integer;
14342 begin
14343 i := FindIdleHandler(OnIdle);
14344 if i <> -1 then
14345 with IdleHandlers{-}^{+} do
14346 begin
14347 Delete(i);
14348 Delete(i);
14349 end;
14350 end;
14352 //[procedure TerminateExecution]
14353 procedure TerminateExecution( var AppletWnd: PControl );
14354 var App: PControl;
14355 Appalreadyterminated: Boolean;
14356 begin
14357 Appalreadyterminated := AppletTerminated;
14358 AppletTerminated := TRUE;
14359 AppletRunning := FALSE;
14360 App := Applet;
14361 Applet := nil;
14362 if (App <> nil) {and (App.RefCount >= 0)} then
14363 begin
14364 App.RefInc;
14365 if not Appalreadyterminated then
14366 begin
14367 App.ProcessMessages;
14368 App.Perform( WM_CLOSE, 0, 0 );
14369 end;
14370 AppletWnd := nil;
14371 App.Free;
14372 App.RefDec;
14373 end;
14374 end;
14376 //[PROCEDURE CallTControlCreateWindow]
14377 {$IFDEF ASM_VERSION}
14378 procedure CallTControlCreateWindow( Ctl: PControl );
14379 begin
14380 Ctl.CreateWindow;
14381 end;
14382 //[END CallTControlCreateWindow]
14384 //[PROCEDURE Run]
14385 procedure Run( var AppletWnd: PControl );
14387 PUSH EBX
14388 XCHG EBX, EAX
14390 INC [AppletRunning]
14391 MOV EAX, [EBX]
14392 MOV [Applet], EAX
14393 CALL CallTControlCreateWindow
14394 JMP @@2
14395 @@1:
14396 CALL WaitMessage
14397 MOV EAX, [EBX]
14398 CALL TControl.ProcessMessages
14399 {$IFNDEF NOT_USE_OnIdle}
14400 MOV EAX, [EBX]
14401 CALL [ProcessIdle]
14402 {$ENDIF}
14403 @@2:
14404 CMP [AppletTerminated],0
14405 JZ @@1
14407 XCHG EAX, EBX
14409 POP EBX
14410 TEST EAX, EAX
14411 JNZ TerminateExecution
14412 end;
14413 {$ELSE ASM_VERSION} //Pascal
14414 procedure Run( var AppletWnd: PControl );
14415 begin
14416 AppletRunning := True;
14417 Applet := AppletWnd;
14418 AppletWnd.CreateWindow; //virtual!!!
14419 while not AppletTerminated do
14420 begin
14421 WaitMessage;
14422 AppletWnd.ProcessMessages;
14423 {$IFNDEF NOT_USE_OnIdle}
14424 ProcessIdle( AppletWnd );
14425 {$ENDIF}
14426 end;
14427 if AppletWnd <> nil then
14428 TerminateExecution( AppletWnd );
14429 end;
14430 //[END Run]
14431 {$ENDIF ASM_VERSION}
14433 //[procedure AppletMinimize]
14434 procedure AppletMinimize;
14435 begin
14436 if Applet = nil then Exit;
14437 Applet.Perform( WM_SYSCOMMAND, SC_MINIMIZE, 0 );
14438 end;
14440 //[procedure AppletHide]
14441 procedure AppletHide;
14442 begin
14443 if Applet = nil then Exit;
14444 AppletMinimize;
14445 Applet.Hide;
14446 end;
14448 //[procedure AppletRestore]
14449 procedure AppletRestore;
14450 begin
14451 if Applet = nil then Exit;
14452 Applet.Show;
14453 Applet.Perform( WM_SYSCOMMAND, SC_RESTORE, 0 );
14454 end;
14456 //[function ScreenWidth]
14457 function ScreenWidth: Integer;
14458 begin
14459 Result := GetSystemMetrics( SM_CXSCREEN );
14460 end;
14461 //[END ScreenWidth]
14463 //[function ScreenHeight]
14464 function ScreenHeight: Integer;
14465 begin
14466 Result := GetSystemMetrics( SM_CYSCREEN );
14467 end;
14468 //[END ScreenHeight]
14476 {$IFDEF USE_CONSTRUCTORS}
14477 {$DEFINE WNDPROCAPP_USED}
14478 {$DEFINE WNDPROCAPP_ASM_USED}
14479 {$ENDIF USE_CONSTRUCTORS}
14480 {$IFNDEF ASM_VERSION}
14481 {$DEFINE WNDPROCAPP_USED}
14482 {$ENDIF ASM_VERSION}
14484 {$DEFINE WNDPROCAPP_USED}
14488 {$IFNDEF WNDPROCAPP_USED}
14489 //[WndProcXXX FORWARD DECLARATIONS]
14490 {$IFNDEF ASM_VERSION}
14491 function WndProcApp( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14492 {$ENDIF}
14493 {$ENDIF}
14494 function WndProcForm( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14495 //function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14496 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14497 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14498 function WndProcGradientEx( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14499 function WndProcLabelEffect( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14500 //function WndProcParentResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14501 //function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14502 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14503 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14504 var fGlobalProcKeybd: function( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean =
14505 WndProcDummy;
14506 //[END OF WndProcXXX FORWARD DECLARATIONS]
14520 { -- Graphics support -- }
14522 //[function _NewGraphicTool]
14523 function _NewGraphicTool: PGraphicTool;
14524 begin
14526 New( Result, Create );
14528 {++}(*Result := PGraphicTool.Create;*){--}
14529 end;
14530 //[END _NewGraphicTool]
14532 //[FUNCTION SimpleGetCtlBrushHandle]
14533 {$IFDEF ASM_VERSION}
14534 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush;
14535 asm // //
14536 @@1: MOV ECX, [EAX].TControl.fParent
14537 JECXZ @@2
14538 MOV EDX, [EAX].TControl.fColor
14539 CMP EDX, [ECX].TControl.fColor
14540 XCHG EAX, ECX
14541 JE @@1
14542 XCHG EAX, ECX
14543 @@2: PUSH EBX
14544 XCHG EBX, EAX
14545 MOV ECX, [EBX].TControl.fTmpBrush
14546 JECXZ @@3
14547 MOV EAX, [EBX].TControl.fColor
14548 CALL Color2RGB
14549 CMP EAX, [EBX].TControl.fTmpBrushColorRGB
14550 JE @@3
14551 XOR EAX, EAX
14552 XCHG [EBX].TControl.fTmpBrush, EAX
14553 PUSH EAX
14554 CALL DeleteObject
14555 @@3: MOV EAX, [EBX].TControl.fTmpBrush
14556 TEST EAX, EAX
14557 JNE @@4
14558 MOV EAX, [EBX].TControl.fColor
14559 CALL Color2RGB
14560 MOV [EBX].TControl.fTmpBrushColorRGB, EAX
14561 PUSH EAX
14562 CALL CreateSolidBrush
14563 MOV [EBX].TControl.fTmpBrush, EAX
14564 @@4: POP EBX
14565 end;
14566 {$ELSE ASM_VERSION PAS_VERSION}
14567 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush;
14568 begin
14569 if (Sender.fParent <> nil) and (Sender.fColor = Sender.fParent.fColor) then
14570 Result := SimpleGetCtlBrushHandle( Sender.fParent )
14571 else
14572 begin
14573 if (Sender.fTmpBrush <> 0) and
14574 (Color2RGB( Sender.fColor ) <> Sender.fTmpBrushColorRGB) then
14575 begin
14576 DeleteObject( Sender.fTmpBrush );
14577 Sender.fTmpBrush := 0;
14578 end;
14579 if Sender.fTmpBrush = 0 then
14580 begin
14581 Sender.fTmpBrushColorRGB := Color2RGB( Sender.fColor );
14582 Sender.fTmpBrush := CreateSolidBrush( Sender.fTmpBrushColorRGB );
14583 end;
14584 Result := Sender.fTmpBrush;
14585 end;
14586 end;
14587 {$ENDIF ASM_VERSION}
14588 //[END SimpleGetCtlBrushHandle]
14590 //[function NormalGetCtlBrushHandle]
14591 function NormalGetCtlBrushHandle( Sender: PControl ): HBrush;
14592 begin
14593 if (Sender.fParent <> nil) then
14594 Sender.Brush.fParentGDITool := Sender.fParent.Brush;
14595 {if (Sender.Brush.fHandle <> 0) and
14596 (Color2RGB( Sender.fBrush.fData.Color ) <> Sender.fBrush.fColorRGB) then
14597 DeleteObject( Sender.Brush.ReleaseHandle );}
14598 Result := Sender.Brush.Handle;
14599 end;
14600 //[END NormalGetCtlBrushHandle]
14602 {++}(*
14603 //[API CreateFontIndirect]
14604 function CreateFontIndirect(const p1: TLogFont): HFONT; stdcall;
14605 external gdi32 name 'CreateFontIndirectA';
14606 *){--}
14607 //[MakeXXXHandle FORWARD DECLARATIONS]
14608 function MakeFontHandle( Self_: PGraphicTool ): THandle; forward;
14609 function MakeBrushHandle( Self_: PGraphicTool ): THandle; forward;
14610 function MakePenHandle( Self_: PGraphicTool ): THandle; forward;
14611 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle; forward;
14612 //[END OF MakeXXXHandle FORWARD DECLARATIONS]
14614 //[FUNCTION NewBrush]
14615 {$IFDEF ASM_VERSION}
14616 function NewBrush: PGraphicTool;
14618 MOV [Global_GetCtlBrushHandle], offset NormalGetCtlBrushHandle
14619 CALL _NewGraphicTool
14620 MOV [EAX].TGraphicTool.fNewProc, offset[NewBrush]
14621 MOV [EAX].TGraphicTool.fType, gttBrush
14622 MOV [EAX].TGraphicTool.fMakeHandleProc, offset[MakeBrushHandle]
14623 MOV [EAX].TGraphicTool.fData.Color, clBtnFace
14624 end;
14625 {$ELSE ASM_VERSION} //Pascal
14626 function NewBrush: PGraphicTool;
14627 begin
14628 Global_GetCtlBrushHandle := NormalGetCtlBrushHandle;
14629 Result := _NewGraphicTool;
14630 with Result {-}^{+} do
14631 begin
14632 fNewProc := @ NewBrush;
14633 fType := gttBrush;
14634 fMakeHandleProc := @ MakeBrushHandle;
14635 Result.fData.Color := clBtnFace;
14636 //Result.fData.Brush.Style := bsSolid;
14637 end;
14638 end;
14639 {$ENDIF ASM_VERSION}
14640 //[END NewBrush]
14642 const size_FontData = sizeof( Integer {fFontHeight} ) + sizeof( Integer {fFontWidth} ) +
14643 sizeof( TFontPitch ) + sizeof( TFontStyle ) +
14644 sizeof( Integer {fFontOrientation} ) +
14645 sizeof( Integer {fFontWeight} ) + sizeof( TFontCharset ) +
14646 sizeof( TFontQuality );
14648 //[FUNCTION NewFont]
14649 {$IFDEF ASM_VERSION}
14650 function NewFont: PGraphicTool;
14651 const FontDtSz = sizeof( TGDIFont );
14653 CALL _NewGraphicTool
14654 MOV [EAX].TGraphicTool.fNewProc, offset[NewFont]
14655 MOV [EAX].TGraphicTool.fType, gttFont
14656 MOV [EAX].TGraphicTool.fMakeHandleProc, offset[MakeFontHandle]
14657 MOV EDX, [DefFontColor]
14658 MOV [EAX].TGraphicTool.fData.Color, EDX
14660 PUSH EAX
14661 LEA EDX, [EAX].TGraphicTool.fData.Font
14662 MOV EAX, offset[ DefFont ]
14663 XOR ECX, ECX
14664 MOV CL, FontDtSz
14665 CALL System.Move
14666 POP EAX
14667 end;
14668 {$ELSE ASM_VERSION} //Pascal
14669 function NewFont: PGraphicTool;
14670 begin
14671 Result := _NewGraphicTool;
14672 with Result {-}^{+} do
14673 begin
14674 fNewProc := @ NewFont;
14675 fType := gttFont;
14676 fMakeHandleProc := @ MakeFontHandle;
14677 fData.Color := DefFontColor;
14678 Move( DefFont, fData.Font, Sizeof( TGDIFont ) );
14679 end;
14680 end;
14681 {$ENDIF ASM_VERSION}
14682 //[END NewFont]
14684 //[FUNCTION NewPen]
14685 {$IFDEF ASM_VERSION}
14686 function NewPen: PGraphicTool;
14688 CALL _NewGraphicTool
14689 MOV [EAX].TGraphicTool.fNewProc, offset[NewPen]
14690 MOV [EAX].TGraphicTool.fType, gttPen
14691 MOV [EAX].TGraphicTool.fMakeHandleProc, offset[MakePenHandle]
14692 MOV [EAX].TGraphicTool.fData.Pen.Mode, pmCopy
14693 end;
14694 {$ELSE ASM_VERSION} //Pascal
14695 function NewPen: PGraphicTool;
14696 begin
14697 Result := _NewGraphicTool;
14698 with Result{-}^{+} do
14699 begin
14700 fNewProc := @ NewPen;
14701 fType := gttPen;
14702 fMakeHandleProc := @ MakePenHandle;
14703 fData.Pen.Mode := pmCopy;
14704 end;
14705 end;
14706 {$ENDIF ASM_VERSION}
14707 //[END NewPen]
14710 //[function Color2RGB]
14711 function Color2RGB( Color: TColor ): TColor;
14712 begin
14713 if Color < 0 then
14714 Result := GetSysColor(Color and $FF) else
14715 Result := Color;
14716 end;
14717 //[END Color2RGB]
14719 //[function ColorsMix]
14720 function ColorsMix( Color1, Color2: TColor ): TColor;
14721 {$IFDEF F_P}
14722 begin
14723 Result := ((Color2RGB( Color1 ) and $FEFEFE) shr 1) +
14724 ((Color2RGB( Color2 ) and $FEFEFE) shr 1);
14725 end;
14726 {$ELSE DELPHI}
14728 PUSH EDX
14729 CALL Color2Rgb
14730 XCHG EAX, [ESP]
14731 CALL Color2Rgb
14732 POP EDX
14733 AND EAX, 0FEFEFEh
14734 AND EDX, 0FEFEFEh
14735 SHR EAX, 1
14736 SHR EDX, 1
14737 ADD EAX, EDX
14738 end;
14739 {$ENDIF F_P/DELPHI}
14740 //[END ColorsMix]
14742 //[FUNCTION Color2RGBQuad]
14743 {$IFDEF ASM_VERSION}
14744 function Color2RGBQuad( Color: TColor ): TRGBQuad;
14746 CALL Color2RGB
14747 // code by bart:
14748 xchg ah,al // xxRRGGBB
14749 ror eax,16 // BBGGxxRR
14750 xchg ah,al // BBGGRRxx
14751 shr eax,8 // 00BBGGRR
14752 end;
14753 {$ELSE ASM_VERSION} //Pascal
14754 function Color2RGBQuad( Color: TColor ): TRGBQuad;
14755 var C: Integer;
14756 begin
14757 C := Color2RGB( Color );
14758 C := ((C shr 16) and $FF)
14759 or ((C shl 16) and $FF0000)
14760 or (C and $FF00);
14761 Result := TRGBQuad( C );
14762 end;
14763 {$ENDIF ASM_VERSION}
14764 //[END Color2RGBQuad]
14766 //[FUNCTION Color2Color16]
14767 {$IFDEF ASM_VERSION}
14768 function Color2Color16( Color: TColor ): WORD;
14770 MOV EDX, EAX
14771 SHR EDX, 19
14772 AND EDX, $1F
14773 MOV ECX, EAX
14774 SHR ECX, 5
14775 AND ECX, $7E0;
14776 MOV AH, AL
14777 AND EAX, $F800
14778 OR EAX, EDX
14779 OR EAX, ECX
14780 end;
14781 {$ELSE ASM_VERSION}
14782 function Color2Color16( Color: TColor ): WORD;
14783 begin
14784 Color := Color2RGB( Color );
14785 Result := (Color shr 19) and $1F or
14786 (Color shr 5) and $7E0 or
14787 (Color shl 8) and $F800;
14788 end;
14789 {$ENDIF ASM_VERSION}
14790 //[END Color2Color16]
14792 { TGraphicTool }
14794 {$IFDEF ASM_VERSION}
14795 //[function TGraphicTool.Assign]
14796 function TGraphicTool.Assign(Value: PGraphicTool): PGraphicTool;
14797 const SzfData = sizeof( fData );
14798 asm // //
14799 TEST EDX, EDX
14800 JNZ @@1
14801 TEST EAX, EAX
14802 JZ @@0
14803 CALL TObj.DoDestroy
14804 XOR EAX, EAX
14805 @@0: RET
14806 @@1: PUSH EDI
14807 MOV EDI, EDX
14808 TEST EAX, EAX
14809 JNZ @@2
14810 XCHG EAX, EDX
14811 CALL dword ptr[EAX].TGraphicTool.fNewProc
14812 @@2: CMP EAX, EDI
14813 JE @@exit
14814 PUSH EBX
14815 XCHG EBX, EAX
14817 MOV ECX, [EBX].TGraphicTool.fHandle
14818 JECXZ @@3
14819 CMP ECX, [EDI].TGraphicTool.fHandle
14820 JE @@exit1
14821 @@3:
14822 MOV EAX, EBX
14823 CALL TGraphicTool.Changed
14824 LEA EDX, [EBX].TGraphicTool.fData
14825 LEA EAX, [EDI].TGraphicTool.fData
14826 MOV ECX, SzfData
14827 CALL System.Move
14828 MOV EAX, EBX
14829 CALL TGraphicTool.Changed
14831 @@exit1:
14832 XCHG EAX, EBX
14833 POP EBX
14834 @@exit: POP EDI
14835 end;
14836 {$ELSE ASM_VERSION}
14837 function TGraphicTool.Assign(Value: PGraphicTool): PGraphicTool;
14838 var _Self: PGraphicTool;
14839 begin
14840 Result := nil;
14841 if Value = nil then
14842 begin
14843 if @Self <> nil then
14844 DoDestroy;
14845 Exit;
14846 end;
14847 _Self := @Self;
14848 if _Self = nil then
14849 _Self := Value.fNewProc();
14850 Result := _Self;
14851 if _Self = Value then Exit; // to avoid infinite loop when assigning to itself
14852 if _Self.fHandle <> 0 then
14853 if Value.fHandle = _Self.fHandle then Exit;
14854 _Self.Changed; // to destroy handle if allocated and release it from the canvas (if any uses it)
14855 Assert( Value.fType = _Self.fType, 'Attempt to assign to different GDI tool type' );
14856 Move( Value.fData, _Self.fData, Sizeof( fData ) );
14857 _Self.Changed; // to inform owner control, that its tool (font, brush) changed
14858 end;
14859 {$ENDIF ASM_VERSION}
14861 //[procedure TGraphicTool.AssignHandle]
14862 procedure TGraphicTool.AssignHandle(NewHandle: Integer);
14863 begin
14864 //------------ by Yury Sidorov --------
14865 //Changed;
14866 //-------------------------------------//
14867 if fHandle <> 0 then //
14868 DeleteObject( fHandle ); //
14869 //-------------------------------------//
14870 fHandle := NewHandle;
14871 GetObject( fHandle, Sizeof( TGDIFont ), @ fData.Font );
14872 Changed;
14873 end;
14875 {$IFDEF ASM_VERSION}
14876 //[procedure TGraphicTool.Changed]
14877 procedure TGraphicTool.Changed;
14879 XOR ECX, ECX
14880 XCHG ECX, [EAX].fHandle
14881 JECXZ @@exit
14882 PUSH EAX
14883 PUSH ECX
14885 CALL @@CallOnChange
14887 CALL DeleteObject
14888 POP EAX
14889 @@exit:
14891 @@CallOnChange:
14892 MOV ECX, [EAX].fOnChange.TMethod.Code
14893 JECXZ @@no_onChange
14894 PUSH EAX
14895 XCHG EDX, EAX
14896 MOV EAX, [EDX].fOnChange.TMethod.Data
14897 CALL ECX
14898 POP EAX
14899 @@no_onChange:
14900 end;
14901 {$ELSE ASM_VERSION} //Pascal
14902 procedure TGraphicTool.Changed;
14903 var H: THandle;
14904 begin
14905 if fHandle <> 0 then
14906 begin
14907 H := fHandle;
14908 fHandle := 0;
14909 ////////////////////////////////
14910 if Assigned( fOnChange ) then
14911 fOnChange( @Self );
14912 ////////////////////////////////
14913 DeleteObject( H );
14914 {$IFDEF DEBUG_GDIOBJECTS}
14915 case fType of
14916 gttBrush: Dec( BrushCount );
14917 gttFont: Dec( FontCount );
14918 gttPen: Dec( PenCount );
14919 end;
14920 {$ENDIF}
14921 end;
14922 //////////////////////////////////
14923 if Assigned( fOnChange ) then
14924 fOnChange( @Self );
14925 //////////////////////////////////
14926 end;
14927 {$ENDIF ASM_VERSION}
14929 {$IFDEF ASM_VERSION}
14930 //[destructor TGraphicTool.Destroy]
14931 destructor TGraphicTool.Destroy;
14933 PUSH EAX
14934 CMP [EAX].fType, gttFont
14935 JE @@0
14936 MOV ECX, [EAX].fData.Brush.Bitmap
14937 JECXZ @@0
14938 PUSH ECX
14939 CALL DeleteObject
14940 POP EAX
14941 PUSH EAX
14942 @@0:
14943 MOV ECX, [EAX].fHandle
14944 JECXZ @@1
14945 PUSH ECX
14946 CALL DeleteObject
14947 @@1:
14948 POP EAX
14949 CALL TObj.Destroy
14950 end;
14951 {$ELSE ASM_VERSION} //Pascal
14952 destructor TGraphicTool.Destroy;
14953 begin
14954 case fType of
14955 gttBrush: if fData.Brush.Bitmap <> 0 then
14956 DeleteObject( fData.Brush.Bitmap );
14957 gttPen: if fData.Pen.BrushBitmap <> 0 then
14958 DeleteObject( fData.Pen.BrushBitmap )
14959 end;
14960 if fHandle <> 0 then
14961 begin
14962 DeleteObject( fHandle );
14963 {$IFDEF DEBUG_GDIOBJECTS}
14964 case fType of
14965 gttPen: Dec( PenCount );
14966 gttBrush: Dec( BrushCount );
14967 gttFont: Dec( FontCount );
14968 end;
14969 {$ENDIF}
14970 //fHandle := 0; Why to do this? It is now destroying!
14971 end;
14972 inherited;
14973 end;
14974 {$ENDIF ASM_VERSION}
14976 //[function TGraphicTool.HandleAllocated]
14977 function TGraphicTool.HandleAllocated: Boolean;
14978 begin
14979 Result := fHandle <> 0;
14980 end;
14982 {$IFDEF ASM_VERSION}
14983 //[function TGraphicTool.ReleaseHandle]
14984 function TGraphicTool.ReleaseHandle: Integer;
14985 asm // //
14986 PUSH EAX
14987 CALL Changed
14988 POP EDX
14989 XOR EAX, EAX
14990 XCHG [EDX].fHandle, EAX
14991 end;
14992 {$ELSE ASM_VERSION PAS_VERSION}
14993 function TGraphicTool.ReleaseHandle: Integer;
14994 begin
14995 Changed;
14996 Result := fHandle;
14997 fHandle := 0;
14998 end;
14999 {$ENDIF ASM_VERSION}
15001 {$IFDEF ASM_VERSION}
15002 //[procedure TGraphicTool.SetInt]
15003 procedure TGraphicTool.SetInt( const Index: Integer; Value: Integer );
15005 LEA EDX, [EDX+EAX].fData
15006 CMP [EDX], ECX
15007 JE @@exit
15008 MOV [EDX], ECX
15009 CALL Changed
15010 @@exit:
15011 end;
15012 {$ELSE ASM_VERSION} //Pascal
15013 procedure TGraphicTool.SetInt( const Index: Integer; Value: Integer );
15014 var Where: PInteger;
15015 begin
15016 Where := Pointer( Integer( @ fData ) + Index );
15017 if Where^ = Value then Exit;
15018 Where^ := Value;
15019 Changed;
15020 end;
15021 {$ENDIF ASM_VERSION}
15023 {$IFDEF F_P}
15024 //[function TGraphicTool.GetInt]
15025 function TGraphicTool.GetInt(const Index: Integer): Integer;
15026 var Where: PInteger;
15027 begin
15028 Where := Pointer( Integer( @ fData ) + Index );
15029 Result := Where^;
15030 end;
15031 {$ENDIF}
15033 //[procedure TGraphicTool.SetColor]
15034 procedure TGraphicTool.SetColor( Value: TColor );
15035 begin
15036 SetInt( go_Color, Value );
15037 fColorRGB := Color2RGB( Value );
15038 end;
15040 {$IFDEF ASM_VERSION}
15041 //[function TGraphicTool.IsFontTrueType]
15042 function TGraphicTool.IsFontTrueType: Boolean;
15044 CALL GetHandle
15045 TEST EAX, EAX
15046 JZ @@exit
15048 PUSH EBX
15050 PUSH EAX // fHandle
15052 PUSH 0
15053 CALL GetDC
15055 PUSH EAX // DC
15056 MOV EBX, EAX
15057 CALL SelectObject
15058 PUSH EAX
15060 XOR ECX, ECX
15061 PUSH ECX
15062 PUSH ECX
15063 PUSH ECX
15064 PUSH ECX
15065 PUSH EBX
15066 CALL GetFontData
15068 XCHG EAX, [ESP]
15070 PUSH EAX
15071 PUSH EBX
15072 CALL SelectObject
15074 PUSH EBX
15075 PUSH 0
15076 CALL ReleaseDC
15078 POP EAX
15079 INC EAX
15080 SETNZ AL
15082 POP EBX
15083 @@exit:
15084 end;
15085 {$ELSE ASM_VERSION} //Pascal
15086 function TGraphicTool.IsFontTrueType: Boolean;
15087 var OldFont: HFont;
15088 DC: HDC;
15089 begin
15090 Result := False;
15091 if GetHandle = 0 then Exit;
15092 DC := GetDC( 0 );
15093 OldFont := SelectObject( DC, fHandle );
15094 if GetFontData( DC, 0, 0, nil, 0 ) <> GDI_ERROR then
15095 Result := True;
15096 SelectObject( DC, OldFont );
15097 ReleaseDC( 0, DC );
15098 end;
15099 {$ENDIF ASM_VERSION}
15101 //[procedure TGraphicTool.SetBrushBitmap]
15102 procedure TGraphicTool.SetBrushBitmap(const Value: HBitmap);
15103 begin
15104 if fData.Brush.Bitmap = Value then Exit;
15105 if fData.Brush.Bitmap <> 0 then
15106 begin
15107 ///////////
15108 Changed; // !!!
15109 ///////////
15110 DeleteObject( fData.Brush.Bitmap );
15111 end;
15112 fData.Brush.Bitmap := Value;
15113 Changed;
15114 end;
15116 //[procedure TGraphicTool.SetBrushStyle]
15117 procedure TGraphicTool.SetBrushStyle(const Value: TBrushStyle);
15118 begin
15119 if fData.Brush.Style = Value then Exit;
15120 fData.Brush.Style := Value;
15121 Changed;
15122 end;
15124 //[procedure TGraphicTool.SetFontCharset]
15125 procedure TGraphicTool.SetFontCharset(const Value: TFontCharset);
15126 begin
15127 if fData.Font.Charset = Value then Exit;
15128 fData.Font.Charset := Value;
15129 Changed;
15130 end;
15132 //[procedure TGraphicTool.SetFontQuality]
15133 procedure TGraphicTool.SetFontQuality(const Value: TFontQuality);
15134 begin
15135 if fData.Font.Quality = Value then Exit;
15136 fData.Font.Quality := Value;
15137 Changed;
15138 end;
15140 //[function TGraphicTool.GetFontName]
15141 function TGraphicTool.GetFontName: String;
15142 begin
15143 Result := fData.Font.Name;
15144 end;
15146 //[procedure TGraphicTool.SetFontName]
15147 procedure TGraphicTool.SetFontName(const Value: String);
15148 begin
15149 if fData.Font.Name = Value then Exit;
15150 FillChar( fData.Font.Name[ 0 ], LF_FACESIZE, 0 );
15151 StrLCopy( fData.Font.Name, PChar( Value ), LF_FACESIZE );
15152 Changed;
15153 end;
15155 {$IFDEF ASM_VERSION}
15156 //[procedure TextAreaEx]
15157 procedure TextAreaEx( Sender: PCanvas; var Sz : TSize; var Pt : TPoint );
15159 PUSH EBX
15160 PUSH ESI
15161 PUSH EDI
15162 PUSH EBP
15163 MOV EBP, ESP
15164 PUSH EDX // [EBP-4] = @Sz
15165 PUSH ECX // [EBP-8] = @Pt
15166 MOV EBX, EAX
15167 CALL TCanvas.GetFont
15168 MOV ESI, [EAX].TGraphicTool.fData.Font.Orientation
15169 CALL TGraphicTool.IsFontTrueType
15170 TEST AL, AL
15171 JZ @@exit
15173 MOV EDI, [EBP-8]
15174 XOR EAX, EAX
15175 STOSD
15176 STOSD
15177 TEST ESI, ESI
15178 JZ @@exit
15180 PUSH EAX // Pts[1].x
15181 PUSH EAX // Pts[1].y
15183 PUSH ESI
15184 FILD dword ptr [ESP]
15185 POP EDX
15187 FILD word ptr [@@1800]
15188 FDIV
15189 //FWAIT
15190 FLDPI
15191 FMUL
15192 //FWAIT
15194 FLD ST(0)
15195 FSINCOS
15196 FWAIT
15198 MOV ESI, [EBP-4]
15199 LODSD // Sz.cx
15200 PUSH EAX
15201 FILD dword ptr [ESP]
15202 FMUL
15203 FISTP dword ptr [ESP] // Pts[2].x
15204 FWAIT
15205 NEG EAX
15206 PUSH EAX
15207 FILD dword ptr [ESP]
15208 FMUL
15209 FISTP dword ptr [ESP] // Pts[2].y
15210 FWAIT
15212 FLDPI
15213 FLD1
15214 FLD1
15215 FADD
15216 FDIV
15217 FADD
15218 FSINCOS
15219 FWAIT
15221 LODSD
15222 NEG EAX
15223 PUSH EAX
15224 FILD dword ptr [ESP]
15225 FMUL
15226 FISTP dword ptr [ESP] // Pts[4].x
15227 FWAIT
15228 NEG EAX
15229 PUSH EAX
15230 FILD dword ptr [ESP]
15231 FMUL
15232 FISTP dword ptr [ESP] // Pts[4].y
15233 FWAIT
15235 POP ECX
15236 POP EDX
15237 PUSH EDX
15238 PUSH ECX
15239 ADD EDX, [ESP+12]
15240 ADD ECX, [ESP+8]
15241 PUSH EDX
15242 PUSH ECX
15244 MOV ESI, ESP
15245 XOR EDX, EDX // MinX
15246 XOR EDI, EDI // MinY
15247 XOR ECX, ECX
15248 MOV CL, 3
15250 @@loo1: LODSD
15251 CMP EAX, EDI
15252 JGE @@1
15253 XCHG EDI, EAX
15254 @@1: LODSD
15255 CMP EAX, EDX
15256 JGE @@2
15257 XCHG EDX, EAX
15258 @@2: LOOP @@loo1
15260 MOV ESI, [EBP-4]
15261 MOV [ESI], ECX
15262 MOV [ESI+4], ECX
15263 MOV CL, 4
15264 @@loo2:
15265 POP EBX
15266 SUB EBX, EDI
15267 CMP EBX, [ESI+4]
15268 JLE @@3
15269 MOV [ESI+4], EBX
15270 @@3:
15271 POP EAX
15272 SUB EAX, EDX
15273 CMP EAX, [ESI]
15274 JLE @@4
15275 MOV [ESI], EAX
15276 @@4:
15277 LOOP @@loo2
15279 MOV EDI, [EBP-8]
15280 STOSD
15281 XCHG EAX, EBX
15282 STOSD
15283 JMP @@exit
15285 @@1800: DW 1800
15287 @@exit:
15288 MOV ESP, EBP
15289 POP EBP
15290 POP EDI
15291 POP ESI
15292 POP EBX
15293 end;
15294 {$ELSE ASM_VERSION} //Pascal
15295 procedure TextAreaEx( Sender: PCanvas; var Sz : TSize; var Pt : TPoint );
15296 var Orient : Integer;
15297 Pts : array[ 1..4 ] of TPoint;
15298 MinX, MinY, I : Integer;
15299 A : Double;
15300 begin
15301 if not Sender.Font.IsFontTrueType then Exit;
15302 Orient := Sender.Font.FontOrientation;
15303 Pt.x := 0; Pt.y := 0;
15304 if Orient = 0 then
15305 Exit;
15306 A := Orient / 1800.0 * PI;
15307 Pts[ 1 ] := Pt;
15308 Pts[ 2 ].x := Round( Sz.cx * cos( A ) );
15309 Pts[ 2 ].y := - Round( Sz.cx * sin( A ) );
15310 Pts[ 4 ].x := - Round( Sz.cy * cos( A + PI / 2 ) );
15311 Pts[ 4 ].y := Round( Sz.cy * sin( A + PI / 2 ) );
15312 Pts[ 3 ].x := Pts[ 2 ].x + Pts[ 4 ].x;
15313 Pts[ 3 ].y := Pts[ 2 ].y + Pts[ 4 ].y;
15314 MinX := 0; MinY := 0;
15315 for I := 2 to 4 do
15316 begin
15317 if Pts[ I ].x < MinX then
15318 MinX := Pts[ I ].x;
15319 if Pts[ I ].y < MinY then
15320 MinY := Pts[ I ].y;
15321 end;
15322 Sz.cx := 0;
15323 Sz.cy := 0;
15324 for I := 1 to 4 do
15325 begin
15326 Pts[ I ].x := Pts[ I ].x - MinX;
15327 Pts[ I ].y := Pts[ I ].y - MinY;
15328 if Pts[ I ].x > Sz.cx then
15329 Sz.cx := Pts[ I ].x;
15330 if Pts[ I ].y > Sz.cy then
15331 Sz.cy := Pts[ I ].y;
15332 end;
15333 Pt := Pts[ 1 ];
15334 end;
15335 {$ENDIF ASM_VERSION}
15337 {$IFDEF ASM_VERSION}
15338 //[procedure TGraphicTool.SetFontOrientation]
15339 procedure TGraphicTool.SetFontOrientation(Value: Integer);
15341 PUSH EAX
15342 @@1: MOV EAX, EDX
15343 MOV ECX, 3600
15345 IDIV ECX // EDX = Value mod 3600
15346 POP EAX
15348 MOV byte ptr [GlobalGraphics_UseFontOrient], 1
15349 MOV [GlobalCanvas_OnTextArea], offset[TextAreaEx]
15351 MOV [EAX].fData.Font.Escapement, EDX
15352 MOV ECX, EDX
15353 MOV DX, go_FontOrientation
15354 CALL SetInt
15355 end;
15356 {$ELSE ASM_VERSION} //Pascal
15357 procedure TGraphicTool.SetFontOrientation(Value: Integer);
15358 begin
15359 GlobalGraphics_UseFontOrient := True;
15360 GlobalCanvas_OnTextArea := TextAreaEx;
15361 Value := Value mod 3600; // -3599..+3599
15362 SetInt( go_FontOrientation, Value );
15363 SetInt( go_FontEscapement, Value );
15364 end;
15365 {$ENDIF ASM_VERSION}
15367 //[procedure TGraphicTool.SetFontPitch]
15368 procedure TGraphicTool.SetFontPitch(const Value: TFontPitch);
15369 begin
15370 if fData.Font.Pitch = Value then Exit;
15371 fData.Font.Pitch := Value;
15372 Changed;
15373 end;
15375 {$IFDEF ASM_VERSION}
15376 //[function TGraphicTool.GetFontStyle]
15377 function TGraphicTool.GetFontStyle: TFontStyle;
15379 MOV EDX, dword ptr [EAX].fData.Font.Italic
15380 AND EDX, $010101
15381 MOV EAX, [EAX].fData.Font.Weight
15382 CMP EAX, 700
15383 SETGE AL //AL:1 = fsBold
15384 ADD EDX, EDX
15385 OR EAX, EDX //AL:2 = fsItalic
15386 SHR EDX, 7
15387 OR EAX, EDX //AL:3 = fsUnderline
15388 SHR EDX, 7
15389 OR EAX, EDX //AL:4 = fsStrikeOut
15390 end;
15391 {$ELSE ASM_VERSION} //Pascal
15392 function TGraphicTool.GetFontStyle: TFontStyle;
15393 type PFontStyle = ^TFontStyle;
15394 begin
15395 Result := [ ];
15396 if fData.Font.Weight >= 700 then Result := [ fsBold ];
15397 if fData.Font.Italic then Result := Result + [ fsItalic ];
15398 if fData.Font.Underline then Result := Result + [ fsUnderline ];
15399 if fData.Font.StrikeOut then Result := Result + [ fsStrikeOut ];
15400 end;
15401 {$ENDIF ASM_VERSION}
15403 {$IFDEF ASM_VERSION}
15404 //[procedure TGraphicTool.SetFontStyle]
15405 procedure TGraphicTool.SetFontStyle(const Value: TFontStyle);
15407 PUSH EDI
15408 MOV EDI, EAX
15409 PUSH EDX
15410 CALL GetFontStyle
15411 POP EDX
15412 CMP AL, DL
15413 JE @@exit
15414 PUSH EDI
15416 LEA EDI, [EDI].fData.Font.Weight
15417 MOV ECX, [EDI]
15418 SHR EDX, 1
15419 JNC @@1
15420 CMP ECX, 700
15421 JGE @@2
15422 MOV ECX, 700
15423 JMP @@2
15424 @@1: CMP ECX, 700
15425 JL @@2
15426 XOR ECX, ECX
15427 @@2: XCHG EAX, ECX
15428 STOSD // change Weight
15429 SHR EDX, 1
15430 SETC AL
15431 STOSB // change Italic
15432 SHR EDX, 1
15433 SETC AL
15434 STOSB // change Underline
15435 SHR EDX, 1
15436 SETC AL
15437 STOSB // change StrikeOut
15438 POP EAX
15439 CALL Changed
15440 @@exit: POP EDI
15441 end;
15442 {$ELSE ASM_VERSION} //Pascal
15443 procedure TGraphicTool.SetFontStyle(const Value: TFontStyle);
15444 begin
15445 if FontStyle = Value then Exit;
15446 if fsBold in Value then
15447 begin
15448 if fData.Font.Weight < 700 then
15449 fData.Font.Weight := 700;
15451 else
15452 begin
15453 if fData.Font.Weight >= 700 then
15454 fData.Font.Weight := 0;
15455 end;
15456 fData.Font.Italic := fsItalic in Value;
15457 fData.Font.Underline := fsUnderline in Value;
15458 fData.Font.StrikeOut := fsStrikeOut in Value;
15459 Changed;
15460 end;
15461 {$ENDIF ASM_VERSION}
15463 //[procedure TGraphicTool.SetPenMode]
15464 procedure TGraphicTool.SetPenMode(const Value: TPenMode);
15465 begin
15466 if fData.Pen.Mode = Value then Exit;
15467 fData.Pen.Mode := Value;
15468 Changed;
15469 end;
15471 //[procedure TGraphicTool.SetPenStyle]
15472 procedure TGraphicTool.SetPenStyle(const Value: TPenStyle);
15473 begin
15474 if fData.Pen.Style = Value then Exit;
15475 fData.Pen.Style := Value;
15476 Changed;
15477 end;
15479 {$IFDEF ASM_VERSION}
15480 //[function TGraphicTool.GetHandle]
15481 function TGraphicTool.GetHandle: THandle;
15482 const DataSz = sizeof( TGDIToolData );
15484 PUSH EBX
15485 @@start:
15486 XCHG EBX, EAX
15487 MOV ECX, [EBX].fHandle
15488 JECXZ @@1
15490 MOV EAX, [EBX].fData.Color
15491 CALL Color2RGB
15492 CMP EAX, [EBX].fColorRGB
15493 JE @@1
15495 MOV EAX, EBX
15496 CALL ReleaseHandle
15497 PUSH EAX
15498 CALL DeleteObject
15500 @@1: MOV ECX, [EBX].fHandle
15501 INC ECX
15502 LOOP @@exit
15504 MOV ECX, [EBX].fParentGDITool
15505 JECXZ @@2
15506 LEA EDX, [ECX].fData
15507 LEA EAX, [EBX].fData
15508 MOV ECX, DataSz
15509 CALL CompareMem
15510 TEST AL, AL
15511 MOV EAX, [EBX].fParentGDITool
15512 JNZ @@start
15514 @@2: MOV ECX, [EBX].fHandle
15515 INC ECX
15516 LOOP @@exit
15518 MOV EAX, [EBX].fData.Color
15519 CALL Color2RGB
15520 MOV [EBX].fColorRGB, EAX
15521 XCHG EAX, EBX
15522 CALL dword ptr [EAX].fMakeHandleProc
15523 XCHG ECX, EAX
15525 @@exit: XCHG EAX, ECX
15526 POP EBX
15527 end;
15528 {$ELSE ASM_VERSION} //Pascal
15529 function TGraphicTool.GetHandle: THandle;
15530 begin
15531 Result := fHandle;
15532 if Result <> 0 then
15533 begin
15534 if Color2RGB( fData.Color ) <> fColorRGB then
15535 begin
15536 DeleteObject( ReleaseHandle );
15537 Result := 0;
15538 end;
15539 end;
15540 if Result = 0 then
15541 begin
15542 if Assigned( fParentGDITool ) then
15543 begin
15544 if CompareMem( @ fData, @ fParentGDITool.fData, Sizeof( fData ) ) then
15545 begin
15546 Result := fParentGDITool.Handle;
15547 Exit;
15548 end;
15549 end;
15551 if fHandle = 0 then
15552 begin
15553 fColorRGB := Color2RGB( fData.Color );
15554 fMakeHandleProc( @Self );
15555 end;
15556 Result := fHandle;
15557 end;
15558 end;
15559 {$ENDIF ASM_VERSION}
15561 //[FUNCTION MakeBrushHandle]
15562 {$IFDEF ASM_VERSION}
15563 function MakeBrushHandle( Self_: PGraphicTool ): THandle;
15565 PUSH EBX
15566 XCHG EBX, EAX
15567 MOV EAX, [EBX].TGraphicTool.fHandle
15568 TEST EAX, EAX
15569 JNZ @@exit
15571 MOV EAX, [EBX].TGraphicTool.fData.Color
15572 CALL Color2RGB // EAX = ColorRef
15574 XOR EDX, EDX
15576 MOV ECX, [EBX].TGraphicTool.fData.Brush.Bitmap
15577 PUSH ECX
15578 JECXZ @@1
15580 MOV DL, BS_PATTERN
15581 JMP @@2
15583 @@1:
15584 MOV CL, [EBX].TGraphicTool.fData.Brush.Style
15585 MOV DL, CL
15586 SUB CL, 2
15587 JL @@2
15589 XCHG ECX, [ESP]
15591 @@2: PUSH EAX
15592 PUSH EDX
15594 PUSH ESP
15595 CALL CreateBrushIndirect
15596 MOV [EBX].TGraphicTool.fHandle, EAX
15598 ADD ESP, 12
15600 @@exit:
15601 POP EBX
15602 end;
15603 {$ELSE ASM_VERSION} //Pascal
15604 function MakeBrushHandle( Self_: PGraphicTool ): THandle;
15606 LogBrush: TLogBrush;
15607 begin
15608 if Self_.fHandle = 0 then
15609 begin
15610 LogBrush.lbColor := Color2RGB( Self_.fData.Color );
15611 if Self_.fData.Brush.Bitmap <> 0 then
15612 begin
15613 LogBrush.lbStyle := BS_PATTERN;
15614 LogBrush.lbHatch := Self_.fData.Brush.Bitmap;
15616 else
15617 begin
15618 LogBrush.lbHatch := 0;
15619 case Self_.fData.Brush.Style of
15620 bsSolid: LogBrush.lbStyle := BS_SOLID;
15621 bsClear: LogBrush.lbStyle := BS_NULL;
15622 else
15623 LogBrush.lbStyle := BS_HATCHED;
15624 LogBrush.lbHatch := Ord( Self_.fData.Brush.Style ) - Ord( bsHorizontal );
15625 LogBrush.lbColor := Color2RGB( Self_.fData.Brush.LineColor );
15626 end;
15627 end;
15628 Self_.fHandle := CreateBrushIndirect(LogBrush);
15629 {$IFDEF DEBUG_GDIOBJECTS}
15630 if Self_.fHandle <> 0 then
15631 Inc( BrushCount )
15632 else
15633 ShowMessage( 'Could not create brush, error ' + Int2Str( GetLastError ) +
15634 ': ' + SysErrorMessage( GetLastError ) );
15635 {$ENDIF}
15636 end;
15637 //GlobalGraphics_OnObjectCreated( @Self );
15638 Result := Self_.fHandle;
15639 end;
15640 {$ENDIF ASM_VERSION}
15641 //[END MakeBrushHandle]
15643 //[FUNCTION MakeFontHandle]
15644 {$IFDEF ASM_VERSION}
15645 function MakeFontHandle( Self_: PGraphicTool ): THandle;
15647 XCHG EDX, EAX
15648 MOV EAX, [EDX].TGraphicTool.fHandle
15649 TEST EAX, EAX
15650 JNZ @@exit
15651 PUSH EDX
15652 LEA ECX, [EDX].TGraphicTool.fData.Font
15653 PUSH ECX
15654 CALL CreateFontIndirect
15655 POP EDX
15656 MOV [EDX].TGraphicTool.fHandle, EAX
15657 @@exit:
15658 end;
15659 {$ELSE ASM_VERSION} //Pascal
15660 function MakeFontHandle( Self_: PGraphicTool ): THandle;
15661 //var LogFont: TLogFont;
15662 begin
15663 with Self_{-}^{+} do
15664 begin
15665 if fHandle = 0 then
15666 begin
15667 fHandle := CreateFontIndirect( PLogFont( @ fData.Font )^ );
15668 {$IFDEF DEBUG_GDIOBJECTS}
15669 Inc( FontCount );
15670 {$ENDIF}
15671 end;
15672 Result := fHandle;
15673 end;
15674 end;
15675 {$ENDIF ASM_VERSION}
15676 //[END MakeFontHandle]
15678 //[FUNCTION MakePenHandle]
15679 {$IFDEF ASM_VERSION}
15680 function MakePenHandle( Self_: PGraphicTool ): THandle;
15682 PUSH EBX
15683 MOV EBX, EAX
15685 MOV EAX, [EBX].TGraphicTool.fHandle
15686 TEST EAX, EAX
15687 JNZ @@exit
15689 MOV EAX, [EBX].TGraphicTool.fData.Color
15690 CALL Color2RGB
15691 PUSH EAX
15692 PUSH EAX
15693 PUSH [EBX].TGraphicTool.fData.Pen.Width
15694 MOVZX EAX, [EBX].TGraphicTool.fData.Pen.Style
15695 PUSH EAX
15696 PUSH ESP
15697 CALL CreatePenIndirect
15698 MOV [EBX].TGraphicTool.fHandle, EAX
15699 ADD ESP, 16
15700 @@exit:
15701 POP EBX
15702 end;
15703 {$ELSE ASM_VERSION} //Pascal
15704 function MakePenHandle( Self_: PGraphicTool ): THandle;
15706 LogPen: TLogPen;
15707 begin
15708 with Self_{-}^{+} do
15709 begin
15710 //GlobalGraphics_OnObjectCreating( @Self );
15711 if fHandle = 0 then
15712 with LogPen do
15713 begin
15714 lopnStyle := Byte( fData.Pen.Style );
15715 lopnWidth.X := fData.Pen.Width;
15716 lopnColor := Color2RGB( fData.Color );
15717 fHandle := CreatePenIndirect( LogPen );
15718 {$IFDEF DEBUG_GDIOBJECTS}
15719 Inc( PenCount );
15720 {$ENDIF}
15721 end;
15722 //GlobalGraphics_OnObjectCreated( @Self );
15723 Result := fHandle;
15724 end;
15725 end;
15726 {$ENDIF ASM_VERSION}
15727 //[END MakePenHandle]
15730 //[procedure TGraphicTool.SetGeometricPen]
15731 procedure TGraphicTool.SetGeometricPen(const Value: Boolean);
15732 begin
15733 if fData.Pen.Geometric = Value then Exit;
15734 fData.Pen.Geometric := Value;
15735 fMakeHandleProc := MakeGeometricPenHandle;
15736 Changed;
15737 end;
15739 //[procedure TGraphicTool.SetPenEndCap]
15740 procedure TGraphicTool.SetPenEndCap(const Value: TPenEndCap);
15741 begin
15742 if fData.Pen.EndCap = Value then Exit;
15743 fData.Pen.EndCap := Value;
15744 Changed;
15745 end;
15747 //[procedure TGraphicTool.SetPenJoin]
15748 procedure TGraphicTool.SetPenJoin(const Value: TPenJoin);
15749 begin
15750 if fData.Pen.Join = Value then Exit;
15751 fData.Pen.Join := Value;
15752 Changed;
15753 end;
15755 //[FUNCTION MakeGeometricPenHandle]
15756 {$IFDEF ASM_VERSION}
15757 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle;
15759 MOV ECX, [EAX].TGraphicTool.fHandle
15760 INC ECX
15761 LOOP @@exit
15763 PUSH EBX
15764 XCHG EBX, EAX
15765 MOV EAX, [EBX].TGraphicTool.fData.Color
15766 CALL Color2RGB // EAX = Color2RGB( fColor )
15767 CDQ // EDX = lbHatch (0)
15768 MOV ECX, [EBX].TGraphicTool.fData.Pen.BrushBitmap
15769 JECXZ @@no_brush_bitmap
15771 XCHG EDX, ECX // lbHatch = fPenBrushBitmap
15772 MOV CL, BS_PATTERN // = 3
15773 JMP @@create_pen
15775 @@no_brush_bitmap:
15776 MOVZX ECX, [EBX].TGraphicTool.fData.Pen.BrushStyle
15777 CMP CL, 1
15778 JLE @@create_pen
15779 MOV EDX, ECX
15780 MOV CL, 2
15781 SUB EDX, ECX
15783 @@create_pen:
15784 PUSH EDX
15785 PUSH EAX
15786 PUSH ECX
15787 MOV ECX, ESP
15790 PUSH EDX
15791 PUSH EDX
15792 PUSH ECX
15793 PUSH [EBX].TGraphicTool.fData.Pen.Width
15794 MOVZX ECX, [EBX].TGraphicTool.fData.Pen.Join
15795 SHL ECX, 12
15796 MOVZX EDX, [EBX].TGraphicTool.fData.Pen.EndCap
15797 SHL EDX, 8
15798 OR EDX, ECX
15799 OR DL, byte ptr [EBX].TGraphicTool.fData.Pen.Style
15800 OR EDX, PS_GEOMETRIC
15801 PUSH EDX
15802 CALL ExtCreatePen
15804 POP ECX
15805 POP ECX
15806 POP ECX
15808 MOV [EBX].TGraphicTool.fHandle, EAX
15809 POP EBX
15811 @@exit:
15812 XCHG EAX, ECX
15813 end;
15814 {$ELSE ASM_VERSION} //Pascal
15815 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle;
15816 const
15817 PenStyles: array[ TPenStyle ] of Word =
15818 (PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL,
15819 PS_INSIDEFRAME);
15820 PenEndCapStyles: array[ TPenEndCap ] of Word =
15821 (PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE, PS_ENDCAP_FLAT);
15822 PenJoinStyles: array[ TPenJoin ] of Word =
15823 (PS_JOIN_ROUND, PS_JOIN_BEVEL, PS_JOIN_MITER );
15825 LogBrush: TLogBrush;
15826 begin
15827 if Self_.fHandle = 0 then
15828 with Self_{-}^{+}, LogBrush do
15829 begin
15830 lbColor := Color2RGB( fData.Color );
15831 lbHatch := 0;
15832 if fData.Pen.BrushBitmap <> 0 then
15833 begin
15834 lbStyle := BS_PATTERN;
15835 lbHatch := fData.Pen.BrushBitmap;
15837 else
15838 case fData.Pen.BrushStyle of
15839 bsSolid: lbStyle := BS_SOLID;
15840 bsClear: lbStyle := BS_NULL;
15841 else begin
15842 lbStyle := BS_HATCHED;
15843 case fData.Pen.BrushStyle of
15844 bsHorizontal: lbHatch := HS_HORIZONTAL;
15845 bsVertical: lbHatch := HS_VERTICAL;
15846 bsFDiagonal: lbHatch := HS_FDIAGONAL;
15847 bsBDiagonal: lbHatch := HS_BDIAGONAL;
15848 bsCross: lbHatch := HS_CROSS;
15849 bsDiagCross: lbHatch := HS_DIAGCROSS;
15850 end;
15851 end;
15852 end;
15853 end;
15854 Self_.fHandle := ExtCreatePen( PS_GEOMETRIC or Byte( Self_.fData.Pen.Style ) or
15855 PenEndCapStyles[ Self_.fData.Pen.EndCap ] or
15856 PenJoinStyles[ Self_.fData.Pen.Join ],
15857 Self_.fData.Pen.Width, LogBrush, 0, nil );
15858 {Assert( Self_.fHandle <> 0, 'Error ' + Int2Str( GetLastError ) +
15859 ': ' + SysErrorMessage( GetLastError ) );}
15860 {$IFDEF DEBUG_GDIOBJECTS}
15861 Inc( PenCount );
15862 {$ENDIF}
15863 Result := Self_.fHandle;
15864 end;
15865 {$ENDIF ASM_VERSION}
15866 //[END MakeGeometricPenHandle]
15868 //[procedure TGraphicTool.SetFontWeight]
15869 procedure TGraphicTool.SetFontWeight(const Value: Integer);
15870 begin
15871 if fData.Font.Weight = Value then Exit;
15872 fData.Font.Weight := Value;
15873 Changed;
15874 end;
15876 //[procedure TGraphicTool.SetLogFontStruct]
15877 procedure TGraphicTool.SetLogFontStruct(const Value: TLogFont);
15878 begin
15879 if CompareMem(@fData.Font, @Value, SizeOf(TLogFont)) then Exit;
15880 Move(Value, fData.Font, SizeOF(TLogFont));
15881 Changed;
15882 end;
15884 //[function TGraphicTool.GetLogFontStruct]
15885 function TGraphicTool.GetLogFontStruct: TLogFont;
15886 begin
15887 Move(fData.Font, Result, SizeOf(TLogFont));
15888 end;
15901 { TCanvas }
15903 type
15904 TStock = Packed Record
15905 StockPen: HPEN;
15906 StockBrush: HBRUSH;
15907 StockFont: HFONT;
15908 end;
15911 Stock: TStock;
15913 //[destructor TCanvas.Destroy]
15914 destructor TCanvas.Destroy;
15915 begin
15916 Handle := 0;
15917 fPen.Free;
15918 fBrush.Free;
15919 fFont.Free;
15920 //if Assigned( GlobalCanvas_OnDestroyCanvas ) then
15921 // GlobalCanvas_OnDestroyCanvas( Self );
15922 inherited;
15923 end;
15925 {$IFDEF ASM_VERSION}
15926 //[function TCanvas.Assign]
15927 function TCanvas.Assign(SrcCanvas: PCanvas): Boolean;
15929 PUSH EBX
15930 PUSH ESI
15931 XCHG EBX, EAX
15932 MOV ESI, EDX
15934 MOV EAX, [EBX].fFont
15935 MOV EDX, [ESI].fFont
15936 CALL TGraphicTool.Assign
15937 MOV [EBX].fFont, EAX
15939 MOV EAX, [EBX].fBrush
15940 MOV EDX, [ESI].fBrush
15941 CALL TGraphicTool.Assign
15942 MOV [EBX].fBrush, EAX
15944 MOV EAX, [EBX].fPen
15945 MOV EDX, [ESI].fPen
15946 CALL TGraphicTool.Assign
15947 MOV [EBX].fPen, EAX
15949 CALL AssignChangeEvents
15951 MOV ECX, [EBX].fFont
15952 OR ECX, [EBX].fBrush
15953 OR ECX, [EBX].fPen
15954 SETNZ AL
15956 MOV EDX, [ESI].fPenPos.x
15957 MOV ECX, [ESI].fPenPos.y
15958 CMP EDX, [EBX].fPenPos.x
15959 JNE @@chg_penpos
15960 CMP ECX, [EBX].fPenPos.y
15961 JE @@1
15962 @@chg_penpos:
15963 MOV AL, 1
15964 MOV [EBX].fPenPos.x, EDX
15965 MOV [EBX].fPenPos.y, ECX
15966 @@1:
15967 MOV EDX, [ESI].fCopyMode
15968 CMP EDX, [EBX].fCopyMode
15969 JE @@2
15970 MOV [EBX].fCopyMode, EDX
15971 MOV AL, 1
15972 @@2:
15973 POP ESI
15974 POP EBX
15975 end;
15976 {$ELSE ASM_VERSION} //Pascal
15977 function TCanvas.Assign(SrcCanvas: PCanvas): Boolean;
15978 begin
15979 fFont := fFont.Assign( SrcCanvas.fFont );
15980 fBrush := fBrush.Assign( SrcCanvas.fBrush );
15981 fPen := fPen.Assign( SrcCanvas.fPen );
15982 AssignChangeEvents;
15983 Result := (fFont <> nil) or (fBrush <> nil) or (fPen <> nil);
15984 if (SrcCanvas.PenPos.x <> PenPos.x) or (SrcCanvas.PenPos.y <> PenPos.y) then
15985 begin
15986 Result := True;
15987 PenPos := SrcCanvas.PenPos;
15988 end;
15989 if SrcCanvas.ModeCopy <> ModeCopy then
15990 begin
15991 Result := True;
15992 ModeCopy := SrcCanvas.ModeCopy;
15993 end;
15994 end;
15995 {$ENDIF ASM_VERSION}
15997 {$IFDEF ASM_VERSION}
15998 //[procedure TCanvas.CreateBrush]
15999 procedure TCanvas.CreateBrush;
16001 PUSH EBX
16002 MOV EBX, EAX
16004 MOV ECX, [EAX].fBrush
16005 JECXZ @@chk_owner
16007 MOV EAX, ECX
16008 CALL TGraphicTool.GetHandle
16009 PUSH EAX
16011 MOV EAX, EBX
16012 CALL AssignChangeEvents
16014 MOV EAX, EBX
16015 CALL TCanvas.GetHandle
16016 PUSH EAX
16018 CALL SelectObject
16020 MOV EDX, [EBX].TCanvas.fBrush
16021 CMP [EDX].TGraphicTool.fData.Brush.Style, bsSolid
16023 MOV EAX, [EDX].TGraphicTool.fData.Color
16024 @@0:
16025 MOV EBX, [EBX].TCanvas.fHandle
16026 MOV ECX, offset[Color2RGB]
16027 JNZ @@1
16029 PUSH OPAQUE
16030 PUSH EBX
16032 CALL ECX //Color2RGB
16033 PUSH EAX
16034 PUSH EBX
16035 JMP @@2
16036 @@1:
16037 PUSH TRANSPARENT
16038 PUSH EBX
16040 CALL ECX //Color2RGB
16041 NOT EAX
16042 PUSH EAX
16043 PUSH EBX
16044 @@2:
16045 CALL SetBkColor
16046 CALL SetBkMode
16047 @@exit:
16048 POP EBX
16051 @@chk_owner:
16052 MOV ECX, [EBX].fOwnerControl
16053 JECXZ @@exit
16055 MOV EAX, [ECX].TControl.fColor
16056 XOR ECX, ECX
16057 JMP @@0
16058 end;
16059 {$ELSE ASM_VERSION} //Pascal
16060 procedure TCanvas.CreateBrush;
16061 begin
16062 //UnrealizeObject( Brush.Handle );
16063 // if GdiObject parameter of UnrealizeObject is brush handle,
16064 // this call does nothing (from Win32.hlp)
16066 if assigned( fBrush ) then
16067 begin
16068 SelectObject( GetHandle, fBrush.Handle );
16069 //fBrush.fOnChange := ObjectChanged;
16070 AssignChangeEvents;
16071 if fBrush.fData.Brush.Style = bsSolid then
16072 begin
16073 SetBkColor( fHandle, Color2RGB( fBrush.fData.Color ) );
16074 SetBkMode( fHandle, OPAQUE );
16076 else
16077 begin
16078 { Win95 doesn't draw brush hatches if bkcolor = brush color }
16079 { Since bkmode is transparent, nothing should use bkcolor anyway }
16080 SetBkColor( fHandle, not Color2RGB( fBrush.fData.Color ) );
16081 SetBkMode( fHandle, TRANSPARENT );
16082 end;
16084 else
16085 if Assigned( fOwnerControl ) then
16086 begin
16087 SetBkColor( GetHandle, Color2RGB( PControl( fOwnerControl ).fColor ) );
16088 SetBkMode( fHandle, OPAQUE );
16089 end;
16090 end;
16091 {$ENDIF ASM_VERSION}
16093 {$IFDEF ASM_VERSION}
16094 //[procedure TCanvas.CreateFont]
16095 procedure TCanvas.CreateFont;
16097 PUSH EBX
16098 MOV EBX, EAX
16100 MOV ECX, [EAX].TCanvas.fFont
16101 JECXZ @@chk_owner
16103 MOV EAX, [ECX].TGraphicTool.fData.Color
16104 PUSH ECX
16105 CALL Color2RGB
16106 XCHG EAX, [ESP]
16108 CALL TGraphicTool.GetHandle
16109 PUSH EAX
16111 MOV EAX, EBX
16112 CALL AssignChangeEvents;
16114 MOV EAX, EBX
16115 CALL TCanvas.GetHandle
16116 PUSH EAX
16117 MOV EBX, EAX
16119 CALL SelectObject
16121 @@set_txcolor:
16122 PUSH EBX
16123 CALL SetTextColor
16125 @@exit:
16126 POP EBX
16129 @@chk_owner:
16130 MOV ECX, [EBX].fOwnerControl
16131 JECXZ @@exit
16133 MOV EBX, [EBX].fHandle
16134 MOV EAX, [ECX].TControl.fTextColor
16135 CALL Color2RGB
16136 PUSH EAX
16137 JMP @@set_txcolor
16138 end;
16139 {$ELSE ASM_VERSION} //Pascal
16140 procedure TCanvas.CreateFont;
16141 begin
16142 if assigned( fFont ) then
16143 begin
16144 SelectObject( GetHandle, fFont.Handle );
16145 SetTextColor( fHandle, Color2RGB( fFont.fData.Color ) );
16146 //fFont.fOnChange := ObjectChanged;
16147 AssignChangeEvents;
16149 else
16150 if Assigned( fOwnerControl ) then
16151 begin
16152 SetTextColor( fHandle, Color2RGB( PControl( fOwnerControl ).fTextColor ) );
16153 end;
16154 end;
16155 {$ENDIF ASM_VERSION}
16157 {$IFDEF ASM_VERSION}
16158 //[procedure TCanvas.CreatePen]
16159 procedure TCanvas.CreatePen;
16161 MOV ECX, [EAX].TCanvas.fPen
16162 JECXZ @@exit
16164 PUSH EBX
16165 MOV EBX, EAX
16167 MOV DL, [ECX].TGraphicTool.fData.Pen.Mode
16168 MOVZX EDX, DL
16169 INC EDX
16170 PUSH EDX
16172 MOV EAX, ECX
16173 CALL TGraphicTool.GetHandle
16174 PUSH EAX
16176 MOV EAX, EBX
16177 CALL AssignChangeEvents
16179 MOV EAX, EBX
16180 CALL TCanvas.GetHandle
16181 PUSH EAX
16182 MOV EBX, EAX
16184 CALL SelectObject
16185 PUSH EBX
16186 CALL SetROP2
16188 POP EBX
16189 @@exit:
16190 end;
16191 {$ELSE ASM_VERSION} //Pascal
16192 procedure TCanvas.CreatePen;
16193 begin
16194 if assigned( fPen ) then
16195 begin
16196 SelectObject( GetHandle, fPen.Handle );
16197 SetROP2( fHandle, Ord( fPen.fData.Pen.Mode ) + 1 );
16198 //fPen.fOnChange := ObjectChanged;
16199 AssignChangeEvents;
16200 end;
16201 end;
16202 {$ENDIF ASM_VERSION}
16204 //[function TCanvas.GetPixels]
16205 function TCanvas.GetPixels(X, Y: Integer): TColor;
16206 begin
16207 RequiredState( HandleValid );
16208 Result := Windows.GetPixel(FHandle, X, Y);
16209 end;
16211 //[procedure TCanvas.SetPixels]
16212 procedure TCanvas.SetPixels(X, Y: Integer; const Value: TColor);
16213 begin
16214 Changing;
16215 RequiredState( HandleValid );
16216 Windows.SetPixel(FHandle, X, Y, Color2RGB( Value ));
16217 end;
16219 {$IFDEF ASM_VERSION}
16220 //[procedure TCanvas.DeselectHandles]
16221 procedure TCanvas.DeselectHandles;
16223 PUSH EBX
16224 PUSH ESI
16225 PUSH EDI
16226 LEA EBX, [EAX].TCanvas.fState
16227 //CALL TCanvas.GetHandle
16228 MOV EAX, [EAX].TCanvas.fHandle
16229 TEST EAX, EAX
16230 JZ @@exit
16232 MOVZX EDX, byte ptr[EBX]
16233 AND DL, PenValid or BrushValid or FontValid
16234 JZ @@exit
16236 PUSH EAX
16237 LEA EDI, [Stock]
16239 MOV ECX, [EDI]
16240 INC ECX
16241 LOOP @@1
16243 MOV ESI, offset[ GetStockObject ]
16245 PUSH BLACK_PEN
16246 CALL ESI
16247 STOSD
16249 PUSH HOLLOW_BRUSH
16250 CALL ESI
16251 STOSD
16253 PUSH SYSTEM_FONT
16254 CALL ESI
16255 STOSD
16257 @@1:
16258 LEA ESI, [Stock]
16259 POP EDX
16261 LODSD
16262 PUSH EAX
16263 PUSH EDX
16265 LODSD
16266 PUSH EAX
16267 PUSH EDX
16269 LODSD
16270 PUSH EAX
16271 PUSH EDX
16273 MOV ESI, offset[ SelectObject ]
16274 CALL ESI
16275 CALL ESI
16276 CALL ESI
16278 AND byte ptr [EBX], not( PenValid or BrushValid or FontValid )
16279 @@exit:
16280 POP EDI
16281 POP ESI
16282 POP EBX
16283 end;
16284 {$ELSE ASM_VERSION} //Pascal
16285 procedure TCanvas.DeselectHandles;
16286 begin
16287 //if (GetHandle <> 0) and
16288 if (fHandle <> 0) and
16289 LongBool(fState and (PenValid or BrushValid or FontValid)) then
16290 with Stock do
16291 begin
16292 if StockPen = 0 then
16293 begin
16294 StockPen := GetStockObject(BLACK_PEN);
16295 StockBrush := GetStockObject(HOLLOW_BRUSH);
16296 StockFont := GetStockObject(SYSTEM_FONT);
16297 end;
16298 SelectObject( fHandle, StockPen );
16299 SelectObject( fHandle, StockBrush );
16300 SelectObject( fHandle, StockFont );
16301 fState := fState and not( PenValid or BrushValid or FontValid );
16302 end;
16303 end;
16304 {$ENDIF ASM_VERSION}
16306 {$IFDEF ASM_VERSION}
16307 //[function TCanvas.RequiredState]
16308 function TCanvas.RequiredState(ReqState: DWORD): Integer; stdcall;
16310 PUSH EBX
16311 PUSH ESI
16312 MOV EBX, ReqState
16313 MOV ESI, [EBP+8] //Self
16314 MOV EAX, ESI
16315 TEST BL, ChangingCanvas
16316 JZ @@1
16317 CALL Changing
16318 @@1: AND BL, 0Fh
16320 TEST BL, HandleValid
16321 JZ @@2
16322 CALL TCanvas.GetHandle
16323 TEST EAX, EAX
16324 JZ @@ret_0
16325 @@2:
16326 MOV AL, [ESI].TCanvas.fState
16327 NOT EAX
16328 AND BL, AL
16329 JZ @@ret_handle
16331 TEST BL, FontValid
16332 JZ @@3
16333 MOV EAX, ESI
16334 CALL CreateFont
16335 @@3: TEST BL, PenValid
16336 JZ @@5
16337 MOV EAX, ESI
16338 CALL CreatePen
16339 MOV ECX, [ESI].TCanvas.fPen
16340 JCXZ @@5
16341 MOV AL, [ECX].TGraphicTool.fData.Pen.Style
16342 DEC AL
16343 {$IFDEF PARANOIA}
16344 DB $2C, 3
16345 {$ELSE}
16346 SUB AL, 3
16347 {$ENDIF}
16348 JB @@6
16349 @@5: TEST BL, BrushValid
16350 JZ @@7
16351 @@6: MOV EAX, ESI
16352 CALL CreateBrush
16353 @@7: OR [ESI].TCanvas.fState, BL
16354 @@ret_handle:
16355 MOV EAX, [ESI].TCanvas.fHandle
16356 @@ret_0:
16357 POP ESI
16358 POP EBX
16359 end;
16360 {$ELSE ASM_VERSION} //Pascal
16361 function TCanvas.RequiredState(ReqState: DWORD): Integer; stdcall;
16363 NeededState: Byte;
16364 begin
16365 if Boolean(ReqState and ChangingCanvas) then
16366 Changing;
16367 ReqState := ReqState and 15;
16368 NeededState := Byte( ReqState ) and not fState;
16369 Result := 0;
16370 if Boolean(ReqState and HandleValid) then
16371 begin
16372 if GetHandle = 0 then Exit;
16373 // Important!
16374 end;
16375 if NeededState <> 0 then
16376 begin
16377 if Boolean( NeededState and FontValid ) then
16378 CreateFont;
16379 if Boolean( NeededState and PenValid ) then
16380 begin
16381 CreatePen;
16382 if assigned( fPen ) then
16383 if fPen.fData.Pen.Style in [psDash, psDot, psDashDot, psDashDotDot] then
16384 NeededState := NeededState or BrushValid;
16385 end;
16386 if Boolean( NeededState and BrushValid ) then
16387 CreateBrush;
16388 fState := fState or NeededState;
16389 end;
16390 Result := fHandle;
16391 end;
16392 {$ENDIF ASM_VERSION}
16394 {$IFDEF ASM_VERSION}
16395 //[procedure TCanvas.SetHandle]
16396 procedure TCanvas.SetHandle(Value: HDC);
16398 PUSH EBX
16399 MOV EBX, EAX
16400 MOV ECX, [EBX].fHandle
16401 CMP ECX, EDX
16402 JZ @@exit
16403 JECXZ @@chk_val
16405 PUSH EDX
16406 PUSH ECX
16407 CALL DeselectHandles
16408 POP EDX
16410 MOV ECX, [EBX].fOwnerControl
16411 JECXZ @@chk_Release
16412 CMP [ECX].TControl.fPaintDC, EDX
16413 JE @@clr_Handle
16415 @@chk_Release:
16416 PUSH EDX
16417 CMP [EBX].fOnGetHandle.TMethod.Code, offset[TControl.DC2Canvas]
16418 JNE @@deldc
16419 PUSH [ECX].TControl.fHandle
16420 CALL ReleaseDC
16421 JMP @@clr_Handle
16422 @@deldc:
16423 CALL DeleteDC
16425 @@clr_Handle:
16426 XOR ECX, ECX
16427 MOV [EBX].TCanvas.fHandle, ECX
16428 MOV [EBX].TCanvas.fIsPaintDC, CL
16429 AND [EBX].TCanvas.fState, not HandleValid
16431 POP EDX
16432 @@chk_val:
16433 TEST EDX, EDX
16434 JZ @@exit
16436 OR [EBX].TCanvas.fState, HandleValid
16437 MOV [EBX].TCanvas.fHandle, EDX
16438 LEA EDX, [EBX].TCanvas.fPenPos
16439 MOV EAX, EBX
16440 CALL SetPenPos
16442 @@exit: POP EBX
16443 end;
16444 {$ELSE ASM_VERSION} //Pascal
16445 procedure TCanvas.SetHandle(Value: HDC);
16446 {$IFDEF F_P}
16447 var Ptr1: Pointer;
16448 {$ENDIF F_P}
16449 begin
16450 if fHandle = Value then Exit;
16451 if fHandle <> 0 then
16452 begin
16453 DeselectHandles;
16454 {if not fIsPaintDC and
16455 not( assigned(fOwnerControl) and
16456 PControl(fOwnerControl).fDoubleBuffered )
16457 then}
16458 if not( assigned(fOwnerControl) and
16459 (PControl(fOwnerControl).fPaintDC = fHandle) ) then
16460 begin
16461 {$IFDEF F_P}
16462 Ptr1 := Self;
16464 MOV EAX, [Ptr1]
16465 MOV EAX, [EAX].TCanvas.fOnGetHandle
16466 MOV [Ptr1], EAX
16467 end [ 'EAX' ];
16468 if Ptr1 = @ TControl.DC2Canvas then
16469 {$ELSE DELPHI}
16470 //////////////////// SLAG
16471 if TMethod(fOnGetHandle).Code =
16472 @TControl.Dc2Canvas then
16473 {$ENDIF F_P/DELPHI}
16474 ReleaseDC(PControl(fOwnerControl).Handle, fHandle )
16475 else
16476 DeleteDC( fHandle );
16477 ////////////////////
16478 end;
16479 fHandle := 0;
16480 fIsPaintDC := False;
16481 fState := fState and not HandleValid;
16482 end;
16483 if Value <> 0 then
16484 begin
16485 fState := fState or HandleValid;
16486 fHandle := Value;
16487 SetPenPos( fPenPos );
16488 end;
16489 end;
16490 {$ENDIF ASM_VERSION}
16492 {$IFDEF ASM_VERSION}
16493 //[procedure TCanvas.SetPenPos]
16494 procedure TCanvas.SetPenPos(const Value: TPoint);
16496 MOV ECX, [EDX].TPoint.y
16497 MOV EDX, [EDX].TPoint.x
16498 MOV [EAX].fPenPos.x, EDX
16499 MOV [EAX].fPenPos.y, ECX
16500 CALL MoveTo
16501 end;
16502 {$ELSE ASM_VERSION} //Pascal
16503 procedure TCanvas.SetPenPos(const Value: TPoint);
16504 begin
16505 fPenPos := Value;
16506 MoveTo( Value.x, Value.y );
16507 end;
16508 {$ENDIF ASM_VERSION}
16510 {$IFDEF ASM_VERSION}
16511 //[procedure TCanvas.Changing]
16512 procedure TCanvas.Changing;
16514 PUSHAD
16515 MOV ECX, [EAX].fOnChange.TMethod.Code
16516 JECXZ @@exit
16517 XCHG EDX, EAX
16518 MOV EAX, [EDX].fOnChange.TMethod.Data
16519 CALL ECX
16520 @@exit:
16521 POPAD
16522 end;
16523 {$ELSE ASM_VERSION} //Pascal
16524 procedure TCanvas.Changing;
16525 begin
16526 if Assigned( fOnChange ) then
16527 fOnChange( @Self );
16528 end;
16529 {$ENDIF ASM_VERSION}
16531 {$IFDEF ASM_VERSION}
16532 //[procedure TCanvas.Arc]
16533 procedure TCanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16535 PUSH ESI
16537 PUSH HandleValid or PenValid or ChangingCanvas
16538 PUSH dword ptr [EBP+8]
16539 CALL RequiredState
16541 MOV EDX, EAX
16543 LEA ESI, [Y4]
16546 XOR ECX, ECX
16547 MOV CL, 8
16548 @@1:
16549 LODSD
16550 PUSH EAX
16552 LOOP @@1
16555 PUSH EDX //Canvas.fHandle
16556 CALL Windows.Arc
16557 POP ESI
16558 end;
16559 {$ELSE ASM_VERSION} //Pascal
16560 procedure TCanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16561 begin
16562 RequiredState( HandleValid or PenValid or ChangingCanvas );
16563 Windows.Arc(FHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);
16564 end;
16565 {$ENDIF ASM_VERSION}
16567 {$IFDEF ASM_VERSION}
16568 //[procedure TCanvas.Chord]
16569 procedure TCanvas.Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16571 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16572 PUSH dword ptr [EBP + 8]
16573 CALL RequiredState
16575 MOV EDX, EAX
16577 PUSH ESI
16578 LEA ESI, [Y4]
16581 XOR ECX, ECX
16582 MOV CL, 8
16583 @@1:
16584 LODSD
16585 PUSH EAX
16587 LOOP @@1
16590 PUSH EDX //Canvas.fHandle
16591 CALL Windows.Chord
16592 POP ESI
16593 end;
16594 {$ELSE ASM_VERSION} //Pascal
16595 procedure TCanvas.Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16596 begin
16597 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16598 Windows.Chord(FHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);
16599 end;
16600 {$ENDIF ASM_VERSION}
16602 {$IFDEF ASM_VERSION}
16603 //[procedure TCanvas.CopyRect]
16604 procedure TCanvas.CopyRect(const DstRect: TRect; SrcCanvas: PCanvas;
16605 const SrcRect: TRect);
16607 PUSH ESI
16608 PUSH EDI
16610 PUSH [EAX].fCopyMode
16612 PUSH EDX
16614 PUSH HandleValid or BrushValid
16615 PUSH ECX
16617 PUSH HandleValid or FontValid or BrushValid or ChangingCanvas
16618 PUSH EAX
16619 MOV ESI, offset[ RequiredState ]
16620 CALL ESI
16621 MOV EDI, EAX // EDI = @Self.fHandle
16623 CALL ESI
16624 MOV EDX, EAX // EDX = SrcCanvas.fHandle
16626 POP ECX // ECX = @DstRect
16628 MOV ESI, [SrcRect]
16630 MOV EAX, [ESI].TRect.Bottom
16631 SUB EAX, [ESI].TRect.Top
16632 PUSH EAX
16634 MOV EAX, [ESI].TRect.Right
16635 SUB EAX, [ESI].TRect.Left
16636 PUSH EAX
16638 PUSH [ESI].TRect.Top
16640 LODSD
16641 PUSH EAX
16643 PUSH EDX
16645 MOV EAX, [ECX].TRect.Bottom
16646 MOV EDX, [ECX].TRect.Top
16647 SUB EAX, EDX
16648 PUSH EAX
16650 MOV EAX, [ECX].TRect.Right
16651 MOV ESI, [ECX].TRect.Left
16652 SUB EAX, ESI
16653 PUSH EAX
16655 PUSH EDX
16657 PUSH ESI
16659 PUSH EDI
16661 CALL StretchBlt
16663 POP EDI
16664 POP ESI
16665 end;
16666 {$ELSE ASM_VERSION} //Pascal
16667 procedure TCanvas.CopyRect(const DstRect: TRect; SrcCanvas: PCanvas;
16668 const SrcRect: TRect);
16669 begin
16670 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
16671 SrcCanvas.RequiredState( HandleValid or BrushValid );
16672 StretchBlt( fHandle, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left,
16673 DstRect.Bottom - DstRect.Top, SrcCanvas.Handle, SrcRect.Left, SrcRect.Top,
16674 SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top, ModeCopy);
16675 end;
16676 {$ENDIF ASM_VERSION}
16678 {$IFDEF ASM_VERSION}
16679 //[procedure TCanvas.DrawFocusRect]
16680 procedure TCanvas.DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16682 PUSH EDX
16684 PUSH HandleValid or BrushValid or FontValid or ChangingCanvas
16685 PUSH EAX
16686 CALL RequiredState
16688 PUSH EAX
16689 CALL Windows.DrawFocusRect
16690 end;
16691 {$ELSE ASM_VERSION} //Pascal
16692 procedure TCanvas.DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16693 begin
16694 RequiredState( HandleValid or BrushValid or FontValid or ChangingCanvas );
16695 Windows.DrawFocusRect(FHandle, Rect);
16696 end;
16697 {$ENDIF ASM_VERSION}
16699 {$IFDEF ASM_VERSION}
16700 //[procedure TCanvas.Ellipse]
16701 procedure TCanvas.Ellipse(X1, Y1, X2, Y2: Integer);
16703 PUSH [Y2]
16704 PUSH [X2]
16705 PUSH ECX
16706 PUSH EDX
16708 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16709 PUSH EAX
16710 CALL RequiredState
16712 PUSH EAX
16713 CALL Windows.Ellipse
16714 end;
16715 {$ELSE ASM_VERSION} //Pascal
16716 procedure TCanvas.Ellipse(X1, Y1, X2, Y2: Integer);
16717 begin
16718 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16719 Windows.Ellipse(FHandle, X1, Y1, X2, Y2);
16720 end;
16721 {$ENDIF ASM_VERSION}
16723 {$IFDEF ASM_VERSION}
16724 //[procedure TCanvas.FillRect]
16725 procedure TCanvas.FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16727 PUSH EBX
16728 XCHG EBX, EAX
16729 PUSH EDX
16730 PUSH HandleValid or BrushValid or ChangingCanvas
16731 PUSH EBX
16732 CALL RequiredState
16733 MOV ECX, [EBX].fBrush
16734 JECXZ @@chk_ctl
16736 @@fill_with_Brush:
16737 XCHG EAX, ECX
16738 CALL TGraphicTool.GetHandle
16739 POP EDX
16740 PUSH EAX
16741 JMP @@fin
16742 @@chk_ctl:
16743 MOV ECX, [EBX].fOwnerControl
16744 JECXZ @@dflt_fill
16745 XCHG EAX, ECX
16746 MOV ECX, [EAX].TControl.fBrush
16747 INC ECX
16748 LOOP @@fill_with_Brush
16749 MOV EAX, [EAX].TControl.fColor
16750 CALL Color2RGB
16751 PUSH EAX
16752 CALL CreateSolidBrush
16753 POP EDX
16754 PUSH EAX
16755 PUSH EAX
16756 PUSH EDX
16757 PUSH [EBX].fHandle
16758 CALL Windows.FillRect
16759 CALL DeleteObject
16760 POP EBX
16762 @@dflt_fill:
16763 POP EDX
16764 PUSH COLOR_WINDOW + 1
16765 @@fin:
16766 PUSH EDX
16767 PUSH [EBX].fHandle
16768 CALL Windows.FillRect
16769 POP EBX
16770 end;
16771 {$ELSE ASM_VERSION} //Pascal
16772 procedure TCanvas.FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16773 var Br: HBrush;
16774 begin
16775 RequiredState( HandleValid or BrushValid or ChangingCanvas );
16776 if assigned( fBrush ) then
16777 begin
16778 Windows.FillRect(fHandle, Rect, fBrush.Handle);
16780 else
16781 if assigned( fOwnerControl ) then
16782 begin
16783 if assigned( PControl( fOwnerControl ).fBrush ) then
16784 Windows.FillRect( fHandle, Rect, PControl( fOwnerControl ).fBrush.Handle )
16785 else
16786 begin
16787 Br := CreateSolidBrush( Color2RGB(PControl(fOwnerControl).fColor) );
16788 Windows.FillRect(fHandle, Rect, Br );
16789 DeleteObject( Br );
16790 end;
16792 else
16793 begin
16794 Windows.FillRect(fHandle, Rect, HBrush(COLOR_WINDOW + 1) );
16795 end;
16796 end;
16797 {$ENDIF ASM_VERSION}
16799 {$IFDEF ASM_VERSION}
16800 //[procedure TCanvas.FillRgn]
16801 procedure TCanvas.FillRgn(const Rgn: HRgn);
16803 PUSH EBX
16804 XCHG EBX, EAX
16805 PUSH EDX
16807 PUSH HandleValid or BrushValid or ChangingCanvas
16808 PUSH EBX
16809 CALL RequiredState
16811 MOV ECX, [EBX].TCanvas.fBrush
16812 JECXZ @@1
16814 //PUSH [ECX].TGraphicTool.fData.Color
16815 //JMP @@cr_br
16817 @@fill_rgn_using_Brush:
16818 XCHG EAX, ECX
16819 CALL TGraphicTool.GetHandle
16820 POP EDX
16821 PUSH EAX
16822 PUSH EDX
16823 PUSH [EBX].fHandle
16824 CALL Windows.FillRgn
16825 JMP @@fin
16827 @@1: MOV ECX, [EBX].TCanvas.fOwnerControl
16828 MOV EAX, -1 // clWhite
16829 JECXZ @@2
16831 XCHG EAX, ECX
16832 MOV ECX, [EAX].TControl.fBrush
16833 INC ECX
16834 LOOP @@fill_rgn_using_Brush
16836 MOV EAX, [EAX].TControl.fColor
16837 @@2:
16838 CALL Color2RGB
16839 PUSH EAX
16840 CALL CreateSolidBrush // EAX = Br
16842 POP EDX // Rgn
16844 PUSH EAX //-------------------//
16845 PUSH EAX // Br
16846 PUSH EDX // Rgn
16847 PUSH [EBX].FHandle // fHandle
16848 CALL Windows.FillRgn
16850 CALL DeleteObject
16852 @@fin:
16853 POP EBX
16854 end;
16855 {$ELSE ASM_VERSION} //Pascal
16856 procedure TCanvas.FillRgn(const Rgn: HRgn);
16857 var Br : HBrush;
16858 begin
16859 RequiredState( HandleValid or BrushValid or ChangingCanvas );
16860 if assigned( fBrush ) then
16861 Windows.FillRgn(FHandle, Rgn, fBrush.Handle )
16862 else
16863 if assigned( fOwnerControl ) then
16864 begin
16865 if Assigned( PControl( fOwnerControl ).fBrush ) then
16866 Windows.FillRgn( FHandle, Rgn, PControl( fOwnerControl ).fBrush.Handle )
16867 else
16868 begin
16869 Br := CreateSolidBrush( Color2RGB(PControl(fOwnerControl).fColor) );
16870 Windows.FillRgn( fHandle, Rgn, Br );
16871 DeleteObject( Br );
16872 end;
16874 else
16875 begin
16876 Br := CreateSolidBrush( DWORD(clWindow) );
16877 Windows.FillRgn( fHandle, Rgn, Br );
16878 DeleteObject( Br );
16879 end;
16880 end;
16881 {$ENDIF ASM_VERSION}
16883 {$IFDEF ASM_!VERSION}
16884 //[procedure TCanvas.FloodFill]
16885 procedure TCanvas.FloodFill(X, Y: Integer; Color: TColor;
16886 FillStyle: TFillStyle);
16888 PUSH EBX
16889 MOV EBX, EAX
16891 MOVZX EAX, [FillStyle]
16892 TEST EAX, EAX
16893 MOV EAX, FLOODFILLSURFACE // = 1
16894 JZ @@1
16895 //MOV EAX, FLOODFILLBORDER // = 0
16896 DEC EAX
16897 @@1:
16898 PUSH EAX
16899 PUSH [Color]
16900 PUSH ECX
16901 PUSH EDX
16903 PUSH HandleValid or BrushValid or ChangingCanvas
16904 PUSH EBX
16905 CALL RequiredState
16906 PUSH EAX
16907 CALL Windows.ExtFloodFill
16909 POP EBX
16910 end;
16911 {$ELSE ASM_VERSION} //Pascal
16912 procedure TCanvas.FloodFill(X, Y: Integer; Color: TColor;
16913 FillStyle: TFillStyle);
16914 const
16915 FillStyles: array[TFillStyle] of Word =
16916 (FLOODFILLSURFACE, FLOODFILLBORDER);
16917 begin
16918 RequiredState( HandleValid or BrushValid or ChangingCanvas );
16919 Windows.ExtFloodFill(FHandle, X, Y, Color, FillStyles[FillStyle]);
16920 end;
16921 {$ENDIF ASM_VERSION}
16923 {$IFDEF ASM_VERSION}
16924 //[procedure TCanvas.FrameRect]
16925 procedure TCanvas.FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16927 PUSH EBX
16928 XCHG EBX, EAX
16929 PUSH EDX
16931 MOV ECX, [EBX].TCanvas.fBrush
16932 JECXZ @@1
16934 PUSH [ECX].TGraphicTool.fData.Color
16935 JMP @@cr_br
16937 @@1: MOV ECX, [EBX].TCanvas.fOwnerControl
16938 JECXZ @@2
16940 PUSH [ECX].TControl.fColor
16941 JMP @@cr_br
16943 @@2: PUSH clWhite
16944 @@cr_br:POP EAX // @Rect
16945 CALL Color2RGB
16946 PUSH EAX
16947 CALL CreateSolidBrush
16948 POP EDX
16949 PUSH EAX
16950 PUSH EAX
16951 PUSH EDX
16953 PUSH HandleValid or ChangingCanvas
16954 PUSH EBX
16955 ///MOV EBX, EDX
16956 CALL RequiredState
16958 PUSH EAX
16959 CALL Windows.FrameRect
16961 ///PUSH EBX
16962 CALL DeleteObject
16964 POP EBX
16965 end;
16966 {$ELSE ASM_VERSION} //Pascal
16967 procedure TCanvas.FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16968 var SolidBr : HBrush;
16969 begin
16970 RequiredState( HandleValid or ChangingCanvas );
16971 if assigned( fBrush ) then
16972 SolidBr := CreateSolidBrush( Color2RGB( fBrush.fData.Color ) )
16973 else
16974 if assigned( fOwnerControl ) then
16975 SolidBr := CreateSolidBrush( PControl(fOwnerControl).fColor )
16976 else
16977 SolidBr := CreateSolidBrush( clWhite );
16978 Windows.FrameRect(FHandle, Rect, SolidBr);
16979 DeleteObject( SolidBr );
16980 end;
16981 {$ENDIF ASM_VERSION}
16983 {$IFDEF ASM_VERSION}
16984 //[procedure TCanvas.LineTo]
16985 procedure TCanvas.LineTo(X, Y: Integer);
16987 PUSH ECX
16988 PUSH EDX
16989 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16990 PUSH EAX
16991 CALL RequiredState
16992 PUSH EAX //Canvas.fHandle
16993 CALL Windows.LineTo
16994 end;
16995 {$ELSE ASM_VERSION} //Pascal
16996 procedure TCanvas.LineTo(X, Y: Integer);
16997 begin
16998 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16999 Windows.LineTo( fHandle, X, Y );
17000 end;
17001 {$ENDIF ASM_VERSION}
17003 {$IFDEF ASM_VERSION}
17004 //[procedure TCanvas.MoveTo]
17005 procedure TCanvas.MoveTo(X, Y: Integer);
17007 PUSH 0
17008 PUSH ECX
17009 PUSH EDX
17010 PUSH HandleValid
17011 PUSH EAX
17012 CALL RequiredState
17013 PUSH EAX //Canvas.fHandle
17014 CALL Windows.MoveToEx
17015 end;
17016 {$ELSE ASM_VERSION} //Pascal
17017 procedure TCanvas.MoveTo(X, Y: Integer);
17018 begin
17019 RequiredState( HandleValid );
17020 Windows.MoveToEx( fHandle, X, Y, nil );
17021 end;
17022 {$ENDIF ASM_VERSION}
17024 //[procedure TCanvas.ObjectChanged]
17025 procedure TCanvas.ObjectChanged(Sender: PGraphicTool);
17026 begin
17027 DeselectHandles;
17028 //if Assigned( GlobalCanvas_OnObjectChanged ) then
17029 // GlobalCanvas_OnObjectChanged( Sender );
17030 end;
17032 {$IFDEF ASM_VERSION}
17033 //[procedure TCanvas.Pie]
17034 procedure TCanvas.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
17036 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
17037 PUSH dword ptr [EBP + 8]
17038 CALL RequiredState
17040 MOV EDX, EAX
17042 PUSH ESI
17043 LEA ESI, [Y4]
17046 XOR ECX, ECX
17047 MOV CL, 8
17048 @@1:
17049 LODSD
17050 PUSH EAX
17052 LOOP @@1
17055 PUSH EDX //Canvas.fHandle
17056 CALL Windows.Pie
17057 POP ESI
17058 end;
17059 {$ELSE ASM_VERSION} //Pascal
17060 procedure TCanvas.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
17061 begin
17062 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
17063 Windows.Pie( fHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);
17064 end;
17065 {$ENDIF ASM_VERSION}
17067 {++}(*
17068 {$IFDEF F_P}
17069 //[Windows API FUNCTIONS ADDITIONAL DECLARATIONS FOR Free Pascal]
17070 function Windows_Polygon; external gdi32 name 'Polygon';
17071 function Windows_Polyline; external gdi32 name 'Polyline';
17072 function FillRect; external user32 name 'FillRect';
17073 function OffsetRect; external user32 name 'OffsetRect';
17074 function CreateAcceleratorTable; external user32 name 'CreateAcceleratorTableA';
17075 function TrackPopupMenu; external user32 name 'TrackPopupMenu';
17076 function AdjustTokenPrivileges(TokenHandle: THandle; DisableAllPrivileges: BOOL;
17077 const NewState: TTokenPrivileges; BufferLength: DWORD;
17078 var PreviousState: TTokenPrivileges; var ReturnLength: DWORD): BOOL; external advapi32 name 'AdjustTokenPrivileges';
17079 function InflateRect; external user32 name 'InflateRect';
17080 {$IFDEF F_P105ORBELOW}
17081 function InvalidateRect; external user32 name 'InvalidateRect';
17082 function ValidateRect; external user32 name 'ValidateRect';
17083 {$ENDIF F_P105ORBELOW}
17084 //[END OF Windows API FUNCTIONS ADDITIONAL DECLARATIONS FOR Free Pascal]
17085 {$ENDIF}
17086 *){--}
17088 {$IFDEF ASM_VERSION}
17089 //[procedure TCanvas.Polygon]
17090 procedure TCanvas.Polygon(const Points: array of TPoint);
17092 INC ECX
17093 PUSH ECX
17094 PUSH EDX
17096 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
17097 PUSH EAX
17098 CALL RequiredState
17100 PUSH EAX
17101 CALL Windows.Polygon
17102 end;
17103 {$ELSE ASM_VERSION} //Pascal
17104 procedure TCanvas.Polygon(const Points: array of TPoint);
17105 type
17106 PPoints = ^TPoints;
17107 TPoints = array[0..0] of TPoint;
17108 begin
17109 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
17110 {$IFDEF F_P} Windows_Polygon
17111 {$ELSE DELPHI} Windows.Polygon
17112 {$ENDIF}( fHandle, PPoints(@Points)^, High(Points) + 1);
17113 end;
17114 {$ENDIF ASM_VERSION}
17116 {$IFDEF ASM_VERSION}
17117 //[procedure TCanvas.Polyline]
17118 procedure TCanvas.Polyline(const Points: array of TPoint);
17120 INC ECX
17121 PUSH ECX
17122 PUSH EDX
17124 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
17125 PUSH EAX
17126 CALL RequiredState
17128 PUSH EAX
17129 CALL Windows.Polyline
17130 end;
17131 {$ELSE ASM_VERSION} //Pascal
17132 procedure TCanvas.Polyline(const Points: array of TPoint);
17133 type
17134 PPoints = ^TPoints;
17135 TPoints = array[0..0] of TPoint;
17136 begin
17137 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
17138 {$IFDEF F_P}Windows_Polyline
17139 {$ELSE DELPHI}Windows.Polyline
17140 {$ENDIF}( fHandle, PPoints(@Points)^, High(Points) + 1);
17141 end;
17142 {$ENDIF ASM_VERSION}
17144 {$IFDEF ASM_VERSION}
17145 //[procedure TCanvas.Rectangle]
17146 procedure TCanvas.Rectangle(X1, Y1, X2, Y2: Integer);
17148 PUSH [Y2]
17149 PUSH [X2]
17150 PUSH ECX
17151 PUSH EDX
17153 PUSH HandleValid or BrushValid or PenValid or ChangingCanvas
17154 PUSH EAX
17155 CALL RequiredState
17157 PUSH EAX
17158 CALL Windows.Rectangle
17159 end;
17160 {$ELSE ASM_VERSION} //Pascal
17161 procedure TCanvas.Rectangle(X1, Y1, X2, Y2: Integer);
17162 begin
17163 RequiredState( HandleValid or BrushValid or PenValid or ChangingCanvas );
17164 Windows.Rectangle( fHandle, X1, Y1, X2, Y2);
17165 end;
17166 {$ENDIF ASM_VERSION}
17168 {$IFDEF ASM_VERSION}
17169 //[procedure TCanvas.RoundRect]
17170 procedure TCanvas.RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
17172 PUSH [Y3]
17173 PUSH [X3]
17174 PUSH [Y2]
17175 PUSH [X2]
17176 PUSH ECX
17177 PUSH EDX
17179 PUSH HandleValid or BrushValid or PenValid or ChangingCanvas
17180 PUSH EAX
17181 CALL RequiredState
17183 PUSH EAX
17184 CALL Windows.RoundRect
17185 end;
17186 {$ELSE ASM_VERSION} //Pascal
17187 procedure TCanvas.RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
17188 begin
17189 RequiredState( HandleValid or BrushValid or PenValid or ChangingCanvas );
17190 Windows.RoundRect( fHandle, X1, Y1, X2, Y2, X3, Y3);
17191 end;
17192 {$ENDIF ASM_VERSION}
17194 {$IFDEF ASM_VERSION}
17195 //[procedure TCanvas.TextArea]
17196 procedure TCanvas.TextArea(const Text: String; var Sz: TSize;
17197 var P0: TPoint);
17199 PUSH EBX
17200 MOV EBX, EAX
17202 PUSH ECX
17203 CALL TextExtent
17204 POP EDX
17206 MOV ECX, [P0]
17207 XOR EAX, EAX
17208 MOV [ECX].TPoint.x, EAX
17209 MOV [ECX].TPoint.y, EAX
17211 CMP [GlobalCanvas_OnTextArea], EAX
17212 JZ @@exit
17213 MOV EAX, EBX
17214 CALL [GlobalCanvas_OnTextArea]
17216 @@exit:
17217 POP EBX
17218 end;
17219 {$ELSE ASM_VERSION} //Pascal
17220 procedure TCanvas.TextArea(const Text: String; var Sz: TSize;
17221 var P0: TPoint);
17222 begin
17223 Sz := TextExtent( Text );
17224 P0.x := 0; P0.y := 0;
17225 if Assigned( GlobalCanvas_OnTextArea ) then
17226 GlobalCanvas_OnTextArea( @Self, Sz, P0 );
17227 end;
17228 {$ENDIF ASM_VERSION}
17230 {$IFDEF ASM_VERSION}
17231 //[function TCanvas.TextExtent]
17232 function TCanvas.TextExtent(const Text: string): TSize;
17234 PUSH EBX
17235 PUSH ESI
17236 MOV EBX, EAX
17238 PUSH ECX // prepare @Result
17240 MOV EAX, EDX
17241 CALL System.@LStrLen
17242 PUSH EAX // prepare Length(Text)
17244 CALL EDX2PChar
17245 PUSH EDX // prepare PChar(Text)
17247 PUSH HandleValid or FontValid
17248 PUSH EBX
17249 CALL RequiredState
17251 XCHG ESI, EAX
17252 TEST ESI, ESI // ESI = fHandle before
17253 JNZ @@1
17255 PUSH ESI
17256 CALL CreateCompatibleDC
17258 MOV EDX, EBX
17259 XCHG EAX, EDX // EAX := @Self; EDX := DC
17260 CALL SetHandle
17261 @@1:
17262 //********************************************************** // Added By M.Gerasimov
17264 CMP [EBX].TCanvas.fIsPaintDC, 1
17265 JZ @@2
17266 XOR ESI,ESI
17267 @@2:
17269 //********************************************************** // Added By M.Gerasimov
17270 PUSH HandleValid or FontValid
17271 PUSH EBX
17272 CALL RequiredState
17273 PUSH EAX // prepare DC
17275 CALL Windows.GetTextExtentPoint32
17277 TEST ESI, ESI
17278 JNZ @@exit
17280 XOR EDX, EDX
17281 XCHG EAX, EBX
17282 CALL SetHandle
17284 @@exit:
17285 POP ESI
17286 POP EBX
17287 end;
17288 {$ELSE ASM_VERSION} //Pascal
17289 function TCanvas.TextExtent(const Text: string): TSize;
17290 var DC : HDC;
17291 ClearHandle : Boolean;
17292 begin
17293 //Result.cX := 0;
17294 //Result.cY := 0;
17295 ClearHandle := False;
17296 RequiredState( HandleValid or FontValid );
17297 DC := fHandle;
17298 if DC = 0 then
17299 begin
17300 DC := CreateCompatibleDC( 0 );
17301 ClearHandle := True;
17302 SetHandle( DC );
17303 end;
17304 //********************************************************** // Added By Gerasimov
17306 If Not fIsPaintDC then ClearHandle := True;
17308 //********************************************************** // Added By Gerasimov
17309 RequiredState( HandleValid or FontValid );
17310 Windows.GetTextExtentPoint32( fHandle, PChar(Text), Length(Text), Result);
17311 if ClearHandle then
17312 SetHandle( 0 );
17313 { DC must be freed here automatically (never leaks):
17314 if Canvas created on base of existing DC, no memDC created,
17315 if Canvas has fHandle:HDC = 0, it is not fIsPaintDC always. }
17316 end;
17317 {$ENDIF ASM_VERSION}
17319 //[function TCanvas.TextHeight]
17320 function TCanvas.TextHeight(const Text: string): Integer;
17321 begin
17322 Result := TextExtent(Text).cY;
17323 end;
17325 {$IFDEF ASM_VERSION}
17326 //[procedure TCanvas.TextOut]
17327 procedure TCanvas.TextOut(X, Y: Integer; const Text: String); stdcall;
17329 PUSH EBX
17330 MOV EBX, [EBP+8]
17332 MOV EAX, [Text]
17333 PUSH EAX
17334 CALL System.@LStrLen
17335 XCHG EAX, [ESP] // prepare Length(Text)
17337 //CALL System.@LStrToPChar // string does not need to be null-terminated !
17338 PUSH EAX // prepare PChar(Text)
17339 PUSH [Y] // prepare Y
17340 PUSH [X] // prepare X
17342 PUSH HandleValid or FontValid or BrushValid or ChangingCanvas
17343 PUSH EBX
17344 CALL RequiredState
17345 PUSH EAX // prepare fHandle
17346 CALL Windows.TextOut
17348 { -- by suggetion of Alexey (Lecha2002)
17349 MOV EAX, EBX
17350 MOV EDX, [Text]
17351 CALL TextWidth
17352 MOV EDX, [X]
17353 ADD EDX, EAX
17355 MOV ECX, [Y]
17356 MOV EAX, EBX
17357 CALL MoveTo
17360 POP EBX
17361 end;
17362 {$ELSE ASM_VERSION} //Pascal
17363 procedure TCanvas.TextOut(X, Y: Integer; const Text: String); stdcall;
17364 begin
17365 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17366 Windows.TextOut(FHandle, X, Y, PChar(Text), Length(Text));
17367 //MoveTo(X + TextWidth(Text), Y); -- by suggestion of Alexey (Lecha2002)
17368 end;
17369 {$ENDIF ASM_VERSION}
17371 {$IFDEF ASM_VERSION}
17372 //[procedure TCanvas.TextRect]
17373 procedure TCanvas.TextRect(const Rect: TRect; X, Y: Integer; const Text: string);
17375 PUSH EBX
17376 XCHG EBX, EAX
17378 PUSH 0 // prepare 0
17380 PUSH EDX
17381 PUSH ECX
17383 MOV EAX, [Text]
17384 //CALL System.@LStrToPChar
17385 PUSH EAX
17387 //MOV EAX, [Text]
17388 CALL System.@LStrLen
17390 POP ECX // ECX = @Text[1]
17392 POP EDX // EDX = X
17393 XCHG EAX, [ESP] // prepare Length(Text), EAX = @Rect
17394 PUSH ECX // prepare PChar(Text)
17395 PUSH EAX // prepare @Rect
17397 XOR EAX, EAX
17398 MOV AL, ETO_CLIPPED // = 4
17399 MOV ECX, [EBX].fBrush
17400 JECXZ @@opaque
17402 CMP [ECX].TGraphicTool.fData.Brush.Style, bsClear
17403 JZ @@txtout
17405 @@opaque:
17406 DB $0C, ETO_OPAQUE //OR AL, ETO_OPAQUE
17407 @@txtout:
17408 PUSH EAX // prepare Options
17409 PUSH [Y] // prepare Y
17410 PUSH EDX // prepare X
17412 PUSH HandleValid or FontValid or BrushValid or ChangingCanvas
17413 PUSH EBX
17414 CALL RequiredState // EAX = fHandle
17415 PUSH EAX // prepare fHandle
17417 CALL Windows.ExtTextOut
17419 POP EBX
17420 end;
17421 {$ELSE ASM_VERSION} //Pascal
17422 procedure TCanvas.TextRect(const Rect: TRect; X, Y: Integer; const Text: string);
17424 Options: Integer;
17425 begin
17426 //Changing;
17427 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17428 Options := ETO_CLIPPED;
17429 if assigned( fBrush ) and (fBrush.fData.Brush.Style <> bsClear)
17430 or not assigned( fBrush ) then Inc(Options, ETO_OPAQUE);
17431 Windows.ExtTextOut( fHandle, X, Y, Options,
17432 @Rect, PChar(Text),
17433 Length(Text), nil);
17434 end;
17435 {$ENDIF ASM_VERSION}
17437 //[procedure TCanvas.ExtTextOut]
17438 procedure TCanvas.ExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect; const Text: String;
17439 const Spacing: array of Integer );
17440 begin
17441 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17442 Windows.ExtTextOut(FHandle, X, Y, Options, @Rect, PChar(Text), Length(Text), @Spacing[ 0 ]);
17443 end;
17445 //[procedure TCanvas.DrawText]
17446 procedure TCanvas.DrawText(Text:String; var Rect:TRect; Flags:DWord);
17447 begin
17448 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17449 Windows.DrawText(Handle,PChar(Text),Length(Text),Rect,Flags);
17450 end;
17452 //[function TCanvas.ClipRect]
17453 function TCanvas.ClipRect: TRect;
17454 begin
17455 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17456 GetClipBox(Handle, Result);
17457 end;
17459 //[function TCanvas.TextWidth]
17460 function TCanvas.TextWidth(const Text: string): Integer;
17461 begin
17462 Result := TextExtent(Text).cX;
17463 end;
17465 {$IFDEF ASM_VERSION}
17466 //[function TCanvas.GetBrush]
17467 function TCanvas.GetBrush: PGraphicTool;
17469 MOV ECX, [EAX].fBrush
17470 INC ECX
17471 LOOP @@exit
17473 PUSH EAX
17474 CALL NewBrush
17475 POP EDX
17476 PUSH EAX
17478 MOV [EDX].fBrush, EAX
17480 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, Offset[TCanvas.ObjectChanged]
17481 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
17482 MOV ECX, [EDX].fOwnerControl
17483 JECXZ @@1
17485 PUSH [ECX].TControl.fBrush
17486 MOV ECX, [ECX].TControl.fColor
17487 MOV [EAX].TGraphicTool.fData.Color, ECX
17488 POP EDX
17489 TEST EDX, EDX
17490 JZ @@1
17492 CALL TGraphicTool.Assign
17494 @@1: POP ECX
17496 @@exit: XCHG EAX, ECX
17497 end;
17498 {$ELSE ASM_VERSION} //Pascal
17499 function TCanvas.GetBrush: PGraphicTool;
17500 begin
17501 if not assigned( fBrush ) then
17502 begin
17503 fBrush := NewBrush;
17504 if assigned( fOwnerControl ) then
17505 begin
17506 fBrush.fData.Color := PControl(fOwnerControl).fColor;
17507 if assigned( PControl(fOwnerControl).fBrush ) then
17508 {fBrush := }fBrush.Assign( PControl(fOwnerControl).fBrush );
17509 // both statements above needed
17510 end;
17511 //fBrush.OnChange := ObjectChanged;
17512 AssignChangeEvents;
17513 end;
17514 Result := fBrush;
17515 end;
17516 {$ENDIF ASM_VERSION}
17518 {$IFDEF ASM_VERSION}
17519 //[function TCanvas.GetFont]
17520 function TCanvas.GetFont: PGraphicTool;
17522 MOV ECX, [EAX].TCanvas.fFont
17523 INC ECX
17524 LOOP @@exit
17526 PUSH EAX
17527 CALL NewFont
17528 POP EDX
17529 PUSH EAX
17531 MOV [EDX].TCanvas.fFont, EAX
17532 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, Offset[TCanvas.ObjectChanged]
17533 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
17535 MOV ECX, [EDX].fOwnerControl
17536 JECXZ @@1
17538 PUSH [ECX].TControl.fFont
17539 MOV ECX, [ECX].TControl.fTextColor
17540 MOV [EAX].TGraphicTool.fData.Color, ECX
17541 POP EDX
17542 TEST EDX, EDX
17543 JZ @@1
17545 CALL TGraphicTool.Assign
17547 @@1: POP ECX
17549 @@exit: MOV EAX, ECX
17550 end;
17551 {$ELSE ASM_VERSION} //Pascal
17552 function TCanvas.GetFont: PGraphicTool;
17553 begin
17554 if not assigned( fFont ) then
17555 begin
17556 fFont := NewFont;
17557 if assigned( fOwnerControl ) then
17558 begin
17559 fFont.Color := PControl(fOwnerControl).fTextColor;
17560 if assigned( PControl(fOwnerControl).fFont ) then
17561 {fFont := }fFont.Assign( PControl(fOwnerControl).fFont );
17562 end;
17563 //fFont.OnChange := ObjectChanged;
17564 AssignChangeEvents;
17565 end;
17566 Result := fFont;
17567 end;
17568 {$ENDIF ASM_VERSION}
17570 {$IFDEF ASM_VERSION}
17571 //[function TCanvas.GetPen]
17572 function TCanvas.GetPen: PGraphicTool;
17574 MOV ECX, [EAX].TCanvas.fPen
17575 INC ECX
17576 LOOP @@exit
17578 PUSH EAX
17579 CALL NewPen
17580 POP EDX
17581 MOV [EDX].fPen, EAX
17582 PUSH EAX
17583 MOV EAX, EDX
17584 CALL AssignChangeEvents
17585 POP ECX
17587 @@exit: MOV EAX, ECX
17588 end;
17589 {$ELSE ASM_VERSION} //Pascal
17590 function TCanvas.GetPen: PGraphicTool;
17591 begin
17592 if not assigned( fPen ) then
17593 begin
17594 fPen := NewPen;
17595 AssignChangeEvents;
17596 end;
17597 Result := fPen;
17598 end;
17599 {$ENDIF ASM_VERSION}
17601 {$IFDEF ASM_VERSION}
17602 //[function TCanvas.GetHandle]
17603 function TCanvas.GetHandle: HDC;
17605 CMP word ptr[EAX].fOnGetHandle.TMethod.Code+2, 0
17606 MOV EDX, EAX
17607 MOV EAX, [EDX].fHandle
17608 JZ @@exit
17609 MOV EAX, [EDX].fOnGetHandle.TMethod.Data
17610 PUSH EDX
17611 CALL [EDX].fOnGetHandle.TMethod.Code
17612 XCHG EAX, [ESP]
17613 POP EDX
17614 PUSH EDX
17615 CALL SetHandle
17616 POP EAX
17617 @@exit:
17618 end;
17619 {$ELSE ASM_VERSION} //Pascal
17620 function TCanvas.GetHandle: HDC;
17621 begin
17622 if assigned( fOnGetHandle ) then
17623 begin
17624 Result := fOnGetHandle( @Self );
17625 //fHandle := Result;
17626 SetHandle( Result );
17628 else
17629 Result := fHandle;
17630 end;
17631 {$ENDIF ASM_VERSION}
17633 {$IFDEF ASM_VERSION}
17634 //[procedure TCanvas.AssignChangeEvents]
17635 procedure TCanvas.AssignChangeEvents;
17637 PUSH ESI
17638 LEA ESI, [EAX].fBrush
17639 MOV CL, 3
17640 MOV EDX, EAX
17641 @@1: LODSD
17642 TEST EAX, EAX
17643 JZ @@nxt
17644 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
17645 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[ ObjectChanged ]
17646 @@nxt: DEC CL
17647 JNZ @@1
17648 POP ESI
17649 end;
17650 {$ELSE ASM_VERSION} //Pascal
17651 procedure TCanvas.AssignChangeEvents;
17652 begin
17653 if assigned( fFont ) then
17654 fFont.fOnChange := ObjectChanged;
17655 if assigned( fBrush ) then
17656 fBrush.fOnChange := ObjectChanged;
17657 if assigned( fPen ) then
17658 fPen.fOnChange := ObjectChanged;
17659 end;
17660 {$ENDIF ASM_VERSION}
17662 {$IFNDEF _FPC}
17663 {$IFNDEF _D2}
17664 //[procedure TCanvas.WDrawText]
17665 procedure TCanvas.WDrawText(WText: WideString; var Rect: TRect;
17666 Flags: DWord);
17667 begin
17668 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17669 Windows.DrawTextW(Handle,PWideChar(WText),Length(WText),Rect,Flags);
17670 end;
17672 //[procedure TCanvas.WExtTextOut]
17673 procedure TCanvas.WExtTextOut(X, Y: Integer; Options: DWORD;
17674 const Rect: TRect; const WText: WideString;
17675 const Spacing: array of Integer);
17676 begin
17677 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17678 Windows.ExtTextOutW(FHandle, X, Y, Options, @Rect, PWideChar(WText), Length(WText), @Spacing[ 0 ]);
17679 end;
17681 //[procedure TCanvas.WTextOut]
17682 procedure TCanvas.WTextOut(X, Y: Integer; const WText: WideString);
17683 begin
17684 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17685 Windows.TextOutW(FHandle, X, Y, PWideChar(WText), Length(WText));
17686 MoveTo(X + WTextWidth(WText), Y);
17687 end;
17689 //[procedure TCanvas.WTextRect]
17690 procedure TCanvas.WTextRect(const Rect: TRect; X, Y: Integer;
17691 const WText: WideString);
17693 Options: Integer;
17694 begin
17695 //Changing;
17696 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17697 Options := ETO_CLIPPED;
17698 if assigned( fBrush ) and (fBrush.fData.Brush.Style <> bsClear)
17699 or not assigned( fBrush ) then Inc(Options, ETO_OPAQUE);
17700 Windows.ExtTextOutW( fHandle, X, Y, Options,
17701 @Rect, PWideChar(WText),
17702 Length(WText), nil);
17703 end;
17705 //[function TCanvas.WTextExtent]
17706 function TCanvas.WTextExtent(const WText: WideString): TSize;
17707 var DC : HDC;
17708 ClearHandle : Boolean;
17709 begin
17710 ClearHandle := False;
17711 RequiredState( HandleValid or FontValid );
17712 DC := fHandle;
17713 if DC = 0 then
17714 begin
17715 DC := CreateCompatibleDC( 0 );
17716 ClearHandle := True;
17717 SetHandle( DC );
17718 end;
17719 RequiredState( HandleValid or FontValid );
17720 Windows.GetTextExtentPoint32W( fHandle, PWideChar(WText), Length(WText), Result);
17721 if ClearHandle then
17722 SetHandle( 0 );
17723 end;
17725 //[function TCanvas.WTextHeight]
17726 function TCanvas.WTextHeight(const WText: WideString): Integer;
17727 begin
17728 Result := WTextExtent( WText ).cy;
17729 end;
17731 //[function TCanvas.WTextWidth]
17732 function TCanvas.WTextWidth(const WText: WideString): Integer;
17733 begin
17734 Result := WTextExtent( WText ).cx;
17735 end;
17736 {$ENDIF _D2}
17737 {$ENDIF _FPC}
17749 //[function MakeInt64]
17750 function MakeInt64( Lo, Hi: DWORD ): I64;
17751 begin
17752 Result.Lo := Lo;
17753 Result.Hi := Hi;
17754 end;
17756 //[function Int2Int64]
17757 function Int2Int64( X: Integer ): I64;
17759 MOV [EDX], EAX
17760 MOV ECX, EDX
17762 MOV [ECX+4], EDX
17763 end;
17765 //[procedure IncInt64]
17766 procedure IncInt64( var I64: I64; Delta: Integer );
17768 ADD [EAX], EDX
17769 ADC dword ptr [EAX+4], 0
17770 end;
17772 //[procedure DecInt64]
17773 procedure DecInt64( var I64: I64; Delta: Integer );
17775 SUB [EAX], EDX
17776 SBB dword ptr [EDX], 0
17777 end;
17779 //[function Add64]
17780 function Add64( const X, Y: I64 ): I64;
17782 PUSH ESI
17783 XCHG ESI, EAX
17784 LODSD
17785 ADD EAX, [EDX]
17786 MOV [ECX], EAX
17787 LODSD
17788 ADC EAX, [EDX+4]
17789 MOV [ECX+4], EAX
17790 POP ESI
17791 end;
17793 //[function Sub64]
17794 function Sub64( const X, Y: I64 ): I64;
17796 PUSH ESI
17797 XCHG ESI, EAX
17798 LODSD
17799 SUB EAX, [EDX]
17800 MOV [ECX], EAX
17801 LODSD
17802 SBB EAX, [EDX+4]
17803 MOV [ECX+4], EAX
17804 POP ESI
17805 end;
17807 //[function Neg64]
17808 function Neg64( const X: I64 ): I64;
17810 MOV ECX, [EAX]
17811 NEG ECX
17812 MOV [EDX], ECX
17813 MOV ECX, 0
17814 SBB ECX, [EAX+4]
17815 MOV [EDX+4], ECX
17816 end;
17818 //[function Mul64EDX]
17819 function Mul64EDX( const X: I64; M: Integer ): I64;
17821 PUSH ESI
17822 PUSH EDI
17823 XCHG ESI, EAX
17824 MOV EDI, ECX
17825 MOV ECX, EDX
17826 LODSD
17827 MUL ECX
17828 STOSD
17829 XCHG EDX, ECX
17830 LODSD
17831 MUL EDX
17832 ADD EAX, ECX
17833 STOSD
17834 POP EDI
17835 POP ESI
17836 end;
17838 //[FUNCTION Mul64i]
17839 {$IFDEF ASM_VERSION}
17840 function Mul64i( const X: I64; Mul: Integer ): I64;
17841 asm //cmd //opd
17842 TEST EDX, EDX
17843 PUSHFD
17844 JGE @@1
17845 NEG EDX
17846 @@1: PUSH ECX
17847 CALL Mul64EDX
17848 POP EAX
17849 POPFD
17850 JGE @@2
17851 MOV EDX, EAX
17852 CALL Neg64
17853 @@2:
17854 end;
17855 {$ELSE ASM_VERSION} //Pascal
17856 function Mul64i( const X: I64; Mul: Integer ): I64;
17857 var Minus: Boolean;
17858 begin
17859 Minus := FALSE;
17860 if Mul < 0 then
17861 begin
17862 Minus := TRUE;
17863 Mul := -Mul;
17864 end;
17865 Result := Mul64EDX( X, Mul );
17866 if Minus then
17867 Result := Neg64( Result );
17868 end;
17869 {$ENDIF ASM_VERSION}
17870 //[END Mul64i]
17872 //[function Div64EDX]
17873 function Div64EDX( const X: I64; D: Integer ): I64;
17875 PUSH ESI
17876 PUSH EDI
17877 XCHG ESI, EAX
17878 MOV EDI, ECX
17879 MOV ECX, EDX
17880 MOV EAX, [ESI+4]
17882 DIV ECX
17883 MOV [EDI+4], EAX
17884 LODSD
17885 DIV ECX
17886 STOSD
17887 POP EDI
17888 POP ESI
17889 end;
17891 //[FUNCTION Div64i]
17892 {$IFDEF ASM_VERSION}
17893 function Div64i( const X: I64; D: Integer ): I64;
17894 asm //cmd //opd
17895 PUSH EBX
17896 XOR EBX, EBX
17897 PUSH ESI
17898 XCHG ESI, EAX
17899 LODSD
17900 MOV [ECX], EAX
17901 LODSD
17902 MOV [ECX+4], EAX
17903 MOV ESI, ECX
17904 PUSH EDX
17905 XCHG EAX, ECX
17906 CALL Sgn64
17907 TEST EAX, EAX
17908 JGE @@1
17909 INC EBX
17910 MOV EAX, ESI
17911 MOV EDX, ESI
17912 CALL Neg64
17913 @@1: POP EDX
17914 TEST EDX, EDX
17915 JGE @@2
17916 XOR EBX, 1
17917 NEG EDX
17918 @@2: MOV EAX, ESI
17919 MOV ECX, ESI
17920 CALL Div64EDX
17921 DEC EBX
17922 JNZ @@3
17923 MOV EDX, ESI
17924 XCHG EAX, ESI
17925 CALL Neg64
17926 @@3: POP ESI
17927 POP EBX
17928 end;
17929 {$ELSE ASM_VERSION} //Pascal
17930 function Div64i( const X: I64; D: Integer ): I64;
17931 var Minus: Boolean;
17932 begin
17933 Minus := FALSE;
17934 if D < 0 then
17935 begin
17936 D := -D;
17937 Minus := TRUE;
17938 end;
17939 Result := X;
17940 if Sgn64( Result ) < 0 then
17941 begin
17942 Result := Neg64( Result );
17943 Minus := not Minus;
17944 end;
17945 Result := Div64EDX( Result, D );
17946 if Minus then
17947 Result := Neg64( Result );
17948 end;
17949 {$ENDIF ASM_VERSION}
17950 //[END Div64i]
17952 //[function Mod64i]
17953 function Mod64i( const X: I64; D: Integer ): Integer;
17954 begin
17955 Result := Sub64( X, Mul64i( Div64i( X, D ), D ) ).Lo;
17956 end;
17958 //[function Sgn64]
17959 function Sgn64( const X: I64 ): Integer;
17961 XOR EDX, EDX
17962 CMP [EAX+4], EDX
17963 XCHG EAX, EDX
17964 JG @@ret_1
17965 JL @@ret_neg
17966 CMP [EDX], EAX
17967 JZ @@exit
17968 @@ret_1:
17969 INC EAX
17971 @@ret_neg:
17972 DEC EAX
17973 @@exit:
17974 end;
17976 //[function Cmp64]
17977 function Cmp64( const X, Y: I64 ): Integer;
17978 begin
17979 Result := Sgn64( Sub64( X, Y ) );
17980 end;
17982 //[function Int64_2Str]
17983 function Int64_2Str( X: I64 ): String;
17984 var M: Boolean;
17985 Y: Integer;
17986 Buf: array[ 0..31 ] of Char;
17987 I: Integer;
17988 begin
17989 M := FALSE;
17990 case Sgn64( X ) of
17991 -1: begin M := TRUE; X := Neg64( X ); end;
17992 0: begin Result := '0'; Exit; end;
17993 end;
17994 I := 31;
17995 Buf[ 31 ] := #0;
17996 while Sgn64( X ) > 0 do
17997 begin
17998 Dec( I );
17999 Y := Mod64i( X, 10 );
18000 Buf[ I ] := Char( Y + Integer( '0' ) );
18001 X := Div64i( X, 10 );
18002 end;
18003 if M then
18004 begin
18005 Dec( I );
18006 Buf[ I ] := '-';
18007 end;
18008 Result := PChar( @Buf[ I ] );
18009 end;
18011 //[function Str2Int64]
18012 function Str2Int64( const S: String ): I64;
18013 var I: Integer;
18014 M: Boolean;
18015 begin
18016 Result.Lo := 0;
18017 Result.Hi := 0;
18018 I := 1;
18019 if S = '' then Exit;
18020 M := FALSE;
18021 if S[ 1 ] = '-' then
18022 begin
18023 M := TRUE;
18024 Inc( I );
18026 else
18027 if S[ 1 ] = '+' then
18028 Inc( I );
18029 while I <= Length( S ) do
18030 begin
18031 if not( S[ I ] in [ '0'..'9' ] ) then
18032 break;
18033 Result := Mul64i( Result, 10 );
18034 IncInt64( Result, Integer( S[ I ] ) - Integer( '0' ) );
18035 Inc( I );
18036 end;
18037 if M then
18038 Result := Neg64( Result );
18039 end;
18041 //[function Int64_2Double]
18042 function Int64_2Double( const X: I64 ): Double;
18044 FILD qword ptr [EAX]
18045 FSTP @Result
18046 end;
18048 //[function Double2Int64]
18049 function Double2Int64( D: Double ): I64;
18051 FLD D
18052 FISTP qword ptr [EAX]
18053 end;
18056 function IsNan(const AValue: Double): Boolean;
18057 {$IFDEF _D2orD3}
18058 type PI64 = ^I64;
18059 {$ENDIF}
18060 begin
18062 Result := (PI64(@AValue).Hi and $7FF00000 = $7FF00000) and
18063 ((PI64(@AValue).Hi and $000FFFFF <> 0) or (PI64(@AValue).Lo <> 0));
18064 {+}{++}(*Result := AValue = NAN;*){--}
18065 end;
18067 //[function IntPower]
18068 function IntPower(Base: Extended; Exponent: Integer): Extended;
18069 {$IFDEF F_P}
18070 begin
18071 if Exponent = 0 then
18072 begin
18073 Result := 1.0;
18074 Exit;
18075 end;
18076 if Exponent < 0 then
18077 begin
18078 Exponent := -Exponent;
18079 Base := 1.0 / Base;
18080 end;
18081 Result := Base;
18082 REPEAT
18083 Result := Result * Base;
18084 Dec( Exponent );
18085 UNTIL Exponent <= 0;
18086 end;
18087 {$ELSE DELPHI}
18088 // This version of code by Galkov:
18089 // Changes in comparison to Delphi standard:
18090 // no Overflow exception if Exponent is very big negative value
18091 // (just 0 in result in such case).
18093 fld1 { Result := 1 }
18094 test eax,eax // check Exponent for 0, return 0 ** 0 = 1
18095 jz @@3 // (though Mathematics says that this is not so...)
18096 fld Base
18097 jg @@2
18098 fdivr ST,ST(1) { Base := 1 / Base }
18099 neg eax
18100 jmp @@2
18101 @@1: fmul ST,ST { X := Base * Base }
18102 @@2: shr eax,1
18103 jnc @@1
18104 fmul ST(1),ST { Result := Result * X }
18105 jnz @@1
18106 fstp st { pop X from FPU stack }
18107 @@3: fwait
18108 end;
18109 (* version of code by Borland:
18111 mov ecx, eax
18113 fld1 { Result := 1 }
18114 xor eax, edx
18115 sub eax, edx { eax := Abs(Exponent) }
18116 jz @@3
18117 fld Base
18118 jmp @@2
18119 @@1: fmul ST, ST { X := Base * Base }
18120 @@2: shr eax,1
18121 jnc @@1
18122 fmul ST(1),ST { Result := Result * X }
18123 jnz @@1
18124 fstp st { pop X from FPU stack }
18125 cmp ecx, 0
18126 jge @@3
18127 fld1
18128 fdivrp { Result := 1 / Result }
18129 @@3:
18130 fwait
18131 end;*)
18132 {$ENDIF F_P/DELPHI}
18134 //[function Str2Double]
18135 function Str2Double( const S: String ): Double;
18136 var I: Integer;
18137 M, Pt: Boolean;
18138 D: Double;
18139 Ex: Integer;
18140 begin
18141 Result := 0.0;
18142 if S = '' then Exit;
18143 M := FALSE;
18144 I := 1;
18145 if S[ 1 ] = '-' then
18146 begin
18147 M := TRUE;
18148 Inc( I );
18149 end;
18150 Pt := FALSE;
18151 D := 1.0;
18152 while I <= Length( S ) do
18153 begin
18154 case S[ I ] of
18155 '.': if not Pt then Pt := TRUE else break;
18156 '0'..'9': if not Pt then
18157 Result := Result * 10.0 + Integer( S[ I ] ) - Integer( '0' )
18158 else
18159 begin
18160 D := D * 0.1;
18161 Result := Result + (Integer( S[ I ] ) - Integer( '0' )) * D;
18162 end;
18163 'e', 'E': begin
18164 Ex := Str2Int( CopyEnd( S, I + 1 ) );
18165 Result := Result * IntPower( 10.0, Ex );
18166 break;
18167 end;
18168 end;
18169 Inc( I );
18170 end;
18171 if M then
18172 Result := -Result;
18173 end;
18175 //[function TruncD]
18176 function TruncD( D: Double ): Double;
18179 FLD D
18180 PUSH ECX
18181 FNSTCW [ESP]
18182 POP ECX
18183 PUSH ECX
18184 OR byte ptr [ESP+1], $0C
18185 FLDCW [ESP]
18186 PUSH ECX
18187 FRNDINT
18188 FSTP @Result
18189 FLDCW [ESP]
18190 POP ECX
18191 POP ECX
18192 end;
18193 {+}{++}(*
18194 begin
18195 Result := Trunc( D );
18196 end;
18197 *){--}
18199 // Precision 15
18200 //[function Extended2Str]
18201 function Extended2Str( E: Extended ): String;
18202 function UnpackFromBuf( const Buf: array of Byte; N: Integer ): String;
18203 var I, J, K, L: Integer;
18204 begin
18205 SetLength( Result, 16 );
18206 J := 1;
18207 for I := 7 downto 0 do
18208 begin
18209 K := Buf[ I ] shr 4;
18210 Result[ J ] := Char( Ord('0') + K );
18211 Inc( J );
18212 K := Buf[ I ] and $F;
18213 Result[ J ] := Char( Ord('0') + K );
18214 Inc( J );
18215 end;
18217 Assert( Result[ 1 ] = '0', 'error!' );
18218 Delete( Result, 1, 1 );
18220 if N <= 0 then
18221 begin
18222 while N < 0 do
18223 begin
18224 Result := '0' + Result;
18225 Inc( N );
18226 end;
18227 Result := '0.' + Result;
18229 else
18230 if N < Length( Result ) then
18231 begin
18232 Result := Copy( Result, 1, N ) + '.' + CopyEnd( Result, N + 1 );
18234 else
18235 begin
18236 while N > Length( Result ) do
18237 begin
18238 Result := Result + '0';
18239 end;
18240 Exit;
18241 end;
18243 L := Length( Result );
18244 while L > 1 do
18245 begin
18246 if not (Result[ L ] in ['0','.']) then break;
18247 Dec( L );
18248 if Result[ L + 1 ] = '.' then break;
18249 end;
18250 if L < Length( Result ) then Delete( Result, L + 1, MaxInt );
18252 end;
18255 S: Boolean;
18256 var F: Extended;
18257 N: Integer;
18258 Buf1: array[ 0..9 ] of Byte;
18259 I10: Integer;
18260 begin
18261 Result := '0';
18262 if E = 0 then Exit;
18263 S := E < 0;
18264 if S then E := -E;
18266 N := 15;
18267 F := 5E12;
18268 I10 := 10;
18269 while E < F do
18270 begin
18271 Dec( N );
18272 E := E * I10;
18273 end;
18274 if N = 15 then
18275 while E >= 1E13 do
18276 begin
18277 Inc( N );
18278 E := E / I10;
18279 end;
18281 while TRUE do
18282 begin
18284 FLD [E]
18285 FBSTP [Buf1]
18286 end;
18287 if Buf1[ 7 ] <> 0 then break;
18288 E := E * I10;
18289 Dec( N );
18290 end;
18292 Result := UnpackFromBuf( Buf1, N );
18294 if S then Result := '-' + Result;
18295 end;
18297 //[function Double2Str]
18298 function Double2Str( D: Double ): String;
18299 begin
18300 Result := Extended2Str( D );
18301 end;
18303 //[function Double2StrEx]
18304 function Double2StrEx( D: Double ): String;
18305 var E, E1, E2: Double;
18306 S: String;
18307 begin
18308 Result := Double2Str( D );
18309 E := Str2Double( Result );
18310 E1 := E - D;
18311 if E1 < 0.0 then E1 := -E1;
18312 if E1 < 1e-307 then Exit;
18313 while TRUE do
18314 begin
18315 E := D - (E - D) * 0.3;
18316 S := Double2Str( E );
18317 if S = Result then break;
18318 E := Str2Double( S );
18319 E2 := E - D;
18320 if E2 < 0.0 then E2 := -E2;
18321 if E2 > E1 * 0.75 then break;
18322 Result := S;
18323 if E2 < E1 * 0.1 then break;
18324 end;
18325 end;
18327 //[function GetBits]
18328 function GetBits( N: DWORD; first, last: Byte ): DWord;
18329 {$IFDEF F_P}
18330 begin
18331 Result := 0;
18332 if last > 31 then last := 31;
18333 if first > last then Exit;
18334 Result := (N and not ($FFFFFFFF shl last)) shr first;
18335 end;
18336 {$ELSE DELPHI}
18338 XCHG EAX, EDX // (1) EDX=N, AL=first
18339 {$IFDEF PARANOIA}
18340 DB $3C, 31
18341 {$ELSE}
18342 CMP AL, 31 // first(AL) > 31 ?
18343 {$ENDIF}
18344 JBE @@1 // (2) åñëè äà, òî Result := 0;
18345 @@0:
18346 XOR EAX, EAX // (2)
18347 RET // (1)
18348 @@1:
18350 XCHG EAX, ECX // (1) AL = last CL = first
18351 SHR EDX, CL // (2) EDX = N shr first
18352 SUB AL, CL // (2) AL = last - first
18353 JL @@0 // (2) åñëè last < first òî Result := 0;
18355 {$IFDEF PARANOIA}
18356 DB $3C, 32
18357 {$ELSE}
18358 CMP AL, 32 // (2) last - first >= 32 ?
18359 {$ENDIF}
18360 XCHG ECX, EAX // (1) CL = last - first
18361 XCHG EAX, EDX // (1) EAX = N shr first
18362 JAE @@exit // (2) åñëè last - first > 31, òî Result := EAX;
18363 SBB EDX, EDX // (2) EDX = -1
18364 DEC EDX // (1) EDX = 1111...10 = -2
18365 SHL EDX, CL // (2) EDX = 111...100..0 (ãäå n(0)=last-first+1)
18366 NOT EDX // (2) EDX = ìàñêà 000..0111...1 (ãäå n(1)=last-first+1)
18367 AND EAX, EDX // (2)
18368 @@exit:
18369 // EAX = ðåçóëüòàò, (1 áàéò íà êîìàíäó RET)
18370 end;
18371 {$ENDIF F_P/DELPHI}
18373 //[function GetBitsL]
18374 function GetBitsL( N: DWORD; from, len: Byte ): DWord;
18375 {$IFDEF F_P}
18376 begin
18377 Result := GetBits( N, from, from + len - 1 );
18378 end;
18379 {$ELSE DELPHI}
18381 ADD CL, DL
18382 DEC CL
18383 JMP GetBits
18384 end;
18385 {$ENDIF F_P/DELPHI}
18387 //[FUNCTION Int2Hex]
18388 {$IFDEF ASM_VERSION}
18389 function Int2Hex( Value : DWord; Digits : Integer ) : String;
18392 // EAX = Value
18393 // EDX = Digits (actually DL needed)
18394 // ECX = @Result
18396 PUSH 0
18397 ADD ESP, -0Ch
18399 PUSH EBX
18400 PUSH ECX
18402 LEA EBX, [ESP+8+0Fh] // EBX := @Buf[ 15 ]
18403 AND EDX, $F
18405 @@loop: DEC EBX
18406 DEC EDX
18408 PUSH EAX
18409 {$IFDEF PARANOIA}
18410 DB $24, $0F
18411 {$ELSE}
18412 AND AL, 0Fh
18413 {$ENDIF}
18414 {$IFDEF PARANOIA}
18415 DB $3C, 9
18416 {$ELSE}
18417 CMP AL, 9
18418 {$ENDIF}
18419 JA @@10
18420 {$IFDEF PARANOIA}
18421 DB $04, 30h-41h+0Ah
18422 {$ELSE}
18423 ADD AL,30h-41h+0Ah
18424 {$ENDIF}
18425 @@10:
18426 {$IFDEF PARANOIA}
18427 DB $04, 41h-0Ah
18428 {$ELSE}
18429 ADD AL,41h-0Ah
18430 {$ENDIF}
18431 MOV byte ptr [EBX], AL
18432 POP EAX
18433 SHR EAX, 4
18435 JNZ @@loop
18437 TEST EDX, EDX
18438 JG @@loop
18440 POP EAX // EAX = @Result
18441 MOV EDX, EBX // EDX = @resulting string
18442 CALL System.@LStrFromPChar
18444 POP EBX
18445 ADD ESP, 10h
18447 {== by KSer - to test it only.
18448 function Int2Hex( Value : DWord; Digits : Integer ) : shortString;
18450 MOV [ECX], DL
18451 XADD EDX, ECX
18452 @@loop1:
18453 PUSH EAX
18454 db $24, $0F // and al,$0F
18456 //AAD
18457 DB $D5, $11
18458 db $04, $30 // add al,$30
18459 MOV [EDX], AL
18460 POP EAX
18461 SHR EAX, 4
18462 DEC EDX
18463 LOOP @@loop1
18465 end;
18466 {$ELSE ASM_VERSION} //Pascal (mixed)
18467 function Int2Hex( Value : DWord; Digits : Integer ) : String;
18468 var Buf: array[ 0..8 ] of Char;
18469 Dest : PChar;
18471 function HexDigit( B : Byte ) : Char;
18472 {$IFDEF F_P}
18473 const
18474 HexDigitChr: array[ 0..15 ] of Char = ( '0','1','2','3','4','5','6','7',
18475 '8','9','A','B','C','D','E','F' );
18476 begin
18477 Result := HexDigitChr[ B and $F ];
18478 end;
18479 {$ELSE DELPHI}
18481 {$IFDEF PARANOIA}
18482 DB $3C,9
18483 {$ELSE}
18484 CMP AL,9
18485 {$ENDIF}
18486 JA @@1
18487 {$IFDEF PARANOIA}
18488 DB $04, $30-$41+$0A
18489 {$ELSE}
18490 ADD AL,30h-41h+0Ah
18491 {$ENDIF}
18492 @@1:
18493 {$IFDEF PARANOIA}
18494 DB $04, $41-$0A
18495 {$ELSE}
18496 ADD AL,41h-0Ah
18497 {$ENDIF}
18498 end;
18499 {$ENDIF F_P/DELPHI}
18500 begin
18501 Dest := @Buf[ 8 ];
18502 Dest^ := #0;
18503 repeat
18504 Dec( Dest );
18505 Dest^ := '0';
18506 if Value <> 0 then
18507 begin
18508 Dest^ := HexDigit( Value and $F );
18509 Value := Value shr 4;
18510 end;
18511 Dec( Digits );
18512 until (Value = 0) and (Digits <= 0);
18513 Result := Dest;
18514 end;
18515 {$ENDIF ASM_VERSION}
18516 //[END Int2Hex]
18518 //[FUNCTION Hex2Int]
18519 {$IFDEF ASM_VERSION}
18520 function Hex2Int( const Value : String) : Integer;
18522 CALL EAX2PChar
18523 PUSH ESI
18524 XCHG ESI, EAX
18525 XOR EDX, EDX
18526 TEST ESI, ESI
18527 JE @@exit
18528 LODSB
18529 {$IFDEF PARANOIA}
18530 DB $3C, '$'
18531 {$ELSE}
18532 CMP AL, '$'
18533 {$ENDIF}
18534 JNE @@1
18535 @@0: LODSB
18536 @@1: TEST AL, AL
18537 JE @@exit
18538 {$IFDEF PARANOIA}
18539 DB $2C, '0'
18540 {$ELSE}
18541 SUB AL, '0'
18542 {$ENDIF}
18543 {$IFDEF PARANOIA}
18544 DB $3C, 9
18545 {$ELSE}
18546 CMP AL, '9' - '0'
18547 {$ENDIF}
18548 JBE @@3
18550 {$IFDEF PARANOIA}
18551 DB $2C, $11
18552 {$ELSE}
18553 SUB AL, 'A' - '0'
18554 {$ENDIF}
18555 {$IFDEF PARANOIA}
18556 DB $3C, 5
18557 {$ELSE}
18558 CMP AL, 'F' - 'A'
18559 {$ENDIF}
18560 JBE @@2
18562 {$IFDEF PARANOIA}
18563 DB $2C, 32
18564 {$ELSE}
18565 SUB AL, 32
18566 {$ENDIF}
18567 {$IFDEF PARANOIA}
18568 DB $3C, 5
18569 {$ELSE}
18570 CMP AL, 'F' - 'A'
18571 {$ENDIF}
18572 JA @@exit
18573 @@2:
18574 {$IFDEF PARANOIA}
18575 DB $04, 0Ah
18576 {$ELSE}
18577 ADD AL, 0Ah
18578 {$ENDIF}
18579 @@3:
18580 SHL EDX, 4
18581 ADD DL, AL
18582 JMP @@0
18584 @@exit: XCHG EAX, EDX
18585 POP ESI
18586 end;
18587 {$ELSE ASM_VERSION} //Pascal
18588 function Hex2Int( const Value : String) : Integer;
18589 var I : Integer;
18590 begin
18591 Result := 0;
18592 I := 1;
18593 if Value = '' then Exit;
18594 if Value[ 1 ] = '$' then Inc( I );
18595 while I <= Length( Value ) do
18596 begin
18597 if Value[ I ] in [ '0'..'9' ] then
18598 Result := (Result shl 4) or (Ord(Value[I]) - Ord('0'))
18599 else
18600 if Value[ I ] in [ 'A'..'F' ] then
18601 Result := (Result shl 4) or (Ord(Value[I]) - Ord('A') + 10)
18602 else
18603 if Value[ I ] in [ 'a'..'f' ] then
18604 Result := (Result shl 4) or (Ord(Value[I]) - Ord('a') + 10)
18605 else
18606 break;
18607 Inc( I );
18608 end;
18609 end;
18610 {$ENDIF ASM_VERSION}
18611 //[END Hex2Int]
18613 //[FUNCTION Octal2Int]
18614 function Octal2Int( const Value: String ) : Integer;
18615 var I: Integer;
18616 begin
18617 Result := 0;
18618 for I := 1 to Length( Value ) do
18619 begin
18620 if Value[ I ] in [ '0'..'7' ] then
18621 Result := Result * 8 + Ord( Value[ I ] ) - Ord( '0' )
18622 else break;
18623 end;
18624 end;
18625 //[END Octal2Int]
18627 //[FUNCTION Binary2Int]
18628 function Binary2Int( const Value: String ) : Integer;
18629 var I: Integer;
18630 begin
18631 Result := 0;
18632 for I := 1 to Length( Value ) do
18633 begin
18634 if Value[ I ] in [ '0'..'1' ] then
18635 Result := Result * 2 + Ord( Value[ I ] ) - Ord( '0' )
18636 else break;
18637 end;
18638 end;
18639 //[END Binary2Int]
18641 //[FUNCTION cHex2Int]
18642 {$IFDEF ASM_VERSION}
18643 function cHex2Int( const Value : String) : Integer;
18645 TEST EAX, EAX
18646 JZ @@exit
18647 CMP word ptr [EAX], '0x'
18648 JZ @@skip_2_chars
18649 CMP word ptr [EAX], '0X'
18650 JNZ @@2Hex2Int
18651 @@skip_2_chars:
18652 INC EAX
18653 INC EAX
18654 @@2Hex2Int:
18655 JMP Hex2Int
18656 @@exit:
18657 end;
18658 {$ELSE ASM_VERSION}
18659 function cHex2Int( const Value : String) : Integer;
18660 begin
18661 if StrEq( Copy( Value, 1, 2 ), '0x' ) then
18662 Result := Hex2Int( CopyEnd( Value, 3 ) )
18663 else Result := Hex2Int( Value );
18664 end;
18665 {$ENDIF ASM_VERSION}
18666 //[END cHex2Int]
18668 //[FUNCTION Int2Str]
18669 {$IFDEF ASM_VERSION}
18670 function Int2Str( Value : Integer ) : String;
18672 XOR ECX, ECX
18673 PUSH ECX
18674 ADD ESP, -0Ch
18676 PUSH EBX
18677 LEA EBX, [ESP + 15 + 4]
18678 PUSH EDX
18679 CMP EAX, ECX
18680 PUSHFD
18681 JGE @@1
18682 NEG EAX
18683 @@1:
18684 MOV CL, 10
18686 @@2:
18687 DEC EBX
18688 XOR EDX, EDX
18689 DIV ECX
18690 ADD DL, 30h
18691 MOV [EBX], DL
18692 TEST EAX, EAX
18693 JNZ @@2
18695 POPFD
18696 JGE @@3
18698 DEC EBX
18699 MOV byte ptr [EBX], '-'
18700 @@3:
18701 POP EAX
18702 MOV EDX, EBX
18703 CALL System.@LStrFromPChar
18705 POP EBX
18706 ADD ESP, 10h
18707 end;
18708 {$ELSE ASM_VERSION} //Pascal
18709 function Int2Str( Value : Integer ) : String;
18710 var Buf : array[ 0..15 ] of Char;
18711 Dst : PChar;
18712 Minus : Boolean;
18713 D: DWORD;
18714 begin
18715 Dst := @Buf[ 15 ];
18716 Dst^ := #0;
18717 Minus := False;
18718 if Value < 0 then
18719 begin
18720 Value := -Value;
18721 Minus := True;
18722 end;
18723 D := Value;
18724 repeat
18725 Dec( Dst );
18726 Dst^ := Char( (D mod 10) + Byte( '0' ) );
18727 D := D div 10;
18728 until D = 0;
18729 if Minus then
18730 begin
18731 Dec( Dst );
18732 Dst^ := '-';
18733 end;
18734 Result := Dst;
18735 end;
18736 {$ENDIF ASM_VERSION}
18737 //[END Int2Str]
18739 //[function UInt2Str]
18740 function UInt2Str( Value: DWORD ): String;
18741 var Buf : array[ 0..15 ] of Char;
18742 Dst : PChar;
18743 D: DWORD;
18744 begin
18745 Dst := @Buf[ 15 ];
18746 Dst^ := #0;
18747 D := Value;
18748 repeat
18749 Dec( Dst );
18750 Dst^ := Char( (D mod 10) + Byte( '0' ) );
18751 D := D div 10;
18752 until D = 0;
18753 Result := Dst;
18754 end;
18756 //[function Int2StrEx]
18757 function Int2StrEx( Value, MinWidth: Integer ): String;
18758 begin
18759 Result := Int2Str( Value );
18760 while Length( Result ) < MinWidth do
18761 Result := ' ' + Result;
18762 end;
18764 //[function Int2Rome]
18765 function Int2Rome( Value: Integer ): String;
18766 const RomeDigs: String = 'IVXLCDMT';
18767 function RomeNum( N, FromIdx: Integer ): String;
18768 begin
18769 CASE N OF
18770 1, 2, 3: Result := StrRepeat( RomeDigs[ FromIdx ], N );
18771 4: Result := RomeDigs[ FromIdx ] + RomeDigs[ FromIdx + 1 ];
18772 5, 6, 7, 8: Result := RomeDigs[ FromIdx + 1 ] + StrRepeat( RomeDigs[ FromIdx ],
18773 N - 5 );
18774 9: Result := RomeDigs[ FromIdx ] + RomeDigs[ FromIdx + 2 ]
18775 else Result := '';
18776 END;
18777 end;
18778 var I, J: Integer;
18779 begin
18780 Result := '';
18781 if Value < 1 then Exit;
18782 if Value > 8999 then Exit;
18783 // maximum possible is TMMMCMXCIX, i.e. 8999
18784 J := 1;
18785 for I := 1 to 3 do
18786 begin
18787 Result := RomeNum( Value mod 10, J ) + Result;
18788 Value := Value div 10;
18789 if Value = 0 then Exit;
18790 Inc( J, 2 );
18791 end;
18792 end;
18794 //[FUNCTION Int2Ths]
18795 {$IFDEF ASM_VERSION}
18796 function Int2Ths( I : Integer ) : String;
18798 PUSH EBP
18799 MOV EBP, ESP
18800 PUSH EAX
18801 PUSH EDX
18802 CALL Int2Str
18803 POP EDX
18804 POP EAX
18805 CMP EAX, 1000
18806 JL @@Exit
18807 PUSH EDX
18808 MOV EAX, [EDX]
18809 PUSH EAX
18810 CALL System.@LStrLen // EAX = Length(Result)
18811 POP EDX
18812 PUSH EDX // EDX = @Result[ 1 ]
18813 XOR ECX, ECX
18815 @@1:
18816 ROL ECX, 8
18817 DEC EAX
18818 MOV CL, [EDX+EAX]
18819 JZ @@fin
18820 CMP ECX, 300000h
18821 JL @@1
18823 PUSH ECX
18824 XOR ECX, ECX
18825 MOV CL, ','
18826 JMP @@1
18828 @@fin: CMP CX, ',-'
18829 JNE @@fin1
18830 MOV CH, 0 // this corrects -,ddd,...
18831 @@fin1: CMP ECX, 01000000h
18832 JGE @@fin2
18833 INC EAX
18834 ROL ECX, 8
18835 JMP @@fin1
18836 @@fin2: PUSH ECX
18838 LEA EDX, [ESP+EAX]
18839 MOV EAX, [EBP-4]
18840 CALL System.@LStrFromPChar
18841 @@Exit:
18842 MOV ESP, EBP
18843 POP EBP
18844 end;
18845 {$ELSE ASM_VERSION} //Pascal
18846 function Int2Ths( I : Integer ) : String;
18847 var S : String;
18848 begin
18849 S := Int2Str( I );
18850 Result := '';
18851 while S <> '' do
18852 begin
18853 if Result <> '' then
18854 Result := ',' + Result;
18855 Result := CopyTail( S, 3 ) + Result;
18856 S := Copy( S, 1, Length( S ) - 3 );
18857 end;
18858 if Copy( Result, 1, 2 ) = '-,' then
18859 Result := '-' + CopyEnd( Result, 3 );
18860 end;
18861 {$ENDIF ASM_VERSION}
18862 //[END Int2Ths]
18864 //[FUNCTION Int2Digs]
18865 {$IFDEF ASM_VERSION}
18866 function Int2Digs( Value, Digits : Integer ) : String;
18868 PUSH EBP
18869 MOV EBP, ESP
18870 PUSH EDX // [EBP-4] = Digits
18871 PUSH ECX
18872 MOV EDX, ECX
18873 CALL Int2Str
18874 POP ECX
18875 PUSH ECX // [EBP-8] = @Result
18876 MOV EAX, [ECX]
18877 PUSH EAX
18878 CALL System.@LStrLen
18879 POP EDX // EDX = @Result[1]
18880 MOV ECX, EAX // ECX = Length( Result )
18881 ADD EAX, EAX
18882 SUB ESP, EAX
18883 MOV EAX, ESP
18884 PUSHAD
18885 CALL StrCopy
18886 POPAD
18887 MOV EDX, EAX
18888 ADD ESP, -100
18889 CMP byte ptr [EDX], '-'
18890 PUSHFD
18891 JNE @@1
18892 INC EDX
18893 @@1:
18894 MOV EAX, [EBP-4] // EAX = Digits
18895 CMP ECX, EAX
18896 JGE @@2
18897 DEC EDX
18898 MOV byte ptr [EDX], '0'
18899 INC ECX
18900 JMP @@1
18901 @@2:
18902 POPFD
18903 JNE @@3
18904 DEC EDX
18905 MOV byte ptr [EDX], '-'
18906 @@3:
18907 MOV EAX, [EBP-8]
18908 CALL System.@LStrFromPChar
18909 MOV ESP, EBP
18910 POP EBP
18911 end;
18912 {$ELSE ASM_VERSION} //Pascal
18913 function Int2Digs( Value, Digits : Integer ) : String;
18914 var M : String;
18915 begin
18916 Result := Int2Str( Value );
18917 M := '';
18918 if Value < 0 then
18919 begin
18920 M := '-';
18921 Result := CopyEnd( Result, 2 );
18922 end;
18923 if Digits >= 0 then
18924 while Length( M + Result ) < Digits do
18925 Result := '0' + Result
18926 else
18927 while Length( Result ) < -Digits do
18928 Result := '0' + Result;
18929 Result := M + Result;
18930 end;
18931 {$ENDIF ASM_VERSION}
18932 //[END Int2Digs]
18934 //[FUNCTION Num2Bytes]
18935 {$IFDEF ASM_VERSION}
18936 function Num2Bytes( Value : Double ) : String;
18938 PUSH EBX
18939 PUSH ESI
18940 PUSH EDI
18941 MOV EBX, ESP
18942 MOV ESI, EAX
18944 MOV ECX, 4
18945 MOV EDX, 'TGMk'
18946 @@1:
18947 FLD [Value]
18948 @@10:
18949 FICOM dword ptr [@@1024]
18950 FSTSW AX
18951 SAHF
18952 JB @@2
18954 FIDIV dword ptr [@@1024]
18955 FST [Value]
18956 WAIT
18958 TEST DL, 20h
18959 JE @@ror
18960 AND DL, not 20h
18961 JMP @@nxt
18962 @@1024: DD 1024
18963 @@100: DD 100
18965 @@ror:
18966 ROR EDX, 8
18967 @@nxt:
18968 LOOP @@10
18969 @@2:
18970 TEST DL, 20h
18971 JZ @@3
18972 MOV DL, 0
18973 @@3: MOV DH, 0
18974 PUSH DX
18975 MOV EDI, ESP
18977 FLD ST(0)
18978 CALL System.@TRUNC
18979 {$IFDEF _D2orD3}
18980 PUSH 0
18981 {$ELSE}
18982 PUSH EDX
18983 {$ENDIF}
18984 PUSH EAX
18985 FILD qword ptr [ESP]
18986 POP EDX
18987 POP EDX
18989 MOV EDX, ESI
18990 CALL Int2Str
18992 FSUBP ST(1), ST
18993 FIMUL dword ptr [@@100]
18994 CALL System.@TRUNC
18996 TEST EAX, EAX
18997 JZ @@4
18999 XOR ECX, ECX
19000 MOV CL, 0Ah
19002 IDIV ECX
19003 TEST EDX, EDX
19004 JZ @@5
19006 MOV AH, DL
19007 SHL EAX, 16
19008 ADD EAX, '00. '
19009 PUSH EAX
19010 MOV EDI, ESP
19011 INC EDI
19012 JMP @@4
19014 @@5: SHL EAX, 8
19015 ADD AX, '0.'
19016 PUSH AX
19017 MOV EDI, ESP
19019 @@4:
19020 MOV EAX, [ESI]
19021 CALL System.@LStrLen
19022 ADD ESP, -100
19024 SUB EDI, EAX
19025 PUSH ESI
19026 PUSH EDI
19027 MOV ESI, [ESI]
19028 MOV ECX, EAX
19029 REP MOVSB
19031 POP EDX
19032 POP EAX
19033 CALL System.@LStrFromPChar
19035 MOV ESP, EBX
19036 POP EDI
19037 POP ESI
19038 POP EBX
19039 end;
19040 {$ELSE ASM_VERSION} //Pascal
19041 function Num2Bytes( Value : Double ) : String;
19042 const Suffix = 'KMGT';
19043 var V, I : Integer;
19044 begin
19045 Result := '';
19046 I := 0;
19047 while (Value >= 1024) and (I < 4) do
19048 begin
19049 Inc( I );
19050 Value := Value / 1024.0;
19051 end;
19052 Result := Int2Str( Trunc( Value ) );
19053 V := Trunc( (Value - Trunc( Value )) * 100 );
19054 if V <> 0 then
19055 begin
19056 if (V mod 10) = 0 then
19057 V := V div 10;
19058 Result := Result + ',' + Int2Str( V );
19059 end;
19060 if I > 0 then
19061 Result := Result + Suffix[ I ];
19062 end;
19063 {$ENDIF ASM_VERSION}
19064 //[END Num2Bytes]
19066 //[FUNCTION S2Int]
19067 {$IFDEF ASM_VERSION}
19068 function S2Int( S: PChar ): Integer;
19070 XCHG EDX, EAX
19071 XOR EAX, EAX
19072 TEST EDX, EDX
19073 JZ @@exit
19075 XOR ECX, ECX
19076 MOV CL, [EDX]
19077 INC EDX
19078 CMP CL, '-'
19079 PUSHFD
19080 JE @@0
19081 @@1: CMP CL, '+'
19082 JNE @@2
19083 @@0: MOV CL, [EDX]
19084 INC EDX
19085 @@2: SUB CL, '0'
19086 CMP CL, '9'-'0'
19087 JA @@fin
19088 LEA EAX, [EAX+EAX*4] //
19089 LEA EAX, [ECX+EAX*2] //
19090 JMP @@0
19091 @@fin: POPFD
19092 JNE @@exit
19093 NEG EAX
19094 @@exit:
19095 end;
19096 {$ELSE ASM_VERSION} //Pascal
19097 function S2Int( S: PChar ): Integer;
19098 var M : Integer;
19099 begin
19100 Result := 0;
19101 if S = '' then Exit;
19102 M := 1;
19103 if S^ = '-' then
19104 begin
19105 M := -1;
19106 Inc( S );
19108 else
19109 if S^ = '+' then
19110 Inc( S );
19111 while S^ in [ '0'..'9' ] do
19112 begin
19113 Result := Result * 10 + Integer( S^ ) - Integer( '0' );
19114 Inc( S );
19115 end;
19116 if M < 0 then
19117 Result := -Result;
19118 end;
19119 {$ENDIF ASM_VERSION}
19120 //[END S2Int]
19122 //[FUNCTION Str2Int]
19123 {$IFDEF ASM_VERSION}
19124 function Str2Int(const Value : String) : Integer;
19126 CALL EAX2PChar
19127 CALL S2Int
19128 end;
19129 {$ELSE ASM_VERSION} //Pascal
19130 function Str2Int(const Value : String) : Integer;
19131 begin
19132 Result := S2Int( PChar( Value ) );
19133 end;
19134 {$ENDIF ASM_VERSION}
19135 //[END Str2Int]
19137 //[function StrCopy]
19138 function StrCopy( Dest, Source: PChar ): PChar; assembler;
19140 {$IFDEF F_P}
19141 MOV EAX, [Dest]
19142 MOV EDX, [Source]
19143 {$ENDIF F_P}
19144 PUSH EDI
19145 PUSH ESI
19146 MOV ESI,EAX
19147 MOV EDI,EDX
19148 OR ECX, -1
19149 XOR AL,AL
19150 REPNE SCASB
19151 NOT ECX
19152 MOV EDI,ESI
19153 MOV ESI,EDX
19154 MOV EDX,ECX
19155 MOV EAX,EDI
19156 SHR ECX,2
19157 REP MOVSD
19158 MOV ECX,EDX
19159 AND ECX,3
19160 REP MOVSB
19161 POP ESI
19162 POP EDI
19163 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
19165 function StrCat( Dest, Source: PChar ): PChar;
19166 begin
19167 StrCopy( StrScan( Dest, #0 ), Source );
19168 Result := Dest;
19169 end;
19171 //[function StrScan]
19172 function StrScan(Str: PChar; Chr: Char): PChar; assembler;
19174 {$IFDEF F_P}
19175 MOV EAX, [Str]
19176 MOVZX EDX, [Chr]
19177 {$ENDIF}
19178 PUSH EDI
19179 PUSH EAX
19180 MOV EDI,Str
19181 OR ECX, -1
19182 XOR AL,AL
19183 REPNE SCASB
19184 NOT ECX
19185 POP EDI
19186 XCHG EAX, EDX
19187 REPNE SCASB
19189 XCHG EAX, EDI
19190 POP EDI
19192 JE @@1
19193 XOR EAX, EAX
19196 @@1: DEC EAX
19197 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
19199 //[function StrRScan]
19200 function StrRScan(const Str: PChar; Chr: Char): PChar; assembler;
19202 {$IFDEF F_P}
19203 MOV EAX, [Str]
19204 MOVZX EDX, [Chr]
19205 {$ENDIF F_P}
19206 PUSH EDI
19207 MOV EDI,Str
19208 MOV ECX,0FFFFFFFFH
19209 XOR AL,AL
19210 REPNE SCASB
19211 NOT ECX
19213 DEC EDI
19214 MOV AL,Chr
19215 REPNE SCASB
19216 MOV EAX,0
19217 JNE @@1
19218 MOV EAX,EDI
19219 INC EAX
19220 @@1: CLD
19221 POP EDI
19222 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
19224 //[function StrScanLen]
19225 function StrScanLen(Str: PChar; Chr: Char; Len: Integer): PChar; assembler;
19227 {$IFDEF F_P}
19228 MOV EAX, [Str]
19229 MOVZX EDX, [Chr]
19230 MOV ECX, [Len]
19231 {$ENDIF F_P}
19232 PUSH EDI
19233 XCHG EDI, EAX
19234 XCHG EAX, EDX
19235 REPNE SCASB
19237 XCHG EAX, EDI
19238 POP EDI
19239 { -> EAX => to next character after found or to the end of Str,
19240 ZF = 0 if character found. }
19241 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
19243 //[FUNCTION TrimLeft]
19244 {$IFDEF ASM_VERSION}
19245 function TrimLeft(const S: string): string;
19247 XCHG EAX, EDX
19248 CALL EDX2PChar
19249 DEC EDX
19250 @@1: INC EDX
19251 MOVZX ECX, byte ptr [EDX]
19252 JECXZ @@fin
19253 CMP CL, ' '
19254 JBE @@1
19255 @@fin:
19256 CALL System.@LStrFromPChar
19257 end;
19258 {$ELSE ASM_VERSION} //Pascal
19259 function TrimLeft(const S: string): string;
19261 I, L: Integer;
19262 begin
19263 L := Length(S);
19264 I := 1;
19265 while (I <= L) and (S[I] <= ' ') do Inc(I);
19266 Result := Copy(S, I, Maxint);
19267 end;
19268 {$ENDIF ASM_VERSION}
19269 //[END TrimLeft]
19271 //[FUNCTION TrimRight]
19272 {$IFDEF ASM_VERSION}
19273 function TrimRight(const S: string): string;
19275 PUSH EDX
19276 PUSH EAX
19278 PUSH EAX
19279 CALL System.@LStrLen
19280 XCHG EAX, [ESP]
19281 //CALL System.@LStrToPChar
19282 CALL EAX2PChar
19283 POP ECX
19284 INC ECX
19285 @@1: DEC ECX
19286 MOV DL, [EAX+ECX]
19287 JL @@fin
19288 CMP DL, ' '
19289 JBE @@1
19290 @@fin:
19291 INC ECX
19292 POP EAX
19293 XOR EDX, EDX
19294 INC EDX
19295 CALL System.@LStrCopy
19296 end;
19297 {$ELSE ASM_VERSION} //Pascal
19298 function TrimRight(const S: string): string;
19300 I: Integer;
19301 begin
19302 I := Length(S);
19303 while (I > 0) and (S[I] <= ' ') do Dec(I);
19304 Result := Copy(S, 1, I);
19305 end;
19306 {$ENDIF ASM_VERSION}
19307 //[END TrimRight]
19309 //[FUNCTION Trim]
19310 {$IFDEF ASM_VERSION}
19311 function Trim( const S : string): string;
19313 PUSH EDX
19314 CALL TrimRight
19315 POP EDX
19316 MOV EAX, [EDX]
19317 CALL TrimLeft
19318 end;
19319 {$ELSE ASM_VERSION} //Pascal
19320 function Trim( const S : string): string;
19321 begin
19322 Result := TrimLeft( TrimRight( S ) );
19323 end;
19324 {$ENDIF ASM_VERSION}
19325 //[END Trim]
19327 //[function RemoveSpaces]
19328 function RemoveSpaces( const S: String ): String;
19329 var I: Integer;
19330 begin
19331 Result := S;
19332 for I := Length( S ) downto 1 do
19333 if S[ I ] <= ' ' then Delete( Result, I, 1 );
19334 end;
19336 //[procedure Str2LowerCase]
19337 procedure Str2LowerCase( S: PChar );
19339 {$IFDEF F_P}
19340 MOV EAX, [S]
19341 {$ENDIF}
19342 XOR ECX, ECX
19343 @@1:
19344 MOV CL, byte ptr [EAX]
19345 JECXZ @@exit
19346 SUB CL, 'A'
19347 CMP CL, 'Z'-'A'
19348 JA @@2
19349 ADD byte ptr [EAX], 32
19350 @@2: INC EAX
19351 JMP @@1
19352 @@exit:
19353 end {$IFDEF F_P} [ 'EAX', 'ECX' ] {$ENDIF};
19355 //[FUNCTION LowerCase]
19356 {$IFDEF ASM_VERSION}
19357 function LowerCase(const S: string): string;
19359 PUSH ESI
19360 XCHG EAX, EDX
19361 PUSH EAX
19362 CALL System.@LStrAsg
19363 POP EAX
19365 CALL UniqueString
19367 PUSH EAX
19368 CALL System.@LStrLen
19369 POP ESI
19371 XCHG ECX, EAX
19373 JECXZ @@exit
19375 @@go:
19376 LODSB
19377 {$IFDEF PARANOIA}
19378 DB $2C, 'A'
19379 {$ELSE}
19380 SUB AL, 'A'
19381 {$ENDIF}
19382 {$IFDEF PARANOIA}
19383 DB $3C, 26
19384 {$ELSE}
19385 CMP AL, 'Z'-'A'+1
19386 {$ENDIF}
19387 JNB @@1
19389 ADD byte ptr [ESI - 1], 20h
19390 @@1:
19391 LOOP @@go
19392 @@exit:
19393 POP ESI
19394 end;
19395 {$ELSE ASM_VERSION} //Pascal
19396 function LowerCase(const S: string): string;
19397 var I : Integer;
19398 begin
19399 Result := S;
19400 for I := 1 to Length( S ) do
19401 if Result[ I ] in [ 'A'..'Z' ] then
19402 Inc( Result[ I ], 32 );
19403 end;
19404 {$ENDIF ASM_VERSION}
19405 //[END LowerCase]
19407 //[FUNCTION UpperCase]
19408 {$IFDEF ASM_VERSION}
19409 function UpperCase(const S: string): string;
19411 PUSH ESI
19412 XCHG EAX, EDX
19413 PUSH EAX
19414 CALL System.@LStrAsg
19415 POP EAX
19417 CALL UniqueString
19419 PUSH EAX
19420 CALL System.@LStrLen
19421 POP ESI
19423 XCHG ECX, EAX
19425 JECXZ @@exit
19427 @@go:
19428 LODSB
19429 {$IFDEF PARANOIA}
19430 DB $2C, 'a'
19431 {$ELSE}
19432 SUB AL, 'a'
19433 {$ENDIF}
19434 {$IFDEF PARANOIA}
19435 DB $3C, $1A
19436 {$ELSE}
19437 CMP AL, 'z'-'a'+1
19438 {$ENDIF}
19439 JNB @@1
19441 SUB byte ptr [ESI - 1], 20h
19442 @@1:
19443 LOOP @@go
19444 @@exit:
19445 POP ESI
19446 end;
19447 {$ELSE ASM_VERSION} //Pascal
19448 function UpperCase(const S: string): string;
19449 var I : Integer;
19450 begin
19451 Result := S;
19452 for I := 1 to Length( S ) do
19453 if Result[ I ] in [ 'a'..'z' ] then
19454 Dec( Result[ I ], 32 );
19455 end;
19456 {$ENDIF ASM_VERSION}
19457 //[END UpperCase]
19459 {$IFDEF F_P}
19460 //[function DummyStrFun]
19461 function DummyStrFun( const S: String ): String;
19462 begin
19463 Result := S;
19464 end;
19465 {$ENDIF F_P}
19467 //[FUNCTION CopyEnd]
19468 {$IFDEF ASM_VERSION}
19469 function CopyEnd( const S : String; Idx : Integer ) : String;
19471 PUSH ECX
19472 PUSH EAX
19473 PUSH EDX
19475 CALL System.@LStrLen
19477 POP EDX
19478 TEST EDX, EDX
19479 JG @@1
19480 XOR EDX, EDX
19481 INC EDX
19482 @@1:
19483 SUB EAX, EDX
19484 MOV ECX, EAX
19486 POP EAX
19487 JGE @@ret_end
19489 POP EAX
19490 JL System.@LStrClr
19492 @@ret_end:
19493 INC ECX
19494 CALL System.@LStrCopy
19495 end;
19496 {$ELSE ASM_VERSION} //Pascal
19497 function CopyEnd( const S : String; Idx : Integer ) : String;
19498 begin
19499 Result := Copy( S, Idx, MaxInt );
19500 end;
19501 {$ENDIF ASM_VERSION}
19502 //[END CopyEnd]
19504 //[FUNCTION CopyTail]
19505 {$IFDEF ASM_VERSION}
19506 function CopyTail( const S : String; Len : Integer ) : String;
19508 PUSH ECX
19509 PUSH EAX
19510 PUSH EDX
19511 CALL System.@LStrLen
19512 POP ECX
19513 CMP ECX, EAX
19514 {$IFDEF USE_CMOV}
19515 CMOVG ECX, EAX
19516 {$ELSE}
19517 JLE @@1
19518 MOV ECX, EAX
19519 @@1: {$ENDIF}
19521 MOV EDX, EAX
19522 SUB EDX, ECX
19523 INC EDX
19524 POP EAX
19525 CALL System.@LStrCopy
19526 end;
19527 {$ELSE ASM_VERSION} //Pascal
19528 function CopyTail( const S : String; Len : Integer ) : String;
19529 var L : Integer;
19530 begin
19531 L := Length( S );
19532 if L < Len then
19533 Len := L;
19534 Result := '';
19535 if Len = 0 then Exit;
19536 Result := Copy( S, L - Len + 1, Len );
19537 end;
19538 {$ENDIF ASM_VERSION}
19539 //[END CopyTail]
19541 //[PROCEDURE DeleteTail]
19542 {$IFDEF ASM_VERSION}
19543 procedure DeleteTail( var S : String; Len : Integer );
19545 PUSH EAX
19546 PUSH EDX
19547 MOV EAX, [EAX]
19548 CALL System.@LStrLen
19549 POP ECX
19550 CMP ECX, EAX
19551 {$IFDEF USE_CMOV}
19552 CMOVG ECX, EAX
19553 {$ELSE}
19554 JLE @@1
19555 MOV ECX, EAX
19556 @@1: {$ENDIF}
19558 MOV EDX, EAX
19559 SUB EDX, ECX
19560 INC EDX
19561 POP EAX
19562 CALL System.@LStrDelete
19563 end;
19564 {$ELSE ASM_VERSION} //Pascal
19565 procedure DeleteTail( var S : String; Len : Integer );
19566 var L : Integer;
19567 begin
19568 L := Length( S );
19569 if Len > L then
19570 Len := L;
19571 Delete( S, L - Len + 1, Len );
19572 end;
19573 {$ENDIF ASM_VERSION}
19574 //[END DeleteTail]
19576 //[FUNCTION IndexOfChar]
19577 {$IFDEF ASM_VERSION}
19578 function IndexOfChar( const S : String; Chr : Char ) : Integer;
19580 //PUSH EDX
19581 //CALL System.@LStrToPChar
19582 //POP EDX
19583 CALL EAX2PChar
19584 PUSH EAX
19585 CALL StrScan
19586 POP EDX
19587 TEST EAX, EAX
19588 JE @@exit__1
19589 SUB EAX, EDX
19590 INC EAX
19592 @@exit__1:
19593 DEC EAX
19594 end;
19595 {$ELSE ASM_VERSION} //Pascal
19596 function IndexOfChar( const S : String; Chr : Char ) : Integer;
19597 var P, F : PChar;
19598 begin
19599 P := PChar( S );
19600 F := StrScan( P, Chr );
19601 Result := -1;
19602 if F = nil then Exit;
19603 Result := Integer( F ) - Integer( P ) + 1;
19604 end;
19605 {$ENDIF ASM_VERSION}
19606 //[END IndexOfChar]
19608 //[FUNCTION IndexOfCharsMin]
19609 {$IFDEF ASM_VERSION}
19610 function IndexOfCharsMin( const S, Chars : String ) : Integer;
19612 PUSH ESI
19613 PUSH EAX
19614 CALL EDX2PChar
19615 MOV ESI, EDX
19617 XOR ECX, ECX
19618 DEC ECX
19620 @@1: LODSB
19621 TEST AL, AL
19622 JZ @@exit
19624 XCHG EDX, EAX
19625 POP EAX
19626 PUSH EAX
19628 PUSH ECX
19629 CALL IndexOfChar
19630 POP ECX
19631 TEST EAX, EAX
19632 JLE @@1
19634 TEST ECX, ECX
19635 JLE @@2
19636 CMP EAX, ECX
19637 JGE @@1
19638 @@2: //XCHG ECX, EAX
19639 //JMP @@1
19641 @@exit: XCHG EAX, ECX
19642 JL @@1
19643 POP ECX
19644 POP ESI
19645 end;
19646 {$ELSE ASM_VERSION} //Pascal
19647 function IndexOfCharsMin( const S, Chars : String ) : Integer;
19648 var I, J : Integer;
19649 begin
19650 Result := -1;
19651 for I := 1 to Length( Chars ) do
19652 begin
19653 J := IndexOfChar( S, Chars[ I ] );
19654 if J > 0 then
19655 begin
19656 if (Result < 0) or (J < Result) then
19657 Result := J;
19658 end;
19659 end;
19660 end;
19661 {$ENDIF ASM_VERSION}
19662 //[END IndexOfCharsMin]
19664 {$IFNDEF _FPC}
19665 {$IFNDEF _D2}
19666 //[function IndexOfWideCharsMin]
19667 function IndexOfWideCharsMin( const S, Chars : WideString ) : Integer;
19668 var I, J : Integer;
19669 begin
19670 Result := -1;
19671 for I := 1 to Length( Chars ) do
19672 begin
19673 J := pos( Chars[ I ], S );
19674 if J > 0 then
19675 begin
19676 if (Result < 0) or (J < Result) then
19677 Result := J;
19678 end;
19679 end;
19680 end;
19681 {$ENDIF _D2}
19682 {$ENDIF _FPC}
19684 //[FUNCTION IndexOfStr]
19685 {$IFDEF ASM_VERSION}
19686 function IndexOfStr( const S, Sub : String ) : Integer;
19688 PUSH EBX
19689 PUSH ESI
19690 PUSH EDI
19692 PUSH EAX
19693 MOV EAX, EDX
19694 PUSH EDX
19695 CALL System.@LStrLen
19696 MOV EDI, EAX
19697 POP EAX
19698 //CALL System.@LStrToPChar
19699 CALL EAX2PChar
19700 MOV BL, [EAX]
19701 XCHG EAX, [ESP]
19702 //CALL System.@LStrToPChar
19703 CALL EAX2PChar
19705 MOV ESI, EAX
19707 DEC EAX
19708 @@1: INC EAX
19709 MOV DL, BL
19710 CALL StrScan
19711 TEST EAX, EAX
19712 JE @@exit__1
19714 POP EDX
19715 PUSH EDX
19717 MOV ECX, EDI
19718 PUSH EAX
19719 CALL StrLComp
19720 POP EAX
19721 JNE @@1
19723 SUB EAX, ESI
19724 INC EAX
19725 JMP @@exit
19727 @@exit__1:
19728 DEC EAX
19729 @@exit:
19730 POP EDX
19731 POP EDI
19732 POP ESI
19733 POP EBX
19734 end;
19735 {$ELSE ASM_VERSION} //Pascal
19736 function IndexOfStr( const S, Sub : String ) : Integer;
19737 var I : Integer;
19738 begin
19739 Result := Length( S );
19740 if Sub = '' then Exit;
19741 Result := 0;
19742 if S = '' then Exit;
19743 if Length( Sub ) > Length( S ) then Exit;
19744 Result := 1;
19745 while Result + Length( Sub ) - 1 <= Length( S ) do
19746 begin
19747 I := IndexOfChar( CopyEnd( S, Result ), Sub[ 1 ] );
19748 if I <= 0 then break;
19749 Result := Result + I - 1;
19750 if Result <= 0 then Exit;
19751 if Copy( S, Result, Length( Sub ) ) = Sub then Exit;
19752 Inc( Result );
19753 end;
19754 Result := -1;
19755 end;
19756 {$ENDIF ASM_VERSION}
19757 //[END IndexOfStr]
19759 //[FUNCTION Parse]
19760 {$IFDEF ASM_VERSION} //???
19761 function Parse( var S : String; const Separators : String ) : String;
19763 PUSH EBX
19764 PUSH EDI
19765 MOV EBX, EAX
19767 PUSH ECX
19768 MOV EAX, [EBX]
19769 CALL IndexOfCharsMin
19770 INC EAX
19771 JNE @@1
19772 MOV EAX, [EBX]
19773 CALL System.@LStrLen
19774 INC EAX
19775 INC EAX
19776 @@1:
19777 DEC EAX
19778 MOV EDI, EAX
19779 MOV ECX, EAX
19780 DEC ECX
19781 XOR EDX, EDX
19782 INC EDX
19783 MOV EAX, [EBX]
19784 CALL System.@LStrCopy
19786 MOV EAX, [EBX]
19787 MOV EDX, EDI
19788 INC EDX
19789 MOV ECX, EBX
19790 CALL CopyEnd
19792 POP EDI
19793 POP EBX
19794 end;
19795 {$ELSE ASM_VERSION} //Pascal
19796 function Parse( var S : String; const Separators : String ) : String;
19797 var Pos : Integer;
19798 begin
19799 Pos := IndexOfCharsMin( S, Separators );
19800 if Pos <= 0 then
19801 Pos := Length( S ) + 1;
19802 Result := S;
19803 S := Copy( Result, Pos + 1, MaxInt );
19804 Result := Copy( Result, 1, Pos - 1 );
19805 end;
19806 {$ENDIF ASM_VERSION}
19807 //[END Parse]
19809 {$IFNDEF _FPC}
19810 {$IFNDEF _D2}
19811 //[function WParse]
19812 function WParse( var S : WideString; const Separators : WideString ) : WideString;
19813 var Pos : Integer;
19814 begin
19815 Pos := IndexOfWideCharsMin( S, Separators );
19816 if Pos <= 0 then
19817 Pos := Length( S ) + 1;
19818 Result := S;
19819 S := Copy( Result, Pos + 1, MaxInt );
19820 Result := Copy( Result, 1, Pos - 1 );
19821 end;
19822 {$ENDIF _D2}
19823 {$ENDIF _FPC}
19825 //[function ParsePascalString]
19826 function ParsePascalString( var S : String; const Separators : String ) : String;
19827 var Pos, Idx : Integer;
19828 Hex, Spc : boolean;
19829 procedure SkipSpaces;
19830 begin
19831 if not Spc then
19832 while (Length( S ) >= Pos) and (S[ Pos ] = ' ') do
19833 Inc( Pos );
19834 end;
19835 var Buf : String;
19836 Ou, Val : Integer;
19837 begin
19838 Pos := 1;
19839 Spc := IndexOfChar( Separators, ' ' ) >= 0;
19840 SkipSpaces;
19841 if Length( S ) < Pos then
19842 begin
19843 Result := S;
19844 S := '';
19845 exit;
19846 end;
19847 Buf := PChar( S );
19848 Ou := 1;
19849 if S[ Pos ] in [ '''', '#' ] then
19850 begin
19851 // skip here string constant expression
19852 while Pos <= Length( S ) do
19853 begin
19854 if S[ Pos ] = '''' then
19855 begin
19856 Inc( Pos );
19857 while Pos <= Length( S ) do
19858 begin
19859 if S[ Pos ] = '''' then
19860 if (Pos = Length( S )) or (S[ Pos+1 ] <> '''') then
19861 begin
19862 Inc( Pos );
19863 break;
19865 else Inc( Pos );
19866 Buf[ Ou ] := S[ Pos ];
19867 Inc( Ou );
19868 Inc( Pos );
19869 end;
19870 //if Pos < Length( S ) then Inc( Pos );
19872 else
19873 if S[ Pos ] = '#' then
19874 begin
19875 Inc( Pos ); Hex := False; Val := 0;
19876 if (Pos < Length( S )) and (S[ Pos ] = '$') then
19877 begin
19878 Inc( Pos ); Hex := True;
19879 end;
19880 Dec( Pos );
19881 while Pos < Length( S ) do
19882 begin
19883 Inc( Pos );
19884 if (S[ Pos ] in [ '0'..'9' ]) or
19885 Hex and (S[ Pos ] in [ 'a'..'f', 'A'..'F' ]) then
19886 begin
19887 if Hex then
19888 Val := Val * 16
19889 else
19890 Val := Val * 10;
19891 if S[ Pos ] <= '9' then
19892 Val := Val + Integer( S[ Pos ] ) - Integer( '0' )
19893 else
19894 if S[ Pos ] <= 'F' then
19895 Val := Val + 10 + Integer( S[ Pos ] ) - Integer( 'A' )
19896 else
19897 Val := Val + 10 + Integer( S[ Pos ] ) - Integer( 'a' );
19898 continue;
19899 end;
19900 Inc( Pos ); break;
19901 end;
19902 Buf[ Ou ] := Char( Val );
19903 Inc( Ou );
19905 else break;
19906 SkipSpaces;
19907 if S[ Pos ] <> '+' then break;
19908 SkipSpaces;
19909 end;
19910 end;
19911 Idx := IndexOfCharsMin( CopyEnd( S, Pos ), Separators );
19912 if Idx <= 0 then
19913 begin
19914 Result := Copy( Buf, 1, Ou - 1 ) + CopyEnd( S, Pos );
19915 S := '';
19917 else
19918 begin
19919 Result := Copy( Buf, 1, Ou - 1 ) + Copy( S, Pos, Idx - 1 );
19920 S := CopyEnd( S, Pos + Idx );
19921 end;
19922 end;
19924 //[function String2PascalStrExpr]
19925 function String2PascalStrExpr( const S : String ) : String;
19926 var I, Strt : Integer;
19927 function String2DoubleQuotas( const S : String ) : String;
19928 var I, J : Integer;
19929 begin
19930 if IndexOfChar( S, '''' ) <= 0 then
19931 Result := S
19932 else
19933 begin
19934 J := 0;
19935 for I := 1 to Length( S ) do
19936 if S[ I ] = '''' then Inc( J );
19937 SetLength( Result, Length( S ) + J );
19938 J := 1;
19939 for I := 1 to Length( S ) do
19940 begin
19941 Result[ J ] := S[ I ];
19942 Inc( J );
19943 if S[ I ] = '''' then
19944 begin
19945 Result[ J ] := '''';
19946 Inc( J );
19947 end;
19948 end;
19949 end;
19950 end;
19951 begin
19952 Result := '';
19953 if S = '' then
19954 begin
19955 Result := '''''';
19956 exit;
19957 end;
19958 Strt := 1;
19959 for I := 1 to Length( S ) + 1 do
19960 begin
19961 if (I > Length( S )) or (S[ I ] < ' ') then
19962 begin
19963 if (I > Strt) and (I > 1) then
19964 begin
19965 if Result <> '' then
19966 Result := Result + '+';
19967 Result := Result + '''' + String2DoubleQuotas( Copy( S, Strt, I - Strt ) ) + '''';
19968 end;
19969 if I > Length( S ) then break;
19970 if Result <> '' then
19971 Result := Result + '+'
19972 else
19973 Result := Result + '''''+';
19974 Result := Result + '#' + Int2Str( Integer( S[ I ] ) );
19975 Strt := I + 1;
19976 end;
19977 end;
19978 end;
19980 //[function CompareMem]
19981 function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
19983 {$IFDEF F_P}
19984 MOV EAX, [P1]
19985 MOV EDX, [P2]
19986 MOV ECX, [Length]
19987 {$ENDIF}
19988 PUSH ESI
19989 PUSH EDI
19990 MOV ESI,P1
19991 MOV EDI,P2
19992 MOV EDX,ECX
19993 XOR EAX,EAX
19994 AND EDX,3
19995 SHR ECX,1
19996 SHR ECX,1
19997 REPE CMPSD
19998 JNE @@2
19999 MOV ECX,EDX
20000 REPE CMPSB
20001 JNE @@2
20002 @@1: INC EAX
20003 @@2: POP EDI
20004 POP ESI
20005 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20007 //[FUNCTION AllocMem]
20008 {$IFDEF ASM_VERSION}
20009 function AllocMem( Size : Integer ) : Pointer;
20010 asm //cmd //opd
20011 TEST EAX, EAX
20012 JZ @@exit
20013 PUSH EAX
20014 CALL System.@GetMem
20015 POP EDX
20016 PUSH EAX
20017 MOV CL, 0
20018 CALL System.@FillChar
20019 POP EAX
20020 @@exit:
20021 end;
20022 {$ELSE ASM_VERSION} //Pascal
20023 function AllocMem( Size : Integer ) : Pointer;
20024 begin
20025 Result := nil;
20026 if Size > 0 then
20027 begin
20028 GetMem( Result, Size );
20029 FillChar( Result^, Size, 0 );
20030 end;
20031 end;
20032 {$ENDIF ASM_VERSION}
20033 //[END AllocMem]
20035 //[procedure DisposeMem]
20036 procedure DisposeMem( var Addr : Pointer );
20037 begin
20038 if Addr <> nil then
20039 FreeMem( Addr );
20040 Addr := nil;
20041 end;
20043 //[function AnsiUpperCase]
20044 function AnsiUpperCase(const S: string): string;
20046 Len: Integer;
20047 begin
20048 Len := Length(S);
20049 SetString(Result, PChar(S), Len);
20050 if Len > 0 then CharUpperBuff(Pointer(Result), Len);
20051 end;
20053 //[function AnsiLowerCase]
20054 function AnsiLowerCase(const S: string): string;
20056 Len: Integer;
20057 begin
20058 Len := Length(S);
20059 SetString(Result, PChar(S), Len);
20060 if Len > 0 then CharLowerBuff(Pointer(Result), Len);
20061 end;
20063 {$IFNDEF _D2}
20064 {$IFNDEF _FPC}
20065 //[function WAnsiUpperCase]
20066 function WAnsiUpperCase(const S: WideString): WideString;
20067 var Len: Integer;
20068 begin
20069 Len := Length(S);
20070 Result := S;
20071 if Len > 0 then CharUpperBuffW(Pointer(Result), Len);
20072 end;
20074 //[function WAnsiLowerCase]
20075 function WAnsiLowerCase(const S: WideString): WideString;
20076 var Len: Integer;
20077 begin
20078 Len := Length(S);
20079 Result := S;
20080 if Len > 0 then CharLowerBuffW(Pointer(Result), Len);
20081 end;
20082 {$ENDIF _FPC}
20083 {$ENDIF _D2}
20085 //[function AnsiCompareStr]
20086 function AnsiCompareStr(const S1, S2: string): Integer;
20087 begin
20088 Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), -1,
20089 PChar(S2), -1 ) - 2;
20090 end;
20092 //[function _AnsiCompareStr]
20093 function _AnsiCompareStr(S1, S2: PChar): Integer;
20094 begin
20095 Result := CompareString( LOCALE_USER_DEFAULT, 0, S1, -1,
20096 S2, -1) - 2;
20097 end;
20099 //[function AnsiCompareStrNoCase]
20100 function AnsiCompareStrNoCase(const S1, S2: string): Integer;
20101 begin
20102 Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1), -1,
20103 PChar(S2), -1 ) - 2;
20104 end;
20106 //[function _AnsiCompareStrNoCase]
20107 function _AnsiCompareStrNoCase(S1, S2: PChar): Integer;
20108 begin
20109 Result := CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE, S1, -1,
20110 S2, -1) - 2;
20111 end;
20113 //[function AnsiCompareText]
20114 function AnsiCompareText( const S1, S2: String ): Integer;
20115 begin
20116 Result := AnsiCompareStrNoCase( S1, S2 );
20117 end;
20119 //[function StrLCopy]
20120 function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar; assembler;
20122 {$IFDEF F_P}
20123 MOV EAX, [Dest]
20124 MOV EDX, [Source]
20125 MOV ECX, [MaxLen]
20126 {$ENDIF F_P}
20127 PUSH EDI
20128 PUSH ESI
20129 PUSH EBX
20130 MOV ESI,EAX
20131 MOV EDI,EDX
20132 MOV EBX,ECX
20133 XOR AL,AL
20134 TEST ECX,ECX
20135 JZ @@1
20136 REPNE SCASB
20137 JNE @@1
20138 INC ECX
20139 @@1: SUB EBX,ECX
20140 MOV EDI,ESI
20141 MOV ESI,EDX
20142 MOV EDX,EDI
20143 MOV ECX,EBX
20144 SHR ECX,2
20145 REP MOVSD
20146 MOV ECX,EBX
20147 AND ECX,3
20148 REP MOVSB
20149 STOSB
20150 MOV EAX,EDX
20151 POP EBX
20152 POP ESI
20153 POP EDI
20154 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20156 //[FUNCTION StrPCopy]
20157 {$IFDEF ASM_VERSION}
20158 function StrPCopy(Dest: PChar; const Source: string): PChar;
20160 PUSH EAX
20161 MOV EAX, EDX
20162 CALL System.@LStrLen
20163 MOV ECX, EAX
20164 POP EAX
20165 CALL EDX2PChar
20166 CALL StrLCopy
20167 end;
20168 {$ELSE ASM_VERSION} //Pascal
20169 function StrPCopy(Dest: PChar; const Source: string): PChar;
20170 begin
20171 Result := StrLCopy(Dest, PChar(Source), Length(Source));
20172 end;
20173 {$ENDIF ASM_VERSION}
20174 //[END StrPCopy]
20176 //[FUNCTION StrEq]
20177 {$IFDEF ASM_VERSION}
20178 function StrEq( const S1, S2 : String ) : Boolean;
20180 TEST EDX, EDX
20181 JNZ @@1
20182 @@0: CMP EAX, EDX
20183 JMP @@exit
20184 @@1: TEST EAX, EAX
20185 JZ @@0
20186 MOV ECX, [EAX-4]
20187 CMP ECX, [EDX-4]
20188 JNE @@exit
20189 PUSH EAX
20190 PUSH EDX
20191 PUSH 0
20192 MOV EDX, ESP
20193 CALL LowerCase
20194 PUSH 0
20195 MOV EAX, [ESP + 8]
20196 MOV EDX, ESP
20197 CALL LowerCase
20198 POP EAX
20199 POP EDX
20200 PUSH EDX
20201 PUSH EAX
20202 CALL System.@LStrCmp
20203 MOV EAX, ESP
20204 PUSHFD
20205 XOR EDX, EDX
20206 MOV DL, 2
20207 CALL System.@LStrArrayClr
20208 POPFD
20209 POP EDX
20210 POP EDX
20211 POP EDX
20212 POP EDX
20213 @@exit:
20214 SETZ AL
20215 end;
20216 {$ELSE ASM_VERSION} //Pascal
20217 function StrEq( const S1, S2 : String ) : Boolean;
20218 begin
20219 Result := (Length( S1 ) = Length( S2 )) and
20220 (LowerCase( S1 ) = LowerCase( S2 ));
20221 end;
20222 {$ENDIF ASM_VERSION}
20223 //[END StrEq]
20225 //[FUNCTION AnsiEq]
20226 {$IFDEF ASM_VERSION}
20227 function AnsiEq( const S1, S2 : String ) : Boolean;
20229 CALL AnsiCompareStrNoCase
20230 TEST EAX, EAX
20231 SETZ AL
20232 end;
20233 {$ELSE ASM_VERSION} //Pascal
20234 function AnsiEq( const S1, S2 : String ) : Boolean;
20235 begin
20236 Result := AnsiCompareStrNoCase( S1, S2 ) = 0;
20237 end;
20238 {$ENDIF ASM_VERSION}
20239 //[END AnsiEq]
20241 {$IFNDEF _D2}
20242 {$IFNDEF _FPC}
20243 //[function WAnsiEq]
20244 function WAnsiEq( const S1, S2 : WideString ) : Boolean;
20245 begin
20246 Result := WAnsiLowerCase( S1 )=WAnsiLowerCase( S2 );
20247 end;
20248 {$ENDIF _FPC}
20249 {$ENDIF _D2}
20251 //[FUNCTION StrIn]
20252 {$IFDEF ASM_VERSION}
20253 function StrIn(const S: String; const A: array of String): Boolean;
20255 @@1:
20256 TEST ECX, ECX
20257 JL @@ret_0
20259 PUSH EDX
20260 MOV EDX, [EDX+ECX*4]
20261 DEC ECX
20263 PUSH ECX
20264 PUSH EAX
20265 CALL StrEq
20266 DEC AL
20267 POP EAX
20268 POP ECX
20270 POP EDX
20271 JNZ @@1
20273 MOV AL, 1
20276 @@ret_0:XOR EAX, EAX
20277 end;
20278 {$ELSE ASM_VERSION} //Pascal
20279 function StrIn(const S: String; const A: array of String): Boolean;
20280 var I : Integer;
20281 begin
20282 for I := Low( A ) to High( A ) do
20283 if StrEq( S, A[ I ] ) then
20284 begin
20285 Result := True;
20286 Exit;
20287 end;
20288 Result := False;
20289 end;
20290 {$ENDIF ASM_VERSION}
20291 //[END StrIn]
20293 {$IFNDEF _D2}
20294 {$IFNDEF _FPC}
20295 //[function WStrIn]
20296 function WStrIn( const S : WideString; const A : array of WideString ) : Boolean;
20297 var I : Integer;
20298 begin
20299 for I := Low( A ) to High( A ) do
20300 if WAnsiEq( S, A[ I ] ) then
20301 begin
20302 Result := True;
20303 Exit;
20304 end;
20305 Result := False;
20306 end;
20307 {$ENDIF _FPC}
20308 {$ENDIF _D2}
20310 //[function StrIs]
20311 function StrIs( const S : String; const A : array of String; var Idx: Integer ) : Boolean;
20312 var I : Integer;
20313 begin
20314 Idx := -1;
20315 for I := Low( A ) to High( A ) do
20316 if StrEq( S, A[ I ] ) then
20317 begin
20318 Idx := I;
20319 Result := True;
20320 Exit;
20321 end;
20322 Result := False;
20323 end;
20325 //[function IntIn]
20326 function IntIn( Value: Integer; const List: array of Integer ): Boolean;
20327 var I: Integer;
20328 begin
20329 Result := FALSE;
20330 for I := 0 to High( List ) do
20331 begin
20332 if Value = List[ I ] then
20333 begin
20334 Result := TRUE;
20335 break;
20336 end;
20337 end;
20338 end;
20340 //[FUNCTION _StrSatisfy]
20341 {$IFDEF ASM_VERSION}
20342 function _StrSatisfy( S, Mask : PChar ) : Boolean;
20344 TEST EAX, EAX
20345 JZ @@exit
20346 XCHG ECX, EAX
20347 // EDX <- Mask
20348 // ECX <- S
20349 XOR EAX, EAX
20350 MOV AL, '*'
20351 @@rest_satisfy:
20352 PUSH ECX
20353 PUSH EDX
20355 @@nx_char:
20356 MOV AH, [EDX]
20357 OR AH, [ECX]
20358 JZ @@fin //@@ret_true
20360 MOV AH, 0
20362 CMP word ptr [EDX], AX //'*'
20363 JE @@fin //@@ret_true
20365 CMP byte ptr [ECX], AH
20366 JNE @@10
20368 DEC EDX
20369 @@1:
20370 INC EDX
20371 CMP byte ptr [EDX], AL //'*'
20372 JE @@1
20373 //CMP byte ptr [EDX], '?'
20374 //JE @@1
20376 CMP byte ptr [EDX], AH
20377 SETZ AL
20378 JMP @@fin
20380 @@10: CMP byte ptr [EDX], AH
20381 JE @@ret_false
20383 CMP byte ptr [EDX], '?'
20384 JNE @@11
20386 @@go_nx_char:
20387 INC ECX
20388 INC EDX
20389 JMP @@nx_char
20391 @@11:
20392 CMP byte ptr [EDX], AL //'*'
20393 JNE @@20
20395 INC EDX
20396 @@12: CMP byte ptr [ECX], AH
20397 JE @@ret_false
20399 CALL @@rest_satisfy
20400 TEST AL, AL
20401 JNE @@fin
20402 MOV AL, '*'
20404 INC ECX
20405 JMP @@12
20407 @@20: MOV AH, [EDX]
20408 XOR AH, [ECX]
20410 JE @@go_nx_char
20411 @@ret_false:
20412 XOR EAX, EAX
20414 @@fin:
20415 POP EDX
20416 POP ECX
20417 @@exit:
20418 end;
20419 {$ELSE ASM_VERSION} //Pascal
20420 function _StrSatisfy( S, Mask : PChar ) : Boolean;
20421 label next_char;
20422 begin
20423 next_char:
20424 Result := True;
20425 if (S^ = #0) and (Mask^ = #0) then exit;
20426 if (Mask^ = '*') and (Mask[1] = #0) then exit;
20427 if S^ = #0 then
20428 begin
20429 while Mask^ = '*' do
20430 Inc( Mask );
20431 Result := Mask^ = #0;
20432 exit;
20433 end;
20434 Result := False;
20435 if Mask^ = #0 then exit;
20436 if Mask^ = '?' then
20437 begin
20438 Inc( S ); Inc( Mask ); goto next_char;
20439 end;
20440 if Mask^ = '*' then
20441 begin
20442 Inc( Mask );
20443 while S^ <> #0 do
20444 begin
20445 Result := _StrSatisfy( S, Mask );
20446 if Result then exit;
20447 Inc( S );
20448 end;
20449 exit; // (Result = False)
20450 end;
20451 Result := S^ = Mask^;
20452 Inc( S ); Inc( Mask );
20453 if Result then goto next_char;
20454 end;
20455 {$ENDIF ASM_VERSION}
20456 //[END _StrSatisfy]
20458 //[FUNCTION StrSatisfy]
20459 {$IFDEF ASM_VERSION}
20460 function StrSatisfy( const S, Mask: String ): Boolean;
20462 PUSH ESI
20463 XCHG ESI, EAX
20464 PUSH 0
20465 XCHG EAX, EDX
20466 CALL EAX2PChar
20467 MOV EDX, ESP
20469 CMP byte ptr [EAX], 0
20470 JZ @@0
20471 CALL AnsiLowerCase
20472 @@0:
20473 XCHG EAX, ESI
20474 PUSH 0
20475 CALL EAX2PChar
20476 MOV EDX, ESP
20478 CMP byte ptr [EAX], 0
20479 JZ @@1
20480 CALL AnsiLowerCase
20481 @@1:
20482 POP EAX
20483 POP EDX
20484 PUSH EDX
20485 PUSH EAX
20486 CALL _StrSatisfy
20488 XCHG ESI, EAX
20490 CALL RemoveStr
20491 CALL RemoveStr
20492 XCHG EAX, ESI
20494 POP ESI
20495 end;
20496 {$ELSE ASM_VERSION} //Pascal
20497 function StrSatisfy( const S, Mask: String ): Boolean;
20498 begin
20499 Result := _StrSatisfy( PChar( AnsiLowerCase( S ) ),
20500 PChar( AnsiLowerCase( Mask ) ) );
20501 end;
20502 {$ENDIF ASM_VERSION}
20503 //[END StrSatisfy]
20505 //[FUNCTION _2StrSatisfy]
20506 {$IFDEF ASM_VERSION}
20507 function _2StrSatisfy( S, Mask: PChar ): Boolean;
20508 asm // //
20509 PUSH EBX
20510 XCHG EBX, EAX
20511 PUSH 0
20512 MOV EAX, ESP
20513 CALL System.@LStrFromPChar
20514 PUSH 0
20515 MOV EAX, ESP
20516 MOV EDX, EBX
20517 CALL System.@LStrFromPChar
20518 POP EAX
20519 POP EDX
20520 PUSH EDX
20521 PUSH EAX
20522 CALL StrSatisfy
20523 XCHG EBX, EAX
20524 CALL RemoveStr
20525 CALL RemoveStr
20526 XCHG EAX, EBX
20527 POP EBX
20528 end;
20529 {$ELSE ASM_VERSION} // Pascal
20530 function _2StrSatisfy( S, Mask: PChar ): Boolean;
20531 begin
20532 Result := StrSatisfy( S, Mask );
20533 end;
20534 {$ENDIF ASM_VERSION}
20535 //[END _2StrSatisfy]
20537 //[function StrReplace]
20538 function StrReplace( var S: String; const From, ReplTo: String ): Boolean;
20539 var I: Integer;
20540 begin
20541 I := pos( From, S );
20542 if I > 0 then
20543 begin
20544 S := Copy( S, 1, I - 1 ) + ReplTo + CopyEnd( S, I + Length( From ) );
20545 Result := TRUE;
20547 else Result := FALSE;
20548 end;
20551 {$IFDEF _FPC}
20552 //[procedure SetLengthW]
20553 procedure SetLengthW( var W: WideString; NewLength: Integer );
20554 begin
20555 while Length( W ) < NewLength do
20556 W := W + ' ' + W;
20557 if Length( W ) > NewLength then
20558 Delete( W, NewLength + 1, Length( W ) - NewLength );
20559 end;
20561 //[function CopyW]
20562 function CopyW( const W: WideString; From, Count: Integer ): WideString;
20563 begin
20564 Result := '';
20565 if Count <= 0 then Exit;
20566 SetLengthW( Result, Count );
20567 Move( W[ From ], Result[ 1 ], Count * Sizeof( WideChar ) );
20568 end;
20570 //[function posW]
20571 function posW( const S1, S2: String ): Integer;
20572 var I, L1: Integer;
20573 begin
20574 L1 := Length( S1 );
20575 for I := 1 to Length( S2 )-L1+1 do
20576 begin
20577 if Copy( S2, I, L1 ) = S1 then
20578 begin
20579 Result := I;
20580 Exit;
20581 end;
20582 end;
20583 Result := 0;
20584 end;
20585 {$ENDIF _FPC}
20587 {$IFNDEF _FPC}
20588 {$IFNDEF _D2}
20589 //[function WStrReplace]
20590 function WStrReplace( var S: WideString; const From, ReplTo: WideString ): Boolean;
20591 var I: Integer;
20592 begin
20593 I := pos( From, S );
20594 if I > 0 then
20595 begin
20596 S := Copy( S, 1, I - 1 ) + ReplTo + Copy( S, I + Length( From ), MaxInt );
20597 Result := TRUE;
20599 else Result := FALSE;
20600 end;
20602 //[function WStrRepeat]
20603 function WStrRepeat( const S: WideString; Count: Integer ): WideString;
20604 var I, L: Integer;
20605 begin
20606 L := Length( S );
20607 SetLength( Result, L * Count );
20608 for I := 0 to Count-1 do
20609 Move( S[ 1 ], Result[ 1 + I * L ], L * Sizeof( WideChar ) );
20610 end;
20611 {$ENDIF _D2}
20612 {$ENDIF _FPC}
20615 //[function StrRepeat]
20616 function StrRepeat( const S: String; Count: Integer ): String;
20617 var I, L: Integer;
20618 begin
20619 L := Length( S );
20620 SetLength( Result, L * Count );
20621 for I := 0 to Count-1 do
20622 Move( S[ 1 ], Result[ 1 + I * L ], L );
20623 end;
20626 //[PROCEDURE NormalizeUnixText]
20627 {$IFDEF ASM_VERSION}
20628 procedure NormalizeUnixText( var S: String );
20629 asm //cmd //opd
20630 CMP dword ptr [EAX], 0
20631 JZ @@exit
20632 PUSH EBX
20633 PUSH EDI
20634 MOV EBX, EAX
20635 CALL UniqueString
20636 MOV EDI, [EBX]
20637 @@1: MOV EAX, EDI
20638 CALL System.@LStrLen
20639 XCHG ECX, EAX
20640 MOV AX, $0D0A
20642 CMP byte ptr [EDI], AL
20643 JNE @@loo
20644 MOV byte ptr [EDI], AH
20645 @@loo:
20646 TEST ECX, ECX
20647 JZ @@fin
20648 @@loo1:
20649 REPNZ SCASB
20650 JNZ @@fin
20651 CMP byte ptr [EDI-2], AH
20652 JE @@loo
20653 MOV byte ptr [EDI-1], AH
20654 JNE @@loo1
20655 @@fin: POP EDI
20656 POP EBX
20657 @@exit:
20658 end;
20659 {$ELSE ASM_VERSION} //Pascal
20660 procedure NormalizeUnixText( var S: String );
20661 var I: Integer;
20662 begin
20663 if S <> '' then
20664 begin
20665 if S[ 1 ] = #10 then
20666 S[ 1 ] := #13;
20667 for I := 2 to Length(S) do
20668 if (S[I]=#10) and (S[I-1]<>#13) then
20669 S[I] := #13;
20670 end;
20671 end;
20672 {$ENDIF ASM_VERSION}
20673 //[END NormalizeUnixText]
20675 //[function StrComp]
20676 function StrComp(const Str1, Str2: PChar): Integer; assembler;
20678 {$IFDEF F_P}
20679 MOV EAX, [Str1]
20680 MOV EDX, [Str2]
20681 {$ENDIF F_P}
20682 PUSH EDI
20683 PUSH ESI
20684 MOV EDI,EDX
20685 XCHG ESI,EAX
20686 OR ECX, -1
20687 XOR EAX,EAX
20688 REPNE SCASB
20689 NOT ECX
20690 MOV EDI,EDX
20691 XOR EDX,EDX
20692 REPE CMPSB
20693 MOV AL,[ESI-1]
20694 MOV DL,[EDI-1]
20695 SUB EAX,EDX
20696 POP ESI
20697 POP EDI
20698 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20700 function StrComp_NoCase(const Str1, Str2: PChar): Integer;
20702 {$IFDEF F_P}
20703 MOV EAX, [Str1]
20704 MOV EDX, [Str2]
20705 {$ENDIF F_P}
20706 PUSH EDI
20707 PUSH ESI
20708 MOV EDI,EDX
20709 XCHG ESI,EAX
20710 OR ECX, -1
20711 XOR EAX,EAX
20712 REPNE SCASB
20714 NOT ECX
20715 MOV EDI,EDX
20716 @@0:
20717 XOR EDX,EDX
20718 REPE CMPSB
20719 MOV AL,[ESI-1]
20720 MOV AH, AL
20721 SUB AH, 'a'
20722 CMP AH, 25
20723 JA @@1
20724 SUB AL, $20
20725 @@1:
20726 MOV DL,[EDI-1]
20727 MOV AH, DL
20728 SUB AH, 'a'
20729 CMP AH, 25
20730 JA @@2
20731 SUB DL, $20
20732 @@2:
20733 MOV AH, 0
20734 SUB EAX,EDX
20735 JNZ @@exit
20736 CMP DL, 0
20737 JNZ @@0
20739 @@exit:
20740 POP ESI
20741 POP EDI
20742 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20744 //[function StrLComp_NoCase]
20745 function StrLComp_NoCase(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
20747 {$IFDEF F_P}
20748 MOV EAX, [Str1]
20749 MOV EDX, [Str2]
20750 MOV ECX, [MaxLen]
20751 {$ENDIF F_P}
20752 PUSH EDI
20753 PUSH ESI
20754 PUSH EBX
20755 MOV EDI,EDX
20756 MOV ESI,EAX
20757 MOV EBX,ECX
20758 XOR EAX,EAX
20759 OR ECX,ECX
20760 JE @@exit
20761 REPNE SCASB
20762 SUB EBX,ECX
20763 MOV ECX,EBX
20764 MOV EDI,EDX
20765 @@0:
20766 XOR EDX,EDX
20767 REPE CMPSB
20768 MOV AL,[ESI-1]
20769 MOV AH, AL
20770 SUB AH, 'a'
20771 CMP AH, 25
20772 JA @@1
20773 SUB AL, $20
20774 @@1:
20775 MOV DL,[EDI-1]
20776 MOV AH, DL
20777 SUB AH, 'a'
20778 CMP AH, 25
20779 JA @@2
20780 SUB DL, $20
20781 @@2:
20782 MOV AH, 0
20783 SUB EAX,EDX
20784 JECXZ @@exit
20785 JZ @@0
20787 @@exit:
20788 POP EBX
20789 POP ESI
20790 POP EDI
20791 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20793 //[function StrLComp]
20794 function StrLComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer; assembler;
20796 {$IFDEF F_P}
20797 MOV EAX, [Str1]
20798 MOV EDX, [Str2]
20799 MOV ECX, [MaxLen]
20800 {$ENDIF F_P}
20801 PUSH EDI
20802 PUSH ESI
20803 PUSH EBX
20804 MOV EDI,EDX
20805 MOV ESI,EAX
20806 MOV EBX,ECX
20807 XOR EAX,EAX
20808 OR ECX,ECX
20809 JE @@1
20810 REPNE SCASB
20811 SUB EBX,ECX
20812 MOV ECX,EBX
20813 MOV EDI,EDX
20814 XOR EDX,EDX
20815 REPE CMPSB
20816 MOV AL,[ESI-1]
20817 MOV DL,[EDI-1]
20818 SUB EAX,EDX
20819 @@1: POP EBX
20820 POP ESI
20821 POP EDI
20822 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20824 //[function StrLen]
20825 function StrLen(const Str: PChar): Cardinal; assembler;
20827 {$IFDEF F_P}
20828 MOV EAX, [Str]
20829 {$ENDIF F_P}
20830 XCHG EAX, EDI
20831 XCHG EDX, EAX
20832 OR ECX, -1
20833 XOR EAX, EAX
20834 CMP EAX, EDI
20835 JE @@exit0
20836 REPNE SCASB
20837 DEC EAX
20838 DEC EAX
20839 SUB EAX,ECX
20840 @@exit0:
20841 MOV EDI,EDX
20842 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20844 //[FUNCTION __DelimiterLast]
20845 {$IFDEF ASM_VERSION}
20846 function __DelimiterLast( Str: PChar; Delimiters: PChar ): PChar;
20848 PUSH ESI
20850 CALL EAX2PChar
20852 MOV ESI, EDX
20853 MOV EDX, EAX
20855 @@tolast:
20856 CMP byte ptr [EAX], 0
20857 JZ @@next1
20858 INC EAX
20859 JMP @@tolast
20861 @@next1:
20862 PUSH EAX
20864 @@next:
20865 LODSB
20866 TEST AL, AL
20867 JZ @@exit
20869 PUSH EDX
20870 XCHG EDX, EAX
20871 CALL StrRScan
20872 POP EDX
20874 TEST EAX, EAX
20875 JZ @@next
20877 POP ECX
20878 CMP byte ptr [ECX], 0
20879 JZ @@next1
20881 CMP EAX, ECX
20882 JG @@next1
20884 PUSH ECX
20885 JLE @@next
20887 @@exit: POP EAX
20888 POP ESI
20889 end;
20890 {$ELSE ASM_VERSION} //Pascal
20891 function __DelimiterLast( Str: PChar; Delimiters: PChar ): PChar;
20893 P, F : PChar;
20894 begin
20895 P := Str;
20896 Result := P + StrLen( Str );
20897 while Delimiters^ <> #0 do
20898 begin
20899 F := StrRScan( P, Delimiters^ );
20900 if F <> nil then
20901 if (Result^ = #0) or (Integer(F) > Integer(Result)) then
20902 Result := F;
20903 Inc( Delimiters );
20904 end;
20905 end;
20906 {$ENDIF ASM_VERSION}
20907 //[END __DelimiterLast]
20909 //[function SkipSpaces]
20910 function SkipSpaces( P: PChar ): PChar;
20911 begin
20912 while True do
20913 begin
20914 while (P[0] <> #0) and (P[0] <= ' ') do Inc(P);
20915 if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break;
20916 end;
20917 Result := P;
20918 end;
20920 //[function SkipParam]
20921 function SkipParam(P: PChar): PChar;
20922 begin
20923 P := SkipSpaces( P );
20924 while P[0] > ' ' do
20925 if P[0] = '"' then
20926 begin
20927 Inc(P);
20928 while (P[0] <> #0) and (P[0] <> '"') do
20929 Inc(P);
20930 if P[0] <> #0 then Inc(P);
20932 else
20933 Inc(P);
20934 Result := P;
20935 end;
20937 //[FUNCTION ParamStr]
20938 function ParamStr( Idx: Integer ): String;
20940 P, P1: PChar;
20941 Buffer: array[ 0..260 ] of Char;
20942 begin
20943 if Idx = 0 then
20944 SetString( Result, Buffer, GetModuleFileName( 0, Buffer, Sizeof( Buffer ) ) )
20945 else
20946 begin
20947 P := GetCommandLine;
20948 repeat
20949 P := SkipSpaces( P );
20950 P1 := P;
20951 P := SkipParam(P);
20952 if Idx = 0 then Break;
20953 Dec(Idx);
20954 until (Idx < 0) or (P = P1);
20955 Result := Copy( P1, 1, P - P1 );
20956 if Length( Result ) >= 2 then
20957 if (Result[ 1 ] = '"') and (Result[ Length( Result ) ] = '"') then
20958 Result := Copy( Result, 2, Length( Result ) - 2 );
20959 end;
20960 end;
20961 //[END ParamStr]
20963 //[FUNCTION ParamCount]
20964 function ParamCount: Integer;
20966 S: string;
20967 begin
20968 Result := 0;
20969 while True do
20970 begin
20971 S := ParamStr(Result + 1);
20972 if S = '' then Break;
20973 Inc(Result);
20974 end;
20975 end;
20976 //[END ParamCount]
20978 //[FUNCTION DelimiterLast]
20979 {$IFDEF ASM_VERSION}
20980 function DelimiterLast( const Str, Delimiters: String ): Integer;
20982 CALL EAX2PChar
20983 CALL EDX2PChar
20984 PUSH EAX
20985 CALL __DelimiterLast
20986 POP EDX
20987 SUB EAX, EDX
20988 INC EAX
20989 end;
20990 {$ELSE ASM_VERSION} //Pascal
20991 function DelimiterLast( const Str, Delimiters: String ): Integer;
20992 var PStr: PChar;
20993 begin
20994 PStr := PChar( Str );
20995 Result := Integer( __DelimiterLast( PStr, PChar( Delimiters ) ) )
20996 - Integer( PStr )
20997 + 1; // {Viman}
20998 end;
20999 {$ENDIF ASM_VERSION}
21000 //[END DelimiterLast]
21002 // Thanks to Marco Bobba - Marisa Bo for this code
21003 //[function StrIsStartingFrom]
21004 function StrIsStartingFrom( Str, Pattern: PChar ): Boolean;
21006 {$IFDEF F_P}
21007 MOV EAX, [Str]
21008 MOV EDX, [Pattern]
21009 {$ENDIF F_P}
21010 XOR ECX, ECX
21011 @@1:
21012 MOV CL, [EDX] // pattern[ i ]
21013 INC EDX
21014 MOV CH, [EAX] // str[ i ]
21015 INC EAX
21016 JECXZ @@2 // str = pattern; CL = #0, CH = #0
21017 CMP CL, CH
21018 JE @@1
21019 @@2:
21020 TEST CL, CL
21021 SETZ AL
21022 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
21024 function StrIsStartingFromNoCase( Str, Pattern: PChar ): Boolean;
21026 {$IFDEF F_P}
21027 MOV EAX, [Str]
21028 MOV EDX, [Pattern]
21029 {$ENDIF F_P}
21030 XOR ECX, ECX
21031 @@1:
21032 MOV CL, [EDX] // pattern[ i ]
21033 INC EDX
21034 MOV CH, [EAX] // str[ i ]
21035 INC EAX
21036 JECXZ @@2 // str = pattern; CL = #0, CH = #0
21037 CMP CL, 'a'
21038 JB @@cl_ok
21039 CMP CL, 'z'
21040 JA @@cl_ok
21041 SUB CL, 32
21042 @@cl_ok:
21043 CMP CH, 'a'
21044 JB @@ch_ok
21045 CMP CH, 'z'
21046 JA @@ch_ok
21047 SUB CH, 32
21048 @@ch_ok:
21049 CMP CL, CH
21050 JE @@1
21051 @@2:
21052 TEST CL, CL
21053 SETZ AL
21054 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
21056 {$IFNDEF _FPC}
21057 //[FUNCTION Format]
21058 {$IFDEF ASM_VERSION}
21059 function Format( const fmt: string; params: array of const ): String;
21061 PUSH ESI
21062 PUSH EDI
21063 PUSH EBX
21064 MOV EBX, ESP
21065 ADD ESP, -2048
21066 MOV ESI, ESP
21068 INC ECX
21069 JZ @@2
21070 @@1:
21071 MOV EDI, [EDX + ECX*8 - 8]
21072 PUSH EDI
21073 LOOP @@1
21074 @@2:
21075 PUSH ESP
21076 PUSH EAX
21077 PUSH ESI
21079 CALL wvsprintf
21081 MOV EDX, ESI
21082 MOV EAX, @Result
21083 CALL System.@LStrFromPChar
21085 MOV ESP, EBX
21086 POP EBX
21087 POP EDI
21088 POP ESI
21089 end;
21090 {$ELSE ASM_VERSION} //Pascal
21091 function Format( const fmt: string; params: array of const ): String;
21092 var Buffer: array[ 0..2047 ] of Char;
21093 ElsArray, El: PDWORD;
21094 I : Integer;
21095 P : PDWORD;
21096 begin
21097 ElsArray := nil;
21098 if High( params ) >= 0 then
21099 GetMem( ElsArray, (High( params ) + 1) * sizeof( Pointer ) );
21100 El := ElsArray;
21101 for I := 0 to High( params ) do
21102 begin
21103 P := @params[ I ];
21104 P := Pointer( P^ );
21105 El^ := DWORD( P );
21106 Inc( El );
21107 end;
21108 wvsprintf( @Buffer[0], PChar( fmt ), PChar( ElsArray ) );
21109 Result := Buffer;
21110 if ElsArray <> nil then
21111 FreeMem( ElsArray );
21112 end;
21113 {$ENDIF ASM_VERSION}
21114 //[END Format]
21116 //[function LStrFromPWCharLen]
21117 function LStrFromPWCharLen(Source: PWideChar; Length: Integer): String;
21119 DestLen: Integer;
21120 Buffer: array[0..2047] of Char;
21121 begin
21122 if Length <= 0 then
21123 begin
21124 //_LStrClr(Result);
21125 Result := '';
21126 Exit;
21127 end;
21128 if Length < SizeOf(Buffer) div 2 then
21129 begin
21130 DestLen := WideCharToMultiByte(0, 0, Source, Length,
21131 Buffer, SizeOf(Buffer), nil, nil);
21132 if DestLen > 0 then
21133 begin
21134 Result := Buffer;
21135 //System.LStrFromPCharLen(Result, Buffer, DestLen);
21136 Exit;
21137 end;
21138 end;
21139 DestLen := WideCharToMultiByte(0, 0, Source, Length, nil, 0, nil, nil);
21140 // _LStrFromPCharLen(Dest, nil, DestLen);
21141 SetLength( Result, DestLen );
21142 WideCharToMultiByte(0, 0, Source, Length, Pointer(Result), DestLen, nil, nil);
21143 end;
21145 //[function LStrFromPWChar]
21146 function LStrFromPWChar(Source: PWideChar): String;
21147 {* from Delphi5 - because D2 does not contain it. }
21149 PUSH EDX
21150 XOR EDX,EDX
21151 TEST EAX,EAX
21152 JE @@5
21153 PUSH EAX
21154 @@0: CMP DX,[EAX+0]
21155 JE @@4
21156 CMP DX,[EAX+2]
21157 JE @@3
21158 CMP DX,[EAX+4]
21159 JE @@2
21160 CMP DX,[EAX+6]
21161 JE @@1
21162 ADD EAX,8
21163 JMP @@0
21164 @@1: ADD EAX,2
21165 @@2: ADD EAX,2
21166 @@3: ADD EAX,2
21167 @@4: XCHG EDX,EAX
21168 POP EAX
21169 SUB EDX,EAX
21170 SHR EDX,1
21171 @@5: POP ECX
21172 JMP LStrFromPWCharLen
21173 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
21174 {$ENDIF _FPC}
21177 /////////////////////////////////////////////////////////////////////////
21180 // F I L E S
21183 /////////////////////////////////////////////////////////////////////////
21184 //[FILES]
21186 This part of the unit modified by Tim Slusher and Vladimir Kladov.
21189 {* Set of utility methods to work with files
21190 and reqistry.
21191 When programming KOL, which is Windows API-oriented, You should
21192 avoid alien (for Windows) embedded Pascal files handling, and
21193 use API-calls which implemented very well. This set of functions
21194 is intended to make this easier.
21195 Also TDirList object implementation present here and some registry
21196 access functions, which allow to make code more elegant.
21199 {$UNDEF ASM_LOCAL}
21200 {$IFDEF ASM_VERSION}
21201 {$DEFINE ASM_LOCAL}
21202 {$ENDIF ASM_VERSION}
21204 //[FUNCTION FileCreate]
21205 {$IFDEF ASM_VERSION}
21206 function FileCreate( const FileName: string; OpenFlags: DWord): THandle;
21208 XOR ECX, ECX
21209 PUSH ECX
21210 MOV ECX, EDX
21211 SHR ECX, 16
21212 AND CX, $1FFF
21213 JNZ @@1
21214 MOV CL, FILE_ATTRIBUTE_NORMAL
21215 @@1: PUSH ECX
21216 MOV CL, DH
21217 PUSH ECX // CreationMode
21218 PUSH 0
21219 MOV CL, DL
21220 PUSH ECX // ShareMode
21221 MOV DX, 0
21222 PUSH EDX // AccessMode
21223 //CALL System.@LStrToPChar // FileName must not be ''
21224 PUSH EAX
21225 CALL CreateFile
21226 end;
21227 {$ELSE ASM_VERSION} //Pascal
21228 function FileCreate(const FileName: string; OpenFlags: DWord): THandle;
21229 var Attr: DWORD;
21230 begin
21231 Attr := (OpenFlags shr 16) and $1FFF;
21232 if Attr = 0 then Attr := FILE_ATTRIBUTE_NORMAL;
21233 Result := CreateFile( PChar(FileName), OpenFlags and $F0000000,
21234 OpenFlags and $F, nil, (OpenFlags shr 8) and $F,
21235 Attr, 0 );
21236 end;
21237 {$ENDIF ASM_VERSION}
21238 //[END FileCreate]
21240 //[FUNCTION FileClose]
21241 {$IFDEF ASM_VERSION}
21242 function FileClose( Handle: THandle): Boolean;
21244 PUSH EAX
21245 CALL CloseHandle
21246 TEST EAX, EAX
21247 SETNZ AL
21248 end;
21249 {$ELSE ASM_VERSION} //Pascal
21250 function FileClose(Handle: THandle): boolean;
21251 begin
21252 Result := CloseHandle(Handle);
21253 end;
21254 {$ENDIF ASM_VERSION}
21255 //[END FileClose]
21257 //[FUNCTION FileExists]
21258 {$IFDEF ASM_VERSION}
21259 function FileExists( const FileName : String ) : Boolean;
21260 const size_TWin32FindData = sizeof( TWin32FindData );
21262 CALL EAX2PChar
21263 PUSH EAX
21264 CALL GetFileAttributes
21265 INC EAX
21266 JZ @@exit
21267 DEC EAX
21268 {$IFDEF PARANOIA}
21269 DB $24, FILE_ATTRIBUTE_DIRECTORY
21270 {$ELSE}
21271 AND AL, FILE_ATTRIBUTE_DIRECTORY
21272 {$ENDIF}
21273 SETZ AL
21274 @@exit:
21275 end;
21276 {$ELSE ASM_VERSION} //Pascal
21277 function FileExists( const FileName : String ) : Boolean;
21279 Code: Integer;
21280 begin
21281 Code := GetFileAttributes(PChar(FileName));
21282 Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code = 0);
21283 end;
21284 {$ENDIF ASM_VERSION}
21285 //[END FileExists]
21287 //[FUNCTION FileSeek]
21288 {$IFDEF ASM_VERSION}
21289 function FileSeek( Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
21291 MOVZX ECX, CL
21292 PUSH ECX
21293 PUSH 0
21294 PUSH EDX
21295 PUSH EAX
21296 CALL SetFilePointer
21297 end;
21298 {$ELSE ASM_VERSION} //Pascal
21299 function FileSeek(Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
21300 begin
21301 Result := SetFilePointer(Handle, MoveTo, nil, Ord( MoveMethod ) );
21302 end;
21303 {$ENDIF ASM_VERSION}
21304 //[END FileSeek]
21306 //[FUNCTION FileRead]
21307 {$IFDEF ASM_VERSION}
21308 function FileRead( Handle: THandle; var Buffer; Count: DWord): DWord;
21310 PUSH EBP
21311 PUSH 0
21312 MOV EBP, ESP
21313 PUSH 0
21314 PUSH EBP
21315 PUSH ECX
21316 PUSH EDX
21317 PUSH EAX
21318 CALL ReadFile
21319 TEST EAX, EAX
21320 POP EAX
21321 JNZ @@exit
21322 XOR EAX, EAX
21323 @@exit:
21324 POP EBP
21325 end;
21326 {$ELSE ASM_VERSION} //Pascal
21327 function FileRead(Handle: THandle; var Buffer; Count: DWord): DWord;
21328 begin
21329 if not ReadFile(Handle, Buffer, Count, Result, nil) then
21330 Result := 0;
21331 end;
21332 {$ENDIF ASM_VERSION}
21333 //[END FileRead]
21335 //[FUNCTION File2Str]
21336 {$IFDEF ASM_VERSION}
21337 function File2Str( Handle: THandle): String;
21339 PUSH EDX
21340 TEST EAX, EAX
21341 JZ @@exit // return ''
21343 PUSH EBX
21344 MOV EBX, EAX // EBX = Handle
21345 XOR EDX, EDX
21346 XOR ECX, ECX
21347 INC ECX
21348 CALL FileSeek
21349 PUSH EAX // Pos
21350 PUSH 0
21351 PUSH EBX
21352 CALL GetFileSize
21353 POP EDX
21354 SUB EAX, EDX // EAX = Size - Pos
21355 JZ @@exitEBX
21357 PUSH EAX
21358 CALL System.@GetMem
21359 XCHG EAX, EBX
21360 MOV EDX, EBX
21361 POP ECX
21362 PUSH ECX
21363 CALL FileRead
21364 POP ECX
21365 MOV EDX, EBX
21366 POP EBX
21367 POP EAX
21368 PUSH EDX
21369 {$IFDEF _D2}
21370 CALL _LStrFromPCharLen
21371 {$ELSE}
21372 CALL System.@LStrFromPCharLen
21373 {$ENDIF}
21374 JMP @@freebuf
21376 @@exitEBX:
21377 POP EBX
21378 @@exit:
21379 XCHG EDX, EAX
21380 POP EAX // @Result
21381 PUSH EDX
21382 CALL System.@LStrFromPChar
21383 @@freebuf:
21384 POP EAX
21385 TEST EAX, EAX
21386 JZ @@fin
21387 CALL System.@FreeMem
21388 @@fin:
21389 end;
21390 {$ELSE ASM_VERSION} //Pascal
21391 function File2Str(Handle: THandle): String;
21392 var Pos, Size: DWORD;
21393 begin
21394 Result := '';
21395 if Handle = 0 then Exit;
21396 Pos := FileSeek( Handle, 0, spCurrent );
21397 Size := GetFileSize( Handle, nil );
21398 SetString( Result, nil, Size - Pos + 1 );
21399 FileRead( Handle, Result[ 1 ], Size - Pos );
21400 Result[ Size - Pos + 1 ] := #0;
21401 end;
21402 {$ENDIF ASM_VERSION}
21403 //[END File2Str]
21405 //[FUNCTION FileWrite]
21406 {$IFDEF ASM_VERSION}
21407 function FileWrite( Handle: THandle; const Buffer; Count: DWord): DWord;
21409 PUSH EBP
21410 PUSH EBP
21411 MOV EBP, ESP
21412 PUSH 0
21413 PUSH EBP
21414 PUSH ECX
21415 PUSH EDX
21416 PUSH EAX
21417 CALL WriteFile
21418 TEST EAX, EAX
21419 POP EAX
21420 JNZ @@exit
21421 XOR EAX, EAX
21422 @@exit:
21423 POP EBP
21424 end;
21425 {$ELSE ASM_VERSION} //Pascal
21426 function FileWrite(Handle: THandle; const Buffer; Count: DWord): DWord;
21427 begin
21428 if not WriteFile(Handle, Buffer, Count, Result, nil) then
21429 Result := 0;
21430 end;
21431 {$ENDIF ASM_VERSION}
21432 //[END FileWrite]
21434 //[FUNCTION FileEOF]
21435 {$IFDEF ASM_VERSION}
21436 function FileEOF( Handle: THandle ) : Boolean;
21438 PUSH EAX
21440 PUSH 0
21441 PUSH EAX
21442 CALL GetFileSize
21444 XCHG EAX, [ESP]
21446 MOV CL, spCurrent
21447 XOR EDX, EDX
21448 CALL FileSeek
21450 POP EDX
21451 CMP EAX, EDX
21452 SETGE AL
21453 end;
21454 {$ELSE ASM_VERSION} //Pascal
21455 function FileEOF( Handle: THandle ) : Boolean;
21456 var Siz, Pos : DWord;
21457 begin
21458 Siz := GetFileSize( Handle, nil );
21459 Pos := FileSeek( Handle, 0, spCurrent );
21460 Result := Pos >= Siz;
21461 end;
21462 {$ENDIF ASM_VERSION}
21463 //[END FileEOF]
21465 //[FUNCTION FileFullPath]
21466 {$IFDEF ASM_noVERSION}
21467 function FileFullPath( const FileName: String ) : String;
21468 const
21469 BkSlash: String = '\';
21470 szTShFileInfo = sizeof( TShFileInfo );
21472 PUSH EBX
21473 PUSH ESI
21474 MOV EBX, EDX
21475 PUSH EAX
21477 XCHG EAX, EDX
21478 CALL System.@LStrClr
21480 POP EDX
21481 PUSH 0
21482 MOV EAX, ESP
21483 CALL System.@LStrAsg
21484 MOV ESI, ESP
21486 @@loo: CMP dword ptr [ESI], 0
21487 JZ @@fin
21489 MOV EAX, ESI
21490 MOV EDX, [BkSlash]
21491 PUSH 0
21492 MOV ECX, ESP
21493 CALL Parse
21495 CMP dword ptr [EBX], 0
21496 JE @@1
21497 MOV EAX, EBX
21498 MOV EDX, [BkSlash]
21499 CALL System.@LStrCat
21500 JMP @@2
21501 @@1:
21502 POP EAX
21503 PUSH EAX
21504 CALL System.@LStrLen
21505 CMP EAX, 2
21506 JNE @@2
21507 POP EAX
21508 PUSH EAX
21509 CMP byte ptr [EAX+1], ':'
21510 JNE @@2
21512 MOV EAX, EBX
21513 POP EDX
21514 PUSH EDX
21515 CALL System.@LStrAsg
21516 JMP @@3
21517 @@2:
21518 PUSH 0
21519 MOV EAX, ESP
21520 MOV EDX, [EBX]
21521 CALL System.@LStrAsg
21522 MOV EAX, ESP
21523 MOV EDX, [ESP+4]
21524 CALL System.@LStrCat
21525 POP EAX
21526 PUSH EAX
21527 SUB ESP, szTShFileInfo
21528 MOV EDX, ESP
21529 PUSH SHGFI_DISPLAYNAME
21530 PUSH szTShFileInfo
21531 PUSH EDX
21532 PUSH 0
21533 PUSH EAX
21534 CALL ShGetFileInfo
21535 LEA EDX, [ESP].TShFileInfo.szDisplayName
21536 CMP byte ptr [EDX], 0
21537 JE @@clr_stk
21538 LEA EAX, [ESP+szTShFileInfo+4]
21539 CALL System.@LStrFromPChar
21540 @@clr_stk:
21541 ADD ESP, szTShFileInfo
21542 CALL RemoveStr
21543 POP EDX
21544 PUSH EDX
21545 MOV EAX, EBX
21546 CALL System.@LStrCat
21548 @@3: CALL RemoveStr
21549 JMP @@loo
21551 @@fin: CALL RemoveStr
21552 POP ESI
21553 POP EBX
21554 end;
21555 {$ELSE ASM_VERSION} //Pascal
21556 function FileFullPath( const FileName: String ) : String;
21557 var SFI: TShFileInfo;
21558 Src, S: String;
21559 begin
21560 Result := '';
21561 Src := FileName;
21562 while Src <> '' do
21563 begin
21564 S := Parse( Src, '\' );
21565 if Result <> '' then
21566 Result := Result + '\';
21567 if (Result = '') and (Length( S ) = 2) and (S[ 2 ] = ':') then
21568 Result := S
21569 else
21570 begin
21571 ShGetFileInfo( PChar( Result + S ), 0, SFI, Sizeof( SFI ),
21572 SHGFI_DISPLAYNAME );
21573 if SFI.szDisplayName[ 0 ] <> #0 then
21574 S := SFI.szDisplayName;
21575 Result := Result + S;
21576 end;
21577 end;
21578 if ExtractFileExt( Result ) = '' then
21579 // case when flag 'Hide extensions for registered file types' is set on
21580 // in the Explorer:
21581 Result := Result + ExtractFileExt( FileName );
21582 end;
21583 {$ENDIF ASM_VERSION}
21584 //[END FileFullPath]
21586 //[function FileShortPath]
21587 function FileShortPath( const FileName: String ): String;
21588 var Buf: array[ 0..MAX_PATH ] of Char;
21589 begin
21590 GetShortPathName( PChar( FileName ), Buf, Sizeof( Buf ) );
21591 Result := Buf;
21592 end;
21594 //[function FileIconSystemIdx]
21595 function FileIconSystemIdx( const Path: String ): Integer;
21596 var SFI: TShFileInfo;
21597 begin
21598 SFI.iIcon := 0; // Bartov
21599 ShGetFileInfo( PChar( Path ), 0, SFI, sizeof( SFI ),
21600 //-- Babenko Alexey: -----------------//
21601 // SHGFI_ICON or //
21602 //----------------------------------//
21603 SHGFI_SMALLICON or SHGFI_SYSICONINDEX );
21604 Result := SFI.iIcon;
21605 end;
21607 //[function FileIconSysIdxOffline]
21608 function FileIconSysIdxOffline( const Path: String ): Integer;
21609 var SFI: TShFileInfo;
21610 begin
21611 SFI.iIcon := 0; // Bartov
21612 ShGetFileInfo( PChar( Path ), FILE_ATTRIBUTE_NORMAL, SFI, sizeof( SFI ),
21613 //-- Babenko Alexey: -----------------//
21614 //SHGFI_ATTRIBUTES or SHGFI_ICON or //
21615 //----------------------------------//
21616 SHGFI_SMALLICON or SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES );
21617 Result := SFI.iIcon;
21618 end;
21620 //[procedure LogFileOutput]
21621 procedure LogFileOutput( const filepath, str: String );
21622 var F: HFile;
21623 begin
21624 F := FileCreate( filepath, ofOpenWrite or ofOpenAlways );
21625 if F = INVALID_HANDLE_VALUE then Exit;
21626 FileSeek( F, 0, spEnd );
21627 FileWrite( F, {$IFNDEF _D2} String {$ENDIF}
21628 ( str + #13#10 )[ 1 ], Length( str ) + 2 );
21629 FileClose( F );
21630 end;
21632 //[function StrSaveToFile]
21633 function StrSaveToFile( const Filename, Str: String ): Boolean;
21634 begin
21635 Result := Mem2File( PChar( Filename ), PChar( Str ), Length( Str ) )
21636 = Length( Str );
21637 end;
21639 //[function StrLoadFromFile]
21640 function StrLoadFromFile( const Filename: String ): String;
21641 var F: HFile;
21642 begin
21643 Result := '';
21644 F := FileCreate( Filename, ofOpenRead or ofOpenExisting or ofShareDenyWrite );
21645 if F = INVALID_HANDLE_VALUE then Exit;
21646 Result := File2Str( F );
21647 FileClose( F ); {??ee(zhog); Dark Knight}
21648 end;
21650 //[function Mem2File]
21651 function Mem2File( Filename: PChar; Mem: Pointer; Len: Integer ): Integer;
21652 var F: HFile;
21653 begin
21654 Result := 0;
21655 F := FileCreate( Filename, ofOpenWrite or ofOpenAlways );
21656 if F = INVALID_HANDLE_VALUE then Exit;
21657 Result := FileWrite( F, Mem^, Len );
21658 FileClose( F );
21659 end;
21661 //[function File2Mem]
21662 function File2Mem( Filename: PChar; Mem: Pointer; MaxLen: Integer ): Integer;
21663 var F: HFile;
21664 begin
21665 Result := 0;
21666 F := FileCreate( Filename, ofOpenRead or ofOpenExisting or ofShareDenyWrite );
21667 if F = INVALID_HANDLE_VALUE then Exit;
21668 Result := FileRead( F, Mem^, MaxLen );
21669 FileClose( F );
21670 end;
21672 //[FUNCTION DirectoryExists]
21673 {$IFDEF ASM_VERSION}
21674 function DirectoryExists( const Name: string): Boolean;
21676 //CALL System.@LStrToPChar // Name must not be ''
21677 PUSH EAX
21678 CALL GetFileAttributes
21679 INC EAX
21680 JZ @@exit
21681 DEC EAX
21682 {$IFDEF PARANOIA}
21683 DB $24, FILE_ATTRIBUTE_DIRECTORY
21684 {$ELSE}
21685 AND AL, FILE_ATTRIBUTE_DIRECTORY
21686 {$ENDIF}
21687 SETNZ AL
21688 @@exit:
21689 end;
21690 {$ELSE ASM_VERSION} //Pascal
21691 function DirectoryExists(const Name: string): Boolean;
21693 Code: Integer;
21694 begin
21695 Code := GetFileAttributes(PChar(Name));
21696 Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
21697 end;
21698 {$ENDIF ASM_VERSION}
21699 //[END DirectoryExists]
21701 //[function CheckDirectoryContent]
21702 function CheckDirectoryContent( const Name: String; SubDirsOnly: Boolean; const Mask: String ): Boolean;
21703 var FD: TWin32FindData;
21704 FH: THandle;
21705 begin
21706 if not DirectoryExists( Name ) then
21707 Result := TRUE
21708 else
21709 begin
21710 FH := Windows.FindFirstFile( PChar( IncludeTrailingPathDelimiter( Name )
21711 + Mask ), FD );
21712 if FH = INVALID_HANDLE_VALUE then
21713 Result := TRUE
21714 else
21715 begin
21716 Result := TRUE;
21717 repeat
21718 if not StrIn( FD.cFileName, ['.','..'] ) then
21719 begin
21720 if SubDirsOnly and LongBool(FD.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)
21721 or not SubDirsOnly then
21722 begin
21723 Result := FALSE;
21724 break;
21725 end;
21726 end;
21727 until not Windows.FindNextFile( FH, FD );
21728 Windows.FindClose( FH );
21729 end;
21730 end;
21731 end;
21733 //[function DirectoryEmpty]
21734 function DirectoryEmpty(const Name: String): Boolean;
21735 begin
21736 Result := CheckDirectoryContent( Name, FALSE, '*.*' );
21737 end;
21740 //[function DirectorySize]
21741 function DirectorySize( const Path: String ): I64;
21742 var DirList: PDirList;
21743 I: Integer;
21744 begin
21745 Result := MakeInt64( 0, 0 );
21746 DirList := NewDirList( Path, '*.*', 0 );
21747 for I := 0 to DirList.Count-1 do
21748 begin
21749 if LongBool( DirList.Items[ I ].dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY ) then
21750 Result := Add64( Result, DirectorySize( DirList.Path + DirList.Names[ I ] ) )
21751 else
21752 Result := Add64( Result, MakeInt64( DirList.Items[ I ].nFileSizeLow,
21753 DirList.Items[ I ].nFileSizeHigh ) );
21754 end;
21755 DirList.Free;
21756 end;
21759 //[function DirectoryHasSubdirs]
21760 function DirectoryHasSubdirs( const Path: String ): Boolean;
21761 begin
21762 Result := not CheckDirectoryContent( Path, TRUE, '*.*' );
21763 end;
21765 //[function GetFileList]
21766 function GetFileList(const dir: string): PStrList;
21768 Srch: TWin32FindData;
21769 flag: Integer;
21770 succ: boolean;
21771 begin
21772 result := nil;
21773 flag := FindFirstFile(PChar(dir), Srch);
21774 //succ := flag <> 0; //---------------------------------------
21775 succ := flag <> Integer(INVALID_HANDLE_VALUE); // M.V.Chirikov
21776 while succ do begin
21777 if (not (Srch.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0))then begin
21778 if Result = nil then begin
21779 Result := NewStrList;
21780 end;
21781 Result.Add(Srch.cFileName);
21782 end;
21783 succ := FindNextFile(Flag, Srch);
21784 end;
21785 FindClose(Flag);
21786 end;
21788 //[function ExcludeTrailingChar]
21789 function ExcludeTrailingChar( const S: String; C: Char ): String;
21790 begin
21791 Result := S;
21792 if Result <> '' then
21793 if Result[ Length( Result ) ] = C then
21794 Delete( Result, Length( Result ), 1 );
21795 end;
21797 //[function IncludeTrailingChar]
21798 function IncludeTrailingChar( const S: String; C: Char ): String;
21799 begin
21800 Result := S;
21801 if (Result = '') or (Result[ Length( Result ) ] <> C) then
21802 Result := Result + C;
21803 end;
21805 //---------------------------------------------------------
21806 // Following functions/procedures are created by Edward Aretino:
21807 // IncludeTrailingPathDelimiter, ExcludeTrailingPathDelimiter,
21808 // ForceDirectories, CreateDir, ChangeFileExt
21809 //---------------------------------------------------------
21810 //[function IncludeTrailingPathDelimiter]
21811 function IncludeTrailingPathDelimiter(const S: string): string;
21812 begin
21813 {if CopyTail(S, 1) <> '\' then
21814 Result := S + '\'
21815 else
21816 Result := S;}
21817 Result := IncludeTrailingChar( S, '\' );
21818 end;
21820 //[function ExcludeTrailingPathDelimiter]
21821 function ExcludeTrailingPathDelimiter(const S: string): string;
21822 begin
21823 {Result := S;
21824 if Length(Result) = 0 then Exit;
21826 if (CopyTail(Result, 1) = '\') then
21827 DeleteTail(Result, 1);}
21828 Result := ExcludeTrailingChar( S, '\' );
21829 end;
21831 //[function ForceDirectories]
21832 function ForceDirectories(Dir: string): Boolean;
21833 begin
21834 Result := Length(Dir) > 0; {Centronix}
21835 If not Result then Exit;
21836 Dir := ExcludeTrailingPathDelimiter(Dir);
21837 If (Length(Dir) < 3) or DirectoryExists(Dir) or
21838 (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
21839 Result := ForceDirectories(ExtractFilePath(Dir)) and CreateDir(Dir);
21840 end;
21842 //[function CreateDir]
21843 function CreateDir(const Dir: string): Boolean;
21844 begin
21845 Result := Windows.CreateDirectory(PChar(Dir), nil);
21846 end;
21848 //[function ChangeFileExt]
21849 function ChangeFileExt(FileName: String; const Extension: string): string;
21851 FileExt: String;
21852 begin
21853 FileExt := ExtractFileExt(FileName);
21854 DeleteTail(FileName, Length(FileExt));
21855 Result := FileName+ Extension;
21856 end;
21858 {$IFDEF ASM_VERSION}
21859 {$IFNDEF _D2}
21860 {$DEFINE ASM_LStrFromPCharLen}
21861 {$ENDIF}
21862 {$ENDIF ASM_VERSION}
21864 {$IFDEF ASM_LStrFromPCharLen}
21865 {$DEFINE ASM_DIRDelimiters}
21866 {$ENDIF}
21868 {$IFDEF ASM_VERSION}
21869 {$DEFINE ASM_DIRDelimiters}
21870 {$ENDIF ASM_VERSION}
21872 {$IFDEF ASM_DIRDelimiters}
21873 const
21874 DirDelimiters: PChar = ':\';
21875 {$ENDIF}
21877 //[FUNCTION ExtractFileName]
21878 {$IFDEF ASM_VERSION}
21879 function ExtractFileName( const Path : String ) : String;
21881 PUSH EDX
21882 PUSH EAX
21883 MOV EDX, [DirDelimiters]
21884 CALL __DelimiterLast
21885 POP EDX
21886 CMP byte ptr [EAX], 0
21887 JZ @@1
21888 XCHG EDX, EAX
21889 INC EDX
21890 @@1: POP EAX
21891 CALL System.@LStrFromPChar
21892 end;
21893 {$ELSE ASM_VERSION} //Pascal
21894 function ExtractFileName( const Path : String ) : String;
21895 var P: PChar;
21896 begin
21897 P := __DelimiterLast( PChar( Path ), ':\' );
21898 if P^ = #0 then
21899 Result := Path
21900 else
21901 Result := P + 1;
21902 end;
21903 {$ENDIF ASM_VERSION}
21904 //[END ExtractFileName]
21906 //[FUNCTION ExtractFilePath]
21907 {$IFDEF ASM_LStrFromPCharLen} // LStrFromPCharLen - there are no in D2
21908 function ExtractFilePath( const Path : String ) : String;
21910 PUSH EDX
21911 MOV EDX, [DirDelimiters]
21912 CALL EAX2PChar
21913 PUSH EAX
21914 CALL __DelimiterLast
21915 XCHG EDX, EAX
21916 XOR ECX, ECX
21917 POP EAX
21918 CMP byte ptr [EDX], CL
21919 JZ @@ret_0
21920 SUB EDX, EAX
21921 INC EDX
21922 XCHG EDX, EAX
21923 XCHG ECX, EAX
21924 @@ret_0:
21925 POP EAX
21926 CALL System.@LStrFromPCharLen
21927 end;
21928 {$ELSE} //Pascal
21929 function ExtractFilePath( const Path : String ) : String;
21930 //var I : Integer;
21931 var P, P0: PChar;
21932 begin
21933 P0 := PChar( Path );
21934 P := __DelimiterLast( P0, ':\' );
21935 if P^ = #0 then
21936 Result := ''
21937 else
21938 Result := Copy( Path, 1, P - P0 + 1 );
21939 end;
21940 {$ENDIF}
21942 //[function ExtractFileNameWOext]
21943 function ExtractFileNameWOext( const Path : String ) : String;
21944 begin
21945 Result := ExtractFileName( Path );
21946 Result := Copy( Result, 1, Length( Result ) - Length( ExtractFileExt( Result ) ) );
21947 end;
21949 {$IFDEF ASM_VERSION}
21950 const
21951 ExtDelimeters: PChar = '.';
21953 //[function ExtractFileExt]
21954 function ExtractFileExt( const Path : String ) : String;
21956 PUSH EDX
21957 MOV EDX, [ExtDelimeters]
21958 CALL EAX2PChar
21959 CALL __DelimiterLast
21960 @@1: XCHG EDX, EAX
21961 POP EAX
21962 CALL System.@LStrFromPChar
21963 end;
21964 {$ELSE ASM_VERSION} //Pascal
21965 function ExtractFileExt( const Path : String ) : String;
21966 var P: PChar;
21967 begin
21968 P := __DelimiterLast( PChar( Path ), '.' );
21969 Result := P;
21970 end;
21971 {$ENDIF ASM_VERSION}
21972 //[END ExtractFilePath]
21974 //[function ReplaceFileExt]
21975 function ReplaceFileExt( const Path, NewExt: String ): String;
21976 begin
21977 Result := ExtractFilePath( Path ) +
21978 ExtractFileNameWOext( ExtractFileName( Path ) ) +
21979 NewExt;
21980 end;
21982 //[function ExtractShortPathName]
21983 function ExtractShortPathName( const Path: String ): String;
21985 Buffer: array[0..MAX_PATH - 1] of Char;
21986 begin
21987 SetString(Result, Buffer,
21988 GetShortPathName(PChar(Path), Buffer, SizeOf(Buffer)));
21989 end;
21991 //[function FilePathShortened]
21992 function FilePathShortened( const Path: String; MaxLen: Integer ): String;
21993 begin
21994 Result := FilePathShortenPixels( Path, 0, MaxLen );
21995 end;
21997 //[function PixelsLength]
21998 function PixelsLength( DC: HDC; const Text: String ): Integer;
21999 var Sz: TSize;
22000 begin
22001 if DC = 0 then
22002 Result := Length( Text )
22003 else
22004 begin
22005 Windows.GetTextExtentPoint32( DC, PChar( Text ), Length( Text ), Sz );
22006 Result := Sz.cx;
22007 end;
22008 end;
22010 //[function FilePathShortenPixels]
22011 function FilePathShortenPixels( const Path: String; DC: HDC; MaxPixels: Integer ): String;
22012 var L0, L1: Integer;
22013 Prev: String;
22014 begin
22015 Result := Path;
22016 L0 := PixelsLength( DC, Result );
22017 while L0 > MaxPixels do
22018 begin
22019 Prev := Result;
22020 L1 := pos( '\...\', Result );
22021 if L1 <= 0 then
22022 Result := ExcludeTrailingPathDelimiter( ExtractFilePath( Result ) )
22023 else
22024 Result := Copy( Result, 1, L1 - 1 );
22025 if Result <> '' then
22026 Result := IncludeTrailingPathDelimiter( ExtractFilePath( Result ) ) + '...\' + ExtractFileName( Path );
22027 if (Result = '') or (Result = Prev) then
22028 begin
22029 L1 := Length( ExtractFilePath( Result ) );
22030 while (PixelsLength( DC, Result ) > MaxPixels) and (L1 > 1) do
22031 begin
22032 Dec( L1 );
22033 Result := Copy( Result, 1, L1 ) + '...\' + ExtractFileName( Result );
22034 end;
22035 if PixelsLength( DC, Result ) > MaxPixels then
22036 begin
22037 L1 := MaxPixels + 1;
22038 while ((MaxPixels > 0) and (L1 > 1) or (MaxPixels = 0) and (L1 > 0)) and
22039 (PixelsLength( DC, Result ) > MaxPixels) do
22040 begin
22041 Dec( L1 );
22042 Result := Copy( ExtractFileName( Path ), 1, L1 ) + '...';
22043 end;
22044 end;
22045 break;
22046 end;
22047 L0 := PixelsLength( DC, Result );
22048 end;
22049 end;
22051 //[procedure CutFirstDirectory]
22052 procedure CutFirstDirectory(var S: String);
22054 Root: Boolean;
22055 P: Integer;
22056 begin
22057 if S = '\' then
22058 S := ''
22059 else
22060 begin
22061 if S[1] = '\' then
22062 begin
22063 Root := True;
22064 Delete(S, 1, 1);
22066 else
22067 Root := False;
22068 if S[1] = '.' then
22069 Delete(S, 1, 4);
22070 P := pos('\',S);
22071 if P <> 0 then
22072 begin
22073 Delete(S, 1, P);
22074 S := '...\' + S;
22076 else
22077 S := '';
22078 if Root then
22079 S := '\' + S;
22080 end;
22081 end;
22083 //[function MinimizeName]
22084 function MinimizeName( const Path: String; DC: HDC; MaxPixels: Integer ): String;
22086 Drive, Dir, Name: String;
22087 begin
22088 Result := Path;
22089 Dir := ExtractFilePath(Result);
22090 Name := ExtractFileName(Result);
22092 if (Length(Dir) >= 2) and (Dir[2] = ':') then
22093 begin
22094 Drive := Copy(Dir, 1, 2);
22095 Delete(Dir, 1, 2);
22097 else
22098 Drive := '';
22099 while ((Dir <> '') or (Drive <> '')) and (PixelsLength(DC, Result) > MaxPixels) do
22100 begin
22101 if Dir = '\...\' then
22102 begin
22103 Drive := '';
22104 Dir := '...\';
22106 else if Dir = '' then
22107 Drive := ''
22108 else
22109 CutFirstDirectory(Dir);
22110 Result := Drive + Dir + Name;
22111 end;
22112 end;
22114 //[FUNCTION FileSize]
22115 {$IFDEF ASM_VERSION}
22116 function FileSize( const Path : String ) : Integer;
22117 const size_TWin32FindData = sizeof( TWin32FindData );
22119 ADD ESP, - size_TWin32FindData
22120 PUSH ESP
22121 //CALL System.@LStrToPChar // Path must not be ''
22122 PUSH EAX
22123 CALL FindFirstFile
22124 INC EAX
22125 JZ @@exit
22126 DEC EAX
22127 PUSH EAX
22128 CALL FindClose
22130 MOV EAX, [ESP].TWin32FindData.nFileSizeLow
22131 @@exit:
22132 ADD ESP, size_TWin32FindData
22133 end;
22134 {$ELSE ASM_VERSION} //Pascal
22135 function FileSize( const Path : String ) : Integer;
22136 var FD : TWin32FindData;
22137 FH : THandle;
22138 begin
22139 FH := FindFirstFile( PChar( Path ), FD );
22140 Result := 0;
22141 if FH = INVALID_HANDLE_VALUE then exit;
22142 Result := FD.nFileSizeLow;
22143 if ((FD.nFileSizeLow and $80000000) <> 0) or
22144 (FD.nFileSizeHigh <> 0) then Result := -1;
22145 FindClose( FH );
22146 end;
22147 {$ENDIF ASM_VERSION}
22148 //[END FileSize]
22151 //[function FileTimeCompare]
22152 function FileTimeCompare( const FT1, FT2 : TFileTime ) : Integer;
22153 var ST1, ST2 : TSystemTime;
22154 begin
22155 FileTimeToSystemTime( FT1, ST1 );
22156 FileTimeToSystemTime( FT2, ST2 );
22157 Result := CompareSystemTime( ST1, ST2 );
22158 end;
22160 //[function GetSystemDir]
22161 function GetSystemDir: String;
22162 var Buf: array[ 0..MAX_PATH ] of Char;
22163 begin
22164 GetSystemDirectory( @ Buf[ 0 ], MAX_PATH + 1 );
22165 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
22166 end;
22169 //[function GetWindowsDir]
22170 function GetWindowsDir : string;
22171 var Buf : array[ 0..MAX_PATH ] of Char;
22172 begin
22173 GetWindowsDirectory( @Buf[ 0 ], MAX_PATH + 1 );
22174 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
22175 end;
22177 //[function GetWorkDir]
22178 function GetWorkDir : string;
22179 var Buf: array[ 0..MAX_PATH ] of Char;
22180 begin
22181 GetCurrentDirectory( MAX_PATH + 1, @ Buf[ 0 ] );
22182 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
22183 end;
22186 //[function GetTempDir]
22187 function GetTempDir : string;
22188 var Buf : array[ 0..MAX_PATH ] of Char;
22189 begin
22190 Windows.GetTempPath( MAX_PATH + 1, @Buf[ 0 ] );
22191 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
22192 end;
22194 //[function CreateTempFile]
22195 function CreateTempFile( const DirPath, Prefix: String ): String;
22196 var Buf: array[ 0..MAX_PATH ] of Char;
22197 begin
22198 GetTempFileName( PChar( DirPath ), PChar( Prefix ), 0, Buf );
22199 Result := Buf;
22200 end;
22202 //[function GetFileListStr]
22203 function GetFileListStr(FPath{e.g.'c:\tmp\'}, FMask{e.g.'*.*'}: string): string;
22204 {* List of files in string, separating each path from others with semicolon (';').
22205 E.g.: 'c:\tmp\unit1.dcu;c:\tmp\unit1.~pa' (for use with DeleteFile2Recycle())}
22207 Srch: TWin32FindData;
22208 flag: Integer;
22209 succ: boolean;
22210 dir:string;
22211 begin
22212 result := '';
22213 if (FPath<>'') and (FPath[length(FPath)]<>'\') then FPath:=FPath+'\';
22214 if (FMask<>'') and (FMask[1]='\') then FMask:=CopyEnd(FMask,2);
22215 dir:=FPath+FMask;
22216 flag := FindFirstFile(PChar(dir), Srch);
22217 succ := flag <> 0;
22218 while succ do begin
22219 if (not (Srch.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0))then begin
22220 if Result<>''then Result:=Result+';';
22221 Result:=Result+FPath+Srch.cFileName;
22222 end;
22223 succ := FindNextFile(Flag, Srch);
22224 end;
22225 FindClose(Flag);
22226 end;
22228 //[function DeleteFiles]
22229 function DeleteFiles( const DirPath: String ): Boolean;
22230 var Files, Name: String;
22231 begin
22232 Files := GetFileListStr( ExtractFilePath( DirPath ), ExtractFileName( DirPath ) );
22233 Result := TRUE;
22234 while Files <> '' do
22235 begin
22236 Name := Parse( Files, ';' );
22237 Result := Result and DeleteFile( PChar( Name ) );
22238 end;
22239 end;
22242 //[function DeleteFile2Recycle]
22243 function DeleteFile2Recycle( const Filename : String ) : Boolean;
22244 var FOS : TSHFileOpStruct;
22245 Buf : PChar;
22246 L : Integer;
22247 begin
22248 L := Length( Filename );
22249 GetMem( Buf, L + 2 );
22250 StrCopy( Buf, PChar( Filename ) );
22251 Buf[ L + 1 ] := #0;
22252 for L := L downto 0 do
22253 if Buf[ L ] = ';' then Buf[ L ] := #0;
22254 FillChar( FOS, Sizeof( FOS ), 0 );
22255 if Applet <> nil then
22256 FOS.Wnd := Applet.Handle;
22257 FOS.wFunc := FO_DELETE;
22258 FOS.pFrom := Buf;
22259 FOS.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION;
22260 FOS.fAnyOperationsAborted := True;
22261 FOS.lpszProgressTitle := PChar( 'Delete ' + Filename + ' to Recycle bin' );
22262 Result := SHFileOperation( FOS ) = 0;
22263 if Result then
22264 Result := not FOS.fAnyOperationsAborted;
22265 FreeMem( Buf );
22266 end;
22268 //[function CopyMoveFiles]
22269 function CopyMoveFiles( const FromList, ToList: String; Move: Boolean ): Boolean;
22270 var FOS : TSHFileOpStruct;
22271 Buf : PChar;
22272 L : Integer;
22273 begin
22274 L := Length( FromList );
22275 GetMem( Buf, L + 2 );
22276 StrCopy( Buf, PChar( FromList ) );
22277 Buf[ L + 1 ] := #0;
22278 for L := L downto 0 do
22279 if Buf[ L ] = ';' then Buf[ L ] := #0;
22280 FillChar( FOS, Sizeof( FOS ), 0 );
22281 if Applet <> nil then
22282 FOS.Wnd := Applet.Handle;
22283 if Move then
22284 begin
22285 FOS.wFunc := FO_MOVE;
22286 FOS.lpszProgressTitle := PChar( 'Move files' );
22288 else
22289 begin
22290 FOS.wFunc := FO_COPY;
22291 FOS.lpszProgressTitle := PChar( 'Copy files' );
22292 end;
22293 FOS.pFrom := Buf;
22294 FOS.pTo := PChar( ToList + #0 );
22295 FOS.fFlags := FOF_ALLOWUNDO;
22296 FOS.fAnyOperationsAborted := True;
22297 Result := SHFileOperation( FOS ) = 0;
22298 if Result then
22299 Result := not FOS.fAnyOperationsAborted;
22300 FreeMem( Buf );
22301 end;
22304 //[function DiskFreeSpace]
22305 function DiskFreeSpace( const Path: String ): I64;
22306 type TGetDFSEx = function( Path: PChar; CallerFreeBytes, TotalBytes, FreeBytes: Pointer )
22307 : Bool; stdcall;
22308 var GetDFSEx: TGetDFSEx;
22309 Kern32: THandle;
22310 V: TOSVersionInfo;
22311 Ex: Boolean;
22312 SpC, BpS, NFC, TNC: DWORD;
22313 FBA, TNB: I64;
22314 begin
22315 GetDFSEx := nil;
22316 V.dwOSVersionInfoSize := Sizeof( V );
22317 GetVersionEx( V );
22318 Ex := FALSE;
22319 if V.dwPlatformId = VER_PLATFORM_WIN32_NT then
22320 begin
22321 Ex := V.dwMajorVersion >= 4;
22323 else
22324 if V.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then
22325 begin
22326 Ex := V.dwMajorVersion > 4;
22327 if not Ex then
22328 if V.dwMajorVersion = 4 then
22329 begin
22330 Ex := V.dwMinorVersion > 0;
22331 if not Ex then
22332 Ex := LoWord( V.dwBuildNumber ) >= $1111;
22333 end;
22334 end;
22335 if Ex then
22336 begin
22337 Kern32 := GetModuleHandle( 'kernel32.dll' );
22338 GetDFSEx := GetProcAddress( Kern32, 'GetDiskFreeSpaceExA' );
22339 end;
22340 if Assigned( GetDFSEx ) then
22341 GetDFSEx( PChar( Path ), @ FBA, @ TNB, @Result )
22342 else
22343 begin
22344 GetDiskFreeSpace( PChar( Path ), SpC, BpS, NFC, TNC );
22345 Result := Mul64i( MakeInt64( SpC * BpS, 0 ), NFC );
22346 end;
22347 end;
22351 //[function GetUniqueFilename]
22352 function GetUniqueFilename( PathName: string ) : String;
22353 var Path, Nam, Ext : String;
22354 I, J, K : Integer;
22355 begin
22356 Result := PathName;
22357 Path := ExtractFilePath( PathName );
22358 if not DirectoryExists( Path ) then Exit;
22359 Nam := ExtractFileNameWOext( PathName );
22360 if Nam = '' then
22361 begin
22362 if Path[ Length( Path ) ] = '\' then
22363 Path := Copy( Path, 1, Length( Path ) - 1 );
22364 PathName := Path;
22365 Result := Path;
22366 end;
22367 Nam := ExtractFileNameWOext( PathName );
22368 Ext := ExtractFileExt( PathName );
22369 I := Length( Nam );
22370 for J := I downto 1 do
22371 if not (Nam[ J ] in [ '0'..'9' ]) then
22372 begin
22373 I := J;
22374 break;
22375 end;
22376 K := Str2Int( CopyEnd( Nam, I + 1 ) );
22377 while FileExists( Result ) do
22378 begin
22379 Inc( K );
22380 Result := Path + Copy( Nam, 1, I ) + Int2Str( K ) + Ext;
22381 end;
22382 end;
22384 //[FUNCTION GetStartDir]
22385 {$IFDEF ASM_VERSION}
22386 function GetStartDir : String;
22388 PUSH EBX
22389 MOV EBX, EAX
22391 XOR EAX, EAX
22392 MOV AH, 2
22393 SUB ESP, EAX
22394 MOV EDX, ESP
22395 PUSH EAX
22396 PUSH EDX
22397 PUSH 0
22398 CALL GetModuleFileName
22400 LEA EDX, [ESP + EAX]
22401 @@1: DEC EDX
22402 CMP byte ptr [EDX], '\'
22403 JNZ @@1
22405 INC EDX
22406 MOV byte ptr [EDX], 0
22408 MOV EAX, EBX
22409 MOV EDX, ESP
22410 CALL System.@LStrFromPChar
22412 ADD ESP, 200h
22413 POP EBX
22414 end;
22415 {$ELSE ASM_VERSION} //Pascal
22416 function GetStartDir : String;
22417 var Buffer:array[0..260] of Char;
22418 I : Integer;
22419 begin
22420 I := GetModuleFileName( 0, Buffer, Sizeof( Buffer ) );
22421 for I := I downto 0 do
22422 if Buffer[ I ] = '\' then
22423 begin
22424 Buffer[ I + 1 ] := #0;
22425 break;
22426 end;
22427 Result := Buffer;
22428 end;
22429 {$ENDIF ASM_VERSION}
22430 //[END GetStartDir]
22432 //[END FILES]
22436 { TDirList }
22438 //[function NewDirList]
22439 function NewDirList( const DirPath, Filter: String; Attr: DWORD ): PDirList;
22440 begin
22442 New( Result, Create );
22443 {+}{++}(*Result := PDirList.Create;*){--}
22444 Result.ScanDirectory( DirPath, Filter, Attr );
22445 end;
22446 //[END NewDirList]
22448 //[function NewDirListEx]
22449 function NewDirListEx( const DirPath, Filters: String; Attr: DWORD ): PDirList;
22450 begin
22452 New( Result, Create );
22453 {+}{++}(*Result := PDirList.Create;*){--}
22454 Result.ScanDirectoryEx( DirPath, Filters, Attr );
22455 end;
22456 //[END NewDirListEx]
22458 {$IFDEF ASM_VERSION}
22459 //[procedure TDirList.Clear]
22460 procedure TDirList.Clear;
22462 XOR ECX, ECX
22463 XCHG ECX, [EAX].fList
22464 JECXZ @@exit
22465 XCHG EAX, ECX
22466 CALL TList.Release
22467 @@exit:
22468 end;
22469 {$ELSE ASM_VERSION} //Pascal
22470 procedure TDirList.Clear;
22471 begin
22472 if FList <> nil then
22473 FList.Release;
22474 FList := nil;
22475 end;
22476 {$ENDIF ASM_VERSION}
22478 {$IFDEF ASM_VERSION}
22479 //[destructor TDirList.Destroy]
22480 destructor TDirList.Destroy;
22482 PUSH EBX
22483 MOV EBX, EAX
22484 CALL Clear
22485 LEA EAX, [EBX].FPath
22486 CALL System.@LStrClr
22487 XCHG EAX, EBX
22488 CALL TObj.Destroy
22489 POP EBX
22490 end;
22491 {$ELSE ASM_VERSION} //Pascal
22492 destructor TDirList.Destroy;
22493 begin
22494 Clear;
22495 FPath := '';
22496 inherited;
22497 end;
22498 {$ENDIF ASM_VERSION}
22500 //[FUNCTION FindFilter]
22501 {$IFDEF ASM_VERSION}
22502 function FindFilter( const Filter: String): String;
22504 XCHG EAX, EDX
22505 PUSH EAX
22506 CALL System.@LStrAsg
22507 POP EAX
22508 CMP dword ptr [EAX], 0
22509 JNE @@exit
22510 LEA EDX, @@mask_all
22511 JE System.@LStrFromPChar
22512 @@mask_all: DB '*.*',0
22513 @@exit:
22514 end;
22515 {$ELSE ASM_VERSION} //Pascal
22516 function FindFilter(const Filter: String): String;
22517 begin
22518 Result := Filter;
22519 if Result = '' then Result := '*.*';
22520 end;
22521 {$ENDIF ASM_VERSION}
22522 //[END FindFilter]
22525 //[function TDirList.Get]
22526 function TDirList.Get(Idx: Integer): PWin32FindData;
22527 begin
22528 Result := FList.fItems[ Idx ];
22529 end;
22531 {$IFDEF ASM_VERSION}
22532 //[function TDirList.GetCount]
22533 function TDirList.GetCount: Integer;
22535 MOV EAX, [EAX].fList
22536 TEST EAX, EAX
22537 {$IFDEF USE_CMOV}
22538 CMOVNZ EAX, [EAX].TList.fCount
22539 {$ELSE}
22540 JZ @@exit
22541 MOV EAX, [EAX].TList.fCount
22542 @@exit: {$ENDIF}
22543 end;
22544 {$ELSE ASM_VERSION} //Pascal
22545 function TDirList.GetCount: Integer;
22546 begin
22547 Result := 0;
22548 if FList = nil then Exit;
22549 Result := FList.Count;
22550 end;
22551 {$ENDIF ASM_VERSION}
22553 {$IFDEF ASM_VERSION}
22554 //[function TDirList.GetNames]
22555 function TDirList.GetNames(Idx: Integer): string;
22557 MOV EAX, [EAX].fList
22558 MOV EAX, [EAX].TList.fItems
22559 MOV EDX, [EAX + EDX*4]
22560 //*/////////////////////////////////////////////////////
22561 // ADD EDX, TWin32FindData.cFileName
22562 //*/////////////////////////////////////////////////////
22563 ADD EDX, offset TWin32FindData.cFileName //
22564 //*/////////////////////////////////////////////////////
22565 MOV EAX, ECX
22566 CALL System.@LStrFromPChar
22567 end;
22568 {$ELSE ASM_VERSION} //Pascal
22569 function TDirList.GetNames(Idx: Integer): string;
22570 begin
22571 Result := PChar(@PWin32FindData(fList.fItems[ Idx ]).cFileName[0]);
22572 //Result := PChar(@Items[Idx].cFileName[0]);
22573 end;
22574 {$ENDIF ASM_VERSION}
22576 //[function TDirList.GetIsDirectory]
22577 function TDirList.GetIsDirectory(Idx: Integer): Boolean;
22578 begin
22579 Result := LongBool( Items[ Idx ].dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY );
22580 end;
22582 {$IFDEF ASM_noVERSION}
22583 //[function TDirList.SatisfyFilter]
22584 function TDirList.SatisfyFilter(FileName: PChar; FileAttr,
22585 FindAttr: DWord): Boolean;
22587 PUSH EBX
22588 PUSH ESI
22589 PUSH EDI
22590 XCHG EBX, EAX // EBX = @ Self
22591 MOV EAX, [FindAttr]
22592 MOV EDI, EDX // EDI = FileName
22593 MOV EDX, EAX
22594 AND EDX, ECX
22595 CMP EDX, EAX
22596 JE @@1
22598 TEST AL, FILE_ATTRIBUTE_NORMAL
22599 JZ @@ret_false
22600 @@1:
22601 CMP word ptr [EDI], '.'
22602 JE @@1_1
22603 CMP word ptr [EDI], '..'
22604 JNE @@1_1
22605 CMP byte ptr [EDI+2], 0
22606 JNE @@1_1
22607 @@1_0:
22608 MOV ECX, [FindAttr]
22609 TEST CL, FILE_ATTRIBUTE_NORMAL
22610 JZ @@1_1
22611 CMP ECX, FILE_ATTRIBUTE_NORMAL
22612 JE @@1_1
22613 TEST AL, FILE_ATTRIBUTE_DIRECTORY
22614 JZ @@1_1
22615 TEST CL, FILE_ATTRIBUTE_DIRECTORY
22616 JNZ @@ret_true
22618 @@1_1:
22619 MOV ECX, [EBX].fFilters
22620 JECXZ @@ret_false //?
22622 MOV ESI, [ECX].TStrList.fList
22623 MOV ESI, [ESI].TList.fItems
22624 MOV ECX, [ECX].TStrList.fCount
22625 JECXZ @@ret_false
22627 @@2:
22628 LODSD
22629 TEST EAX, EAX
22630 JZ @@nx_filter
22632 PUSHAD
22634 MOV EDX, [EAX]
22635 CMP DX, $002E
22636 JE @@F_d_dd
22637 AND EDX, $FFFFFF
22638 CMP EDX, $002E2E
22639 JE @@F_d_dd
22641 MOV EDX, [EDI]
22642 CMP DX, $002E
22643 JE @@4
22644 AND EDX, $FFFFFF
22645 CMP EDX, $002E2E
22646 JE @@4
22647 JMP @@chk_anti
22649 @@F_d_dd:
22650 MOV EDX, EDI
22651 PUSH EAX
22652 CALL StrComp
22653 TEST EAX, EAX
22654 POP EAX
22655 JZ @@popad_ret_true
22657 @@chk_anti:
22658 XCHG EDX, EAX // EDX = filter[ i ]
22659 MOV EAX, EDI // EAX = FileName
22660 CMP byte ptr [EDX], '^'
22661 JNE @@3
22663 INC EDX
22664 CALL _2StrSatisfy
22665 TEST AL, AL
22666 JZ @@4
22667 POPAD
22668 JMP @@ret_false
22670 @@3: CALL _2StrSatisfy
22671 TEST AL, AL
22672 JZ @@4
22673 @@popad_ret_true:
22674 POPAD
22675 @@ret_true:
22676 MOV AL, 1
22677 JMP @@exit
22679 @@4: POPAD
22680 @@nx_filter:
22681 LOOP @@2
22683 @@ret_false:
22684 XOR EAX, EAX
22685 @@exit:
22686 POP EDI
22687 POP ESI
22688 POP EBX
22689 end;
22690 {$ELSE ASM_VERSION} //Pascal
22691 function TDirList.SatisfyFilter(FileName: PChar; FileAttr,
22692 FindAttr: DWord): Boolean;
22693 {$IFDEF F_P}
22694 const Dot: String = '.';
22695 {$ENDIF F_P}
22696 var I: Integer;
22697 F: PChar;
22698 HasOnlyNegFilters: Boolean;
22699 begin
22700 Result := (((FileAttr and FindAttr) = FindAttr) or
22701 LongBool(FindAttr and FILE_ATTRIBUTE_NORMAL));
22702 if not Result then Exit;
22704 if (FileName <> {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) and
22705 (FileName <> '..') then
22706 if LongBool( FindAttr and FILE_ATTRIBUTE_NORMAL ) and
22707 (FindAttr <> FILE_ATTRIBUTE_NORMAL) then
22708 if LongBool( FindAttr and FILE_ATTRIBUTE_DIRECTORY ) and
22709 LongBool( FileAttr and FILE_ATTRIBUTE_DIRECTORY ) then Exit;
22711 HasOnlyNegFilters := TRUE;
22712 for I := 0 to fFilters.fCount - 1 do
22713 begin
22714 F := PChar(fFilters.fList.fItems[ I ]);
22715 if F = '' then continue;
22717 if (F = {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) or (F = '..') then
22718 begin
22719 if FileName = F then
22720 Exit;
22722 else
22723 if (Filename = {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) or (FileName = '..') then
22724 begin
22725 //Result := FALSE;
22726 continue;
22727 end;
22729 if F[ 0 ] = '^' then
22730 begin
22731 if StrSatisfy( FileName, PChar(@F[ 1 ]) ) then
22732 begin
22733 Result := False;
22734 Exit;
22735 end;
22737 else
22738 begin
22739 HasOnlyNegFilters := FALSE;
22740 if StrSatisfy( FileName, F ) then
22741 begin
22742 Result := True;
22743 Exit;
22744 end;
22745 end;
22746 end;
22748 Result := HasOnlyNegFilters and
22749 (FileName <> {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) and
22750 (FileName <> '..');
22752 end;
22753 {$ENDIF ASM_VERSION}
22755 {$IFDEF ASM_VERSION}
22756 //[procedure TDirList.ScanDirectory]
22757 procedure TDirList.ScanDirectory(const DirPath, Filter: String;
22758 Attr: DWord);
22759 const sz_win32finddata = sizeof(TWin32FindData);
22761 PUSH EBX
22762 PUSH EDI
22763 MOV EBX, EAX
22765 PUSHAD
22766 CALL Clear
22767 CALL NewList
22768 MOV [EBX].fList, EAX
22769 POPAD
22771 PUSHAD
22772 LEA EAX, [EBX].fPath
22773 CALL System.@LStrAsg
22774 POPAD
22776 MOV EAX, [EBX].fPath
22777 TEST EAX, EAX
22778 JE @@exit
22780 PUSHAD
22781 LEA EDX, [EBX].fPath
22782 MOV EAX, [EDX]
22783 CALL IncludeTrailingPathDelimiter
22785 MOV EAX, [EBX].fFilters
22786 TEST EAX, EAX
22787 JNZ @@1
22788 CALL NewStrList
22789 MOV [EBX].fFilters, EAX
22790 POPAD
22792 PUSHAD
22793 PUSH ECX
22794 XCHG EAX, ECX
22795 MOV EDX, offset[@@star_d_star]
22796 CALL StrComp
22797 TEST AL, AL
22798 POP EDX
22799 JNZ @@asg_Filter
22800 MOV EDX, offset[@@star]
22801 @@asg_Filter:
22802 MOV EAX, [EBX].fFilters
22803 CALL TStrList.Add
22804 JMP @@1
22806 @@star_d_star:
22807 DB '*.*', 0
22808 DD -1, 1
22809 @@star: DB '*', 0
22811 @@1:
22812 POPAD
22814 ADD ESP, -sz_win32finddata
22815 XOR EDX, EDX
22816 PUSH EDX
22817 PUSH EDX
22818 XCHG EAX, ECX
22819 MOV EDX, ESP
22820 CALL FindFilter
22822 LEA EAX, [ESP+4]
22823 MOV EDX, [EBX].fPath
22824 POP ECX
22825 PUSH ECX
22826 CALL System.@LStrCat3
22827 CALL RemoveStr
22829 POP EAX
22830 MOV EDX, ESP
22831 PUSH EAX
22832 PUSH EDX
22833 PUSH EAX
22834 CALL FindFirstFile
22835 MOV EDI, EAX
22836 INC EAX
22837 MOV EAX, ESP
22839 PUSHFD
22840 CALL System.@LStrClr
22841 POPFD
22842 POP ECX
22844 JZ @@fin
22846 @@loop:
22847 MOV ECX, [ESP].TWin32FindData.dwFileAttributes
22848 PUSH [Attr]
22849 LEA EDX, [ESP+4].TWin32FindData.cFileName
22850 MOV EAX, EBX
22851 CALL SatisfyFilter
22853 TEST AL, AL
22854 JZ @@next
22856 MOV ECX, [EBX].fOnItem.TMethod.Code
22857 JECXZ @@accept
22858 MOV EAX, [EBX].fOnItem.TMethod.Data
22859 MOV ECX, ESP
22860 PUSH 1
22861 MOV EDX, ESP
22862 PUSH EDX
22863 MOV EDX, EBX
22864 CALL dword ptr [EBX].fOnItem.TMethod.Code
22865 POP ECX
22866 JECXZ @@next
22867 LOOP @@fin
22869 @@accept:
22870 MOV EAX, sz_win32finddata
22871 PUSH EAX
22872 CALL System.@GetMem
22873 PUSH EAX
22874 XCHG EDX, EAX
22875 MOV EAX, [EBX].fList
22876 CALL TList.Add
22877 POP EDX
22878 POP ECX
22879 MOV EAX, ESP
22880 CALL System.Move
22882 @@next:
22883 PUSH ESP
22884 PUSH EDI
22885 CALL FindNextFile
22886 TEST EAX, EAX
22887 JNZ @@loop
22889 PUSH EDI
22890 CALL FindClose
22892 @@fin:
22893 ADD ESP, sz_win32finddata
22894 @@exit:
22895 XOR EAX, EAX
22896 XCHG EAX, [EBX].fFilters
22897 CALL TObj.Free
22898 POP EDI
22899 POP EBX
22900 end;
22901 {$ELSE ASM_VERSION} //Pascal
22902 procedure TDirList.ScanDirectory(const DirPath, Filter: String;
22903 Attr: DWord);
22904 var FindData : TWin32FindData;
22905 E : PWin32FindData;
22906 FindHandle : THandle;
22907 Action: TDirItemAction;
22908 begin
22909 Clear;
22910 FList := NewList;
22911 FPath := DirPath;
22912 if FPath = '' then Exit;
22913 FPath := IncludeTrailingPathDelimiter( FPath );
22914 if fFilters = nil then
22915 begin
22916 fFilters := NewStrList;
22917 if Filter = '*.*' then
22918 fFilters.Add( '*' )
22919 else
22920 fFilters.Add( Filter );
22921 end;
22922 FindHandle := FindFirstFile( PChar( FPath + FindFilter( Filter ) ),
22923 FindData );
22924 if FindHandle = INVALID_HANDLE_VALUE then Exit;
22925 while True do
22926 begin
22927 if SatisfyFilter( PChar(@FindData.cFileName[0]),
22928 FindData.dwFileAttributes, Attr ) then
22929 begin
22930 Action := diAccept;
22931 if Assigned( OnItem ) then
22932 OnItem( @Self, FindData, Action );
22933 CASE Action OF
22934 diSkip: ;
22935 diAccept:
22936 begin
22937 GetMem( E, Sizeof( FindData ) );
22938 E^ := FindData;
22939 FList.Add( E );
22940 end;
22941 diCancel: break;
22942 END;
22943 end;
22944 if not FindNextFile( FindHandle, FindData ) then break;
22945 end;
22946 FindClose( FindHandle );
22947 fFilters.Free;
22948 fFilters := nil;
22949 end;
22950 {$ENDIF ASM_VERSION}
22952 {$IFDEF ASM_VERSION}
22953 //[procedure TDirList.ScanDirectoryEx]
22954 procedure TDirList.ScanDirectoryEx(const DirPath, Filters: String;
22955 Attr: DWord);
22957 PUSH EBX
22958 MOV EBX, EAX
22960 PUSHAD
22961 CALL NewStrList
22962 MOV [EBX].fFilters, EAX
22963 POPAD
22965 PUSHAD
22966 PUSH 0
22967 MOV EAX, ESP
22968 MOV EDX, ECX
22969 CALL System.@LStrLAsg
22970 @@1: MOV ECX, [ESP]
22971 JECXZ @@2
22972 MOV EAX, ESP
22973 MOV EDX, offset[@@semicolon]
22974 PUSH 0
22975 MOV ECX, ESP
22976 CALL Parse
22977 MOV EAX, [ESP]
22978 MOV EDX, ESP
22979 CALL Trim
22980 POP EDX
22981 PUSH EDX
22982 TEST EDX, EDX
22983 JZ @@filt_added
22984 MOV EAX, [EBX].fFilters
22985 CALL TStrList.Add
22986 @@filt_added:
22987 CALL RemoveStr
22988 JMP @@1
22990 // ';' string literal
22991 DD -1, 1
22992 @@semicolon:
22993 DB ';',0
22995 @@2: POP ECX
22996 POPAD
22997 XOR ECX, ECX
22998 PUSH [Attr]
22999 CALL ScanDirectory
23000 {XOR EAX, EAX
23001 XCHG EAX, [EBX].fFilters
23002 CALL TObj.Free}
23003 POP EBX
23004 @@exit:
23005 end;
23006 {$ELSE ASM_VERSION} //Pascal
23007 procedure TDirList.ScanDirectoryEx(const DirPath, Filters: String;
23008 Attr: DWord);
23009 var F, FF: String;
23010 begin
23011 FF := Filters;
23012 fFilters := NewStrList;
23013 while FF <> '' do
23014 begin
23015 F := Trim( Parse( FF, ';' ) );
23016 if F <> '' then
23017 fFilters.Add( F );
23018 end;
23019 ScanDirectory( DirPath, '', Attr );
23020 end;
23021 {$ENDIF ASM_VERSION}
23023 type
23024 PSortDirData = ^TSortDirData;
23025 TSortDirData = packed Record
23026 FoldersFirst, CaseSensitive : Boolean;
23027 Rules : array[ 0..11 ] of TSortDirRules;
23028 Dir : PDirList;
23029 end;
23031 //[FUNCTION CompareDirItems]
23032 {$IFDEF ASM_noVERSION}
23033 function CompareDirItems( const Data : PSortDirData; const e1, e2 : DWORD ) : Integer;
23035 PUSH EBX
23036 PUSH ESI
23037 PUSH EDI
23038 XCHG EBX, EAX
23039 MOV EAX, [EBX].TSortDirData.Dir
23040 MOV EAX, [EAX].TDirList.fList
23041 MOV EAX, [EAX].TList.fItems
23042 MOV ESI, [EAX+EDX*4]
23043 MOV EDI, [EAX+ECX*4]
23044 MOV DL, byte ptr[ESI].TWin32FindData.dwFileAttributes
23045 MOV DH, byte ptr[EDI].TWin32FindData.dwFileAttributes
23046 AND DX, 2020h
23047 XOR EAX, EAX
23048 CMP DL, DH
23049 JE @@1
23050 CMP [EBX].TSortDirData.FoldersFirst, AL
23051 JE @@1
23052 OR AL, DL
23053 JNE @@exit_near
23054 DEC EAX
23055 //JMP @@exit
23056 @@exit_near:
23057 POP EDI
23058 POP ESI
23059 POP EBX
23062 @@sdrByDateChanged:
23063 LEA EAX, [ESI].TWin32FindData.ftLastWriteTime
23064 LEA EDX, [EDI].TWin32FindData.ftLastWriteTime
23065 JMP @@sdrByDate1
23067 @@sdrByDateAccessed:
23068 LEA EAX, [ESI].TWin32FindData.ftLastAccessTime
23069 LEA EDX, [EDI].TWin32FindData.ftLastAccessTime
23070 JMP @@sdrByDate1
23072 @@jmp_table:
23073 DD offset[@@exit1], offset[@@2], offset[@@2]
23074 DD offset[@@sdrByName], offset[@@sdrByExt]
23075 DD offset[@@sdrBySize], offset[@@sdrBySize]
23076 DD offset[@@sdrByDateCreate], offset[@@sdrByDateChanged]
23077 DD offset[@@sdrByDateAccessed]
23079 @@1:
23080 LEA EDX, [EBX].TSortDirData.Rules
23081 PUSH EDX
23082 @@2:
23083 POP EDX
23084 XOR EAX, EAX
23085 MOV AL, [EDX]
23086 INC EDX
23087 PUSH EDX
23089 JMP dword ptr [@@jmp_table+EAX*4]
23090 //////// ///////////////////
23092 @@sdrByDateCreate:
23093 LEA EAX, [ESI].TWin32FindData.ftCreationTime
23094 LEA EDX, [EDI].TWin32FindData.ftCreationTime
23095 @@sdrByDate1:
23096 PUSH EDX
23097 PUSH EAX
23098 CALL CompareFileTime
23099 TEST EAX, EAX
23100 JE @@2
23101 JMP @@exit1
23103 @@sdrBySize:
23104 MOV EAX, [ESI].TWin32FindData.nFileSizeHigh
23105 SUB EAX, [EDI].TWin32FindData.nFileSizeHigh
23106 JNE @@sdrBySize1
23107 MOV EAX, [ESI].TWin32FindData.nFileSizeLow
23108 SUB EAX, [EDI].TWin32FindData.nFileSizeLow
23109 @@to_2:
23110 JE @@2
23111 @@sdrBySize1:
23112 POP EDX
23113 DEC EDX
23114 CMP byte ptr[EDX], sdrBySizeDescending
23115 JNE @@sdrBySize2
23116 NEG EAX
23117 @@sdrBySize2:
23118 JNE @@exit
23119 //////// ///////////////////
23121 DD -1, 1
23122 @@point:DB '.',0
23124 @@sdrByExt:
23125 LEA EAX, [EDI].TWin32FindData.cFileName
23126 MOV EDX, offset[@@point]
23127 PUSH EDX
23128 CALL __DelimiterLast
23129 POP EDX
23130 PUSH EAX
23131 LEA EAX, [ESI].TWin32FindData.cFileName
23132 CALL __DelimiterLast
23133 POP EDX
23134 JMP @@sdrByName0
23136 @@sdrByName:
23137 LEA EAX, [ESI].TWin32FindData.cFileName
23138 LEA EDX, [EDI].TWin32FindData.cFileName
23139 @@sdrByName0:
23140 CMP [EBX].TSortDirData.CaseSensitive, 0
23141 JNE @@sdrByName1
23142 CALL _AnsiCompareStrNoCase
23143 JMP @@sdrByName2
23144 @@sdrByName1:
23145 CALL _AnsiCompareStr
23146 @@sdrByName2:
23147 TEST EAX, EAX
23148 JE @@to_2
23149 //JMP @@exit1
23151 @@exit1:
23152 POP EDX
23153 @@exit:
23154 POP EDI
23155 POP ESI
23156 POP EBX
23157 end;
23158 {$ELSE ASM_VERSION} //Pascal
23159 function CompareDirItems( const Data : PSortDirData; const e1, e2 : DWORD ) : Integer;
23160 var I : Integer;
23161 Item1, Item2 : PWin32FindData;
23162 S1, S2 : PChar;
23163 IsDir1, IsDir2 : Boolean;
23164 Date1, Date2 : PFileTime;
23165 begin
23166 Item1 := Data.Dir.fList.fItems[ e1 ];
23167 Item2 := Data.Dir.fList.fItems[ e2 ];
23168 Result := 0;
23169 IsDir1 := (Item1.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0;
23170 IsDir2 := (Item2.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0;
23171 if (IsDir1 <> IsDir2) and Data.FoldersFirst then
23172 begin
23173 if IsDir1 then Result := -1 else Result := 1;
23174 exit;
23175 end;
23176 for I := 0 to High(Data.Rules) do
23177 begin
23178 case Data.Rules[ I ] of
23179 sdrByName:
23180 begin
23181 S1 := Item1.cFileName;
23182 S2 := Item2.cFileName;
23183 if not Data.CaseSensitive then
23184 Result := _AnsiCompareStrNoCase( S1, S2 )
23185 else
23186 Result := _AnsiCompareStr( S1, S2 );
23187 end;
23188 sdrByExt:
23189 begin
23190 S1 := Item1.cFileName;
23191 S2 := Item2.cFileName;
23192 S1 := __DelimiterLast( S1, '.' );
23193 S2 := __DelimiterLast( S2, '.' );
23194 if not Data.CaseSensitive then
23195 Result := _AnsiCompareStrNoCase( S1, S2 )
23196 else
23197 Result := _AnsiCompareStr( S1, S2 );
23198 end;
23199 sdrBySize, sdrBySizeDescending:
23200 begin
23201 if Item1.nFileSizeHigh < Item2.nFileSizeHigh then
23202 Result := -1
23203 else
23204 if Item1.nFileSizeHigh > Item2.nFileSizeHigh then
23205 Result := 1
23206 else
23207 if Item1.nFileSizeLow < Item2.nFileSizeLow then
23208 Result := -1
23209 else
23210 if Item1.nFileSizeLow > Item2.nFileSizeLow then
23211 Result := 1;
23212 if Data.Rules[ I ] = sdrBySizeDescending then
23213 Result := -Result;
23214 end;
23215 sdrByDateCreate:
23216 begin
23217 Date1 := @Item1.ftCreationTime;
23218 Date2 := @Item2.ftCreationTime;
23219 Result := CompareFileTime( Date1^, Date2^ );
23220 end;
23221 sdrByDateChanged:
23222 begin
23223 Date1 := @Item1.ftLastWriteTime;
23224 Date2 := @Item2.ftLastWriteTime;
23225 Result := CompareFileTime( Date1^, Date2^ );
23226 end;
23227 sdrByDateAccessed:
23228 begin
23229 Date1 := @Item1.ftLastAccessTime;
23230 Date2 := @Item2.ftLastAccessTime;
23231 Result := CompareFileTime( Date1^, Date2^ );
23232 end;
23233 end; {case}
23234 if Result <> 0 then break;
23235 end;
23236 end;
23237 {$ENDIF ASM_VERSION}
23238 //[END CompareDirItems]
23240 //[PROCEDURE SwapDirItems]
23241 {$IFDEF ASM_VERSION}
23242 procedure SwapDirItems( const Data : PSortDirData; const e1, e2 : DWORD );
23244 MOV EAX, [EAX].TSortDirData.Dir
23245 MOV EAX, [EAX].TDirList.fList
23246 MOV EAX, [EAX].TList.fItems
23247 LEA EDX, [EAX+EDX*4]
23248 LEA ECX, [EAX+ECX*4]
23249 MOV EAX, [EDX]
23250 XCHG EAX, [ECX]
23251 MOV [EDX], EAX
23252 end;
23253 {$ELSE ASM_VERSION} //Pascal
23254 procedure SwapDirItems( const Data : PSortDirData; const e1, e2 : DWORD );
23255 var Tmp : Pointer;
23256 begin
23257 Tmp := Data.Dir.FList.fItems[ e1 ];
23258 Data.Dir.FList.fItems[ e1 ] := Data.Dir.FList.fItems[ e2 ];
23259 Data.Dir.FList.fItems[ e2 ] := Tmp;
23260 end;
23261 {$ENDIF ASM_VERSION}
23262 //[END SwapDirItems]
23265 TSortDirData = packed Record
23266 FoldersFirst, CaseSensitive : Boolean;
23267 Rules : array[ 0..11 ] of TSortDirRules;
23268 Dir : PDirList;
23269 end;
23271 {$IFDEF ASM_VERSION}
23272 procedure TDirList.Sort(Rules: array of TSortDirRules);
23273 const high_DefSortDirRules = High( DefSortDirRules );
23275 PUSH EBX
23276 PUSH ESI
23277 XOR EBX,EBX
23278 CMP [EAX].fList, EBX
23279 JE @@exit
23281 PUSH EAX // prepare Dir = @Self
23282 XOR EAX, EAX
23283 PUSH EAX
23284 PUSH EAX
23285 PUSH EAX
23286 MOV ESI, ESP
23287 INC ECX // ECX = High(Rules)
23288 JZ @@2
23289 @@1: MOV AH, [EDX] // AH = Rules[ I ]
23290 INC EDX
23291 CALL @@add_rule
23292 LOOP @@1
23293 @@2: LEA EDX, [DefSortDirRules]
23294 MOV CL, high_DefSortDirRules + 1
23295 @@21: MOV AH, [EDX]
23296 INC EDX
23297 CALL @@add_rule
23298 LOOP @@21
23300 PUSH BX // prepare FoldersFirst(BL), CaseSensitive(BH)
23301 MOV EBX, [ESP].TSortDirData.Dir
23302 MOV EAX, ESP
23303 PUSH offset[SwapDirItems]
23304 MOV ECX, offset[CompareDirItems]
23305 MOV EDX, [EBX].fList
23306 MOV EDX, [EDX].TList.fCount
23307 CALL SortData
23309 ADD ESP, 18
23310 JMP @@exit
23312 @@add_rule:
23313 PUSH ESI
23314 PUSH ECX
23315 MOV CL, 11
23316 @@a1: LODSB
23317 TEST AL, AL
23318 JZ @@a2
23319 CMP AL, AH
23320 JE @@a3
23321 LOOP @@a1
23322 @@a2: DEC ESI
23323 MOV [ESI], AH
23324 CMP AH, sdrFoldersFirst
23325 JNE @@a4
23326 INC BL
23327 @@a4: CMP AH, sdrCaseSensitive
23328 JNE @@a3
23329 INC BH
23330 @@a3: POP ECX
23331 POP ESI
23334 @@exit:
23335 POP ESI
23336 POP EBX
23337 end;
23338 {$ELSE ASM_VERSION} //Pascal
23339 procedure TDirList.Sort(Rules: array of TSortDirRules);
23340 var SortDirData : TSortDirData;
23341 I, J : Integer;
23343 function RulePresent( Rule : TSortDirRules ) : Boolean;
23344 var K : Integer;
23345 begin
23346 Result := True;
23347 for K := J - 1 downto 0 do
23348 if Rule = SortDirData.Rules[ K ] then exit;
23349 Result := False;
23350 end;
23352 procedure AddRule( Rule : TSortDirRules );
23353 begin
23354 if J > High( SortDirData.Rules ) then exit;
23355 if RulePresent( Rule ) then exit;
23356 SortDirData.Rules[ J ] := Rule;
23357 Inc( J );
23358 end;
23359 begin
23360 if fList = nil then Exit;
23361 J := 0;
23362 for I := 0 to High(Rules) do
23363 AddRule( Rules[ I ] );
23364 for I := 0 to High(DefSortDirRules) do
23365 AddRule( DefSortDirRules[ I ] );
23366 while J < High( SortDirData.Rules ) do
23367 begin
23368 SortDirData.Rules[ J ] := sdrNone;
23369 Inc( J );
23370 end;
23372 SortDirData.Dir := @Self;
23373 SortDirData.FoldersFirst := RulePresent( sdrFoldersFirst );
23374 SortDirData.CaseSensitive := RulePresent( sdrCaseSensitive );
23375 SortData( Pointer( @SortDirData ), fList.fCount, @CompareDirItems, @SwapDirItems );
23376 end;
23377 {$ENDIF ASM_VERSION}
23380 //[function TDirList.FileList]
23381 function TDirList.FileList(const Separator: String; Dirs,
23382 FullPaths: Boolean): String;
23383 var I: Integer;
23384 begin
23385 Result := '';
23386 for I := 0 to Count-1 do
23387 begin
23388 if not Dirs and IsDirectory[ I ] then Continue;
23389 if FullPaths then
23390 Result := Result + Path;
23391 Result := Result + Names[ I ] + Separator;
23392 end;
23393 end;
23399 ////////////////////////////////////////////////////////////////////////
23402 // R E G I S T R Y
23405 ////////////////////////////////////////////////////////////////////////
23409 {++}(*
23410 function RegSetValueEx; external advapi32 name 'RegSetValueExA';
23411 *){--}
23414 { -- registry -- }
23416 //[function RegKeyOpenRead]
23417 function RegKeyOpenRead( Key: HKey; const SubKey: String ): HKey;
23418 begin
23419 if RegOpenKeyEx( Key, PChar( SubKey ), 0, KEY_READ, Result ) <> ERROR_SUCCESS then
23420 Result := 0;
23421 end;
23423 //[function RegKeyOpenWrite]
23424 function RegKeyOpenWrite( Key: HKey; const SubKey: String ): HKey;
23425 begin
23426 if RegOpenKeyEx( Key, PChar( SubKey ), 0, KEY_READ or KEY_WRITE, Result ) <> ERROR_SUCCESS then
23427 Result := 0;
23428 end;
23430 //[function RegKeyOpenCreate]
23431 function RegKeyOpenCreate( Key: HKey; const SubKey: String ): HKey;
23432 var dwDisp: DWORD;
23433 begin
23434 if RegCreateKeyEx( Key, PChar( SubKey ), 0, nil, 0, KEY_ALL_ACCESS, nil, Result,
23435 @dwDisp ) <> ERROR_SUCCESS then
23436 Result := 0;
23437 end;
23439 //[function RegKeyGetDw]
23440 function RegKeyGetDw( Key: HKey; const ValueName: String ): DWORD;
23441 var dwType, dwSize: DWORD;
23442 begin
23443 dwSize := sizeof( DWORD );
23444 Result := 0;
23445 if (Key = 0) or
23446 (RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType, PByte( @Result ), @dwSize ) <> ERROR_SUCCESS)
23447 or (dwType <> REG_DWORD) then Result := 0;
23448 end;
23450 //[function RegKeyGetStr]
23451 function RegKeyGetStr( Key: HKey; const ValueName: String ): String;
23452 var dwType, dwSize: DWORD;
23453 Buffer: PChar;
23455 function Query: Boolean;
23456 begin
23457 Result := RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType,
23458 Pointer( Buffer ), @dwSize ) = ERROR_SUCCESS;
23459 end;
23460 begin
23461 Result := '';
23462 if Key = 0 then Exit;
23463 dwSize := 0;
23464 Buffer := nil;
23465 if not Query or (dwType <> REG_SZ) then Exit;
23466 GetMem( Buffer, dwSize );
23467 if Query then
23468 Result := Buffer;
23469 FreeMem( Buffer );
23470 end;
23472 //[function RegKeyGetStrEx]
23473 function RegKeyGetStrEx( Key: HKey; const ValueName: String ): String;
23474 var dwType, dwSize: DWORD;
23475 Buffer, Buffer2: PChar;
23476 Sz: Integer;
23477 function Query: Boolean;
23478 begin
23479 Result := RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType,
23480 Pointer( Buffer ), @dwSize ) = ERROR_SUCCESS;
23481 end;
23482 begin
23483 Result := '';
23484 if Key = 0 then Exit;
23485 dwSize := 0;
23486 Buffer := nil;
23487 if not Query or ((dwType <> REG_SZ) and (dwtype <> REG_EXPAND_SZ)) then Exit;
23488 GetMem( Buffer, dwSize );
23489 if Query then
23490 begin
23491 if dwtype = REG_EXPAND_SZ then
23492 begin
23493 //------------------------------------------------------ by Dmitry Zharov
23494 // Sz := ExpandEnvironmentStrings(Buffer,nil,0); 18-Aug-2004
23495 // SetLength( Result, Sz );
23496 // ExpandEnvironmentStrings(Buffer, PChar(Result), Sz);
23497 //---------------------------------------------//
23498 Sz := ExpandEnvironmentStrings(Buffer,nil,0); // bug in size detection! sometimes we get an additional 2 bytes at the end...
23499 GetMem(Buffer2,Sz); //
23500 ExpandEnvironmentStrings(Buffer, Buffer2, Sz); //
23501 Result:=Buffer2; //
23502 FreeMem(Buffer2); //
23503 //---------------------------------------------//
23505 else
23506 Result := Buffer;
23507 end;
23508 FreeMem( Buffer );
23509 end;
23511 //[function RegKeySetDw]
23512 function RegKeySetDw( Key: HKey; const ValueName: String; Value: DWORD ): Boolean;
23513 begin
23514 Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0, REG_DWORD, @Value, sizeof( DWORD ) )
23515 = ERROR_SUCCESS);
23516 end;
23518 //[function RegKeySetStr]
23519 function RegKeySetStr( Key: HKey; const ValueName: String; const Value: String ): Boolean;
23520 begin
23521 Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0,
23522 REG_SZ, PChar(Value),
23523 Length( Value ) + 1 ) = ERROR_SUCCESS);
23524 end;
23526 //[function RegKeySetStrEx]
23527 function RegKeySetStrEx( Key: HKey; const ValueName: string; const Value: string;
23528 expand: boolean): Boolean;
23529 var dwType: DWORD;
23530 begin
23531 dwType := REG_SZ;
23532 if expand then
23533 dwType := REG_EXPAND_SZ;
23534 Result := (Key <> 0) and (RegSetValueEx(Key, PChar(ValueName), 0, dwType,
23535 PChar(Value), Length(Value) + 1) = ERROR_SUCCESS);
23536 end;
23538 //[procedure RegKeyClose]
23539 procedure RegKeyClose( Key: HKey );
23540 begin
23541 if Key <> 0 then
23542 RegCloseKey( Key );
23543 end;
23545 //[function RegKeyDelete]
23546 function RegKeyDelete( Key: HKey; const SubKey: String ): Boolean;
23547 begin
23548 Result := FALSE;
23549 if Key <> 0 then
23550 Result := RegDeleteKey( Key, PChar( SubKey ) ) = ERROR_SUCCESS;
23551 end;
23553 //[function RegKeyDeleteValue]
23554 function RegKeyDeleteValue( Key: HKey; const SubKey: String ): Boolean;
23555 begin
23556 Result := FALSE;
23557 if Key <> 0 then
23558 Result := RegDeleteValue( Key, PChar( SubKey ) ) = ERROR_SUCCESS;
23559 end;
23561 //[function RegKeyExists]
23562 function RegKeyExists( Key: HKey; const SubKey: String ): Boolean;
23563 var K: Integer;
23564 begin
23565 if Key = 0 then
23566 begin
23567 Result := FALSE;
23568 Exit;
23569 end;
23570 K := RegKeyOpenRead( Key, SubKey );
23571 Result := K <> 0;
23572 if K <> 0 then
23573 RegKeyClose( K );
23574 end;
23576 //[function RegKeyValExists]
23577 function RegKeyValExists( Key: HKey; const ValueName: String ): Boolean;
23578 var dwType, dwSize: DWORD;
23579 begin
23580 Result := (Key <> 0) and
23581 (RegQueryValueEx( Key, PChar( ValueName ), nil,
23582 @dwType, nil, @dwSize ) = ERROR_SUCCESS);
23583 end;
23585 //[function RegKeyValueSize]
23586 function RegKeyValueSize( Key: HKey; const ValueName: String ): Integer;
23587 begin
23588 Result := 0;
23589 if Key = 0 then Exit;
23590 RegQueryValueEx( Key, PChar( ValueName ), nil, nil, nil, @ DWORD( Result ) );
23591 end;
23593 //[function RegKeyGetBinary]
23594 function RegKeyGetBinary( Key: HKey; const ValueName: String; var Buffer; Count: Integer ): Integer;
23595 begin
23596 Result := 0;
23597 if Key = 0 then Exit;
23598 Result := Count;
23599 RegQueryValueEx( Key, PChar( ValueName ), nil, nil, @ Buffer, @ Result );
23600 end;
23602 //[function RegKeySetBinary]
23603 function RegKeySetBinary( Key: HKey; const ValueName: String; const Buffer; Count: Integer ): Boolean;
23604 begin
23605 Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0,
23606 REG_BINARY, @ Buffer, Count ) = ERROR_SUCCESS);
23607 end;
23609 //[function RegKeyGetDateTime]
23610 function RegKeyGetDateTime(Key: HKey; const ValueName: String): TDateTime;
23611 begin
23612 RegKeyGetBinary( Key, ValueName, Result, Sizeof( Result ) );
23613 end;
23615 //[function RegKeySetDateTime]
23616 function RegKeySetDateTime(Key: HKey; const ValueName: String; DateTime: TDateTime): Boolean;
23617 begin
23618 Result := RegKeySetBinary( Key, ValueName, DateTime, Sizeof( DateTime ) );
23619 end;
23621 //-----------------------------------------------
23622 // functions by Valerian Luft <luft@valerian.de>
23623 //-----------------------------------------------
23624 //[function RegKeyGetSubKeys]
23625 function RegKeyGetSubKeys( const Key: HKEY; List: PStrList) : Boolean;
23627 I, Size, NumSubKeys, MaxSubKeyLen : DWORD;
23628 KeyName: String;
23629 begin
23630 Result := False;
23631 List.Clear ;
23632 if RegQueryInfoKey(Key, nil, nil, nil, @NumSubKeys, @MaxSubKeyLen, nil, nil, nil, nil,
23633 nil, nil) = ERROR_SUCCESS then
23634 begin
23635 if NumSubKeys > 0 then begin
23636 for I := 0 to NumSubKeys-1 do
23637 begin
23638 Size := MaxSubKeyLen+1;
23639 SetLength(KeyName, Size);
23640 //FillChar(KeyName[1],Size,#0);
23641 RegEnumKeyEx(Key, I, @KeyName[1], Size, nil, nil, nil, nil);
23642 SetLength(KeyName, lstrlen(@KeyName[1]));
23643 List.Add(KeyName);
23644 end;
23645 end;
23646 Result:= True;
23647 end;
23648 end;
23651 //[function RegKeyGetValueNames]
23652 function RegKeyGetValueNames(const Key: HKEY; List: PStrList): Boolean;
23654 I, Size, NumSubKeys, NumValueNames, MaxValueNameLen: DWORD;
23655 ValueName: String;
23656 begin
23657 List.Clear ;
23658 Result:=False;
23659 if RegQueryInfoKey(Key, nil, nil, nil, @NumSubKeys, nil, nil, @NumValueNames,
23660 @MaxValueNameLen, nil, nil, nil) = ERROR_SUCCESS then
23661 begin
23662 if NumValueNames > 0 then
23663 for I := 0 to NumValueNames - 1 do begin
23664 Size := MaxValueNameLen + 1;
23665 SetLength(ValueName, Size);
23666 //FillChar(ValueName[1],Size,#0);
23667 RegEnumValue(Key, I, @ValueName[1], Size, nil, nil, nil, nil);
23668 SetLength(ValueName, lstrlen(@ValueName[1]));
23669 List.Add(ValueName);
23670 end;
23671 Result := True;
23672 end ;
23673 end;
23676 //[function RegKeyGetValueTyp]
23677 function RegKeyGetValueTyp (const Key:HKEY; const ValueName: String) : DWORD;
23678 begin
23679 Result:= Key ;
23680 if Key <> 0 then
23681 RegQueryValueEx (Key,@ValueName[1],NIL,@Result,NIL,NIL)
23682 end;
23696 { -- TDirChange -- }
23698 const FilterFlags: array[ TFileChangeFilters ] of Integer = (
23699 FILE_NOTIFY_CHANGE_FILE_NAME, FILE_NOTIFY_CHANGE_DIR_NAME,
23700 FILE_NOTIFY_CHANGE_ATTRIBUTES, FILE_NOTIFY_CHANGE_SIZE,
23701 FILE_NOTIFY_CHANGE_LAST_WRITE, $20 {FILE_NOTIFY_CHANGE_LAST_ACCESS},
23702 $40 {FILE_NOTIFY_CHANGE_CREATION}, FILE_NOTIFY_CHANGE_SECURITY );
23704 //[FUNCTION _NewDirChgNotifier]
23705 {$IFDEF ASM_VERSION}
23706 function _NewDirChgNotifier: PDirChange;
23707 begin
23708 New( Result, Create );
23709 end;
23710 //[function NewDirChangeNotifier]
23711 function NewDirChangeNotifier( const Path: String; Filter: TFileChangeFilter;
23712 WatchSubtree: Boolean; ChangeProc: TOnDirChange )
23713 : PDirChange;
23714 const Dflt_Flags = FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or
23715 FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_SIZE or
23716 FILE_NOTIFY_CHANGE_LAST_WRITE;
23718 PUSH EBX
23719 PUSH ECX // [EBP-8] = WatchSubtree
23720 PUSH EDX // [EBP-12] = Filter
23721 PUSH EAX // [EBP-16] = Path
23722 CALL _NewDirChgNotifier
23723 XCHG EBX, EAX
23724 LEA EAX, [EBX].TDirChange.FPath
23725 POP EDX
23726 CALL System.@LStrAsg
23727 MOV EAX, [ChangeProc].TMethod.Code
23728 MOV [EBX].TDirChange.FOnChange.TMethod.Code, EAX
23729 MOV EAX, [ChangeProc].TMethod.Data
23730 MOV [EBX].TDirChange.FOnChange.TMethod.Data, EAX
23731 POP ECX
23732 MOV EAX, Dflt_Flags
23733 MOVZX ECX, CL
23734 JECXZ @@flags_ready
23735 PUSH ECX
23736 MOV EAX, ESP
23737 MOV EDX, offset[FilterFlags]
23738 XOR ECX, ECX
23739 MOV CL, 7
23740 CALL MakeFlags
23741 POP ECX
23742 @@flags_ready: // EAX = Flags
23743 POP EDX
23744 MOVZX EDX, DL // EDX = WatchSubtree
23745 PUSH EAX
23746 PUSH EDX
23747 PUSH [EBX].TDirChange.FPath
23748 CALL FindFirstChangeNotification
23749 MOV [EBX].TDirChange.FHandle, EAX
23750 INC EAX
23751 JZ @@fault
23752 PUSH EBX
23753 PUSH offset[TDirChange.Execute]
23754 CALL NewThreadEx
23755 MOV [EBX].TDirChange.FMonitor, EAX
23756 JMP @@exit
23757 @@fault:
23758 XCHG EAX, EBX
23759 CALL TObj.Free
23760 @@exit:
23761 XCHG EAX, EBX
23762 POP EBX
23763 end;
23764 {$ELSE ASM_VERSION} //Pascal
23765 function NewDirChangeNotifier( const Path: String; Filter: TFileChangeFilter;
23766 WatchSubtree: Boolean; ChangeProc: TOnDirChange )
23767 : PDirChange;
23768 var Flags: DWORD;
23769 begin
23771 New( Result, Create );
23772 {+}{++}(*Result := PDirChange.Create;*){--}
23774 Result.FPath := Path;
23775 Result.FOnChange := ChangeProc;
23776 if Filter = [ ] then
23777 Flags := FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or
23778 FILE_NOTIFY_CHANGE_ATTRIBUTES or FILE_NOTIFY_CHANGE_SIZE or
23779 FILE_NOTIFY_CHANGE_LAST_WRITE
23780 else
23781 Flags := MakeFlags( @Filter, FilterFlags );
23782 Result.FHandle := FindFirstChangeNotification(PChar(Result.FPath),
23783 Bool( Integer( WatchSubtree ) ), Flags);
23784 if Result.FHandle <> INVALID_HANDLE_VALUE then
23785 Result.FMonitor := NewThreadEx( Result.Execute )
23786 else //MsgOK( 'Can not monitor ' + Result.FPath + #13'Error ' + Int2Str( GetLastError ) );
23787 begin
23788 Result.Free;
23789 Result := nil;
23790 end;
23791 end;
23792 {$ENDIF ASM_VERSION}
23793 //[END _NewDirChgNotifier]
23795 { TDirChange }
23797 {$IFDEF ASM_VERSION}
23798 //[procedure TDirChange.Changed]
23799 procedure TDirChange.Changed;
23801 MOV ECX, [EAX].FPath
23802 XCHG EDX, EAX
23803 MOV EAX, [EDX].FOnChange.TMethod.Data
23804 CALL [EDX].FOnChange.TMethod.Code
23805 end;
23806 {$ELSE ASM_VERSION} //Pascal
23807 procedure TDirChange.Changed;
23808 begin
23809 FOnChange(@Self, FPath); // must be assigned always!!!
23810 end;
23811 {$ENDIF ASM_VERSION}
23813 {$IFDEF ASM_VERSION}
23814 //[destructor TDirChange.Destroy]
23815 destructor TDirChange.Destroy;
23817 PUSH EBX
23818 XCHG EBX, EAX
23819 MOV ECX, [EBX].FMonitor
23820 JECXZ @@no_monitor
23821 XCHG EAX, ECX
23822 CALL TObj.Free
23823 @@no_monitor:
23824 MOV ECX, [EBX].FHandle
23825 JECXZ @@exit
23826 PUSH ECX
23827 CALL FindCloseChangeNotification
23828 @@exit:
23829 LEA EAX, [EBX].FPath
23830 CALL System.@LStrClr
23831 XCHG EAX, EBX
23832 CALL TObj.Destroy
23833 POP EBX
23834 end;
23835 {$ELSE ASM_VERSION} //Pascal
23836 destructor TDirChange.Destroy;
23837 begin
23838 if FMonitor <> nil then
23839 FMonitor.Free;
23840 if FHandle > 0 then // FHandle <> INVALID_HANDLE_VALUE AND FHandle <> 0
23841 FindCloseChangeNotification(FHandle);
23842 FPath := '';
23843 inherited;
23844 end;
23845 {$ENDIF ASM_VERSION}
23847 {$IFDEF ASM_noVERSION}
23848 //[function TDirChange.Execute]
23849 function TDirChange.Execute(Sender: PThread): Integer;
23851 PUSH EBX
23852 PUSH ESI
23853 XCHG EBX, EAX
23854 MOV ESI, EDX
23855 @@loo:
23856 MOVZX ECX, [ESI].TThread.FTerminated
23857 INC ECX
23858 LOOP @@e_loop
23860 MOV ECX, [EBX].FHandle
23861 INC ECX
23862 JZ @@e_loop
23864 PUSH INFINITE
23865 PUSH ECX
23866 CALL WaitForSingleObject
23867 OR EAX, EAX
23868 JNZ @@loo
23870 PUSH [EBX].FHandle
23871 MOV EAX, [EBX].FMonitor
23872 PUSH EBX
23873 PUSH offset[TDirChange.Changed]
23874 CALL TThread.Synchronize
23875 CALL FindNextChangeNotification
23876 JMP @@loo
23877 @@e_loop:
23879 POP ESI
23880 POP EBX
23881 XOR EAX, EAX
23882 end;
23883 {$ELSE ASM_VERSION} //Pascal
23884 function TDirChange.Execute(Sender: PThread): Integer;
23885 begin
23886 while (not Sender.Terminated and (FHandle <> INVALID_HANDLE_VALUE)) do
23887 if (WaitForSingleObject(FHandle, INFINITE) = WAIT_OBJECT_0) then
23888 begin
23889 if AppletTerminated then break;
23890 Applet.GetWindowHandle;
23891 FMonitor.Synchronize( Changed );
23892 FindNextChangeNotification(FHandle);
23893 end;
23894 Result := 0;
23895 end;
23896 {$ENDIF ASM_VERSION}
23910 //////////////////////////////////////////////////////////////////////
23913 // D A T E A N D T I M E
23916 //////////////////////////////////////////////////////////////////////
23928 { -- date and time utilities -- }
23930 {* This part of the unit contains date-time routines. It is not a simple compilation
23931 of Delphi VCL date-time. E.g., TDateTime type is not based on 31-Dec-1899,
23932 but it is based on 31-Dec-0000 instead, allowing easy manipulating of dates
23933 at all Christian era, and all other historical era too. }
23935 //[procedure DivMod]
23936 procedure DivMod(Dividend: Integer; Divisor: Word;
23937 var Result, Remainder: Word);
23938 {$IFDEF F_P}
23939 begin
23940 Result := Dividend div Divisor;
23941 Remainder := Dividend mod Divisor;
23942 end;
23943 {$ELSE DELPHI}
23945 PUSH EBX
23946 MOV EBX,EDX
23947 MOV EDX,EAX
23948 SHR EDX,16
23949 DIV BX
23950 MOV EBX,Remainder
23951 MOV [ECX],AX
23952 MOV [EBX],DX
23953 POP EBX
23954 end;
23955 {$ENDIF}
23957 {++}(*
23958 //[API GetLocalTime, GetSystemTime]
23959 procedure GetLocalTime; external kernel32 name 'GetLocalTime';
23960 procedure GetSystemTime; external kernel32 name 'GetSystemTime';
23961 *){--}
23964 //[function Now]
23965 function Now : TDateTime;
23966 var SystemTime : TSystemTime;
23967 begin
23968 GetLocalTime( SystemTime );
23969 SystemTime2DateTime( SystemTime, Result );
23970 end;
23972 //[function Date]
23973 function Date: TDateTime;
23974 begin
23975 Result := Trunc( Now );
23976 end;
23978 //[procedure DecodeDateFully]
23979 procedure DecodeDateFully( DateTime: TDateTime; var Year, Month, Day, DayOfWeek: WORD );
23980 var ST: TSystemTime;
23981 begin
23982 DateTime2SystemTime( DateTime, ST );
23983 Year := ST.wYear;
23984 Month := ST.wMonth;
23985 Day := ST.wDay;
23986 DayOfWeek := ST.wDayOfWeek;
23987 end;
23989 //[procedure DecodeDate]
23990 procedure DecodeDate( DateTime: TDateTime; var Year, Month, Day: WORD );
23991 var Dummy: Word;
23992 begin
23993 DecodeDateFully( DateTime, Year, Month, Day, Dummy );
23994 end;
23996 //[function EncodeDate]
23997 function EncodeDate( Year, Month, Day: WORD; var DateTime: TDateTime ): Boolean;
23998 var ST: TSystemTime;
23999 begin
24000 FillChar( ST, Sizeof( ST ), 0 );
24001 ST.wYear := Year;
24002 ST.wMonth := Month;
24003 ST.wDay := Day;
24004 Result := SystemTime2DateTime( ST, DateTime );
24005 end;
24007 //[FUNCTION CompareSystemTime]
24008 {$IFDEF ASM_VERSION}
24009 function CompareSystemTime( const D1, D2 : TSystemTime) : Integer; assembler;
24011 PUSH ESI
24012 PUSH EBX
24013 MOV ESI, EAX
24014 XOR EAX, EAX
24015 XOR ECX, ECX
24016 MOV CL, 8 // 8 words: wYear, wMonth,..., wMilliseconds
24017 @@loo:
24018 LODSW
24019 MOV BX, [EDX]
24020 INC EDX
24021 INC EDX
24023 CMP CL, 6
24024 JE @@cont // skip compare DayOfWeek
24026 SUB AX, BX
24027 JNE @@calc
24029 @@cont:
24030 LOOP @@loo
24031 JMP @@exit
24033 @@calc:
24034 SBB EAX, EAX
24035 {$IFDEF PARANOIA}
24036 DB $0C, 1
24037 {$ELSE}
24038 OR AL, 1
24039 {$ENDIF}
24041 @@exit:
24042 POP EBX
24043 POP ESI
24044 end;
24045 {$ELSE ASM_VERSION} //Pascal
24046 function CompareSystemTime(const D1, D2 : TSystemTime) : Integer;
24047 var R: Integer;
24048 procedure CompareFields(const F1, F2 : Integer);
24049 begin
24050 if R <> 0 then Exit;
24051 if F1 = F2 then Exit;
24052 if F1 < F2 then
24053 R := -1
24054 else
24055 R := 1;
24056 end;
24057 begin
24058 R := 0;
24059 CompareFields( D1.wYear, D2.wYear );
24060 CompareFields( D1.wMonth, D2.wMonth );
24061 CompareFields( D1.wDay, D2.wDay );
24062 CompareFields( D1.wHour, D2.wHour );
24063 CompareFields( D1.wMinute, D2.wMinute );
24064 CompareFields( D1.wSecond, D2.wSecond );
24065 CompareFields( D1.wMilliseconds, D2.wMilliseconds );
24066 Result := R;
24067 end;
24068 {$ENDIF ASM_VERSION}
24069 //[END CompareSystemTime]
24072 //[procedure IncDays]
24073 procedure IncDays( var SystemTime : TSystemTime; DaysNum : Integer );
24074 var DateTime : TDateTime;
24075 begin
24076 SystemTime2DateTime( SystemTime, DateTime );
24077 DateTime := DateTime + DaysNum;
24078 DateTime2SystemTime( DateTime, SystemTime );
24079 end;
24082 //[procedure IncMonths]
24083 procedure IncMonths( var SystemTime : TSystemTime; MonthsNum : Integer );
24084 var M : Integer;
24085 DateTime : TDateTime;
24086 begin
24087 M := SystemTime.wMonth + MonthsNum - 1;
24088 Inc( SystemTime.wYear, M div 12 );
24089 SystemTime.wMonth := M mod 12 + 1;
24091 // Normalize wDayOfWeek field:
24092 SystemTime2DateTime( SystemTime, DateTime );
24093 DateTime2SystemTime( DateTime, SystemTime );
24094 end;
24097 //[function IsLeapYear]
24098 function IsLeapYear(Year: Word): Boolean;
24099 begin
24100 Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));
24101 end;
24104 //[function SystemTime2DateTime]
24105 function SystemTime2DateTime(const SystemTime : TSystemTime; var DateTime : TDateTime ) : Boolean;
24106 var I : Integer;
24107 Day : Integer;
24108 DayTable: PDayTable;
24109 begin
24110 Result := False;
24111 DateTime := 0.0;
24112 DayTable := @MonthDays[IsLeapYear(SystemTime.wYear)];
24113 with SystemTime do
24114 //-------- by Vadim Petrov ----------------------------------------------------------------
24115 //if (wYear >= 1) and (wYear <= 9999) and (wMonth >= 1) and (wMonth <= 12) and
24116 // (wDay >= 1) and (wDay <= DayTable^[wMonth]) and
24117 // (wHour < 24) and (wMinute < 60) and (wSecond < 60) and (wMilliSeconds < 1000) then
24118 //---------------------------------------------------------------------------------------//
24119 if {(wYear >= 0) !always true! and} (wYear <= 9999) and
24120 {(wMonth >= 0) !always true! and} (wMonth <= 12) and
24121 {(wDay >= 0) !always true! and} (wDay <= DayTable^[wMonth]) and //
24122 (wHour < 24) and (wMinute < 60) and (wSecond < 60) and (wMilliSeconds < 1000) then //
24123 //---------------------------------------------------------------------------------------//
24124 begin
24125 Day := wDay;
24126 for I := 1 to wMonth - 1 do
24127 Inc(Day, DayTable^[I]);
24128 I := wYear - 1;
24129 //--------------- by Vadim Petrov ------++
24130 if I<0 then i := 0; //
24131 //--------------------------------------++
24132 DateTime := I * 365 + I div 4 - I div 100 + I div 400 + Day
24133 + (wHour * 3600000 + wMinute * 60000 + wSecond * 1000 + wMilliSeconds) / MSecsPerDay;
24134 Result := True;
24135 end;
24136 end;
24139 //[function DayOfWeek]
24140 function DayOfWeek(Date: TDateTime): Integer;
24141 begin
24142 Result := (Trunc( Date ) + 6) mod 7 + 1;
24143 end;
24146 //[function DateTime2SystemTime]
24147 function DateTime2SystemTime(const DateTime : TDateTime; var SystemTime : TSystemTime ) : Boolean;
24148 const
24149 D1 = 365;
24150 D4 = D1 * 4 + 1;
24151 D100 = D4 * 25 - 1;
24152 D400 = D100 * 4 + 1;
24153 var Days : Integer;
24154 Y, M, D, I: Word;
24155 MSec : Integer;
24156 DayTable: PDayTable;
24157 MinCount, MSecCount: Word;
24158 begin
24159 Days := Trunc( DateTime );
24160 MSec := Round((DateTime - Days) * MSecsPerDay);
24161 Result := False;
24162 with SystemTime do
24163 if Days > 0 then
24164 begin
24165 Dec(Days);
24166 Y := 1;
24167 while Days >= D400 do
24168 begin
24169 Dec(Days, D400);
24170 Inc(Y, 400);
24171 end;
24172 DivMod(Days, D100, I, D);
24173 if I = 4 then
24174 begin
24175 Dec(I);
24176 Inc(D, D100);
24177 end;
24178 Inc(Y, I * 100);
24179 DivMod(D, D4, I, D);
24180 Inc(Y, I * 4);
24181 DivMod(D, D1, I, D);
24182 if I = 4 then
24183 begin
24184 Dec(I);
24185 Inc(D, D1);
24186 end;
24187 Inc(Y, I);
24188 DayTable := @MonthDays[IsLeapYear(Y)];
24189 M := 1;
24190 while True do
24191 begin
24192 I := DayTable^[M];
24193 if D < I then Break;
24194 Dec(D, I);
24195 Inc(M);
24196 end;
24197 wYear := Y;
24198 wMonth := M;
24199 wDay := D + 1;
24200 wDayOfWeek := DayOfWeek( DateTime );
24201 DivMod(MSec, 60000, MinCount, MSecCount);
24202 DivMod(MinCount, 60, wHour, wMinute);
24203 DivMod(MSecCount, 1000, wSecond, wMilliSeconds);
24204 Result := True;
24205 end;
24206 end;
24208 function DateTime_DiffSysLoc: TDateTime;
24209 var ST, LT: TSystemTime;
24210 FT, FT1: TFileTime;
24211 D1, D2: TDateTime;
24212 begin
24213 GetSystemTime( ST );
24214 SystemTimeToFileTime( ST, FT );
24215 FileTimeToLocalFileTime( FT, FT1 );
24216 FileTimeToSystemTime( FT1, LT );
24217 SystemTime2DateTime( ST, D1 );
24218 SystemTime2DateTime( LT, D2 );
24219 Result := D2 - D1;
24220 end;
24222 //[function DateTime_System2Local]
24223 function DateTime_System2Local( DTSys: TDateTime ): TDateTime;
24224 begin
24225 Result := DTSys + DateTime_DiffSysLoc;
24226 end;
24228 //[function DateTime_Local2System]
24229 function DateTime_Local2System( DTLoc: TDateTime ): TDateTime;
24230 begin
24231 Result := DTLoc - DateTime_DiffSysLoc;
24232 end;
24235 //[function CatholicEaster]
24236 function CatholicEaster( nYear: Integer ): TDateTime;
24238 nMoon, nEpact, nSunday, nGold, nCent, nCorx, nCorz: Integer;
24239 SystemTime : TSystemTime;
24240 begin
24241 FillChar( SystemTime, Sizeof( SystemTime ), 0 );
24242 with SystemTime do
24243 begin
24245 wYear := nYear;
24247 { The Golden Number of the year in the 19 year Metonic Cycle }
24248 nGold := ( ( wYear mod 19 ) + 1 );
24250 { Calculate the Century }
24251 nCent := ( ( wYear div 100 ) + 1 );
24253 { No. of Years in which leap year was dropped in order to keep in step
24254 with the sun }
24255 nCorx := ( ( 3 * nCent ) div 4 - 12 );
24257 { Special Correction to Syncronize Easter with the moon's orbit }
24258 nCorz := ( ( 8 * nCent + 5 ) div 25 - 5 );
24260 { Find Sunday }
24261 nSunday := ( ( 5 * wYear ) div 4 - nCorx - 10 );
24263 { Set Epact (specifies occurance of full moon }
24264 nEpact := ( ( 11 * nGold + 20 + nCorz - nCorx ) mod 30 );
24266 if ( nEpact < 0 ) then
24267 nEpact := nEpact + 30;
24269 if ( ( nEpact = 25 ) and ( nGold > 11 ) ) or ( nEpact = 24 ) then
24270 nEpact := nEpact + 1;
24272 { Find Full Moon }
24273 nMoon := 44 - nEpact;
24275 if ( nMoon < 21 ) then
24276 nMoon := nMoon + 30;
24278 { Advance to Sunday }
24279 nMoon := ( nMoon + 7 - ( ( nSunday + nMoon ) mod 7 ) );
24281 if ( nMoon > 31 ) then
24282 begin
24283 wMonth := 4;
24284 wDay := ( nMoon - 31 );
24286 else
24287 begin
24288 wMonth := 3;
24289 wDay := nMoon;
24290 end;
24291 end;
24292 SystemTime2DateTime( SystemTime, Result );
24293 end;
24296 //[function SystemDate2Str]
24297 function SystemDate2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
24298 const DfltDateFormat : TDateFormat; const DateFormat : PChar ) : String;
24299 var Buf : PChar;
24300 Sz : Integer;
24301 Flags : DWORD;
24302 begin
24303 Sz := 100;
24304 Buf := nil;
24305 Result := '';
24306 Flags := 0;
24307 if DateFormat = nil then
24308 if DfltDateFormat = dfShortDate then
24309 Flags := DATE_SHORTDATE
24310 else
24311 Flags := DATE_LONGDATE;
24312 while True do
24313 begin
24314 if Buf <> nil then
24315 FreeMem( Buf );
24316 GetMem( Buf, Sz );
24317 if Buf = nil then Exit;
24318 if GetDateFormat( LocaleID, Flags, @SystemTime, DateFormat, Buf, Sz )
24319 = 0 then
24320 begin
24321 if GetLastError = ERROR_INSUFFICIENT_BUFFER then
24322 Sz := Sz * 2
24323 else
24324 break;
24326 else
24327 begin
24328 Result := Buf;
24329 break;
24330 end;
24331 end;
24332 if Buf <> nil then
24333 FreeMem( Buf );
24334 end;
24337 //[function SystemTime2Str]
24338 function SystemTime2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
24339 const Flags : TTimeFormatFlags; const TimeFormat : PChar ) : String;
24340 var Buf : PChar;
24341 Sz : Integer;
24342 Flg : DWORD;
24343 begin
24344 Sz := 100;
24345 Buf := nil;
24346 Result := '';
24347 Flg := 0;
24348 if tffNoMinutes in Flags then
24349 Flg := TIME_NOMINUTESORSECONDS
24350 else
24351 if tffNoSeconds in Flags then
24352 Flg := TIME_NOSECONDS;
24353 if tffNoMarker in Flags then
24354 Flg := Flg or TIME_NOTIMEMARKER;
24355 if tffForce24 in Flags then
24356 Flg := Flg or TIME_FORCE24HOURFORMAT;
24357 while True do
24358 begin
24359 if Buf <> nil then
24360 FreeMem( Buf );
24361 GetMem( Buf, Sz );
24362 if Buf = nil then Exit;
24363 if GetTimeFormat( LocaleID, Flg, @SystemTime, TimeFormat, Buf, Sz )
24364 = 0 then
24365 begin
24366 if GetLastError = ERROR_INSUFFICIENT_BUFFER then
24367 Sz := Sz * 2
24368 else
24369 break;
24371 else
24372 begin
24373 Result := Buf;
24374 break;
24375 end;
24376 end;
24377 if Buf <> nil then
24378 FreeMem( Buf );
24379 end;
24381 //[function Date2StrFmt]
24382 function Date2StrFmt( const Fmt: String; D: TDateTime ): String;
24383 var ST: TSystemTime;
24384 lpFmt: PChar;
24385 begin
24386 DateTime2SystemTime( D, ST );
24387 lpFmt := nil;
24388 if Fmt <> '' then lpFmt := PChar( Fmt );
24389 Result := SystemDate2Str( ST, LOCALE_USER_DEFAULT, dfShortDate, lpFmt );
24390 end;
24392 //[function Time2StrFmt]
24393 function Time2StrFmt( const Fmt: String; D: TDateTime ): String;
24394 var ST: TSystemTime;
24395 lpFmt: PChar;
24396 begin
24397 if D < 1 then D := D + 1;
24398 DateTime2SystemTime( D, ST );
24399 lpFmt := nil;
24400 if Fmt <> '' then lpFmt := PChar( Fmt );
24401 Result := SystemTime2Str( ST, LOCALE_USER_DEFAULT, [], lpFmt );
24402 end;
24404 //[function DateTime2StrShort]
24405 function DateTime2StrShort( D: TDateTime ): String;
24406 var ST: TSystemTime;
24407 begin
24408 //--------- by Vadim Petrov --------++
24409 if D < 1 then D := D + 1; //
24410 //----------------------------------++
24411 DateTime2SystemTime( D, ST );
24412 Result := SystemDate2Str( ST, LOCALE_USER_DEFAULT {GetUserDefaultLCID}, dfShortDate, nil ) + ' ' +
24413 SystemTime2Str( ST, LOCALE_USER_DEFAULT {GetUserDefaultLCID}, [], nil );
24414 end;
24416 //[function Str2DateTimeFmt]
24417 function Str2DateTimeFmt( const sFmtStr, sS: String ): TDateTime;
24418 var h12, hAM: Boolean;
24419 FmtStr, S: PChar;
24421 function GetNum( var S: PChar; NChars: Integer ): Integer;
24422 begin
24423 Result := 0;
24424 while (S^ <> #0) and (NChars <> 0) do
24425 begin
24426 Dec( NChars );
24427 if S^ in ['0'..'9'] then
24428 begin
24429 Result := Result * 10 + Ord(S^) - Ord('0');
24430 Inc( S );
24432 else
24433 break;
24434 end;
24435 end;
24437 function GetYear( var S: PChar; NChars: Integer ): Integer;
24438 var STNow: TSystemTime;
24439 OldDate: Boolean;
24440 begin
24441 Result := GetNum( S, NChars );
24442 GetSystemTime( STNow );
24443 OldDate := Result < 50;
24444 Result := Result + STNow.wYear - STNow.wYear mod 100;
24445 if OldDate then Dec( Result, 100 );
24446 end;
24448 function GetMonth( const fmt: String; var S: PChar ): Integer;
24449 var SD: TSystemTime;
24450 M: Integer;
24451 C, MonthStr: String;
24452 begin
24453 GetSystemTime( SD );
24454 for M := 1 to 12 do
24455 begin
24456 SD.wMonth := M;
24457 C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/dd/yyyy/' ) );
24458 MonthStr := Parse( C, '/' );
24459 if AnsiCompareStrNoCase( MonthStr, Copy( S, 1, Length( MonthStr ) ) ) = 0 then
24460 begin
24461 Result := M;
24462 Inc( S, Length( MonthStr ) );
24463 Exit;
24464 end;
24465 end;
24466 Result := 1;
24467 end;
24469 procedure SkipDayOfWeek( const fmt: String; var S: PChar );
24470 var SD: TSystemTime;
24471 Dt: TDateTime;
24472 D: Integer;
24473 C, DayWeekStr: String;
24474 begin
24475 GetSystemTime( SD );
24476 SystemTime2DateTime( SD, Dt );
24477 Dt := Dt - SD.wDayOfWeek;
24478 for D := 0 to 6 do
24479 begin
24480 DateTime2SystemTime( Dt, SD );
24481 C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/MM/yyyy/' ) );
24482 DayWeekStr := Parse( C, '/' );
24483 if AnsiCompareStrNoCase( DayWeekStr, Copy( S, 1, Length( DayWeekStr ) ) ) = 0 then
24484 begin
24485 Inc( S, Length( DayWeekStr ) );
24486 Exit;
24487 end;
24488 Dt := Dt + 1.0;
24489 end;
24490 end;
24492 procedure GetTimeMark( const fmt: String; var S: PChar );
24493 var SD: TSystemTime;
24494 AM: Boolean;
24495 C, TimeMarkStr: String;
24496 begin
24497 GetSystemTime( SD );
24498 SD.wHour := 0;
24499 for AM := FALSE to TRUE do
24500 begin
24501 C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/HH/mm' ) );
24502 TimeMarkStr := Parse( C, '/' );
24503 if AnsiCompareStrNoCase( TimeMarkStr, Copy( S, 1, Length( TimeMarkStr ) ) ) = 0 then
24504 begin
24505 Inc( S, Length( TimeMarkStr ) );
24506 hAM := AM;
24507 Exit;
24508 end;
24509 SD.wHour := 13;
24510 end;
24511 Result := 1;
24512 end;
24514 function FmtIs1( S: PChar ): Boolean;
24515 begin
24516 if StrIsStartingFrom( FmtStr, S ) then
24517 begin
24518 Inc( FmtStr, StrLen( S ) );
24519 Result := TRUE;
24521 else
24522 Result := FALSE;
24523 end;
24525 function FmtIs( S1, S2: PChar ): Boolean;
24526 begin
24527 Result := FmtIs1( S1 ) or FmtIs1( S2 );
24528 end;
24530 var ST: TSystemTime;
24531 begin
24532 FmtStr := PChar( sFmtStr);
24533 S := PChar( sS );
24534 FillChar( ST, Sizeof( ST ), 0 );
24535 h12 := FALSE;
24536 hAM := FALSE;
24537 while (FmtStr^ <> #0) and (S^ <> #0) do
24538 begin
24539 if (FmtStr^ in ['a'..'z','A'..'Z']) and (S^ in ['0'..'9']) then
24540 begin
24541 if FmtIs1( 'yyyy' ) then ST.wYear := GetNum( S, 4 )
24542 else if FmtIs1( 'yy' ) then ST.wYear := GetYear( S, 2 )
24543 else if FmtIs1( 'y' ) then ST.wYear := GetYear( S, -1 )
24544 else if FmtIs( 'dd', 'd' ) then ST.wDay := GetNum( S, 2 )
24545 else if FmtIs( 'MM', 'M' ) then ST.wMonth := GetNum( S, 2 )
24546 else if FmtIs( 'HH', 'H' ) then ST.wHour := GetNum( S, 2 )
24547 else if FmtIs( 'hh', 'h' ) then begin ST.wHour := GetNum( S, 2 ); h12 := TRUE end
24548 else if FmtIs( 'mm', 'm' ) then ST.wMinute := GetNum( S, 2 )
24549 else if FmtIs( 'ss', 's' ) then ST.wSecond := GetNum( S, 2 )
24550 else break; // + ECM
24552 else
24553 if (FmtStr^ in [ 'M', 'd', 'g' ]) then
24554 begin
24555 if FmtIs1( 'MMMM' ) then ST.wMonth := GetMonth( 'MMMM', S )
24556 else if FmtIs1( 'MMM' ) then ST.wMonth := GetMonth( 'MMM', S )
24557 else if FmtIs1( 'dddd' ) then SkipDayOfWeek( 'dddd', S )
24558 else if FmtIs1( 'ddd' ) then SkipDayOfWeek( 'ddd', S )
24559 else if FmtIs1( 'tt' ) then GetTimeMark( 'tt', S )
24560 else if FmtIs1( 't' ) then GetTimeMark( 't', S )
24561 else break; // + ECM
24563 else
24564 begin
24565 if FmtStr^ = S^ then
24566 Inc( FmtStr );
24567 Inc( S );
24568 end;
24569 end;
24571 if h12 then
24572 if hAM then
24573 Inc( ST.wHour, 12 );
24575 SystemTime2DateTime( ST, Result );
24576 end;
24578 var FmtBuf: PChar;
24579 DateSeparator : Char = #0; // + ECM
24581 //[function Str2DateTimeShort]
24582 function Str2DateTimeShort( const S: String ): TDateTime;
24583 var FmtStr, FmtStr2: String;
24585 function EnumDateFmt( lpstrFmt: PChar ): Boolean; stdcall;
24586 begin
24587 GetMem( FmtBuf, StrLen( lpstrFmt ) + 1 );
24588 StrCopy( FmtBuf, lpstrFmt );
24589 Result := FALSE;
24590 end;
24592 begin
24593 FmtStr := 'dd.MM.yyyy';
24594 FmtBuf := nil;
24595 EnumDateFormats( @ EnumDateFmt, LOCALE_USER_DEFAULT, DATE_SHORTDATE );
24596 if FmtBuf <> nil then
24597 begin
24598 FmtStr := FmtBuf;
24599 FreeMem( FmtBuf );
24600 end;
24602 FmtStr2 := 'H:mm:ss';
24603 FmtBuf := nil;
24604 EnumTimeFormats( @ EnumDateFmt, LOCALE_USER_DEFAULT, 0 );
24605 if FmtBuf <> nil then
24606 begin
24607 FmtStr2 := FmtBuf;
24608 FreeMem( FmtBuf );
24609 end;
24611 Result := Str2DateTimeFmt( FmtStr + ' ' + FmtStr2, S );
24612 end;
24614 // + ECM
24615 //[function Str2DateTimeShortEx]
24616 function Str2DateTimeShortEx( const S: String ): TDateTime;
24617 var St: String;
24618 Buff: Array[0..1] of Char;
24619 begin
24620 if DateSeparator = #0 then
24621 begin
24622 if GetLocaleInfo(GetThreadLocale,LOCALE_SDATE,Buff,2) > 0 then
24623 DateSeparator := Buff[0];
24624 end;
24625 St := S;
24626 if Pos(DateSeparator,S) = 0 then
24627 St := '0.0.0 '+S;
24628 Result := Str2DateTimeShort(St);
24629 end;
24648 ///////////////////////////////////////////////////////////////////////
24651 // T H R E A D S
24654 ///////////////////////////////////////////////////////////////////////
24663 { -- Thread -- }
24665 //[function ThreadFunc]
24666 function ThreadFunc(Thread: PThread): integer; stdcall;
24667 begin
24668 Result := Thread.Execute;
24669 end;
24671 {$IFDEF USE_CONSTRUCTORS}
24672 //[function NewThread]
24673 function NewThread: PThread;
24674 begin
24675 new( Result, ThreadCreate );
24676 end;
24677 //[END NewThread]
24678 {$ELSE not_USE_CONSTRUCTORS}
24680 //[function NewThread]
24681 function NewThread: PThread;
24682 begin
24683 {$IFNDEF FPC105ORBELOW}
24684 IsMultiThread := True;
24685 {$ENDIF}
24687 New( Result, Create );
24689 {++}(*Result := PThread.Create;*){--}
24690 Result.FSuspended := True;
24691 Result.FHandle := CreateThread( nil, // no security
24692 0, // the same stack size
24693 @ThreadFunc, // thread entry point
24694 Result, // parameter to pass to ThreadFunc
24695 CREATE_SUSPENDED, // always SUSPENDED
24696 Result.FThreadID ); // receive thread ID
24697 end;
24698 //[END NewThread]
24699 {$ENDIF USE_CONSTRUCTORS}
24701 {$IFDEF USE_CONSTRUCTORS}
24702 //[function NewThreadEx]
24703 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
24704 begin
24705 new( Result, ThreadCreateEx( Proc ) );
24706 end;
24707 {$ELSE not_USE_CONSTRUCTORS}
24709 //[FUNCTION NewThreadEx]
24710 {$IFDEF ASM_VERSION}
24711 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
24713 CALL NewThread
24714 POP EBP
24715 POP ECX
24716 POP EDX
24717 MOV [EAX].TThread.fOnExecute.TMethod.Code, EDX
24718 POP EDX
24719 MOV [EAX].TThread.fOnExecute.TMethod.Data, EDX
24720 PUSH ECX
24721 PUSH EAX
24722 CALL TThread.Resume
24723 POP EAX
24725 end;
24726 {$ELSE ASM_VERSION} //Pascal
24727 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
24728 begin
24729 Result := NewThread;
24730 Result.OnExecute := {++}(*{$IFDEF F_P} @ {$ENDIF}*){--}Proc;
24731 Result.Resume;
24732 end;
24733 {$ENDIF ASM_VERSION}
24734 //[END NewThreadEx]
24736 {$ENDIF USE_CONSTRUCTORS}
24738 //[function NewThreadAutoFree]
24739 function NewThreadAutoFree( const Proc: TOnThreadExecute ): PThread;
24740 begin
24741 Result := NewThread;
24742 Result.OnExecute := {++}(*{$IFDEF F_P} @ {$ENDIF}*){--}Proc;
24743 Result.F_AutoFree := TRUE;
24744 if Assigned( Proc ) then
24745 Result.Resume;
24746 end;
24748 { TThread }
24750 {$IFDEF ASM_VERSION}
24751 //[destructor TThread.Destroy]
24752 destructor TThread.Destroy;
24754 PUSH EBX
24755 MOV EBX, EAX
24756 CMP [EAX].FTerminated, 0
24757 JNZ @@1
24758 CALL Terminate
24759 MOV EAX, EBX
24760 CALL WaitFor
24761 @@1: MOV ECX, [EBX].FHandle
24762 JECXZ @@2
24763 PUSH ECX
24764 CALL CloseHandle
24765 @@2: POP EAX
24766 XCHG EBX, EAX
24767 JMP TObj.Destroy
24768 end;
24769 {$ELSE ASM_VERSION} //Pascal
24770 destructor TThread.Destroy;
24771 begin
24772 if not FTerminated then
24773 begin
24774 Terminate;
24775 WaitFor;
24776 end;
24777 if (FHandle <> 0) then
24778 CloseHandle(FHandle);
24779 inherited;
24780 end;
24781 {$ENDIF ASM_VERSION}
24784 //[function TThread.Execute]
24785 function TThread.Execute: integer;
24786 begin
24787 Result := 0;
24788 if Assigned( FOnExecute ) then
24789 Result := FOnExecute( @Self );
24790 if F_AutoFree then
24791 begin
24792 FTerminated := TRUE; // fake thread object (to prevent terminating while freeing)
24793 Free;
24794 end;
24795 end;
24798 //[function TThread.GetPriorityCls]
24799 function TThread.GetPriorityCls: Integer;
24800 begin
24801 Result := GetPriorityClass(FHandle);
24802 end;
24805 //[function TThread.GetThrdPriority]
24806 function TThread.GetThrdPriority: Integer;
24807 begin
24808 Result := GetThreadPriority(FHandle);
24809 end;
24812 //[procedure TThread.Resume]
24813 procedure TThread.Resume;
24814 begin
24815 FSuspended := False;
24816 if (ResumeThread(FHandle) > 1) then
24817 FSuspended := True
24818 else
24819 if Assigned(FOnResume) then
24820 FOnResume(@Self);
24821 end;
24824 //[procedure TThread.SetPriorityCls]
24825 procedure TThread.SetPriorityCls(Value: Integer);
24826 begin
24827 {$IFDEF DEBUG}
24828 if not SetPriorityClass(GetCurrentProcess, Value) then
24829 begin
24830 ShowMessage( SysErrorMessage( GetLastError ) );
24831 end;
24832 {$ELSE}
24833 SetPriorityClass(GetCurrentProcess, Value);
24834 {$ENDIF}
24835 end;
24838 //[procedure TThread.SetThrdPriority]
24839 procedure TThread.SetThrdPriority(Value: Integer);
24840 begin
24841 SetThreadPriority(FHandle, Value);
24842 end;
24845 //[procedure TThread.Suspend]
24846 procedure TThread.Suspend;
24847 begin
24848 FSuspended := TRUE;
24849 if Assigned(FOnSuspend) then
24850 Synchronize( FOnSuspend );
24851 SuspendThread(FHandle);
24852 end;
24855 //[procedure CallSynchronized]
24856 procedure CallSynchronized( Sender: PObj; Param: Pointer );
24857 var Thread: PThread;
24858 begin
24859 Thread := PThread( Sender );
24860 if Param <> nil then
24861 Thread.FMethodEx( Thread, Param )
24862 else
24863 Thread.FMethod( );
24864 end;
24867 //[procedure TThread.Synchronize]
24868 procedure TThread.Synchronize(Method: TThreadMethod);
24869 begin
24870 Global_Synchronized := CallSynchronized;
24871 FMethod := Method;
24872 if Applet <> nil then
24873 SendMessage( Applet.fHandle, CM_EXECPROC, 0, Integer( @Self ) );
24874 end;
24876 //[procedure TThread.SynchronizeEx]
24877 procedure TThread.SynchronizeEx( Method: TThreadMethodEx; Param: Pointer );
24878 begin
24879 Assert( Param <> nil, 'Parameter must not be NIL' );
24880 Global_Synchronized := CallSynchronized;
24881 FMethodEx := Method;
24882 SendMessage( Applet.fHandle, CM_EXECPROC, Integer( Param ), Integer( @Self ) );
24883 end;
24886 //[procedure TThread.Terminate]
24887 procedure TThread.Terminate;
24888 begin
24889 TerminateThread(FHandle,0);
24890 FTerminated := True;
24891 end;
24894 //[function TThread.WaitFor]
24895 function TThread.WaitFor: Integer;
24896 begin
24897 RefInc;
24898 Result := -1;
24899 if FHandle = 0 then Exit;
24900 WaitForSingleObject(FHandle, INFINITE);
24901 GetExitCodeThread(FHandle, DWORD(Result));
24902 RefDec;
24903 end;
24907 { TStream }
24909 {* This part of the unit contains implementation of streams for KOL. Please note,
24910 that both stream types (file stream and memory stream) are incapsulated
24911 by a single object type TStream. To avoid including unnedeed code,
24912 use constructing functions NewReadFileStream and NewWriteFileStream
24913 to work with file streams, which do not require both types of operation. }
24915 {* To create new type of stream, define your own methods, and in your
24916 constructing function, pass it to _NewStream function (through
24917 TStreamMethods record). In a field Custom, You can store a reference to
24918 your own data of any type (but do not forget to define correct releasing
24919 of such data in your fClose procedure). }
24921 //[function TStream.GetPosition]
24922 function TStream.GetPosition: DWord;
24923 begin
24924 Result := Seek( 0, spCurrent );
24925 end;
24927 //[procedure TStream.SetPosition]
24928 procedure TStream.SetPosition(Value: DWord);
24929 begin
24930 Seek( Value, spBegin );
24931 end;
24933 {$IFDEF ASM_VERSION}
24934 //[function TStream.GetSize]
24935 function TStream.GetSize: DWord;
24937 CALL [EAX].fMethods.fGetSiz
24938 end;
24939 {$ELSE ASM_VERSION} //Pascal
24940 function TStream.GetSize: DWord;
24941 begin
24942 Result := fMethods.fGetSiz( @Self );
24943 end;
24944 {$ENDIF ASM_VERSION}
24946 {$IFDEF ASM_VERSION}
24947 //[procedure TStream.SetSize]
24948 procedure TStream.SetSize(NewSize: DWord);
24950 CALL [EAX].fMethods.fSetSiz
24951 end;
24952 {$ELSE ASM_VERSION} //Pascal
24953 procedure TStream.SetSize(NewSize: DWord);
24954 begin
24955 fMethods.fSetSiz( @Self, NewSize );
24956 end;
24957 {$ENDIF ASM_VERSION}
24959 //[function TStream.GetFileStreamHandle]
24960 function TStream.GetFileStreamHandle: THandle;
24961 begin
24962 Result := fData.fHandle;
24963 end;
24965 {$IFDEF ASM_VERSION}
24966 //[function TStream.Read]
24967 function TStream.Read(var Buffer; Count: DWord): DWord;
24969 CALL [EAX].fMethods.fRead
24970 end;
24971 {$ELSE ASM_VERSION} //Pascal
24972 function TStream.Read(var Buffer; Count: DWord): DWord;
24973 begin
24974 Result := fMethods.fRead( @Self, Buffer, Count );
24975 end;
24976 {$ENDIF ASM_VERSION}
24978 //[function TStream.GetCapacity]
24979 function TStream.GetCapacity: DWORD;
24980 begin
24981 Result := fData.fCapacity;
24982 end;
24984 //[procedure TStream.SetCapacity]
24985 procedure TStream.SetCapacity(const Value: DWORD);
24986 var OldSize: DWORD;
24987 begin
24988 if fData.fCapacity >= Value then Exit;
24989 OldSize := Size;
24990 Size := Value;
24991 Size := OldSize;
24992 end;
24994 //[function TStream.Busy]
24995 function TStream.Busy: Boolean;
24996 begin
24997 Result := Assigned( fData.fThread );
24998 end;
25000 //[function TStream.DoAsyncRead]
25001 function TStream.DoAsyncRead( Sender: PThread ): Integer;
25002 begin
25003 Read( Pointer( fParam1 )^, fParam2 );
25004 fData.fThread := nil;
25005 Result := 0;
25006 end;
25008 //[procedure TStream.ReadAsync]
25009 procedure TStream.ReadAsync(var Buffer; Count: DWord);
25010 begin
25011 if Busy then Wait;
25012 fData.fThread := NewThreadAutoFree( nil );
25013 fData.fThread.OnExecute := DoAsyncRead;
25014 fParam1 := DWORD( @ Buffer );
25015 fParam2 := Count;
25016 fData.fThread.Resume;
25017 end;
25019 //[function TStream.DoAsyncSeek]
25020 function TStream.DoAsyncSeek( Sender: PThread ): Integer;
25021 begin
25022 Seek( fParam1, TMoveMethod( fParam2 ) );
25023 fData.fThread := nil;
25024 Result := 0;
25025 end;
25027 //[procedure TStream.SeekAsync]
25028 procedure TStream.SeekAsync(MoveTo: Integer; MoveMethod: TMoveMethod);
25029 begin
25030 if Busy then Wait;
25031 fData.fThread := NewThreadAutoFree( nil );
25032 fData.fThread.OnExecute := DoAsyncSeek;
25033 fParam1 := MoveTo;
25034 fParam2 := Ord( MoveMethod );
25035 fData.fThread.Resume;
25036 end;
25038 //[function TStream.DoAsyncWrite]
25039 function TStream.DoAsyncWrite( Sender: PThread ): Integer;
25040 begin
25041 Write( Pointer( fParam1 )^, fParam2 );
25042 fData.fThread := nil;
25043 Result := 0;
25044 end;
25046 //[procedure TStream.WriteAsync]
25047 procedure TStream.WriteAsync(var Buffer; Count: DWord);
25048 begin
25049 if Busy then Wait;
25050 fData.fThread := NewThreadAutoFree( nil );
25051 fData.fThread.OnExecute := DoAsyncWrite;
25052 fParam1 := DWORD( @ Buffer );
25053 fParam2 := Count;
25054 fData.fThread.Resume;
25055 end;
25057 //[procedure TStream.Wait]
25058 procedure TStream.Wait;
25059 begin
25060 if not Assigned( fData.fThread ) then Exit;
25061 if Assigned( fMethods.fWait ) then
25062 fMethods.fWait( @Self )
25063 else
25064 fData.fThread.WaitFor;
25065 end;
25067 {$IFDEF ASM_VERSION}
25068 //[function TStream.Write]
25069 function TStream.Write(var Buffer; Count: DWord): DWord;
25071 CALL [EAX].fMethods.fWrite
25072 end;
25073 {$ELSE ASM_VERSION} //Pascal
25074 function TStream.Write(var Buffer; Count: DWord): DWord;
25075 begin
25076 Result := fMethods.fWrite( @Self, Buffer, Count );
25077 end;
25078 {$ENDIF ASM_VERSION}
25080 //[function TStream.WriteStr]
25081 function TStream.WriteStr(S: String): DWORD;
25082 begin
25083 if S <> '' then
25084 Result := fMethods.fWrite( @Self, S[1], Length( S ) )
25085 else
25086 Result := 0;
25087 end;
25089 //[function TStream.ReadStrZ]
25090 function TStream.ReadStrZ: String;
25091 var C: Char;
25092 begin
25093 Result := '';
25094 REPEAT
25095 C := #0;
25096 Read( C, 1 );
25097 if C <> #0 then Result := Result + C;
25098 UNTIL C = #0;
25099 end;
25101 //[function TStream.ReadStr]
25102 function TStream.ReadStr: String;
25103 var C: Char;
25104 begin
25105 Result := '';
25106 REPEAT
25107 C := #0;
25108 Read( C, 1 );
25109 if C <> #0 then
25110 begin
25111 if C = #13 then
25112 begin
25113 C := #0;
25114 Read( C, 1 );
25115 if C <> #10 then Position := Position - 1;
25116 C := #13;
25118 else
25119 if C = #10 then
25120 C := #13;
25121 if C <> #13 then
25122 Result := Result + C;
25123 end;
25124 UNTIL C in [ #13, #0 ];
25125 end;
25127 //[function TStream.WriteStrZ]
25128 function TStream.WriteStrZ(S: String): DWORD;
25129 var C: Char;
25130 begin
25131 if S = '' then
25132 begin
25133 C := #0;
25134 Result := Write( C, 1 );
25136 else
25137 Result := Write( S[ 1 ], Length( S ) + 1 );
25138 end;
25140 //[function TStream.WriteStrEx]
25141 function TStream.WriteStrEx(S: String): DWord;
25142 begin
25143 result:=length(s);
25144 fmethods.fwrite(@self,result,Sizeof(DWORD));
25145 if result<>0 then result:=fmethods.fwrite(@self,s[1],result);
25146 end;
25148 //[function TStream.ReadStrExVar]
25149 function TStream.ReadStrExVar(var S: String): DWord;
25150 begin
25151 fmethods.fread(@self,result,Sizeof(DWORD));
25152 setlength(s,result);
25153 if result<>0 then result:=fmethods.fread(@self,s[1],result);
25154 end;
25156 //[function TStream.ReadStrEx]
25157 function TStream.ReadStrEx: String;
25158 begin
25159 readstrexvar(result);
25160 end;
25162 //[function TStream.WriteStrPas]
25163 function TStream.WriteStrPas( S: String ): DWORD;
25164 var L: Integer;
25165 begin
25166 Result := 0;
25167 L := Length( S );
25168 if L > 255 then L := 255;
25169 if Write( L, 1 ) < 1 then Exit;
25170 Result := 1;
25171 if L > 0 then
25172 Result := Write( S[ 1 ], L ) + 1;
25173 end;
25175 //[function TStream.ReadStrPas]
25176 function TStream.ReadStrPas: String;
25177 var L: Byte;
25178 begin
25179 Result := '';
25180 if Read( L, 1 ) < 1 then Exit;
25181 SetLength( Result, L );
25182 L := Read( Result[ 1 ], L );
25183 Result := Copy( Result, 1, L );
25184 end;
25187 {$IFDEF ASM_VERSION}
25188 //[function TStream.Seek]
25189 function TStream.Seek(MoveTo: integer; MoveMethod: TMoveMethod): DWord;
25191 CALL [EAX].fMethods.fSeek
25192 end;
25193 {$ELSE ASM_VERSION} //Pascal
25194 function TStream.Seek(MoveTo: integer; MoveMethod: TMoveMethod): DWord;
25195 begin
25196 Result := fMethods.fSeek( @Self, MoveTo, MoveMethod );
25197 end;
25198 {$ENDIF ASM_VERSION}
25200 {$IFDEF ASM_VERSION}
25201 //[destructor TStream.Destroy]
25202 destructor TStream.Destroy;
25204 PUSH EAX
25205 PUSH [EAX].fData.fThread
25206 CALL [EAX].fMethods.fClose
25207 POP EAX
25208 CALL TObj.Free
25209 POP EAX
25210 CALL TObj.Destroy
25211 end;
25212 {$ELSE ASM_VERSION} //Pascal
25213 destructor TStream.Destroy;
25214 begin
25215 fMethods.fClose( @Self );
25216 fData.fThread.Free;
25217 inherited;
25218 end;
25219 {$ENDIF ASM_VERSION}
25221 //+-
25222 //[function _NewStream]
25223 function _NewStream( const StreamMethods: TStreamMethods ): PStream;
25224 begin
25226 New( Result, Create );
25227 {+}{++}(*Result := PStream.Create;*){--}
25228 Move( StreamMethods, Result.fMethods, Sizeof( TStreamMethods ) );
25229 Result.fPMethods := @Result.fMethods;
25230 end;
25233 //[function SeekFileStream]
25234 function SeekFileStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
25235 begin
25236 Result := FileSeek( Strm.fData.fHandle, MoveTo, MoveFrom );
25237 end;
25240 //[function GetSizeFileStream]
25241 function GetSizeFileStream( Strm: PStream ): DWORD;
25242 begin
25243 Result := GetFileSize( Strm.fData.fHandle, nil );
25244 if Result = DWORD( -1 ) then Result := 0;
25245 end;
25247 //[procedure DummySetSize]
25248 procedure DummySetSize( Strm: PStream; Value: DWORD );
25249 begin
25250 end;
25252 //[procedure DummyStreamProc]
25253 procedure DummyStreamProc(Strm: PStream);
25254 begin
25255 end;
25257 //[function DummyReadWrite]
25258 function DummyReadWrite( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25260 XOR EAX, EAX
25261 end;
25263 //[function ReadFileStream]
25264 function ReadFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25265 begin
25266 Result := FileRead( Strm.fData.fHandle, Buffer, Count );
25267 end;
25269 //[function WriteFileStream]
25270 function WriteFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25271 begin
25272 Result := FileWrite( Strm.fData.fHandle, Buffer, Count );
25273 end;
25275 //[FUNCTION WriteFileStreamEOF]
25276 {$IFDEF ASM_VERSION}
25277 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25279 PUSH EBX
25280 PUSH [EAX].TStream.fData.fHandle
25281 CALL WriteFileStream
25282 XCHG EBX, EAX
25283 CALL SetEndOfFile
25284 XCHG EAX, EBX
25285 POP EBX
25286 end;
25287 {$ELSE ASM_VERSION} //Pascal
25288 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25289 begin
25290 Result := WriteFileStream( Strm, Buffer, Count );
25291 SetEndOfFile( Strm.fData.fHandle );
25292 end;
25293 {$ENDIF ASM_VERSION}
25294 //[END WriteFileStreamEOF]
25296 //[procedure CloseFileStream]
25297 procedure CloseFileStream( Strm: PStream );
25298 begin
25299 FileClose( Strm.fData.fHandle );
25300 end;
25302 //[FUNCTION SeekMemStream]
25303 {$IFDEF ASM_VERSION}
25304 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
25306 PUSH EBX
25307 MOV EBX, EDX
25308 AND ECX, $FF
25309 LOOP @@not_from_cur
25310 ADD EBX, [EAX].TStream.fData.fPosition
25311 @@not_from_cur:
25312 LOOP @@not_from_end
25313 ADD EBX, [EAX].TStream.fData.fSize
25314 @@not_from_end:
25315 CMP EBX, [EAX].TStream.fData.fSize
25316 JLE @@space_ok
25317 PUSH EAX
25318 MOV EDX, EBX
25319 CALL TStream.SetSize
25320 POP EAX
25321 @@space_ok:
25322 XCHG EAX, EBX
25323 MOV [EBX].TStream.fData.fPosition, EAX
25324 POP EBX
25325 end;
25326 {$ELSE ASM_VERSION} //Pascal
25327 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
25328 var NewPos: DWORD;
25329 begin
25330 case MoveFrom of
25331 spBegin: NewPos := MoveTo;
25332 spCurrent: NewPos := Strm.fData.fPosition + DWORD( MoveTo );
25333 else //spEnd:
25334 NewPos := Strm.fData.fSize + DWORD( MoveTo );
25335 end;
25336 if NewPos > Strm.fData.fSize then
25337 Strm.SetSize( NewPos );
25338 Strm.fData.fPosition := NewPos;
25339 Result := NewPos;
25340 end;
25341 {$ENDIF ASM_VERSION}
25342 //[END SeekMemStream]
25344 //[function GetSizeMemStream]
25345 function GetSizeMemStream( Strm: PStream ): DWORD;
25346 begin
25347 Result := Strm.fData.fSize;
25348 end;
25350 //[PROCEDURE SetSizeMemStream]
25351 {$IFDEF ASM_VERSION}
25352 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );
25354 CMP [EAX].TStream.fData.fCapacity, EDX
25355 JGE @@cap_ok
25356 PUSH EDX
25357 PUSH EAX
25358 MOV ECX, [EAX].TStream.fMemory
25359 JECXZ @@get_mem
25360 TEST EDX, EDX
25361 JZ @@free_mem
25362 LEA EAX, [EAX].TStream.fMemory
25363 CALL System.@ReallocMem
25364 JMP @@1
25365 @@get_mem:
25366 XCHG EAX, EDX
25367 CALL System.@GetMem
25368 XCHG EDX, EAX
25369 POP EAX
25370 MOV [EAX].TStream.fMemory, EDX
25371 JMP @@2
25372 @@free_mem:
25373 XCHG EDX, [EAX].TStream.fMemory
25374 XCHG EAX, EDX
25375 CALL System.@FreeMem
25376 @@1:
25377 POP EAX
25378 @@2:
25379 POP EDX
25381 @@cap_ok:
25382 MOV [EAX].TStream.fData.fSize, EDX
25383 CMP [EAX].TStream.fData.fPosition, EDX
25384 JLE @@exit
25385 MOV [EAX].TStream.fData.fPosition, EDX
25386 @@exit:
25387 end;
25388 {$ELSE ASM_VERSION} //Pascal
25389 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );
25390 var S: PStream;
25391 begin
25392 S := Strm;
25393 if S.fData.fCapacity < NewSize then
25394 begin
25395 if S.fMemory = nil then
25396 begin
25397 if NewSize <> 0 then
25398 GetMem( S.fMemory, NewSize );
25400 else
25401 if NewSize = 0 then
25402 begin
25403 FreeMem( S.fMemory );
25404 S.fMemory := nil;
25406 else
25407 ReallocMem( S.fMemory, NewSize );
25408 S.fData.fCapacity := NewSize;
25409 end;
25410 S.fData.fSize := NewSize;
25411 if S.fData.fPosition > S.fData.fSize then
25412 S.fData.fPosition := S.fData.fSize;
25413 end;
25414 {$ENDIF ASM_VERSION}
25415 //[END SetSizeMemStream]
25417 //[FUNCTION ReadMemStream]
25418 {$IFDEF ASM_VERSION}
25419 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25421 PUSH EBX
25422 XCHG EBX, EAX
25423 MOV EAX, [EBX].TStream.fData.fPosition
25424 ADD EAX, ECX
25425 CMP EAX, [EBX].TStream.fData.fSize
25426 JLE @@count_ok
25427 MOV ECX, [EBX].TStream.fData.fSize
25428 SUB ECX, [EBX].TStream.fData.fPosition
25429 @@count_ok:
25430 PUSH ECX
25431 MOV EAX, [EBX].TStream.fMemory
25432 ADD EAX, [EBX].TStream.fData.fPosition
25433 CALL System.Move
25434 POP EAX
25435 ADD [EBX].TStream.fData.fPosition, EAX
25436 POP EBX
25437 end;
25438 {$ELSE ASM_VERSION} //Pascal
25439 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25440 var S: PStream;
25441 begin
25442 S := Strm;
25443 if Count + S.fData.fPosition > S.fData.fSize then
25444 Count := S.fData.fSize - S.fData.fPosition;
25445 Result := Count;
25446 Move( Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Buffer, Result );
25447 Inc( S.fData.fPosition, Result );
25448 end;
25449 {$ENDIF ASM_VERSION}
25450 //[END ReadMemStream]
25452 //[FUNCTION WriteMemStream]
25453 {$IFDEF ASM_VERSION}
25454 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25456 PUSH EBX
25457 XCHG EBX, EAX
25458 MOV EAX, [EBX].TStream.fData.fPosition
25459 ADD EAX, ECX
25460 CMP EAX, [EBX].TStream.fData.fSize
25461 PUSH EDX
25462 PUSH ECX
25463 JLE @@count_ok
25464 XCHG EDX, EAX
25465 MOV EAX, EBX
25466 CALL TStream.SetSize
25467 @@count_ok:
25468 POP ECX
25469 POP EAX
25470 MOV EDX, [EBX].TStream.fMemory
25471 ADD EDX, [EBX].TStream.fData.fPosition
25472 PUSH ECX
25473 CALL System.Move
25474 POP EAX
25475 ADD [EBX].TStream.fData.fPosition, EAX
25476 POP EBX
25477 end;
25478 {$ELSE ASM_VERSION} //Pascal
25479 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25480 var S: PStream;
25481 begin
25482 S := Strm;
25483 if Count + S.fData.fPosition > S.fData.fSize then
25484 S.SetSize( S.fData.fPosition + Count );
25485 Result := Count;
25486 Move( Buffer, Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Result );
25487 Inc( S.fData.fPosition, Result );
25488 end;
25489 {$ENDIF ASM_VERSION}
25490 //[END WriteMemStream]
25492 //[PROCEDURE CloseMemStream]
25493 {$IFDEF ASM_VERSION}
25494 procedure CloseMemStream( Strm: PStream );
25496 MOV ECX, [EAX].TStream.fMemory
25497 JECXZ @@exit
25498 XCHG EAX, ECX
25499 CALL System.@FreeMem
25500 @@exit:
25501 end;
25502 {$ELSE ASM_VERSION} //Pascal
25503 procedure CloseMemStream( Strm: PStream );
25504 var S: PStream;
25505 begin
25506 S := Strm;
25507 if S.fMemory <> nil then
25508 FreeMem( S.fMemory );
25509 end;
25510 {$ENDIF ASM_VERSION}
25511 //[END CloseMemStream]
25513 const
25514 BaseFileMethods: TStreamMethods = (
25515 fSeek: SeekFileStream;
25516 fGetSiz: GetSizeFileStream;
25517 fSetSiz: DummySetSize;
25518 fRead: DummyReadWrite;
25519 fWrite: DummyReadWrite;
25520 fClose: CloseFileStream;
25521 fCustom: nil;
25524 MemoryMethods: TStreamMethods = (
25525 fSeek: SeekMemStream;
25526 fGetSiz: GetSizeMemStream;
25527 fSetSiz: SetSizeMemStream;
25528 fRead: ReadMemStream;
25529 fWrite: WriteMemStream;
25530 fClose: CloseMemStream;
25531 fCustom: nil;
25534 // by Roman Vorobets:
25535 //[procedure SetSizeFileStream]
25536 procedure SetSizeFileStream( Strm: PStream; NewSize: DWORD );
25538 P: DWORD;
25539 begin
25540 P:=Strm.Position;
25541 Strm.Position:=NewSize;
25542 SetEndOfFile(Strm.Handle);
25543 if P < NewSize then
25544 Strm.Position:=P;
25545 end;
25547 //[function NewFileStream]
25548 function NewFileStream( const FileName: String; Options: DWORD ): PStream;
25549 begin
25550 Result := _NewStream( BaseFileMethods );
25551 Result.fMethods.fRead := ReadFileStream;
25552 Result.fMethods.fWrite := WriteFileStream; // not WriteStreamEOF, Àëåêñåé Øóâàëîâ
25553 Result.fMethods.fSetSiz := SetSizeFileStream;
25554 Result.fData.fHandle := FileCreate( FileName, Options );
25555 end;
25557 //[FUNCTION NewReadFileStream]
25558 {$IFDEF ASM_VERSION}
25559 function NewReadFileStream( const FileName: String ): PStream;
25561 PUSH EBX
25562 XCHG EBX, EAX
25563 MOV EAX, offset[BaseFileMethods]
25564 CALL _NewStream
25565 MOV [EAX].TStream.fMethods.fRead, offset[ReadFileStream]
25566 XCHG EBX, EAX
25567 MOV EDX, ofOpenRead or ofOpenExisting or ofShareDenyNone // org ofShareDenyWrite
25568 CALL FileCreate
25569 MOV [EBX].TStream.fData.fHandle, EAX
25570 XCHG EAX, EBX
25571 POP EBX
25572 end;
25573 {$ELSE ASM_VERSION} //Pascal
25574 function NewReadFileStream( const FileName: String ): PStream;
25575 begin
25576 Result := _NewStream( BaseFileMethods );
25577 Result.fMethods.fRead := ReadFileStream;
25578 Result.fData.fHandle := FileCreate( FileName,
25579 ofOpenRead or ofShareDenyWrite or ofOpenExisting );
25580 end;
25581 {$ENDIF ASM_VERSION}
25582 //[END NewReadFileStream]
25584 //[FUNCTION NewWriteFileStream]
25585 {$IFDEF ASM_VERSION}
25586 function NewWriteFileStream( const FileName: String ): PStream;
25588 PUSH EBX
25589 XCHG EBX, EAX
25590 MOV EAX, offset[BaseFileMethods]
25591 CALL _NewStream
25592 MOV [EAX].TStream.fMethods.fWrite, offset[WriteFileStreamEOF]
25593 MOV [EAX].TStream.fMethods.fSetSiz, offset[SetSizeFileStream]
25594 XCHG EBX, EAX
25595 MOV EDX, ofOpenWrite or ofOpenAlways or ofShareDenyWrite
25596 CALL FileCreate
25597 MOV [EBX].TStream.fData.fHandle, EAX
25598 XCHG EAX, EBX
25599 POP EBX
25600 end;
25601 {$ELSE ASM_VERSION} //Pascal
25602 function NewWriteFileStream( const FileName: String ): PStream;
25603 begin
25604 Result := _NewStream( BaseFileMethods );
25605 Result.fMethods.fWrite := WriteFileStreamEOF;
25606 Result.fMethods.fSetSiz := SetSizeFileStream;
25607 Result.fData.fHandle := FileCreate( FileName,
25608 //ofOpenWrite or ofCreateAlways );
25609 ofOpenWrite or ofOpenAlways or ofShareDenyWrite );
25610 end;
25611 {$ENDIF ASM_VERSION}
25612 //[END NewWriteFileStream]
25614 //[FUNCTION NewReadWriteFileStream]
25615 {$IFDEF ASM_noVERSION}
25616 function NewReadWriteFileStream( const FileName: String ): PStream;
25618 PUSH EBX
25619 XCHG EBX, EAX
25620 MOV EAX, offset[BaseFileMethods]
25621 CALL _NewStream
25622 MOV [EAX].TStream.fMethods.fRead, offset[ReadFileStream]
25623 MOV [EAX].TStream.fMethods.fWrite, offset[WriteFileStream]
25624 MOV [EAX].TStream.fMethods.fSetSiz, offset[SetSizeFileStream]
25625 XCHG EBX, EAX
25627 PUSH EAX
25628 CALL FileExists
25629 MOV EDX, ofOpenReadWrite or ofCreateAlways or ofShareDenyWrite
25630 ADD DH, AL // $200 (ofCreateAlways) -> $300 (ofCreateExisting)
25631 POP EAX
25633 CALL FileCreate
25634 MOV [EBX].TStream.fData.fHandle, EAX
25635 XCHG EAX, EBX
25636 POP EBX
25637 end;
25638 {$ELSE ASM_VERSION} //Pascal
25639 function NewReadWriteFileStream( const FileName: String ): PStream;
25640 var Creation: DWORD;
25641 begin
25642 Result := _NewStream( BaseFileMethods );
25643 Result.fMethods.fRead := ReadFileStream;
25644 Result.fMethods.fWrite := WriteFileStream;
25645 Result.fMethods.fSetSiz := SetSizeFileStream;
25646 Creation := ofCreateAlways;
25647 if FileExists( FileName ) then Creation := ofOpenExisting;
25648 Result.fData.fHandle := FileCreate( FileName,
25649 ofOpenReadWrite or Creation or ofShareDenyWrite );
25650 end;
25651 {$ENDIF ASM_VERSION}
25652 //[END NewReadWriteFileStream]
25654 //[function NewMemoryStream]
25655 function NewMemoryStream: PStream;
25656 begin
25657 Result := _NewStream( MemoryMethods );
25658 end;
25660 //[FUNCTION WriteExMemoryStream]
25661 {$IFDEF ASM_VERSION}
25662 function WriteExMemoryStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25664 PUSH EBX
25665 XCHG EBX, EAX
25666 MOV EAX, [EBX].TStream.fData.fSize
25667 SUB EAX, [EBX].TStream.fData.fPosition
25668 CMP EAX, ECX
25669 JGE @@1
25670 XCHG ECX, EAX
25671 @@1:
25672 PUSH EDX
25673 PUSH ECX
25674 JLE @@count_ok
25675 XCHG EDX, EAX
25676 MOV EAX, EBX
25677 CALL TStream.SetSize
25678 @@count_ok:
25679 POP ECX
25680 POP EAX
25681 MOV EDX, [EBX].TStream.fMemory
25682 ADD EDX, [EBX].TStream.fData.fPosition
25683 PUSH ECX
25684 CALL System.Move
25685 POP EAX
25686 ADD [EBX].TStream.fData.fPosition, EAX
25687 POP EBX
25688 end;
25689 {$ELSE ASM_VERSION}
25690 function WriteExMemoryStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25691 var S: PStream;
25692 begin
25693 S := Strm;
25694 if Count + S.fData.fPosition > S.fData.fSize then
25695 Count := S.fData.fSize - S.fData.fPosition;
25696 Result := Count;
25697 Move( Buffer, Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Result );
25698 Inc( S.fData.fPosition, Result );
25699 end;
25700 {$ENDIF ASM_VERSION}
25701 //[END WriteExMemoryStream]
25703 //[procedure DummyClose_ExMemStream]
25704 procedure DummyClose_ExMemStream( Strm: PStream );
25705 begin
25706 // nothing to do - ignore call (memory is not released by any way)
25707 end;
25709 //[function NewExMemoryStream]
25710 function NewExMemoryStream( ExistingMem: Pointer; Size: DWORD ): PStream;
25711 begin
25712 Result := NewMemoryStream;
25713 Result.fMemory := ExistingMem;
25714 Result.fData.fCapacity := Size;
25715 Result.fData.fSize := Size;
25716 Result.fMethods.fWrite := WriteExMemoryStream;
25717 Result.fMethods.fSetSiz := DummySetSize;
25718 Result.fMethods.fClose := DummyClose_ExMemStream;
25719 end;
25722 //[function Stream2Stream]
25723 function Stream2Stream( Dst, Src: PStream; Count: DWORD ): DWORD;
25724 var Buf: Pointer;
25725 begin
25726 if Src.fMemory <> nil then
25727 begin
25728 if Src.fData.fPosition + Count > Src.fData.fSize then
25729 Count := Src.fData.fSize - Src.fData.fPosition;
25730 Result := Dst.Write( Pointer(DWORD(Src.fMemory)+Src.fData.fPosition)^,
25731 Count );
25732 Inc( Src.fData.fPosition, Result );
25734 else
25735 if Dst.fMemory <> nil then
25736 begin
25737 if Dst.fData.fPosition + Count > Dst.fData.fSize then
25738 Dst.SetSize( Dst.fData.fPosition + Count );
25739 Result := Src.Read( Pointer( DWORD( Dst.fMemory ) + Dst.fData.fPosition )^,
25740 Count );
25741 Inc( Dst.fData.fPosition, Result );
25743 else
25744 begin
25745 GetMem( Buf, Count );
25746 Count := Src.Read( Buf^, Count );
25747 Result := Dst.Write( Buf^, Count );
25748 FreeMem( Buf );
25749 end;
25750 end;
25752 //[function Stream2StreamEx]
25753 function Stream2StreamEx( Dst, Src: PStream; Count: DWORD ): DWORD;
25754 begin
25755 Result := Stream2StreamExBufSz( Dst, Src, Count, 65536 );
25756 end;
25758 //[function Stream2StreamExBufSz]
25759 function Stream2StreamExBufSz( Dst, Src: PStream; Count, BufSz: DWORD ): DWORD;
25761 buf:pointer;
25762 rd, wr:dword;
25763 begin
25764 if count=0 then result:=0 else
25765 begin
25766 result:=0;
25767 BufSz := Min( BufSz, Count );
25768 if BufSz = 0 then BufSz := Count;
25769 getmem(buf,BufSz);
25770 repeat
25771 if count<BufSz then rd:=count else rd:=BufSz;
25772 rd:=src.read(buf^,rd);
25773 wr := dst.write(buf^,rd);
25774 inc(result,wr);
25775 dec(Count, rd);
25776 until (rd<>BufSz) or (Count=0);
25777 freemem(buf);
25778 end;
25779 end;
25781 //[FUNCTION Resource2Stream]
25782 {$IFDEF ASM_VERSION}
25783 function Resource2Stream( DestStrm : PStream; Inst : HInst;
25784 ResName : PChar; ResType : PChar ): Integer;
25786 PUSH EBX
25787 PUSH ESI
25788 MOV EBX, EDX // EBX = Inst
25789 PUSH EAX // DestStrm
25790 PUSH ResType
25791 PUSH ECX
25792 PUSH EDX
25793 CALL FindResource
25794 TEST EAX, EAX
25795 JZ @@exit0
25797 PUSH EAX
25798 PUSH EBX
25799 PUSH EAX
25800 PUSH EBX
25801 CALL SizeofResource
25802 XCHG EBX, EAX
25803 CALL LoadResource
25804 TEST EAX, EAX
25805 JZ @@exit0
25806 XCHG ESI, EAX
25808 PUSH ESI
25809 CALL GlobalLock
25810 TEST EAX, EAX
25811 JNZ @@P_ok
25813 CALL GetLastError
25814 CMP EAX, ERROR_INVALID_HANDLE
25815 JNZ @@exit_00
25816 MOV EAX, ESI
25818 @@P_ok:
25819 XCHG EDX, EAX
25820 POP EAX // DestStrm
25821 PUSH EDX
25822 MOV ECX, EBX
25823 CALL TStream.Write
25825 //EAX = Result (length of written data)
25826 XCHG EBX, EAX
25827 POP EAX
25828 CMP ESI, EAX
25829 JE @@not_unlock
25831 PUSH ESI
25832 CALL GlobalUnlock
25833 @@not_unlock:
25834 XCHG EAX, EBX
25835 JMP @@exit
25837 @@exit_00:
25838 XOR EAX, EAX
25839 @@exit0:
25840 POP ECX
25841 @@exit:
25842 POP ESI
25843 POP EBX
25844 end;
25845 {$ELSE ASM_VERSION} //Pascal
25846 function Resource2Stream( DestStrm : PStream; Inst : HInst;
25847 ResName : PChar; ResType : PChar ): Integer;
25848 var R : HRSRC;
25849 G : HGlobal;
25850 P : PChar;
25851 Sz : DWORD;
25852 E : Integer;
25853 begin
25854 Result := 0;
25855 R := FindResource( Inst, ResName, ResType );
25856 if R <> 0 then
25857 begin
25858 Sz := SizeofResource( Inst, R );
25859 G := LoadResource( Inst, R );
25860 if G <> 0 then
25861 begin
25862 P := GlobalLock( G );
25863 if P = nil then
25864 begin
25865 E := GetLastError;
25866 if E = ERROR_INVALID_HANDLE then
25867 P := Pointer( G )
25868 else
25869 Exit;
25870 end;
25871 Result := DestStrm.Write( P^, Sz );
25872 if P <> Pointer( G ) then
25873 GlobalUnlock( G );
25874 //FreeResource( G );
25875 { from Win32.hlp: "You do not need to call the FreeResource
25876 function to free a resource loaded by using the LoadResource
25877 function." }
25878 end;
25879 end;
25880 end;
25881 {$ENDIF ASM_VERSION}
25882 //[END Resource2Stream]
25895 ///////////////////////////////////////////////////////////////////////////
25898 // I N I - F I L E S
25901 ///////////////////////////////////////////////////////////////////////////
25904 { TIniFile }
25906 {$IFDEF ASM_VERSION}
25907 //[destructor TIniFile.Destroy]
25908 destructor TIniFile.Destroy;
25909 asm //cmd //opd
25910 PUSH EAX
25911 LEA EDX, [EAX].fFileName
25912 PUSH EDX
25913 LEA EAX, [EAX].fSection
25914 CALL System.@LStrClr
25915 POP EAX
25916 CALL System.@LStrClr
25917 POP EAX
25918 CALL TObj.Destroy
25919 end;
25920 {$ELSE ASM_VERSION} //Pascal
25921 destructor TIniFile.Destroy;
25922 begin
25923 fFileName := '';
25924 fSection := '';
25925 inherited;
25926 end;
25927 {$ENDIF ASM_VERSION}
25929 {$IFNDEF _D5orHigher}
25930 // Place here correct definition for WritePrivateProfileStruct
25931 // and GetPrivateProfileStruct (a bug in Delphi2, Delphi3 and Delphi4)
25932 //[API WritePrivateProfileStruct]
25933 function WritePrivateProfileStruct(lpszSection, lpszKey: PChar;
25934 lpStruct: Pointer; uSizeStruct: UINT; szFile: PChar): BOOL; stdcall;
25935 external kernel32 name 'WritePrivateProfileStructA';
25936 //[API GetPrivateProfileStruct]
25937 function GetPrivateProfileStruct(lpszSection, lpszKey: PAnsiChar;
25938 lpStruct: Pointer; uSizeStruct: UINT; szFile: PAnsiChar): BOOL; stdcall;
25939 external kernel32 name 'GetPrivateProfileStructA';
25941 // + by Slava A. Gavrik:
25942 ////////////////////////////////////////////////////////////////////////////
25943 //[function WritePrivateProfileSection]
25944 function WritePrivateProfileSection(lpAppName, lpString,
25945 lpFileName: PChar): BOOL; stdcall;
25946 external kernel32 name 'WritePrivateProfileSectionA';
25947 //[function GetPrivateProfileSection]
25948 function GetPrivateProfileSection(lpAppName: PChar; lpReturnedString: PChar;
25949 nSize: DWORD; lpFileName: PChar): DWORD; stdcall;
25950 external kernel32 name 'GetPrivateProfileSectionA';
25952 //[function GetPrivateProfileSectionNames]
25953 function GetPrivateProfileSectionNames(lpszReturnBuffer: PChar; nSize:
25954 DWORD;
25955 lpFileName: PChar): DWORD; stdcall;
25956 external kernel32 name 'GetPrivateProfileSectionNamesA';
25957 ////////////////////////////////////////////////////////////////////////////
25958 {$ENDIF}
25961 //[procedure TIniFile.ClearAll]
25962 procedure TIniFile.ClearAll;
25963 begin
25964 WritePrivateProfileString( nil, nil, nil,
25965 PChar( fFileName ) );
25966 end;
25968 //[procedure TIniFile.ClearKey]
25969 procedure TIniFile.ClearKey(const Key: String);
25970 begin
25971 WritePrivateProfileString( PChar( fSection ), PChar( Key ), nil,
25972 PChar( fFileName ) );
25973 end;
25975 //[procedure TIniFile.ClearSection]
25976 procedure TIniFile.ClearSection;
25977 begin
25978 WritePrivateProfileString( PChar( fSection ), nil, nil,
25979 PChar( fFileName ) );
25980 end;
25982 //[function TIniFile.ValueBoolean]
25983 function TIniFile.ValueBoolean(const Key: String; Value: Boolean): Boolean;
25984 begin
25985 if fMode = ifmRead then
25986 Result := GetPrivateProfileInt( PChar( fSection ), PChar( Key ),
25987 Integer( Value ), PChar( fFileName ) ) <> 0
25988 else
25989 begin
25990 WritePrivateProfileString( PChar( fSection ), PChar( Key ),
25991 PChar( Int2Str( Integer( Value ) ) ), PChar( fFileName ) );
25992 Result := Value;
25993 end;
25994 end;
25996 //[function TIniFile.ValueData]
25997 function TIniFile.ValueData(const Key: String; Value: Pointer;
25998 Count: Integer): Boolean;
25999 begin
26000 if fMode = ifmRead then
26001 Result := GetPrivateProfileStruct( PChar( fSection ), PChar( Key ),
26002 Value, Count, PChar( fFileName ) )
26003 else
26004 Result := WritePrivateProfileStruct( PChar( fSection ), PChar( Key ),
26005 Value, Count, PChar( fFileName ) );
26006 end;
26008 //[function TIniFile.ValueInteger]
26009 function TIniFile.ValueInteger(const Key: String; Value: Integer): Integer;
26010 begin
26011 if fMode = ifmRead then
26012 Result := GetPrivateProfileInt( PChar( fSection ), PChar( Key ),
26013 Integer( Value ), PChar( fFileName ) )
26014 else
26015 begin
26016 Result := Value;
26017 WritePrivateProfileString( PChar( fSection ), PChar( Key ),
26018 PChar( Int2Str( Value ) ), PChar( fFileName ) );
26019 end;
26020 end;
26022 //[function TIniFile.ValueString]
26023 function TIniFile.ValueString(const Key, Value: String): String;
26025 Buffer: array[0..2047] of Char;
26026 begin
26027 if fMode = ifmRead then
26028 begin
26029 Buffer[ 0 ] := #0;
26030 GetPrivateProfileString(PChar(fSection),
26031 PChar(Key), PChar(Value), Buffer, SizeOf(Buffer), PChar(fFileName));
26032 Result := Buffer;
26034 else
26035 begin
26036 Result := Value;
26037 WritePrivateProfileString( PChar( fSection ), PChar( Key ),
26038 PChar( Value ), PChar( fFileName ) );
26039 end;
26040 end;
26042 //[function OpenIniFile]
26043 function OpenIniFile( const FileName: String ): PIniFile;
26044 begin
26046 New( Result, Create );
26047 {+}{++}(*Result := PIniFile.Create;*){--}
26048 Result.fFileName := FileName;
26049 end;
26051 /////////////////////////////////////////////////// GetSectionNames, SectionData
26052 // - by Vyacheslav A. Gavrik :
26054 const
26055 IniBufferSize = 32767;
26056 IniBufferStrSize = IniBufferSize+4; /// äëÿ ìàõèíàöèé :)
26058 {$IFDEF ASM_VERSION}
26059 //[procedure _FillStrList]
26060 procedure _FillStrList; // Ýòà ÷àñòü êîäà îáùàÿ äëÿ äâóõ ñëåäóþùèõ ïðîöåäóð
26062 ///////////////////////////////
26063 OR EAX,0
26064 JE @@EXIT //ERROR
26065 // LEA EAX,[EAX-IniBufferSize]
26066 // JE @@EXIT
26067 // âîçìîæíà íåõâàòêà Áóôåðà... â ïðèíöèïå íå îøèáêà :)
26068 // âîçâðàùàåì ÷òî âëåçëî...
26069 //////////////////////////////
26070 @@LOOP:
26071 LEA EAX,[ESI+4]
26072 CALL StrLen
26073 MOV [ESI],EAX
26074 LEA EDX,[ESI+4]
26075 INC EAX
26076 ADD ESI,EAX
26078 MOV EAX,EDI
26080 CALL TStrList.ADD
26082 CMP byte ptr [ESI+4],0
26083 JNE @@LOOP
26085 @@EXIT:
26086 POP EAX
26087 CALL System.@FreeMem
26090 POP ECX
26091 POP EBX
26092 POP EDI
26093 POP ESI
26094 end;
26097 //[procedure TIniFile.GetSectionNames]
26098 procedure TIniFile.GetSectionNames(Names: PStrList);
26100 PUSH ESI
26101 PUSH EDI
26102 PUSH EBX
26103 PUSH ECX
26105 MOV EBX,EAX
26106 MOV EAX, IniBufferStrSize
26107 MOV EDI,EDX
26109 CALL System.@GetMem
26110 MOV ESI,EAX
26111 PUSH EAX
26113 PUSH [EBX].fFileName
26114 MOV EAX,IniBufferSize
26115 PUSH EAX
26117 LEA EAX,[ESI+4]
26118 PUSH EAX
26120 CALL GetPrivateProfileSectionNames
26121 JMP _FillStrList
26122 end;
26124 //[procedure TIniFile.SectionData]
26125 procedure TIniFile.SectionData(Names: PStrList);
26127 PUSH ESI
26128 PUSH EDI
26129 PUSH EBX
26130 PUSH ECX
26132 MOV EBX,EAX
26133 MOV EAX, IniBufferStrSize
26134 MOV EDI,EDX
26136 CALL System.@GetMem
26137 MOV ESI,EAX
26138 PUSH EAX
26140 OR [EBX].fMode,0
26141 JNE @@DOWrite
26143 PUSH [EBX].fFileName
26144 MOV EAX,IniBufferSize
26145 PUSH EAX
26147 LEA EAX,[ESI+4]
26148 PUSH EAX
26149 PUSH [EBX].fSection
26151 CALL GetPrivateProfileSection
26152 JMP _FillStrList
26154 @@DOWrite:
26156 PUSH EBX
26157 PUSH ESI
26158 PUSH EDX
26159 PUSH EBP
26161 MOV EDX,0
26162 MOV EBP,[EDI].TStrList.fCount
26163 MOV EBX,IniBufferSize-2 // îñòàâèì ìåñòî äëÿ #0#0
26165 {ECM+++>} OR EBP,EBP // otherwise GetPChars when StrList.Count = 0 crashed
26167 @@LOOP:
26168 JE @@ENDLOOP
26170 OR EBX,EBX
26171 JE @@ENDLOOP
26173 PUSH EDX
26174 MOV EAX,EDI
26175 CALL TStrList.GetPChars
26177 PUSH EAX
26178 CALL StrLen
26179 POP EAX
26181 XOR ECX,-1
26182 MOV EDX,ESI
26184 SUB EBX,ECX
26185 JA @@L1
26186 ADD ECX,EBX
26187 XOR EBX,EBX
26188 @@L1:
26190 ADD ESI,ECX
26192 CALL MOVE
26193 @@L2:
26194 POP EDX
26195 INC EDX
26196 DEC EBP
26197 JMP @@LOOP
26198 @@ENDLOOP:
26199 MOV WORD PTR [ESI],0
26201 POP EBP
26202 POP EDX
26203 POP ESI
26204 POP EBX
26205 ///////////////////////////////////
26206 MOV EAX,EBX // íîäî î÷èùàòü
26207 CALL ClearSection
26208 //////////////////////////////////
26210 PUSH [EBX].fFileName
26211 PUSH ESI
26212 PUSH [EBX].fSection
26214 CALL WritePrivateProfileSection
26216 POP EAX
26217 CALL System.@FreeMem
26219 POP ECX
26220 POP EBX
26221 POP EDI
26222 POP ESI
26224 end;
26225 {$ELSE ASM_VERSION} //Pascal
26227 //[procedure TIniFile.GetSectionNames]
26228 procedure TIniFile.GetSectionNames(Names: PStrList);
26230 i:integer;
26231 Pc:PChar;
26232 PcEnd:PChar;
26233 Buffer:Pointer;
26234 begin
26235 GetMem(Buffer,IniBufferSize);
26236 Pc:=Buffer;
26237 i := GetPrivateProfileSectionNames(Buffer, IniBufferSize, PChar(fFileName));
26238 PcEnd:=Pc+i;
26239 repeat
26240 Names.Add(Pc);
26241 Pc:=PC+Length(PC)+1;
26242 until PC>=PcEnd;
26243 FreeMem(Buffer);
26244 end;
26246 //[procedure TIniFile.SectionData]
26247 procedure TIniFile.SectionData(Names: PStrList);
26249 i:integer;
26250 Pc:PChar;
26251 PcEnd:PChar;
26252 Buffer:Pointer;
26253 begin
26254 GetMem(Buffer,IniBufferSize);
26255 Pc:=Buffer;
26256 if fMode = ifmRead then
26257 begin
26258 i:=GetPrivateProfileSection(PChar(fSection), Buffer, IniBufferSize, PChar(fFileName));
26259 PcEnd:=Pc+i;
26260 while PC < PcEnd do // Chg by ECM from REPEAT-UNTIL: i=0 (empty section) => Names.Count=1
26261 begin
26262 Names.Add(Pc);
26263 Pc:=PC+Length(PC)+1;
26264 end;
26265 end else
26266 begin
26267 for i:= 0 to Names.Count-1 do
26268 begin
26269 StrCopy(Pc,Names.ItemPtrs[i]);
26270 Pc:=PC+Length(PC)+1;
26271 end;
26272 Pc[0]:=#0;
26273 ClearSection;
26274 WritePrivateProfileSection(PChar(fSection), Buffer, PChar(fFileName));
26276 end;
26277 FreeMem(Buffer);
26278 end;
26279 {$ENDIF ASM_VERSION}
26281 //////////////////////////////////////////////////////////////////////
26293 /////////////////////////////////////////////////////////////////////////
26296 // M E N U
26299 /////////////////////////////////////////////////////////////////////////
26301 { -- Menu implementation -- }
26303 //[FUNCTION MakeAccelerator]
26304 {$IFDEF ASM_VERSION}
26305 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;
26307 MOVZX EAX, AL
26308 PUSH EAX
26309 MOV [ESP+1], DX
26310 POP EAX
26311 end;
26312 {$ELSE ASM_VERSION} //Pascal
26313 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;
26314 begin
26315 Result.fVirt := fVirt;
26316 Result.Key := Key;
26317 end;
26318 {$ENDIF ASM_VERSION}
26319 //[END MakeAccelerator]
26321 //[FUNCTION GetAcceleratorText]
26322 function GetAcceleratorText( const Accelerator: TMenuAccelerator ): string;
26324 KeyName: array[0..255] of Char;
26326 procedure AddKeyName( Code: Integer );
26327 begin
26328 Code := MapVirtualKey(Code, 0);
26329 if Code = 0 then exit;
26330 if GetKeyNameText(Code shl 16, KeyName, SizeOf(KeyName)) > 0 then begin
26331 if Result <> '' then
26332 Result := Result + '+';
26333 Result := Result + KeyName;
26334 end;
26335 end;
26337 begin
26338 Result := '';
26339 with Accelerator do begin
26340 if fVirt and FCONTROL <> 0 then
26341 AddKeyName(VK_CONTROL);
26342 if fVirt and FSHIFT <> 0 then
26343 AddKeyName(VK_SHIFT);
26344 if fVirt and FALT <> 0 then
26345 AddKeyName(VK_ALT);
26346 if fVirt and $20 <> 0 then
26347 AddKeyName(VK_LWIN);
26348 if fVirt and $40 <> 0 then
26349 AddKeyName(VK_RWIN);
26351 AddKeyName(Key);
26352 end;
26353 end;
26354 //[END GetAcceleratorText]
26357 const
26358 MIDATA_CHECKITEM = $40000000;
26359 MIDATA_RADIOITEM = $80000000;
26361 //[function WndProcMenu]
26362 {$IFNDEF NEW_MENU_ACCELL}
26363 function WndProcMenu( Sender: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
26364 var M, M1: PMenu;
26365 Idx: Integer;
26366 Id: Integer;
26367 begin
26368 Result := False;
26369 if Msg.message = WM_COMMAND then
26370 begin
26371 if (Msg.lParam = 0) and (HIWORD( Msg.wParam ) <= 1) then
26372 begin
26373 M := PMenu( Sender.fMenuObj );
26374 while M <> nil do
26375 begin
26376 Id := LoWord( Msg.wParam );
26377 M1 := M.Items[ Id ];
26378 if M1 <> nil then
26379 begin
26380 Result := True;
26381 Rslt := 0;
26382 Idx := M.IndexOf( M1 );
26383 M.fByAccel := HiWord( Msg.wParam ) <> 0;
26384 if M1.FRadioGroup <> 0 then
26385 M1.RadioCheckItem
26386 else
26387 if M1.FIsCheckItem then
26388 M1.Checked := not M1.Checked;
26389 if Assigned(M1.FOnMenuItem) then
26390 M1.FOnMenuItem( M, Idx )
26391 else if Assigned( M.FOnMenuItem ) then
26392 M.FOnMenuItem( M, Idx );
26393 //M.FProcessed := True;
26394 break;
26395 end;
26396 M := M.fNextMenu;
26397 end;
26398 end;
26399 end;
26400 end;
26402 {$ELSE}
26404 function WndProcMenu( Sender: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
26406 function ProcessMenuItem(M: PMenu; Id: Integer): Boolean;
26408 M1: PMenu;
26409 Idx: Integer;
26410 begin
26411 M1 := M.Items[ Id ];
26412 Result := (M1 <> nil);
26413 if Result then
26414 begin
26415 Idx := M.IndexOf( M1 );
26416 M.fByAccel := HiWord( Msg.wParam ) <> 0;
26417 if M1.FRadioGroup <> 0 then
26418 M1.RadioCheckItem
26419 else
26420 if M1.FIsCheckItem then
26421 M1.Checked := not M1.Checked;
26422 if Assigned(M1.FOnMenuItem) then begin
26423 {$IFDEF USE_MENU_CURCTL} // fixed
26424 M.fCurCtl := Sender; // fixed
26425 {$ENDIF} // fixed
26426 M1.FOnMenuItem( M, Idx )
26428 else if Assigned( M.FOnMenuItem ) then
26429 M.FOnMenuItem( M, Idx );
26430 end;
26431 end;
26434 M: PMenu;
26435 Id: Integer;
26436 begin
26437 Result := False;
26438 if Msg.message = WM_COMMAND then
26439 if (Msg.lParam = 0) and (HIWORD( Msg.wParam ) <= 1) then begin
26440 Id := LoWord(Msg.wParam);
26441 M := PMenu(Sender.fAutoPopupMenu);
26442 if (M <> nil) and ProcessMenuItem(M, Id) then begin
26443 Result := True;
26444 Rslt := 0;
26446 else begin
26447 M := PMenu(Sender.fMenuObj);
26448 while M <> nil do begin
26449 if ProcessMenuItem(M, Id) then begin
26450 Result := True;
26451 Rslt := 0;
26452 Break;
26453 end;
26454 M := M.fNextMenu;
26455 end;
26456 end;
26457 end;
26458 end;
26459 {$ENDIF}
26462 var FDynamicMenuID: DWORD = $1000;
26464 //[function NewMenu]
26465 function NewMenu( AParent : PControl; MaxCmdReserve : DWORD; const Template : array of PChar;
26466 aOnMenuItem: TOnMenuItem ): PMenu;
26467 var M: PMenu;
26468 begin
26470 New( Result, Create );
26471 {+}{++}(*Result := PMenu.Create;*){--}
26472 Result.FVisible := TRUE;
26473 Result.FPopupFlags := TPM_LEFTALIGN or TPM_LEFTBUTTON;
26474 Result.FItems := NewList;
26475 Result.FOnMenuItem := aOnMenuItem;
26476 if (High(Template)>=0) and (Template[0] <> nil) then
26477 begin
26478 if (AParent <> nil) and (AParent.fMenuObj = nil) and not AParent.fIsControl then
26479 Result.FHandle := CreateMenu
26480 else
26481 Result.FHandle := CreatePopupMenu;
26482 Result.FillMenuItems( Result.FHandle, 0, Template );
26483 end;
26484 if assigned( AParent ) then
26485 begin
26486 Result.FControl := AParent;
26487 if AParent.fMenuObj <> nil then
26488 begin
26489 // add popup menu to the end of menu chain
26490 M := PMenu( AParent.fMenuObj );
26491 while M.fNextMenu <> nil do
26492 M := M.fNextMenu;
26493 M.fNextMenu := Result;
26495 else
26496 begin
26497 if not AParent.fIsControl then
26498 AParent.Menu := Result.FHandle;
26499 AParent.fMenuObj := Result;
26500 AParent.AttachProc( WndProcMenu );
26501 end;
26502 end;
26503 end;
26504 //[END NewMenu]
26506 //[function NewMenuEx]
26507 function NewMenuEx( AParent : PControl; FirstCmd : Integer; const Template : array of PChar;
26508 aOnMenuItems: array of TOnMenuItem ): PMenu;
26509 begin
26510 Result := NewMenu( AParent, FirstCmd, Template, nil );
26511 Result.AssignEvents( 0, aOnMenuItems );
26512 end;
26513 //[END NewMenuEx]
26515 { TMenu }
26517 const
26518 Breaks: array[ TMenuBreak ] of DWORD = ( 0, MFT_MENUBREAK, MFT_MENUBARBREAK );
26520 { + by AK - Andrzej Kubaszek }
26521 //[function MenuStructSize]
26522 function MenuStructSize: Integer;
26523 begin
26524 Result := 44;
26525 if not( WinVer in [wv31, wv95, wvNT] ) then
26526 Result := {48=} Sizeof( TMenuItemInfo );
26527 end;
26529 //[destructor TMenu.Destroy]
26530 destructor TMenu.Destroy;
26531 var Next, Prnt: PMenu;
26532 begin
26533 if Count > 0 then
26534 begin
26535 FItems.ReleaseObjects;
26536 FItems := NewList;
26537 end;
26538 if FParent <> nil then
26539 begin
26540 Prnt := FParent;
26541 FParent := nil;
26542 Next := Prnt.RemoveSubMenu( FId );
26543 Prnt.FItems.Remove( @ Self );
26544 if Next = nil then Exit;
26545 end;
26546 if (FControl <> nil) and (FControl.fMenu = FHandle) and (FHandle <> 0) then
26547 begin
26548 //if FControl.fHandle <> 0 then
26549 begin
26550 Windows.SetMenu( FControl.fHandle, 0 );
26551 // this removes main menu from window, but does not destroy it
26552 end;
26553 FControl.fMenu := 0;
26554 Next := PMenu( FControl.fMenuObj );
26555 while Next <> nil do
26556 begin
26557 if Next.fNextMenu = @Self then
26558 begin
26559 Next.fNextMenu := fNextMenu;
26560 break;
26561 end;
26562 Next := Next.fNextMenu;
26563 end;
26564 end;
26565 Next := fNextMenu;
26566 if FBitmap <> 0 then
26567 Bitmap := 0;
26568 if FHandle <> 0 then
26569 DestroyMenu( FHandle );
26570 FCaption := '';
26571 FItems.Free;
26572 inherited;
26573 Next.Free;
26574 // all later created (popup) menus (of the same control)
26575 // are destroyed too
26576 end;
26578 //[function TMenu.GetInfo]
26579 function TMenu.GetInfo( var MII: TMenuItemInfo ): Boolean;
26580 begin
26581 MII.cbSize := MenuStructSize;
26582 Result := GetMenuItemInfo( Parent.FHandle, FId, FALSE,
26583 Windows.PMenuitemInfo( @ MII )^ );
26584 end;
26586 //[procedure TMenu.RedrawFormMenuBar]
26587 procedure TMenu.RedrawFormMenuBar;
26588 var C: PControl;
26589 begin
26590 C := TopParent.FControl;
26591 if not AppletTerminated then
26592 if (C <> nil) and (Pointer( C.fMenuObj ) = Pointer( TopParent )) then
26593 DrawMenuBar( C.FHandle );
26594 end;
26596 //[function TMenu.SetInfo]
26597 function TMenu.SetInfo( var MII: TMenuItemInfo ): Boolean;
26598 var H: THandle;
26599 begin
26600 MII.cbSize := MenuStructSize;
26601 H := FHandle;
26602 if FParent <> nil then
26603 H := FParent.FHandle;
26604 Result := SetMenuItemInfo( H, FId, FALSE, Windows.PMenuitemInfo( @ MII )^ );
26605 if Result and ((FParent = nil) or (FParent.FParent = nil)) then {YS}
26606 RedrawFormMenuBar;
26607 end;
26609 //[function TMenu.SetTypeInfo]
26610 function TMenu.SetTypeInfo( var MII: TMenuItemInfo ): Boolean;
26611 begin
26612 if not FIsSeparator then
26613 begin
26614 if FBmpItem = 0 then
26615 MII.dwTypeData := PChar( FCaption )
26616 else
26617 MII.dwTypeData := Pointer( FBmpItem );
26618 MII.cch := Length( FCaption );
26619 end;
26620 Result := SetInfo( MII );
26621 end;
26623 //[function TMenu.GetTopParent]
26624 function TMenu.GetTopParent: PMenu;
26625 begin
26626 Result := @ Self;
26627 while Result.FParent <> nil do
26628 Result := Result.FParent;
26629 end;
26631 //[function TMenu.GetControl]
26632 function TMenu.GetControl: PControl;
26633 begin
26634 Result := TopParent.FControl;
26635 end;
26637 //[function TMenu.GetItems]
26638 function TMenu.GetItems( Id: HMenu ): PMenu;
26639 function SearchItems( ParentMenu: PMenu; var FromIdx: Integer ): PMenu;
26640 var I: Integer;
26641 begin
26642 Result := ParentMenu;
26643 if Id = HMenu( FromIdx ) then Exit;
26644 if (Id >= 4096) and (DWORD( ParentMenu.FId ) = Id) then Exit;
26645 if ParentMenu.FItems = nil then Exit;
26646 for I := 0 to ParentMenu.FItems.FCount-1 do
26647 begin
26648 Inc( FromIdx );
26649 Result := SearchItems( ParentMenu.FItems.Items[ I ], FromIdx );
26650 if Result <> nil then Exit;
26651 end;
26652 Result := nil;
26653 end;
26654 var I: Integer;
26655 begin
26656 I := -1;
26657 Result := SearchItems( @ Self, I );
26658 end;
26660 //[function TMenu.GetCount]
26661 function TMenu.GetCount: Integer;
26662 var I: Integer;
26663 SubM: PMenu;
26664 begin
26665 Result := FItems.FCount;
26666 for I := 0 to Result-1 do
26667 begin
26668 SubM := FItems.Items[ I ];
26669 Result := Result + SubM.Count;
26670 end;
26671 end;
26673 //[function TMenu.IndexOf]
26674 function TMenu.IndexOf( Item: PMenu ): Integer;
26675 function SearchMenu( ParentMenu: PMenu; var FromIdx: Integer ): PMenu;
26676 var I: Integer;
26677 begin
26678 Result := ParentMenu;
26679 if Result = Item then Exit;
26680 for I := 0 to ParentMenu.FItems.FCount-1 do
26681 begin
26682 Inc( FromIdx );
26683 Result := SearchMenu( ParentMenu.FItems.Items[ I ], FromIdx );
26684 if Result <> nil then Exit;
26685 end;
26686 Result := nil;
26687 end;
26688 begin
26689 Result := -1;
26690 if SearchMenu( @ Self, Result ) = nil then
26691 Result := -2;
26692 end;
26694 //[function TMenu.GetState]
26695 function TMenu.GetState( const Index: Integer ): Boolean;
26696 var MII: TMenuItemInfo;
26697 begin
26698 if FVisible then
26699 begin
26700 MII.fMask := MIIM_STATE;
26701 if GetInfo( MII ) then
26702 FSavedState := MII.fState;
26703 end;
26704 Result := LongBool( FSavedState and Index );
26705 if Index < 0 then
26706 Result := not Result;
26707 end;
26709 //[procedure TMenu.SetState]
26710 procedure TMenu.SetState( const Index: Integer; Value: Boolean );
26711 var MII: TMenuItemInfo;
26712 begin
26713 GetState( 0 );
26714 if Value xor (Index < 0) then
26715 FSavedState := FSavedState or DWORD( Index and $7FFFFFFF )
26716 else
26717 FSavedState := FSavedState and not DWORD( Index );
26718 if FVisible then
26719 begin
26720 MII.fMask := MIIM_STATE;
26721 if GetInfo( MII ) then
26722 begin
26723 MII.fState := FSavedState;
26724 SetInfo( MII );
26725 end;
26726 end;
26727 end;
26729 //[procedure TMenu.SetData]
26730 procedure TMenu.SetData( Value: Pointer );
26731 var MII: TMenuItemInfo;
26732 begin
26733 MII.fMask := MIIM_DATA;
26734 MII.dwItemData := DWORD( Value );
26735 SetInfo( MII );
26736 FData := Value;
26737 end;
26739 //[procedure TMenu.ClearBitmaps]
26740 procedure TMenu.ClearBitmaps;
26741 begin
26742 if FBitmap <> 0 then
26743 DeleteObject( FBitmap );
26744 if FBmpChecked <> 0 then
26745 DeleteObject( FBmpChecked );
26746 if FBmpItem <> 0 then
26747 DeleteObject( FBmpItem );
26748 end;
26750 //[procedure TMenu.SetBitmap]
26751 procedure TMenu.SetBitmap( Value: HBitmap );
26752 var MII: TMenuItemInfo;
26753 begin
26754 if not FClearBitmaps then
26755 begin
26756 FClearBitmaps := TRUE;
26757 Add2AutoFreeEx( ClearBitmaps );
26758 end;
26759 if Value = FBitmap then Exit;
26760 if FBitmap <> 0 then
26761 DeleteObject( FBitmap ); // seems not necessary.
26762 FBitmap := Value;
26763 MII.fMask := MIIM_CHECKMARKS;
26764 MII.hbmpChecked := FBmpChecked;
26765 MII.hbmpUnchecked := FBitmap;
26766 SetInfo( MII );
26767 end;
26769 //[procedure TMenu.SetBmpChecked]
26770 procedure TMenu.SetBmpChecked( Value: HBitmap );
26771 var MII: TMenuItemInfo;
26772 begin
26773 if not FClearBitmaps then
26774 begin
26775 FClearBitmaps := TRUE;
26776 Add2AutoFreeEx( ClearBitmaps );
26777 end;
26778 if Value = FBmpChecked then Exit;
26779 if FBmpChecked <> 0 then
26780 DeleteObject( FBmpChecked );
26781 FBmpChecked := Value;
26782 MII.fMask := MIIM_CHECKMARKS;
26783 MII.hbmpChecked := FBmpChecked;
26784 MII.hbmpUnchecked := FBitmap;
26785 SetInfo( MII );
26786 end;
26788 //[procedure TMenu.SetBmpItem]
26789 procedure TMenu.SetBmpItem( Value: HBitmap );
26790 var MII: TMenuItemInfo;
26791 begin
26792 if not FClearBitmaps then
26793 begin
26794 FClearBitmaps := TRUE;
26795 Add2AutoFreeEx( ClearBitmaps );
26796 end;
26797 if Value = FBmpItem then Exit;
26798 if FBmpItem <> 0 then
26799 DeleteObject( FBmpItem );
26800 FBmpItem := Value;
26801 if WinVer >= wv98 then {AK}
26802 begin {AK}
26803 MII.fMask := $80 {MIIM_BITMAP} ; {AK}
26804 MII.hbmpItem:=Value; {AK}
26805 end {AK}
26806 else {AK}
26807 begin//I haven't possibility to test it in Win95 {AK}
26808 MII.fType := MFT_BITMAP;
26809 MII.dwItemData := Value;
26810 end; {AK}
26811 SetInfo( MII );
26812 end;
26814 //[procedure TMenu.SetAccelerator]
26815 {$IFNDEF NEW_MENU_ACCELL}
26816 procedure TMenu.SetAccelerator(const Value: TMenuAccelerator);
26817 const MaxAccel = 1000;
26818 type TAccTab = array[0..10000] of TAccel;
26819 PAccTab = ^TAccTab;
26820 //TSetAcceleratorProc = procedure( Self_: PMenu; Idx: Integer; const Value: TMenuAccelerator );
26821 var AccTab: PAccTab;
26822 I, N : Integer;
26823 M, SubM: PMenu;
26824 C: PControl;
26825 Main: Boolean;
26826 begin
26827 //SetAcceleratorProc := TSetAcceleratorProc( MakeMethod( nil, @TMenu.SetAccelerator ).Code );
26828 if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then Exit;
26829 FAccelerator := Value;
26830 C := TopParent.FControl;
26831 if C = nil then Exit;
26832 if C.fAccelTable <> 0 then
26833 DestroyAcceleratorTable( C.fAccelTable );
26834 C.fAccelTable := 0;
26835 GetMem( AccTab, sizeof( TAccel ) * MaxAccel );
26836 N := 0;
26837 M := PMenu( C.fMenuObj );
26838 Main := TRUE;
26839 while M <> nil do
26840 begin
26841 if Main or M.Visible then
26842 begin
26843 for I := 0 to MaxInt-1 do
26844 begin
26845 SubM := M.Items[ I ];
26846 if SubM = nil then break;
26847 if SubM.FVisible then
26848 if (SubM.FAccelerator.Key <> 0) or (SubM.FAccelerator.fVirt <> 0) then
26849 begin
26850 AccTab[ N ].fVirt := SubM.FAccelerator.fVirt;
26851 AccTab[ N ].key := SubM.FAccelerator.Key;
26852 AccTab[ N ].cmd := WORD( SubM.FId );
26853 Inc( N );
26854 if N > MaxAccel then break;
26855 end;
26856 end;
26857 end;
26858 if N > MaxAccel then break;
26859 M := M.fNextMenu;
26860 end;
26861 if N > 0 then
26862 begin
26863 C.fAccelTable := CreateAcceleratorTable( AccTab[ 0 ], N );
26864 C := C.ParentForm;
26865 if C <> nil then
26866 C.SupportMnemonics;
26867 end;
26868 FreeMem( AccTab );
26869 end;
26871 {$ELSE NEW_MENU_ACCELL}
26873 procedure TMenu.SetAccelerator(const Value: TMenuAccelerator);
26875 C: PControl;
26876 M: PMenu;
26877 begin
26878 if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then Exit;
26879 FAccelerator := Value;
26880 C := FControl;
26881 M := @Self;
26882 while (C = nil) and (M <> nil) do begin
26883 M := M.Parent;
26884 if (M <> nil) then
26885 C := M.FControl;
26886 end;
26887 if (C <> nil) then
26888 C.SupportMnemonics;
26889 end;
26891 {$ENDIF NEW_MENU_ACCELL}
26893 //[procedure TMenu.SetMenuItemCaption]
26894 procedure TMenu.SetMenuItemCaption( const Value: String );
26895 var MII: TMenuItemInfo;
26896 begin
26897 FCaption := Value;
26898 {AK}if not (WinVer in [wv95,wvNT]) then
26899 {AK} MII.fMask := $40 {MIIM_STRING}
26900 {AK}else begin
26901 MII.fMask := MIIM_TYPE;
26902 MII.fType := MFT_STRING;
26903 {AK}end;
26904 //+++++++++++++++++++ to fix turning radio mark to check mark in NT4
26905 MII.cch := 0;
26906 GetInfo( MII );
26907 //------------------------------------------------------------------
26908 MII.dwTypeData := PChar( Value );
26909 MII.cch := Length( Value );
26910 SetInfo( MII );
26911 end;
26913 //[procedure TMenu.SetMenuBreak]
26914 procedure TMenu.SetMenuBreak( Value: TMenuBreak );
26915 var MII: TMenuItemInfo;
26916 begin
26917 if FId = 0 then Exit;
26918 if FMenuBreak = Value then Exit;
26919 FMenuBreak := Value;
26920 FillChar( MII, Sizeof( MII ), 0 );
26921 MII.fMask := MIIM_TYPE;
26922 MII.dwTypeData := nil;
26923 if GetInfo( MII ) then
26924 begin
26925 MII.fType := MII.fType and not( MFT_MENUBREAK or MFT_MENUBARBREAK ) or
26926 Breaks[ Value ];
26927 SetTypeInfo( MII );
26928 end;
26929 end;
26931 //[procedure TMenu.SetVisible]
26932 procedure TMenu.SetVisible( Value: Boolean );
26933 var I, J: Integer;
26934 M: PMenu;
26935 Before: Integer;
26936 ByPosition: Boolean;
26937 MII: TMenuItemInfo;
26938 begin
26939 if Value then
26940 if FParent <> nil then
26941 FParent.Visible := TRUE;
26942 if Value = FVisible then Exit;
26943 FVisible := Value;
26944 if (FControl <> nil) and (FControl.fMenuObj = @ Self) then
26945 begin
26946 FControl.GetWindowHandle;
26947 if Value then
26948 SetMenu( FControl.fHandle, FHandle )
26949 else
26950 SetMenu( FControl.fHandle, 0 );
26951 Exit;
26952 end;
26953 if FId = 0 then Exit;
26954 if FParent = nil then Exit;
26955 if Value then
26956 begin // show menu item inserting it again into appropriate position
26957 Before := -1;
26958 ByPosition := TRUE;
26959 I := FParent.FItems.IndexOf( @ Self );
26960 for J := I + 1 to FParent.FItems.FCount-1 do
26961 begin
26962 M := FParent.FItems.Items[ J ];
26963 if M.FVisible then
26964 begin
26965 Before := M.FId;
26966 ByPosition := FALSE;
26967 break;
26968 end;
26969 end;
26971 FillChar( MII, Sizeof( MII ), 0 );
26972 MII.cbSize := MenuStructSize;
26973 MII.fMask := MIIM_CHECKMARKS or MIIM_ID or MIIM_STATE or
26974 MIIM_TYPE;
26975 MII.fType := Breaks[ FMenuBreak ];
26976 MII.fState := FSavedState;
26977 MII.wID := FId;
26978 MII.dwItemData := DWORD( FData );
26980 if not FIsSeparator then
26981 begin
26982 MII.fType := MII.fType or MFT_STRING;
26983 MII.dwTypeData := PChar( FCaption );
26984 MII.cch := Length( FCaption );
26986 else
26987 MII.fType := MII.fType or MFT_SEPARATOR;
26989 if FRadioGroup <> 0 then
26990 MII.fType := MII.fType or MFT_RADIOCHECK;
26992 if FOwnerDraw then
26993 MII.fType := MII.fType or MFT_OWNERDRAW;
26995 if FBitmap <> 0 then
26996 begin
26997 MII.fMask := MII.fMask or MIIM_CHECKMARKS;
26998 MII.hbmpUnchecked := FBitmap;
26999 end;
27001 if FHandle <> 0 then
27002 begin
27003 MII.fMask := MII.fMask or MIIM_SUBMENU;
27004 MII.hSubMenu := FHandle;
27005 end;
27007 InsertMenuItem( FParent.FHandle, Before, ByPosition,
27008 Windows.PMenuitemInfo( @ MII )^ );
27010 else
27011 begin // hide menu item removing it
27012 GetState( 0 ); // store menu item state in FSavedState to allow
27013 // changing its state while it is not attached to
27014 // a menu
27015 RemoveMenu( TopParent.FHandle, FId, MF_BYCOMMAND );
27016 end;
27017 if (FControl <> nil) or (FParent <> nil) and (FParent.FControl <> nil) then
27018 RedrawFormMenuBar;
27019 end;
27021 //[procedure TMenu.RadioCheckItem]
27022 procedure TMenu.RadioCheckItem;
27023 var I, J: Integer;
27024 M, First, Last: PMenu;
27025 begin
27026 if (FParent <> nil) and (FRadioGroup <> 0) then
27027 begin
27028 I := FParent.FItems.IndexOf( @ Self );
27029 if I >= 0 then
27030 begin
27031 First := @ Self;
27032 Last := @ Self;
27033 for J := I-1 downto 0 do
27034 begin
27035 M := FParent.FItems.Items[ J ];
27036 if M.FRadioGroup <> FRadioGroup then break;
27037 if M.FVisible then
27038 First := M;
27039 end;
27040 for J := I+1 to FParent.FItems.FCount-1 do
27041 begin
27042 M := FParent.FItems.Items[ J ];
27043 if M.FRadioGroup <> FRadioGroup then break;
27044 if M.FVisible then
27045 Last := M;
27046 end;
27047 if First <> Last then
27048 begin
27049 CheckMenuRadioItem( FParent.FHandle, First.FId, Last.FId,
27050 FId, MF_BYCOMMAND {or MF_CHECKED} );
27051 Exit;
27052 end;
27053 end;
27054 end;
27055 Checked := TRUE;
27056 end;
27058 //[function TMenu.FillMenuItems]
27059 function TMenu.FillMenuItems(AHandle: HMenu; StartIdx: Integer;
27060 const Template: array of PChar): Integer;
27061 var S, S1: PChar;
27062 I: Integer;
27063 MII: TMenuItemInfo;
27064 Item, PrevItem: PMenu;
27065 begin
27066 PrevItem := nil;
27067 I := StartIdx;
27068 while I <= High( Template ) do
27069 begin
27070 S := Template[ I ];
27071 if (S = nil) or (S^ = #0) then break;
27072 if S = {$IFDEF F_P}'' +{$ENDIF} ')' then
27073 begin
27074 Result := I + 1;
27075 Exit;
27076 end;
27079 new( Item, Create );
27080 {+}{++}(*Item := PMenu.Create;*){--}
27081 Item.FVisible := TRUE;
27082 Item.FParent := @ Self;
27083 Item.FItems := NewList;
27084 FItems.Add( Item );
27086 FillChar( MII, Sizeof( MII ), 0 );
27087 MII.cbSize := MenuStructSize;
27088 MII.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE or MIIM_SUBMENU or MIIM_TYPE;
27089 if S <> {$IFDEF F_P}'' +{$ENDIF} '-' then
27090 begin
27091 if (S^ = {$IFDEF F_P}'' +{$ENDIF} '-') or
27092 (S^ = {$IFDEF F_P}'' +{$ENDIF} '+') then
27093 begin
27094 Item.FIsCheckItem := TRUE;
27095 MII.dwItemData := MIDATA_CHECKITEM;
27096 if S^ <> {$IFDEF F_P}'' +{$ENDIF} '-' then
27097 MII.fState := MII.fState or MFS_CHECKED;
27098 Inc( S );
27099 if S^ = {$IFDEF F_P}'' +{$ENDIF} '!' then
27100 begin
27101 MII.fType := MII.fType or MFT_RADIOCHECK;
27102 MII.dwItemData := MII.dwItemData or MIDATA_RADIOITEM;
27103 Inc( S );
27104 if PrevItem <> nil then
27105 begin
27106 if PrevItem.FRadioGroup <> 0 then
27107 Item.FRadioGroup := PrevItem.FRadioGroup;
27108 end;
27109 if Item.FRadioGroup = 0 then
27110 Inc( Item.FRadioGroup );
27111 if S^ = {$IFDEF F_P}'' +{$ENDIF} '!' then
27112 begin
27113 Inc( S );
27114 Inc( Item.FRadioGroup );
27115 end;
27116 end;
27117 end;
27118 Item.FCaption := S;
27120 else
27121 begin
27122 Item.FIsSeparator := TRUE;
27123 MII.fType := MFT_SEPARATOR;
27124 MII.fState := MFS_GRAYED;
27125 MII.wID := 0;
27126 end;
27127 Item.FId := FDynamicMenuID;
27128 Inc( FDynamicMenuID );
27129 MII.wID := Item.FId;
27130 if I <> High( Template ) then //YS
27131 begin //YS
27132 S1 := Template[ I + 1 ];
27133 if S1 = {$IFDEF F_P}'' +{$ENDIF} '(' then Item.FHandle := CreatePopupMenu;
27134 end; //YS
27135 MII.hSubMenu := Item.FHandle;
27136 MII.dwTypeData := PChar( S );
27137 MII.cch := StrLen( S );
27138 InsertMenuItem( AHandle, DWORD(-1), True, Windows.PMenuitemInfo( @ MII )^ );
27139 if Item.FHandle <> 0 then
27140 I := Item.FillMenuItems( Item.FHandle, I + 2, Template )
27141 else
27142 Inc( I );
27143 PrevItem := Item;
27144 end;
27145 Result := I;
27146 end;
27148 //[procedure TMenu.AssignEvents]
27149 procedure TMenu.AssignEvents(StartIdx: Integer;
27150 Events: array of TOnMenuItem);
27151 var I: Integer;
27152 M: PMenu;
27153 begin
27154 for I := 0 to High(Events) do
27155 begin
27156 M := Items[ StartIdx ];
27157 if M = nil then break;
27158 M.FOnMenuItem := Events[ I ];
27159 Inc( StartIdx );
27160 end;
27161 end;
27163 //[procedure TMenu.Popup]
27164 procedure TMenu.Popup(X, Y: Integer);
27165 begin
27166 if Assigned( fOnPopup ) then fOnPopup( @Self );
27167 if not FNotPopup then
27168 TrackPopupMenu( FHandle, FPopupFlags,
27169 X, Y, 0, FControl.Handle, nil );
27170 end;
27172 //[procedure TMenu.PopupEx]
27173 procedure TMenu.PopupEx( X, Y: Integer );
27174 var OldBounds: TRect;
27175 WasVisible: Boolean;
27176 begin
27177 WasVisible := TRUE;
27178 if FControl <> nil then
27179 begin
27180 OldBounds := FControl.BoundsRect;
27181 if not FControl.fIsControl then
27182 begin
27183 WasVisible := FControl.Visible;
27184 if not WasVisible then
27185 FControl.Top := ScreenHeight + 50;
27186 FControl.Show;
27187 end;
27188 end;
27190 // -- by Martin Larsen: -----------------------\
27191 FControl.ProcessMessage; // specific for Win9x |
27192 //---------------------------------------------/
27194 Popup( X, Y );
27195 if FControl <> nil then
27196 begin
27197 if FControl.Top = ScreenHeight + 50 then
27198 begin
27199 if not WasVisible then
27200 FControl.Visible := FALSE;
27201 FControl.BoundsRect := OldBounds;
27202 end;
27203 end;
27204 end;
27206 //[function TMenu.GetItemChecked]
27207 function TMenu.GetItemChecked( Item : Integer ) : Boolean;
27208 begin
27209 Result := Items[ Item ].Checked;
27210 end;
27212 //[procedure TMenu.SetItemChecked]
27213 procedure TMenu.SetItemChecked( Item : Integer; Value : Boolean );
27214 begin
27215 Items[ Item ].Checked := Value;
27216 end;
27218 //[function TMenu.GetMenuItemHandle]
27219 function TMenu.GetMenuItemHandle( Idx : Integer ): DWORD;
27220 begin
27221 Result := Items[ Idx ].FId;
27222 end;
27224 //[procedure TMenu.RadioCheck]
27225 procedure TMenu.RadioCheck( Idx : Integer );
27226 begin
27227 Items[ Idx ].RadioCheckItem;
27228 end;
27230 //[function TMenu.GetItemBitmap]
27231 function TMenu.GetItemBitmap(Idx: Integer): HBitmap;
27232 begin
27233 Result := Items[ Idx ].Bitmap;
27234 end;
27236 //[procedure TMenu.SetItemBitmap]
27237 procedure TMenu.SetItemBitmap(Idx: Integer; const Value: HBitmap);
27238 begin
27239 Items[ Idx ].Bitmap := Value;
27240 end;
27242 //[procedure TMenu.AssignBitmaps]
27243 procedure TMenu.AssignBitmaps(StartIdx: Integer; Bitmaps: array of HBitmap);
27244 var I: Integer;
27245 begin
27246 for I := 0 to High(Bitmaps) do
27247 ItemBitmap[ I + StartIdx ] := Bitmaps[ I ];
27248 end;
27250 //[function TMenu.GetItemText]
27251 function TMenu.GetItemText(Idx: Integer): String;
27252 begin
27253 Result := Items[ Idx ].FCaption;
27254 end;
27256 //[procedure TMenu.SetItemText]
27257 procedure TMenu.SetItemText(Idx: Integer; const Value: String);
27258 begin
27259 Items[ Idx ].Caption := Value;
27260 end;
27262 //[function TMenu.GetItemEnabled]
27263 function TMenu.GetItemEnabled(Idx: Integer): Boolean;
27264 begin
27265 Result := Items[ Idx ].Enabled;
27266 end;
27268 //[procedure TMenu.SetItemEnabled]
27269 procedure TMenu.SetItemEnabled(Idx: Integer; const Value: Boolean);
27270 begin
27271 Items[ Idx ].Enabled := Value;
27272 end;
27274 //[function TMenu.GetItemVisible]
27275 function TMenu.GetItemVisible(Idx: Integer): Boolean;
27276 begin
27277 Result := Items[ Idx ].Visible;
27278 end;
27280 //[procedure TMenu.SetItemVisible]
27281 procedure TMenu.SetItemVisible(Idx: Integer; const Value: Boolean);
27282 begin
27283 Items[ Idx ].Visible := Value;
27284 end;
27286 //[function TMenu.ParentItem]
27287 function TMenu.ParentItem( Idx: Integer ): Integer;
27288 begin
27289 Result := TopParent.IndexOf( Items[ Idx ].FParent );
27290 end;
27292 //[function TMenu.GetItemAccelerator]
27293 function TMenu.GetItemAccelerator(Idx: Integer): TMenuAccelerator;
27294 begin
27295 Result := Items[ Idx ].Accelerator;
27296 end;
27298 //[procedure TMenu.SetItemAccelerator]
27299 procedure TMenu.SetItemAccelerator(Idx: Integer; const Value: TMenuAccelerator);
27300 begin
27301 Items[ Idx ].Accelerator := Value;
27302 end;
27304 //[function TMenu.GetItemSubMenu]
27305 function TMenu.GetItemSubMenu( Idx: Integer ): HMenu;
27306 begin
27307 Result := Items[ Idx ].SubMenu;
27308 end;
27310 //[function WndProcHelp FORWARD DECLARATION]
27311 function WndProcHelp( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
27312 forward;
27314 //[procedure TMenu.SetHelpContext]
27315 procedure TMenu.SetHelpContext( Value: Integer );
27316 var Form, C: PControl;
27317 begin
27318 if TopParent <> @ Self then Exit;
27319 // Help context can not be associated with individual menu items
27320 FHelpContext := Value;
27321 C := FControl;
27322 if C = nil then Exit;
27323 Form := C.ParentForm;
27324 Form.AttachProc( WndProcHelp );
27325 SetMenuContextHelpID( FHandle, Value );
27326 end;
27328 //[procedure TMenu.SetSubmenu]
27329 procedure TMenu.SetSubmenu( Value: HMenu );
27330 var MII: TMenuItemInfo;
27331 begin
27332 MII.fMask := MIIM_SUBMENU;
27333 MII.hSubMenu := Value;
27334 SetInfo( MII );
27335 FHandle := Value;
27336 end;
27338 //[function WndProcMeasureItem]
27339 function WndProcMeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
27340 var MIS: PMeasureItemStruct;
27341 M, SM: PMenu;
27342 H, I: Integer;
27343 begin
27344 Result := FALSE;
27345 if (Msg.message = WM_MEASUREITEM) and (Msg.wParam = 0) then
27346 begin
27347 MIS := Pointer( Msg.lParam );
27348 if MIS.CtlType = ODT_MENU then
27349 begin
27350 M := Pointer( Sender.fMenuObj );
27351 while M <> nil do
27352 begin
27353 SM := M.Items[ MIS.itemID ];
27354 if SM <> nil then
27355 begin
27356 Sender.CallDefWndProc( Msg );
27357 I := M.IndexOf( SM );
27358 if Assigned( SM.OnMeasureItem ) then
27359 M := SM;
27360 if not Assigned( M.OnMeasureItem ) then
27361 Exit;
27362 H := M.OnMeasureItem( M, I );
27363 if HiWord( H ) <> 0 then
27364 MIS.itemWidth := HiWord( H );
27365 if LoWord( H ) <> 0 then
27366 MIS.itemHeight := LoWord( H );
27367 Rslt := 1;
27368 Result := TRUE;
27369 break;
27370 end;
27371 M := M.fNextMenu;
27372 end;
27373 end;
27374 end;
27375 end;
27377 //[procedure TMenu.SetOnMeasureItem]
27378 procedure TMenu.SetOnMeasureItem( const Value: TOnMeasureItem );
27379 var C: PControl;
27380 begin
27381 FOnMeasureItem := Value;
27382 C := TopParent.FControl;
27383 if C <> nil then
27384 C.AttachProc( WndProcMeasureItem );
27385 end;
27387 //[function WndProcDrawItem]
27388 function WndProcDrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
27389 type PDrawAction = ^TDrawAction;
27390 PDrawState = ^TDrawState;
27391 var DIS: PDrawItemStruct;
27392 M, SM: PMenu;
27393 I: Integer;
27394 begin
27395 Result := FALSE;
27396 if (Msg.message = WM_DRAWITEM) and (Msg.wParam = 0) then
27397 begin
27398 DIS := Pointer( Msg.lParam );
27399 if DIS.CtlType = ODT_MENU then
27400 begin
27401 M := Pointer( Sender.fMenuObj );
27402 while M <> nil do
27403 begin
27404 SM := M.Items[ DIS.itemID ];
27405 if SM <> nil then
27406 begin
27407 I := M.IndexOf( SM );
27408 if Assigned( SM.OnDrawItem ) then
27409 M := SM;
27410 if Assigned( M.OnDrawItem ) then
27411 begin
27412 if not M.OnDrawItem( M, DIS.hDC, DIS.rcItem, I,
27413 PDrawAction( @ DIS.itemAction )^,
27414 PDrawState( @ DIS.itemState )^ ) then Exit;
27416 else Exit;
27417 Rslt := 1;
27418 Result := TRUE;
27419 break;
27420 end;
27421 M := M.fNextMenu;
27422 end;
27423 end;
27424 end;
27425 end;
27427 //[procedure TMenu.SetOnDrawItem]
27428 procedure TMenu.SetOnDrawItem( const Value: TOnDrawItem );
27429 var C: PControl;
27430 begin
27431 FOnDrawItem := Value;
27432 C := TopParent.FControl;
27433 if C <> nil then
27434 C.AttachProc( WndProcDrawItem );
27435 end;
27437 //[procedure TMenu.SetOwnerDraw]
27438 procedure TMenu.SetOwnerDraw( Value: Boolean );
27439 const Masks: array[ Boolean ] of DWORD = ( 0, $FFFFFFFF );
27440 var MII: TMenuItemInfo;
27441 begin
27442 FOwnerDraw := Value;
27443 FillChar( MII, Sizeof( MII ), 0 );
27444 MII.fMask := MIIM_TYPE;
27445 MII.dwTypeData := nil;
27446 if GetInfo( MII ) then
27447 begin
27448 MII.fType := MII.fType and not MFT_OWNERDRAW or
27449 (MFT_OWNERDRAW and Masks[ Value ]);
27450 SetTypeInfo( MII );
27451 end;
27452 end;
27454 //[function TMenu.Insert]
27455 function TMenu.Insert(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;
27456 Options: TMenuOptions): PMenu;
27457 const
27458 MenuStateFlags: array[TMenuOption] of Integer = (MFS_DEFAULT, MFS_DISABLED, MFS_CHECKED, 0, 0,
27459 MFS_DISABLED, 0, 0, 0, 0);
27460 MenuTypeFlags: array[TMenuOption] of Integer = (0, 0, 0, 0, MFT_RADIOCHECK, MFT_SEPARATOR, MFT_BITMAP, 0,
27461 MFT_MENUBREAK, MFT_MENUBARBREAK);
27462 var M: PMenu;
27463 MII: TMenuItemInfo;
27464 begin
27466 new( Result, Create );
27467 {+}{++}(*Result := PMenu.Create;*){--}
27468 Result.FVisible := TRUE;
27469 Result.FParent := @ Self;
27470 Result.FItems := NewList;
27471 Result.FIsSeparator := moSeparator in Options;
27472 if FHandle = 0 then
27473 SetSubMenu( CreatePopupMenu );
27474 M := nil;
27475 if (InsertBefore >= 0) and (InsertBefore < 4096) then
27476 begin
27477 M := Items[ InsertBefore ];
27478 if M <> nil then
27479 begin
27480 InsertBefore := M.FId;
27481 M.Parent.FItems.Insert( M.Parent.FItems.IndexOf( M ), Result );
27482 end;
27483 end;
27484 if M = nil then
27485 begin
27486 InsertBefore := -1;
27487 FItems.Add( Result );
27488 end;
27489 Result.FOnMenuItem := Event;
27491 FillChar( MII, Sizeof( MII ), 0 );
27492 MII.cbSize := MenuStructSize;
27493 MII.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE or MIIM_SUBMENU or MIIM_TYPE;
27495 MII.fState := MakeFlags( Pointer( @Options ), MenuStateFlags);
27496 MII.fType := MakeFlags( Pointer( @Options ), MenuTypeFlags);
27497 Result.FId := FDynamicMenuID;
27498 Inc( FDynamicMenuID );
27499 MII.wID := Result.FId;
27500 if moSubMenu in Options
27501 then begin
27502 Result.FHandle := CreatePopupMenu;
27503 MII.hSubMenu := Result.FHandle;
27504 end;
27505 MII.dwTypeData := ACaption;
27506 if not (moBitmap in Options) then MII.cch := StrLen( ACaption );
27507 InsertMenuItem( FHandle, InsertBefore, InsertBefore = -1,
27508 Windows.PMenuItemInfo( @ MII )^ );
27509 if moBitmap in Options then
27510 begin
27511 Result.BitmapItem := DWORD( ACaption );
27513 else
27514 Result.FCaption := ACaption;
27515 RedrawFormMenuBar;
27516 end;
27518 //[function TMenu.AddItem]
27519 function TMenu.AddItem(ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;
27520 begin
27521 Result := InsertItem( -1, ACaption, Event, Options );
27522 end;
27524 //[function TMenu.InsertItem]
27525 function TMenu.InsertItem( InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;
27526 Options: TMenuOptions): Integer;
27527 begin
27528 Result := InsertItemEx( InsertBefore, ACaption, Event, Options, FALSE );
27529 end;
27531 //[function TMenu.InsertItemEx]
27532 function TMenu.InsertItemEx(InsertBefore: Integer; ACaption: PChar;
27533 Event: TOnMenuItem; Options: TMenuOptions; ByPosition: Boolean): Integer;
27534 var M: PMenu;
27535 begin
27536 M := Insert( InsertBefore, ACaption, Event, Options );
27537 Result := M.FId;
27538 end;
27540 //[procedure TMenu.InsertSubMenu]
27541 procedure TMenu.InsertSubMenu( SubMenuToInsert: PMenu; InsertBefore: Integer );
27542 var AFlags: DWORD;
27543 M: PMenu;
27544 MII: TMenuItemInfo;
27545 begin
27546 if SubMenuToInsert.FParent <> nil then
27547 SubMenuToInsert := SubMenuToInsert.FParent.RemoveSubMenu( SubMenuToInsert.FId );
27548 if SubMenuToInsert = nil then Exit;
27550 AFlags := MF_BYPOSITION;
27551 M := nil;
27552 if (InsertBefore >= 0) and (InsertBefore < 4096) then
27553 begin
27554 M := Items[ InsertBefore ];
27555 if M = nil then
27556 InsertBefore := -1
27557 else
27558 InsertBefore := M.FId;
27559 end;
27560 if M = nil then
27561 begin
27562 FItems.Add( SubMenuToInsert );
27563 SubMenuToInsert.FParent := @ Self;
27565 else
27566 begin
27567 M.FParent.FItems.Insert( M.FParent.FItems.IndexOf( M ), SubMenuToInsert );
27568 SubMenuToInsert.FParent := M.FParent;
27569 end;
27571 if InsertBefore > 0 then
27572 AFlags := MF_BYCOMMAND;
27573 if SubMenuToInsert.FBmpItem <> 0 then
27574 InsertMenu( FHandle, InsertBefore, AFlags or MF_BITMAP or MF_POPUP, SubMenuToInsert.FHandle,
27575 PChar( SubMenuToInsert.FBmpItem ) )
27576 else
27577 InsertMenu( FHandle, InsertBefore, AFlags or MF_STRING or MF_POPUP, SubMenuToInsert.FHandle,
27578 PChar( SubMenuToInsert.Caption ) );
27579 if SubMenuToInsert.FId = 0 then
27580 begin
27581 SubMenuToInsert.FId := FDynamicMenuID;
27582 Inc( FDynamicMenuID );
27583 MII.cbSize := MenuStructSize;
27584 MII.fMask := MIIM_ID;
27585 MII.wID := SubMenuToInsert.FId;
27586 SetMenuItemInfo( SubMenuToInsert.FParent.FHandle, SubMenuToInsert.FParent.FItems.IndexOf( SubMenuToInsert ),
27587 TRUE, Windows.PMenuItemInfo( @ MII )^ );
27588 end;
27589 RedrawFormMenuBar;
27590 end;
27592 //[function TMenu.RemoveSubMenu]
27593 function TMenu.RemoveSubMenu( ItemToRemove: Integer ): PMenu;
27594 {$IFDEF DEBUG_MENU}var OK: Boolean; {$ENDIF}
27595 begin
27596 Result := Items[ ItemToRemove ];
27597 if Result = nil then Exit;
27598 if Result.FParent <> nil then
27599 {$IFDEF DEBUG_MENU} OK := {$ENDIF}
27600 RemoveMenu( Result.FParent.FHandle, Result.FId, MF_BYCOMMAND )
27601 else
27602 {$IFDEF DEBUG_MENU} OK := {$ENDIF}
27603 RemoveMenu( FHandle, Result.FId, MF_BYCOMMAND );
27604 {$IFDEF DEBUG_MENU}
27605 if not OK then
27606 ShowMessage( 'Error removing menu: ' + Int2Str( GetLastError ) + ' - ' +
27607 SysErrorMessage( GetLastError ) );
27608 {$ENDIF}
27609 if Count = 0 then
27610 begin
27611 Result.Free;
27612 Result := nil;
27613 end;
27614 RedrawFormMenuBar;
27615 end;
27617 //[procedure ClearText]
27618 procedure ClearText( Sender: PControl );
27619 begin
27620 Sender.Caption := '';
27621 end;
27623 //[procedure ClearListbox]
27624 procedure ClearListbox( Sender: PControl );
27625 begin
27626 Sender.Perform( LB_RESETCONTENT, 0, 0 );
27627 end;
27629 //[procedure ClearCombobox]
27630 procedure ClearCombobox( Sender: PControl );
27631 begin
27632 Sender.Perform( CB_RESETCONTENT, 0, 0 );
27633 end;
27635 //[procedure ClearListView]
27636 procedure ClearListView( Sender: PControl );
27637 begin
27638 Sender.Perform( LVM_DELETEALLITEMS, 0, 0 );
27639 end;
27641 //[procedure ClearToolbar]
27642 procedure ClearToolbar( Sender: PControl );
27643 begin
27644 while Sender.TBButtonCount > 0 do
27645 Sender.TBDeleteButton( Sender.TBIndex2Item( 0 ) );
27646 Sender.Perform( TB_SETBITMAPSIZE, 0, 0 );
27647 end;
27649 { -- Constructor of canvas -- }
27650 //[function NewCanvas]
27651 function NewCanvas( DC: HDC ): PCanvas;
27652 begin
27654 New( Result, Create );
27656 {++}(*
27657 Result := PCanvas.Create;
27658 *){--}
27659 Result.ModeCopy := cmSrcCopy;
27660 if DC <> 0 then
27661 begin
27662 Result.SetHandle( DC );
27663 //Result.fIsPaintDC := True; // If Canvas will be destroyed, DC will not be deleted
27664 end;
27665 end;
27666 //[END NewCanvas]
27668 { -- Contructors of controls -- }
27670 {$IFDEF ASM_VERSION}
27671 //[FUNCTION _NewTControl]
27672 function _NewTControl( AParent: PControl ): PControl;
27673 begin
27674 New( Result, CreateParented( AParent ) );
27675 end;
27676 //[END _NewTControl]
27678 //[function _NewWindowed]
27679 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;
27681 PUSH EBX
27682 PUSH ESI
27683 PUSH EDI
27685 PUSH ECX // Ctl3D
27686 PUSH EDX // ControlClassName
27688 MOV ESI, EAX // ESI = AParent
27689 CALL _NewTControl
27690 XCHG EBX, EAX // EBX = Result
27691 POP [EBX].TControl.fControlClassName
27692 INC [EBX].TControl.fWindowed
27694 INC EAX
27695 POP EDX // DL = parameter Ctl3D
27696 TEST ESI, ESI
27697 JZ @@no_parent
27699 LEA ESI, [ESI].TControl.fWndProcResizeFlicks
27700 LEA EDI, [EBX].TControl.fWndProcResizeFlicks
27701 MOVSD // fWndProcResizeFlicks
27702 MOVSD // fGotoControl
27703 //MOVSW // fDoubleBuffered, fTransparent
27704 LODSB // fCtl3Dchild
27705 STOSB
27706 DEC AL
27707 LODSB // fCtl3D
27708 JZ @@passed3D
27709 XOR EDX, EDX
27710 @@passed3D:
27711 XCHG EAX, EDX
27712 STOSB // fCtl3D
27714 MOVSD // fTextColor
27715 LODSD
27716 XCHG EDX, EAX
27717 XOR EAX, EAX
27718 PUSH EDX
27719 CALL TGraphicTool.Assign
27720 STOSD // fFont
27721 POP EDX
27722 XCHG ECX, EAX
27723 JECXZ @@no_font
27724 MOV [ECX].TGraphicTool.fParentGDITool, EDX
27725 MOV [ECX].TGraphicTool.fOnChange.TMethod.Code, offset[TControl.FontChanged]
27726 MOV [ECX].TGraphicTool.fOnChange.TMethod.Data, EBX
27727 MOV EAX, EBX
27728 MOV EDX, ECX
27729 CALL TControl.FontChanged
27730 @@no_font:
27732 MOVSD // fColor
27733 LODSD
27734 XCHG EDX, EAX
27735 XOR EAX, EAX
27736 PUSH EDX
27737 CALL TGraphicTool.Assign
27738 STOSD // fBrush
27739 POP EDX
27740 XCHG ECX, EAX
27741 JECXZ @@no_brush
27742 MOV [ECX].TGraphicTool.fParentGDITool, EDX
27743 MOV [ECX].TGraphicTool.fOnChange.TMethod.Code, offset[TControl.BrushChanged]
27744 MOV [ECX].TGraphicTool.fOnChange.TMethod.Data, EBX
27745 MOV EAX, EBX
27746 MOV EDX, ECX
27747 CALL TControl.BrushChanged
27748 @@no_brush:
27750 LODSD
27751 STOSD // fMargin
27752 STOSD // fBoundsRect.Left
27753 PUSH EAX
27754 ADD EAX, [ESI+16] // AParent.fClientTop
27755 STOSD // fBoundsRect.Top
27756 POP EAX
27757 ADD EAX, 64
27758 STOSD // fBoundsRect.Right
27759 STOSD // fBoundsRect.Bottom
27761 @@no_parent:
27762 XCHG EAX, EBX
27763 //DEC byte ptr [EAX].TControl.fAlphaBlend
27764 //INC byte ptr [EAX].TControl.fEraseUpdRgn
27765 POP EDI
27766 POP ESI
27767 POP EBX
27768 end;
27769 {$ELSE ASM_VERSION} //Pascal
27770 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;
27771 begin
27773 New( Result, CreateParented( AParent ) );
27774 {+}{++}(*Result := PControl.CreateParented( AParent );*){--}
27775 Result.fControlClassName := ControlClassName;
27776 if AParent <> nil then
27777 begin
27778 Result.fWndProcResizeFlicks := AParent.fWndProcResizeFlicks;
27779 Result.fGotoControl := AParent.fGotoControl;
27780 //Result.fDoubleBuffered := AParent.fDoubleBuffered;
27781 //Result.fTransparent := AParent.fTransparent;
27782 Result.fCtl3Dchild := AParent.fCtl3Dchild;
27783 if AParent.fCtl3Dchild then
27784 Result.fCtl3D := Ctl3D
27785 else
27786 Result.fCtl3D := False;
27787 Result.fMargin := AParent.fMargin;
27788 with Result.fBoundsRect do
27789 begin
27790 Left := AParent.fMargin + AParent.fClientLeft;
27791 Top := AParent.fMargin + AParent.fClientTop;
27792 Right := Left + 64;
27793 Bottom := Top + 64;
27794 end;
27795 Result.fTextColor := AParent.fTextColor;
27796 Result.fFont := Result.fFont.Assign( AParent.fFont );
27797 if Result.fFont <> nil then
27798 begin
27799 Result.fFont.fParentGDITool := AParent.fFont;
27800 Result.fFont.fOnChange := Result.FontChanged;
27801 Result.FontChanged( Result.fFont );
27802 end;
27803 Result.fColor := AParent.fColor;
27804 Result.fBrush := Result.fBrush.Assign( AParent.fBrush );
27805 if Result.fBrush <> nil then
27806 begin
27807 Result.fBrush.fParentGDITool := AParent.fBrush;
27808 Result.fBrush.fOnChange := Result.BrushChanged;
27809 Result.BrushChanged( Result.fBrush );
27810 end;
27811 end;
27812 //Result.fAlphaBlend := 255;
27813 //Result.fEraseUpdRgn := TRUE;
27814 end;
27815 //[END _NewWindowed]
27816 {$ENDIF ASM_VERSION}
27818 //===================== Form ========================//
27820 {$IFDEF USE_CONSTRUCTORS}
27821 //[function NewForm]
27822 function NewForm( AParent: PControl; const Caption: String ): PControl;
27823 begin
27824 new( Result, CreateForm( AParent, Caption ) );
27825 end;
27826 //[END NewForm]
27827 {$ELSE not_USE_CONSTRUCTORS}
27829 //[FUNCTION NewForm]
27830 {$IFDEF ASM_VERSION}
27831 function NewForm( AParent: PControl; const Caption: String ): PControl;
27832 const FormClass: array[ 0..4 ] of Char = ( 'F', 'o', 'r', 'm', #0 );
27834 PUSH EBX
27835 PUSH EDX
27836 MOV EDX, offset[FormClass]
27837 MOV CL, 1
27838 CALL _NewWindowed
27839 MOV EBX, EAX
27840 INC [EBX].TControl.fSizeGrip
27841 OR byte ptr [EBX].TControl.fClsStyle, CS_DBLCLKS
27842 MOV EDX, offset[WndProcForm]
27843 CALL TControl.AttachProc
27844 MOV EDX, offset[WndProcDoEraseBkgnd]
27845 MOV EAX, EBX
27846 CALL TControl.AttachProc
27847 POP EDX
27848 MOV EAX, EBX
27849 CALL TControl.SetCaption
27850 INC [EBX].TControl.fSizeGrip
27851 INC [EBX].TControl.fIsForm
27852 XCHG EAX, EBX
27853 POP EBX
27854 end;
27855 {$ELSE ASM_VERSION} //Pascal
27856 function NewForm( AParent: PControl; const Caption: String ): PControl;
27857 begin
27858 Result := _NewWindowed( AParent, 'Form', True );
27859 Result.fClsStyle := Result.fClsStyle or CS_DBLCLKS;
27860 Result.AttachProc( WndProcForm );
27861 Result.AttachProc( WndProcDoEraseBkgnd );
27862 Result.Caption := Caption;
27863 Result.fSizeGrip := TRUE;
27864 Result.fIsForm := TRUE;
27865 end;
27866 {$ENDIF ASM_VERSION}
27867 //[END NewForm]
27869 {$ENDIF USE_CONSTRUCTORS}
27871 //===================== Applet button ========================//
27873 //{$DEFINE WNDPROCAPP_USED}
27874 {$IFDEF WNDPROCAPP_USED}
27876 //[FUNCTION WndProcApp]
27877 {$IFDEF ASM_VERSION}
27878 {$IFDEF WNDPROCAPP_ASM_USED}
27879 function WndProcApp(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
27881 CMP word ptr [EDX].TMsg.message, WM_SETFOCUS
27882 JNZ @@chk_CLOSE
27883 MOV ECX, [EAX].TControl.FCurrentControl
27884 JECXZ @@ret_false
27885 XCHG EAX, ECX
27886 PUSH EAX
27887 CALL CallTControlCreateWindow
27888 POP EAX
27889 PUSH [EAX].TControl.fHandle
27890 CALL SetFocus
27891 MOV AL, 1
27893 @@chk_CLOSE:
27894 CMP word ptr [EDX].TMsg.message, WM_SYSCOMMAND
27895 JNZ @@ret_false
27896 MOV EDX, dword ptr [EDX].TMsg.wParam
27897 AND DX, $FFF0
27898 CMP DX, SC_CLOSE
27899 JNZ @@ret_false
27900 PUSH ECX
27901 MOV ECX, [EAX].TControl.fChildren
27902 JECXZ @@ret_false1
27903 XCHG EAX, ECX
27904 MOV ECX, [EAX].TList.fCount
27905 JECXZ @@ret_false1
27906 MOV EAX, [EAX].TList.fItems
27907 MOV ECX, dword ptr [EAX]
27908 JECXZ @@ret_false1
27909 XCHG EAX, ECX
27910 PUSH EAX
27911 CALL TControl.IsMainWindow
27912 TEST EAX, EAX
27913 POP EAX
27914 JZ @@ret_false1
27915 CALL TControl.Close
27916 POP ECX
27917 XOR EAX, EAX
27918 MOV dword ptr [ECX], EAX
27919 INC EAX
27920 JMP @@exit
27921 @@ret_false1:
27922 POP ECX
27923 @@ret_false:
27924 XOR EAX, EAX
27925 @@exit:
27926 end;
27927 {$ENDIF}
27928 {$ELSE ASM_VERSION} //Pascal
27929 function WndProcApp(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
27930 begin
27931 Result := False;
27932 case Msg.message of
27933 WM_SETFOCUS:
27934 {$IFDEF NEW_MODAL}
27935 if Self_.fModalForm <> nil then
27936 SetFocus( Self_.fModalForm.fHandle )
27937 else if ( Self_.FCurrentControl <> nil ) and not
27938 ( Self_.fCurrentControl.IsForm xor Self_.fIsApplet ) then
27939 {$ELSE not_NEW_MODAL}
27940 if Self_.FCurrentControl <> nil then
27941 {$ENDIF NEW_MODAL}
27942 begin
27943 Self_.FCurrentControl.CreateWindow; //virtual!!!
27944 SetFocus( Self_.FCurrentControl.fHandle );
27945 Result := True;
27946 end;
27947 WM_SYSCOMMAND:
27948 if Msg.wParam and $FFF0 = SC_CLOSE then
27949 if (Self_.fChildren <> nil) and (Self_.fChildren.fCount > 0) and
27950 PControl( Self_.fChildren.fItems[ 0 ] ).IsMainWindow then
27951 begin
27952 PControl( Self_.fChildren.fItems[ 0 ] ).Close;
27953 Rslt := 0;
27954 Result := TRUE;
27955 end;
27956 end;
27957 end;
27958 {$ENDIF ASM_VERSION}
27959 //[END WndProcApp]
27961 {$ENDIF WNDPROCAPP_USED}
27963 {$IFDEF USE_CONSTRUCTORS}
27964 {$DEFINE CREATEAPPBUTTON_USED}
27965 //[function NewApplet]
27966 function NewApplet( const Caption: String ): PControl;
27967 begin
27968 new( Result, CreateApplet( Caption ) );
27969 end;
27970 //[END NewApplet]
27971 {$ELSE not_USE_CONSTRUCTORS}
27973 //[FUNCTION NewApplet]
27974 {$IFDEF ASM_VERSION}
27975 function NewApplet( const Caption: String ): PControl;
27976 const AppClass: array[ 0..3 ] of Char = ( 'A', 'p', 'p', #0 );
27978 XOR ECX, ECX
27979 INC ECX
27980 MOV [AppButtonUsed], CL
27981 PUSH EAX
27982 MOV EDX, offset[AppClass]
27983 XOR EAX, EAX
27984 CALL _NewWindowed
27985 INC [EAX].TControl.FIsApplet
27986 MOV word ptr [EAX].TControl.fStyle + 2, $90CA //WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX or WS_CAPTION
27987 MOV byte ptr [EAX].TControl.fExStyle + 2, WS_EX_APPWINDOW shr 16 // WS_EX_APPWINDOW = $40000
27988 CALL @@newapp1
27990 // BODY of CreateAppButton here:
27991 PUSH ESI
27992 PUSH 0
27993 PUSH [EAX].TControl.fHandle
27994 CALL GetSystemMenu
27995 MOV ESI, offset[DeleteMenu]
27997 XCHG ECX, EAX
27998 MOV EAX, SC_MAXIMIZE
28001 PUSH EDX
28002 PUSH EAX
28003 PUSH ECX
28005 PUSH EDX
28006 {$IFDEF PARANOIA}
28007 DB $2C, $20
28008 {$ELSE}
28009 SUB AL, $20 // SC_MOVE
28010 {$ENDIF}
28011 PUSH EAX
28012 PUSH ECX
28014 PUSH EDX
28015 {$IFDEF PARANOIA}
28016 DB $2C, $10
28017 {$ELSE}
28018 SUB AL, $10 // SC_SIZE
28019 {$ENDIF}
28020 PUSH EAX
28021 PUSH ECX
28023 PUSH 1 // MF_GRAYED or MF_BYCOMMAND
28024 MOV AX, SC_RESTORE
28025 PUSH EAX
28026 PUSH ECX
28028 CALL EnableMenuItem
28029 CALL ESI
28030 CALL ESI
28031 CALL ESI
28032 POP ESI
28033 @@ret_false:
28034 XOR EAX, EAX
28037 @@chk_CLOSE:
28038 CMP word ptr [EDX].TMsg.message, WM_SYSCOMMAND
28039 JNZ @@ret_false
28040 MOV EDX, dword ptr [EDX].TMsg.wParam
28041 AND DX, $FFF0
28042 CMP DX, SC_CLOSE
28043 JNZ @@ret_false
28044 PUSH ECX
28045 MOV ECX, [EAX].TControl.fChildren
28046 JECXZ @@ret_false1
28047 XCHG EAX, ECX
28048 MOV ECX, [EAX].TList.fCount
28049 JECXZ @@ret_false1
28050 MOV EAX, [EAX].TList.fItems
28051 MOV ECX, dword ptr [EAX]
28052 JECXZ @@ret_false1
28053 XCHG EAX, ECX
28054 PUSH EAX
28055 CALL TControl.IsMainWindow
28056 TEST EAX, EAX
28057 POP EAX
28058 JZ @@ret_false1
28059 CALL TControl.Close
28060 POP ECX
28061 XOR EAX, EAX
28062 MOV dword ptr [ECX], EAX
28063 INC EAX
28065 @@ret_false1:
28066 POP ECX
28067 JMP @@ret_false
28069 @@newapp1:
28070 //MOV [EAX].TControl.FCreateWndExt, offset[CreateAppButton]
28071 POP [EAX].TControl.FCreateWndExt
28072 PUSH EAX
28073 CALL @@newapp2
28075 // BODY of WndProcApp here:
28076 CMP word ptr [EDX].TMsg.message, WM_SETFOCUS
28077 JNZ @@chk_CLOSE
28078 MOV ECX, [EAX].TControl.FCurrentControl
28079 JECXZ @@ret_false
28080 XCHG EAX, ECX
28082 PUSH EAX
28083 CALL CallTControlCreateWindow
28084 POP EAX
28085 PUSH [EAX].TControl.fHandle
28087 CALL SetFocus
28088 MOV AL, 1
28091 @@newapp2:
28092 POP EDX
28093 CALL TControl.AttachProc
28094 POP EAX
28095 POP EDX
28096 PUSH EAX
28097 CALL TControl.SetCaption
28098 POP EAX
28099 end;
28101 {$ELSE ASM_VERSION} //Pascal
28103 //[procedure CreateAppButton]
28104 procedure CreateAppButton( App: PControl );
28105 var M: HMenu;
28106 begin
28107 M := GetSystemMenu( App.fHandle, False );
28108 DeleteMenu( M, SC_MAXIMIZE, MF_BYCOMMAND );
28109 DeleteMenu( M, SC_MOVE, MF_BYCOMMAND );
28110 DeleteMenu( M, SC_SIZE, MF_BYCOMMAND );
28111 EnableMenuItem( M, SC_RESTORE, MF_GRAYED or MF_BYCOMMAND );
28112 end;
28114 //[function NewApplet]
28115 function NewApplet( const Caption: String ): PControl;
28116 begin
28117 AppButtonUsed := True;
28118 Result := _NewWindowed( nil, 'App', True );
28119 Result.FIsApplet := TRUE;
28120 Result.fStyle := WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX or WS_CAPTION;
28121 Result.fExStyle := WS_EX_APPWINDOW;
28122 Result.FCreateWndExt := CreateAppButton;
28123 Result.AttachProc( WndProcApp );
28124 Result.Caption := Caption;
28125 end;
28126 {$ENDIF ASM_VERSION}
28127 //[END NewApplet]
28128 {$ENDIF USE_CONSTRUCTORS}
28130 {$IFDEF CREATEAPPBUTTON_USED}
28131 procedure CreateAppButton( App: PControl );
28133 {$IFDEF F_P}
28134 MOV EAX, [App]
28135 {$ENDIF F_P}
28136 PUSH ESI
28137 PUSH 0
28138 PUSH [EAX].TControl.fHandle
28139 CALL GetSystemMenu
28140 MOV ESI, offset[DeleteMenu]
28142 XCHG ECX, EAX
28143 MOV EAX, SC_MAXIMIZE
28146 PUSH EDX
28147 PUSH EAX
28148 PUSH ECX
28150 PUSH EDX
28151 {$IFDEF PARANOIA}
28152 DB $2C, $20
28153 {$ELSE}
28154 SUB AL, $20 // SC_MOVE
28155 {$ENDIF}
28156 PUSH EAX
28157 PUSH ECX
28159 PUSH EDX
28160 {$IFDEF PARANOIA}
28161 DB $2C, $10
28162 {$ELSE}
28163 SUB AL, $10 // SC_SIZE
28164 {$ENDIF}
28165 PUSH EAX
28166 PUSH ECX
28168 PUSH 1 // MF_GRAYED or MF_BYCOMMAND
28169 MOV AX, SC_RESTORE
28170 PUSH EAX
28171 PUSH ECX
28173 CALL EnableMenuItem
28174 CALL ESI
28175 CALL ESI
28176 CALL ESI
28177 POP ESI
28178 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
28179 {$ENDIF CREATEAPPBUTTON_USED}
28181 var CtlIdCount: WORD = $8000;
28184 {$IFNDEF ASM_VERSION}
28185 //{$DEFINE CREATEPARAMS2_USED}
28186 {$ENDIF}
28187 {$IFDEF USE_CONSTRUCTORS}
28188 //{$DEFINE CREATEPARAMS2_USED}
28189 {$ENDIF}
28192 {$IFDEF CREATEPARAMS2_USED} // seems not needed more
28193 //[procedure CreateParams2]
28194 procedure CreateParams2( Self_: PControl; var Params: TCreateParams);
28195 begin
28196 Self_.CreateSubclass( Params, Self_.fControlClassName );
28197 end;
28198 {$ENDIF}
28200 //[FUNCTION _NewControl]
28201 {$IFDEF ASM_VERSION}
28202 function _NewControl( AParent: PControl; ControlClassName: PChar;
28203 Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;
28204 const szActions = sizeof(TCommandActions);
28206 PUSH EBX
28207 PUSH EAX // push AParent
28208 PUSH ECX // push Style
28209 MOVZX ECX, Ctl3D
28210 CALL _NewWindowed
28211 XCHG EBX, EAX
28212 INC [EBX].TControl.fIsControl
28213 INC [EBX].TControl.fVerticalAlign
28214 MOV EAX, Actions
28215 TEST EAX, EAX
28216 JZ @@noActions
28217 LEA EDX, [EBX].TControl.fCommandActions
28218 XOR ECX, ECX
28219 MOV CL, szActions
28220 CALL System.Move
28221 @@noActions:
28222 POP EDX // pop Style
28223 OR EDX, WS_CLIPSIBLINGS or WS_CLIPCHILDREN
28224 MOV byte ptr [EBX].TControl.fLookTabKeys, $0F
28225 CMP [EBX].TControl.fCtl3D, 0
28226 JZ @@noCtl3D
28227 AND EDX, not WS_BORDER
28228 OR byte ptr [EBX].TControl.fExStyle + 1, WS_EX_CLIENTEDGE shr 8
28229 @@noCtl3D:
28230 MOV [EBX].TControl.fStyle, EDX
28231 TEST EDX, WS_VISIBLE
28232 SETNZ AL
28233 MOV [EBX].TControl.fVisible, AL
28234 TEST EDX, WS_TABSTOP
28235 POP ECX // pop AParent
28236 PUSHFD
28237 JECXZ @@noParent
28238 MOV EAX, [ECX].TControl.fCursor
28239 MOV [EBX].TControl.fCursor, EAX
28240 XCHG EAX, ECX
28241 CALL TControl.ParentForm
28242 XCHG ECX, EAX
28243 JECXZ @@noParent
28244 INC [ECX].TControl.fTabOrder
28245 MOV EDX, [ECX].TControl.fTabOrder
28246 MOV [EBX].TControl.fTabOrder, EDX
28247 @@noParent:
28248 POPFD
28249 JZ @@noTabStop
28250 INC [EBX].TControl.fTabstop
28251 JECXZ @@noTabstop
28252 XCHG EAX, ECX
28253 MOV ECX, [EAX].TControl.FCurrentControl
28254 INC ECX
28255 LOOP @@noTabStop
28256 MOV [EAX].TControl.FCurrentControl, EBX
28257 @@noTabStop:
28258 MOVZX EDX, [CtlIdCount]
28259 INC [CtlIdCount]
28260 MOV [EBX].TControl.fMenu, EDX
28261 MOV EDX, offset[WndProcCtrl]
28262 MOV EAX, EBX
28263 CALL TControl.AttachProc
28264 XCHG EAX, EBX
28265 POP EBX
28266 end;
28267 {$ELSE ASM_VERSION} //Pascal
28268 function _NewControl( AParent: PControl; ControlClassName: PChar;
28269 Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;
28270 var Form: PControl;
28271 begin
28272 Result := _NewWindowed( AParent, ControlClassName, Ctl3D );
28273 if Actions <> nil then
28274 Result.fCommandActions := Actions^;
28275 Result.fIsControl := True;
28276 Result.fStyle := Style or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
28277 Result.fVerticalAlign := vaTop;
28278 Result.fVisible := (Style and WS_VISIBLE) <> 0;
28279 Result.fTabstop := (Style and WS_TABSTOP) <> 0;
28280 if (AParent <> nil) then
28281 begin
28282 Inc( AParent.ParentForm.fTabOrder );
28283 Result.fTabOrder := AParent.ParentForm.fTabOrder;
28284 Result.fCursor := AParent.fCursor;
28285 end;
28286 Result.fLookTabKeys := [ tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn ];
28287 if Result.fCtl3D then
28288 begin
28289 Result.fStyle := Result.fStyle and not WS_BORDER;
28290 Result.fExStyle := Result.fExStyle or WS_EX_CLIENTEDGE;
28291 end;
28292 if (Style and WS_TABSTOP) <> 0 then
28293 begin
28294 Form := Result.ParentForm;
28295 if Form <> nil then
28296 if Form.FCurrentControl = nil then
28297 Form.FCurrentControl := Result;
28298 end;
28299 //Result.fCreateParamsExt := CreateParams2;
28300 Result.fMenu := CtlIdCount;
28301 Inc( CtlIdCount );
28302 Result.AttachProc( WndProcCtrl );
28303 end;
28304 {$ENDIF ASM_VERSION}
28305 //[END _NewControl]
28307 //===================== Button ========================//
28309 //[function TControl.SetButtonIcon]
28310 function TControl.SetButtonIcon(aIcon: HIcon): PControl;
28311 var PrevImg: THandle;
28312 begin
28313 Style := Style or BS_ICON;
28314 PrevImg := Perform( BM_SETIMAGE, IMAGE_ICON, aIcon );
28315 if PrevImg <> 0 then
28316 DeleteObject( PrevImg );
28317 Result := @ Self;
28318 end;
28320 //[function TControl.SetButtonBitmap]
28321 function TControl.SetButtonBitmap(aBmp: HBitmap): PControl;
28322 var PrevImg: THandle;
28323 begin
28324 Style := Style or BS_BITMAP;
28325 PrevImg := Perform( BM_SETIMAGE, IMAGE_BITMAP, aBmp );
28326 if PrevImg <> 0 then
28327 DeleteObject( PrevImg );
28328 Result := @ Self;
28329 end;
28331 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
28332 //[function WndProcBtnReturnClick]
28333 function WndProcBtnReturnClick( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
28334 begin
28335 Result := FALSE;
28336 if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_KEYUP) or
28337 (Msg.message = WM_CHAR)) and (Msg.wParam = 13) then
28338 Msg.wParam := 32;
28339 end;
28340 {$ENDIF}
28342 {$IFDEF USE_CONSTRUCTORS}
28343 //[function NewButton]
28344 function NewButton( AParent: PControl; const Caption: String ): PControl;
28345 begin
28346 new( Result, CreateButton( AParent, Caption ) );
28347 end;
28348 {$ELSE USE_CONSTRUCTORS}
28350 {$IFDEF ASM_VERSION}
28351 const ButtonClass: array[ 0..6 ] of Char = ( 'B','U','T','T','O','N',#0 );
28352 {$ENDIF ASM_VERSION}
28354 //[FUNCTION NewButton]
28355 {$IFDEF ASM_VERSION}
28356 function NewButton( AParent: PControl; const Caption: String ): PControl;
28357 const szActions = sizeof(TCommandActions);
28359 PUSH EDX
28361 PUSH 0
28362 PUSH offset[ButtonActions]
28364 MOV EDX, offset[ButtonClass]
28365 MOV ECX, WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or WS_TABSTOP
28366 CALL _NewControl
28367 INC [EAX].TControl.fIgnoreDefault
28368 MOV EDX, [EAX].TControl.fBoundsRect.Top
28369 ADD EDX, 22
28370 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
28371 MOV [EAX].TControl.fTextAlign, taCenter
28372 INC [EAX].TControl.fIsButton
28374 POP EDX
28375 PUSH EAX
28376 CALL TControl.SetCaption
28377 POP EAX
28378 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
28379 PUSH EAX
28380 MOV EDX, offset[WndProcBtnReturnClick]
28381 CALL TControl.AttachProc
28382 POP EAX
28383 {$ENDIF}
28384 end;
28385 {$ELSE ASM_VERSION} //Pascal
28386 function NewButton( AParent: PControl; const Caption: String ): PControl;
28387 begin
28388 Result := _NewControl( AParent, 'BUTTON',
28389 WS_VISIBLE or WS_CHILD or
28390 BS_PUSHLIKE or WS_TABSTOP, False, @ButtonActions );
28391 Result.fIgnoreDefault := TRUE;
28392 Result.fCtl3D := TRUE;
28393 with Result.fBoundsRect do
28394 Bottom := Top + 22;
28395 Result.fTextAlign := taCenter;
28396 Result.Caption := Caption;
28397 Result.fIsButton := TRUE;
28398 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
28399 Result.AttachProc( WndProcBtnReturnClick );
28400 {$ENDIF}
28401 end;
28402 {$ENDIF ASM_VERSION}
28403 //[END NewButton]
28405 {$ENDIF USE_CONSTRUCTORS}
28407 //----------------- BitBtn -----------------------
28409 //[FUNCTION WndProc_DrawItem]
28410 {$IFDEF ASM_VERSION}
28411 function WndProc_DrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
28412 : Boolean;
28413 asm //cmd //opd
28414 CMP word ptr [EDX].TMsg.message, WM_DRAWITEM
28415 JNZ @@ret_false
28416 MOV EAX, [EDX].TMsg.lParam
28417 MOV ECX, [EAX].TDrawItemStruct.hwndItem
28418 JECXZ @@ret_false
28419 PUSH EDX
28420 PUSH offset[ID_SELF]
28421 PUSH ECX
28422 CALL GetProp
28423 POP EDX
28424 TEST EAX, EAX
28425 JZ @@ret_false
28426 PUSH [EDX].TMsg.lParam
28427 PUSH [EDX].TMsg.wParam
28428 PUSH CN_DRAWITEM
28429 PUSH EAX
28430 CALL TControl.Perform
28431 MOV AL, 1
28433 @@ret_false:
28434 XOR EAX, EAX
28435 end;
28436 {$ELSE ASM_VERSION} //Pascal
28437 function WndProc_DrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
28438 : Boolean;
28439 var DI: PDrawItemStruct;
28440 Control: PControl;
28441 begin
28442 Result := FALSE;
28443 if Msg.message = WM_DRAWITEM then
28444 begin
28445 DI := Pointer( Msg.lParam );
28446 Control := Pointer( GetProp( DI.hwndItem, ID_SELF ) );
28447 if Control <> nil then
28448 begin
28449 {Rslt := Integer(
28450 Control.OnDrawItem( Control, DI.hDC, DI.rcItem, DI.itemID,
28451 TDrawAction( Byte( DI.itemAction ) ),
28452 TDrawState( Word( DI.itemState ) ) ) );}
28453 Rslt := Control.Perform( CN_DRAWITEM, Msg.wParam, Msg.lParam );
28454 Result := TRUE;
28455 end;
28456 //else Rslt := 0;
28457 end;
28458 end;
28459 {$ENDIF ASM_VERSION}
28460 //[END WndProc_DrawItem]
28462 //[function ExcludeAmpersands]
28463 function ExcludeAmpersands( Self_: PControl; const S: String ): String;
28464 var I: Integer;
28465 begin
28466 Result := S;
28467 if not Self_.FBitBtnDrawMnemonic then Exit;
28468 for I := Length( Result ) downto 1 do
28469 begin
28470 if Result[ I ] = '&' then
28471 Delete( Result, I, 1 );
28472 end;
28473 end;
28475 //[procedure BitBtnExtDraw]
28476 procedure BitBtnExtDraw( Self_: PControl; DC: HDC; X, Y: Integer; const R: TRect;
28477 const CapText, CapTxtOrig: String; Color: TColor );
28478 var I, J, W, H: Integer;
28479 Sz: TSize;
28480 Pen, OldPen: HPen;
28481 begin
28482 if not Self_.FBitBtnDrawMnemonic then Exit;
28483 J := 0;
28484 for I := 1 to Length( CapTxtOrig ) do
28485 begin
28486 if CapTxtOrig[ I ] <> '&' then
28487 Inc( J )
28488 else
28489 begin
28490 Windows.GetTextExtentPoint32( DC, PChar( CapText ), J, Sz );
28491 W := Sz.cx;
28492 Windows.GetTextExtentPoint32( DC, '_', 1, Sz );
28493 H := Sz.cy - 1;
28494 Windows.GetTextExtentPoint32( DC, @ CapTxtOrig[ I + 1 ], 1, Sz );
28495 Windows.MoveToEx( DC, X + W, Y + H, nil );
28497 Pen := CreatePen( PS_SOLID, 0, Color2RGB( Color ) );
28498 OldPen := SelectObject( DC, Pen );
28500 Windows.LineTo( DC, X + W + Sz.cx, Y + H );
28502 SelectObject( DC, OldPen );
28503 DeleteObject( Pen );
28504 end;
28505 end;
28506 end;
28508 //[procedure TControl.SetBitBtnDrawMnemonic]
28509 procedure TControl.SetBitBtnDrawMnemonic(const Value: Boolean);
28510 begin
28511 FBitBtnDrawMnemonic := Value;
28512 FBitBtnGetCaption := ExcludeAmpersands;
28513 FBitBtnExtDraw := BitBtnExtDraw;
28514 Invalidate;
28515 end;
28517 //[function TControl.GetBitBtnImgIdx]
28518 function TControl.GetBitBtnImgIdx: Integer;
28519 begin
28520 Result := LoWord( fGlyphCount );
28521 end;
28523 //[procedure TControl.SetBitBtnImgIdx]
28524 procedure TControl.SetBitBtnImgIdx(const Value: Integer);
28525 begin
28526 if not( bboImageList in fBitBtnOptions ) then Exit;
28527 fGlyphCount := HiWord( fGlyphCount ) or (Value and $FFFF);
28528 Invalidate;
28529 end;
28531 //[function TControl.GetBitBtnImageList]
28532 function TControl.GetBitBtnImageList: THandle;
28533 begin
28534 Result := 0;
28535 if bboImageList in fBitBtnOptions then
28536 Result := fGlyphBitmap;
28537 end;
28539 //[procedure TControl.SetBitBtnImageList]
28540 procedure TControl.SetBitBtnImageList(const Value: THandle);
28541 begin
28542 fGlyphBitmap := Value;
28543 if Value <> 0 then
28544 begin
28545 fBitBtnOptions := fBitBtnOptions + [ bboImageList ];
28546 ImageList_GetIconSize( Value, fGlyphWidth, fGlyphHeight );
28548 else
28549 fBitBtnOptions := fBitBtnOptions - [ bboImageList ];
28550 Invalidate;
28551 end;
28553 //[FUNCTION WndProcBitBtn]
28554 {$IFDEF ASM_noVERSION} // remove &-s from view //+ TextShift & if Y < 0 then Y := 0; // + glyph + TextShift if not glyphOver
28555 function WndProcBitBtn( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
28556 const szBitmapInfo = sizeof(TBitmapInfo);
28558 CMP word ptr [EDX].TMsg.message, WM_LBUTTONDBLCLK
28559 JNZ @@noWM_LBUTTONDBLCLK
28560 PUSH ECX
28561 PUSH [EDX].TMsg.wParam
28562 PUSH [EDX].TMsg.lParam
28563 PUSH WM_LBUTTONDOWN
28564 PUSH EAX
28565 CALL TControl.Perform
28566 POP ECX
28567 MOV [ECX], EAX
28568 MOV AL, 1
28570 @@noWM_LBUTTONDBLCLK:
28571 PUSH EBX
28572 CMP [EDX].TMsg.message, CN_DRAWITEM
28573 JNZ @@noCN_DRAWITEM
28574 PUSH EDI
28575 PUSH ESI
28576 XCHG EDI, EAX // EDI = @Self
28577 MOV dword ptr [ECX], 1
28578 MOV ESI, [EDX].TMsg.lParam // ESI = DIS
28579 XOR EBX, EBX // G = 0
28580 MOV EAX, [ESI].TDrawItemStruct.itemState
28581 TEST byte ptr [EDI].TControl.fBitBtnOptions, 8 //1 shl Ord(bboFixed)
28582 JNZ @@fixed_in_options
28583 {$IFDEF PARANOIA}
28584 DB $A8, ODS_SELECTED
28585 {$ELSE}
28586 TEST AL, ODS_SELECTED
28587 {$ENDIF}
28588 JZ @@not1
28589 JMP @@1
28590 @@fixed_in_options:
28591 TEST byte ptr [EDI].TControl.fChecked, 1
28592 JZ @@not1
28593 @@1: INC EBX
28594 @@not1:
28595 {$IFDEF PARANOIA}
28596 DB $A8, ODS_DISABLED
28597 {$ELSE}
28598 TEST AL, ODS_DISABLED
28599 {$ENDIF}
28600 JZ @@not2
28601 MOV BL, 2
28602 @@not2: TEST EBX, EBX
28603 JNZ @@not3
28604 {$IFDEF PARANOIA}
28605 DB $A8, ODS_FOCUS
28606 {$ELSE}
28607 TEST AL, ODS_FOCUS
28608 {$ENDIF}
28609 JZ @@not3
28610 MOV BL, 3
28611 @@not3: CMP [EDI].TControl.fMouseInControl, BH
28612 JZ @@not4
28613 TEST EBX, EBX
28614 JZ @@4
28615 CMP BL, 3
28616 JNZ @@not4
28617 @@4: MOV BL, 4
28618 @@not4: MOV ECX, [EDI].TControl.fOnBitBtnDraw.TMethod.Code
28619 TEST ECX, ECX
28620 JZ @@noOnBitBtnDraw
28621 //JECXZ @@noOnBitBtnDraw
28622 MOV EAX, [EDI].TControl.fCanvas
28623 PUSH EAX
28624 TEST EAX, EAX
28625 JZ @@noCanvas
28626 MOV EDX, [ESI].TDrawItemStruct.hDC
28627 CALL TCanvas.SetHandle
28628 @@noCanvas:
28629 MOV EAX, [EDI].TControl.fOnBitBtnDraw.TMethod.Data
28630 MOV EDX, EDI
28631 PUSH EBX
28632 XCHG ECX, EBX
28633 CALL EBX
28634 POP EBX
28635 POP ECX // Canvas
28636 PUSH EAX
28637 JECXZ @@noCanvas2
28638 XCHG EAX, ECX
28639 XOR EDX, EDX
28640 CALL TCanvas.SetHandle
28641 @@noCanvas2:
28642 POP EAX
28643 TEST AL, AL
28644 JNZ @@exit_draw
28645 @@noOnBitBtnDraw:
28646 TEST byte ptr [EDI].TControl.fBitBtnOptions, 2 //1 shl Ord(bboNoBorder)
28647 JNZ @@noborder
28648 TEST byte ptr [ESI].TDrawItemStruct.itemState, ODS_FOCUS
28649 JZ @@noDefaultBorder
28650 PUSH BLACK_BRUSH
28651 CALL GetStockObject
28652 LEA EDX, [ESI].TDrawItemStruct.rcItem
28653 OR ECX, -1
28654 PUSH ECX
28655 PUSH ECX
28656 PUSH EDX
28657 PUSH EAX
28658 PUSH EDX
28659 PUSH [ESI].TDrawItemStruct.hDC
28660 CALL Windows.FrameRect
28661 CALL InflateRect
28662 XOR ECX, ECX
28663 JMP @@noFlat
28664 @@noDefaultBorder:
28665 MOVZX ECX, [EDI].TControl.fFlat
28666 JECXZ @@noFlat
28667 AND CL, [EDI].TControl.fMouseInControl
28668 JZ @@noborder
28669 @@noFlat:
28670 TEST byte ptr [ESI].TDrawItemStruct.itemState, ODS_SELECTED
28671 MOV CL, BDR_SUNKENOUTER or BDR_SUNKENINNER
28672 JNZ @@border_sunken
28673 MOV CL, BDR_RAISEDOUTER or BDR_RAISEDINNER
28674 @@border_sunken:
28675 LEA EDX, [ESI].TDrawItemStruct.rcItem
28676 OR EAX, -1
28677 PUSH EAX
28678 PUSH EAX
28679 PUSH EDX
28680 PUSH BF_ADJUST or BF_RECT
28681 PUSH ECX
28682 PUSH EDX
28683 PUSH [ESI].TDrawItemStruct.hDC
28684 CALL DrawEdge
28685 CALL InflateRect
28686 @@noborder:
28687 PUSH [ESI].TDrawItemStruct.rcItem.Bottom
28688 PUSH [ESI].TDrawItemStruct.rcItem.Right
28689 PUSH [ESI].TDrawItemStruct.rcItem.Top
28690 PUSH [ESI].TDrawItemStruct.rcItem.Left
28691 MOV EAX, [EDI].TControl.fGlyphWidth
28692 MOV EDX, [EDI].TControl.fGlyphHeight
28693 TEST EAX, EAX
28694 JLE @@noglyph
28695 TEST EDX, EDX
28696 JLE @@noglyph
28697 PUSH EBP
28698 MOV EBP, ESP
28699 // [EBP+4] = TxRect
28701 PUSH EDX // ImgH -> [EBP-4]
28702 PUSH EAX // ImgW -> [EBP-8]
28703 PUSH EDX // OutH -> [EBP-12]
28704 PUSH EAX // OutW -> [EBP-16]
28705 MOV EAX, [ESI].TDrawItemStruct.rcItem.Left // X = DIS.rcItem.Left
28706 MOV EDX, [ESI].TDrawItemStruct.rcItem.Top // Y = DIS.rcItem.Top
28707 MOV ECX, [ESI].TDrawItemStruct.rcItem.Bottom
28708 SUB ECX, EDX
28709 PUSH ECX // H -> [EBP-20]
28710 MOV ECX, [ESI].TDrawItemStruct.rcItem.Right
28711 SUB ECX, EAX
28712 PUSH ECX // W -> [EBP-24]
28713 MOVZX ECX, [EDI].TControl.fGlyphLayout
28714 PUSH EBX
28715 INC ECX
28716 LOOP @@noGlyphLeft
28717 MOV EBX, EAX // X
28718 ADD EBX, [EBP-16] // +OutW
28719 MOV [EBP+4].TRect.Left, EBX // TxRect.Left = X+OutW
28720 JMP @@centerY
28721 @@noGlyphLeft:
28722 LOOP @@noGlyphTop
28723 MOV EBX, EDX // Y
28724 ADD EBX, [EBP-12] // +OutH
28725 MOV [EBP+4].TRect.Top, EBX // TxRect.Top = Y+OutH
28726 LOOP @@centerX // always JMP, ECX := -1
28727 @@noGlyphTop:
28728 LOOP @@noGlyphRight
28729 MOV EAX, [ESI].TDrawItemStruct.rcItem.Right
28730 SUB EAX, [EBP-16] // -OutW -> X
28731 MOV [EBP+4].TRect.Right, EAX
28732 @@centerY:
28733 MOV EBX, [EBP-20] // H
28734 SUB EBX, [EBP-12] // -OutH
28735 JLE @@noGlyphRight
28736 SAR EBX, 1
28737 ADD EDX, EBX // Y = Y + (H-OutH)/2
28738 @@noGlyphRight:
28739 LOOP @@noGlyphBottom
28740 MOV EDX, [ESI].TDrawItemStruct.rcItem.Bottom
28741 SUB EDX, [EBP-12] // -OutH -> Y
28742 MOV [EBP+4].TRect.Bottom, EDX
28743 LOOP @@centerX // always JMP, ECX := -1
28744 @@noGlyphBottom:
28745 LOOP @@noGlyphOver
28746 @@centerX:
28747 MOV EBX, [EBP-24] // W
28748 SUB EBX, [EBP-16] // -OutW
28749 SHR EBX, 1 // /2
28750 ADD EAX, EBX // +EAX, X = X + (W-OutW)/2
28751 JECXZ @@centerY
28752 @@noGlyphOver:
28753 MOV ECX, [ESI].TDrawItemStruct.rcItem.Left
28754 CMP EAX, ECX
28755 JGE @@ok1
28756 XCHG EAX, ECX
28757 @@ok1: CMP EDX, [ESI].TDrawItemStruct.rcItem.Top
28758 {$IFDEF USE_CMOV}
28759 CMOVL EDX, [ESI].TDrawItemStruct.rcItem.Top
28760 {$ELSE}
28761 JGE @@ok2
28762 MOV EDX, [ESI].TDrawItemStruct.rcItem.Top
28763 @@ok2: {$ENDIF}
28765 MOV ECX, [ESI].TDrawItemStruct.rcItem.Right
28766 SUB ECX, EAX
28767 CMP [EBP-16], ECX
28768 JLE @@ok3
28769 MOV [EBP-16], ECX // OutW := rcItem.Right - X;
28770 @@ok3: MOV ECX, [ESI].TDrawItemStruct.rcItem.Bottom
28771 SUB ECX, EDX
28772 CMP ECX, [EBP-12]
28773 JGE @@ok4
28774 MOV [EBP-12], ECX // OutH := rcItem.Bottom - Y;
28775 @@ok4:
28776 POP EBX // EBX = G
28777 TEST byte ptr [EDI].TControl.fBitBtnOptions, 1 //1 shl Ord(bboImageList)
28778 JZ @@draw_bitmap
28779 MOVZX ECX, word ptr [EDI].TControl.fGlyphCount
28780 CMP word ptr [EDI].TControl.fGlyphCount + 2, BX
28781 JLE @@no_add_glyphIdx
28782 ADD ECX, EBX
28783 @@no_add_glyphIdx:
28784 XOR EBX, EBX
28785 PUSH ILD_TRANSPARENT // Flags = 1 (ILD_TRANSPARENT)
28786 PUSH EBX // Blend = 0
28787 PUSH -1 // Bk = CLR_NONE
28788 PUSH EBX // 0
28789 PUSH EBX // 0
28790 PUSH EDX
28791 PUSH EAX
28792 PUSH [ESI].TDrawItemStruct.hDC
28793 PUSH ECX
28794 PUSH [EDI].TControl.fGlyphBitmap
28795 CMP [EDI].TControl.fTransparent, BL
28796 JNZ @@imgl_transp
28797 MOV EAX, [EDI].TControl.fColor
28798 CALL Color2RGB
28799 MOV [ESP+32], EAX // Bk = Color2RGB(fColor)
28800 MOV [ESP+40], EBX // Flags = 0
28801 @@imgl_transp:
28802 INC EBX
28803 CMP word ptr [EDI].TControl.fGlyphCount + 2, BX
28804 JNZ @@draw_imagelist
28805 DEC byte ptr [ESP+36+3] // $FF, CLR_DEFAULT = $FF000000
28806 TEST byte ptr [ESI].TDrawItemStruct.itemState, ODS_FOCUS
28807 JZ @@draw_imagelist
28808 OR byte ptr [ESP+40], ILD_BLEND25 // Flags != 2
28809 @@draw_imagelist:
28810 CALL ImageList_DrawEx
28811 JMP @@glyph_drawn
28813 @@draw_bitmap:
28814 PUSH EAX // PlaceHold for DC
28815 PUSH EAX // PlaceHold for OldBmp
28816 PUSH SRCCOPY
28817 PUSH dword ptr [EBP-4] // ImgH
28818 PUSH dword ptr [EBP-8] // ImgW
28819 PUSH 0
28820 PUSH EAX // PlaceHold for I
28821 PUSH EAX // PlaceHold for DC
28822 PUSH dword ptr [EBP-12] // OutH
28823 PUSH dword ptr [EBP-16] // OutW
28824 PUSH EDX // Y
28825 PUSH EAX // X
28826 PUSH [ESI].TDrawItemStruct.hDC
28828 PUSH 0
28829 CALL CreateCompatibleDC
28830 MOV [ESP+48], EAX // save DC
28831 MOV [ESP+20], EAX // place DC
28832 PUSH [EDI].TControl.fGlyphBitmap
28833 PUSH EAX
28834 CALL SelectObject
28835 MOV [ESP+44], EAX // save OldBitmap
28836 XOR EAX, EAX
28837 CMP [EDI].TControl.fGlyphCount, EBX
28838 JLE @@no_incGlyIdx
28839 MOV EAX, [EBP-8] // ImgW
28840 IMUL EBX
28841 @@no_incGlyIdx:
28842 MOV [ESP+24], EAX // place I
28843 CALL StretchBlt
28844 CALL FinishDC
28846 @@glyph_drawn:
28847 MOV ESP, EBP
28848 POP EBP
28850 @@noglyph:
28851 TEST byte ptr[EDI].TControl.fBitBtnOptions, 4 //1 shl Ord(bboNoCaption)
28852 JNZ @@noCaption
28855 POP EAX
28856 PUSH EAX
28857 MOV EDX, [ESP].TRect.Right
28858 CMP EDX, EAX
28859 JLE @@noCaption
28860 MOV EDX, [ESP].TRect.Bottom
28861 CMP EDX, [ESP].TRect.Top
28862 JLE @@noCaption
28864 XOR EBX, EBX
28865 PUSH EBX // > CapText
28866 MOV EDX, ESP
28867 MOV EAX, EDI
28868 CALL TControl.GetCaption
28869 PUSH EBX // > Bk
28870 PUSH EBX // > Blend
28871 CMP [EDI].TControl.fTransparent, BL
28872 MOV BL, ETO_CLIPPED
28873 JNZ @@drwTxTransparent
28874 CMP [EDI].TControl.fGlyphLayout, glyphOver
28875 JNZ @@drwTxOpaque
28876 @@drwTxTransparent:
28877 PUSH TRANSPARENT
28878 PUSH [ESI].TDrawItemStruct.hDC
28879 CALL SetBkMode
28880 MOV [ESP+4], EAX // Bk := SetBkMode( DIS.hDC, TRANSPARENT )
28881 JMP @@drwTx1
28882 @@drwTxOpaque:
28883 MOV BL, ETO_CLIPPED or ETO_OPAQUE
28884 MOV EAX, [EDI].TControl.fColor
28885 CALL Color2RGB
28886 PUSH EAX
28887 PUSH [ESI].TDrawItemStruct.hDC
28888 CALL SetBkColor
28889 POP ECX
28890 PUSH EAX // Blend := SetBkColor(DIS.hDC,fColor)
28891 @@drwTx1:
28892 PUSH 0 // > OldFont
28893 PUSH 0 // > OldTextColor
28895 PUSH 0 // push <nil>
28896 MOV EDX, [ESP+20] // CapText
28897 CALL EDX2PChar
28898 PUSH dword ptr [EDX-4] // push Length(CapText)
28899 PUSH EDX // push PChar(CapText)
28900 LEA EAX, [ESP+32]
28901 PUSH EAX // push @TxRect
28902 PUSH EBX // push Flags
28904 MOV EBX, [ESI].TDrawItemStruct.hDC
28906 MOV ECX, [EDI].TControl.fFont
28907 JECXZ @@drwTx_noFont
28908 XCHG EAX, ECX
28909 CALL TGraphicTool.GetHandle
28910 PUSH EAX
28911 PUSH EBX
28912 CALL SelectObject
28913 MOV [ESP+24], EAX // OldFont := SelectObject...
28914 @@drwTx_noFont:
28915 MOV EAX, [EDI].TControl.fTextColor
28916 CALL Color2RGB
28917 PUSH EAX
28918 PUSH EBX
28919 CALL SetTextColor
28920 MOV [ESP+20], EAX // OldTextColor := SetTextColor...
28922 PUSH EAX
28923 PUSH EAX
28924 PUSH ESP
28925 MOV ECX, [ESP+48] // ECX = CapText
28926 XOR EAX, EAX
28927 JECXZ @@drwTx0
28928 MOV EAX, [ECX-4] // EAX = Length(CapText)
28929 @@drwTx0:
28930 PUSH EAX
28931 PUSH ECX
28932 PUSH EBX
28933 CALL GetTextExtentPoint32
28934 POP ECX // ECX = TextSz.cx
28935 POP EDX // EDX = TextSz.cy
28936 MOV EAX, [ESP+40].TRect.Bottom
28937 SUB EAX, [ESP+40].TRect.Top
28938 SUB EAX, EDX
28939 JGE @@yOk
28940 XOR EAX, EAX
28941 @@yOk: SHR EAX, 1
28942 ADD EAX, [ESP+40].TRect.Top
28943 PUSH EAX // push Y
28944 MOV EDX, [ESP+44].TRect.Right
28945 MOV EAX, [ESP+44].TRect.Left // EAX = TxRect.Left
28946 SUB EDX, EAX // EDX = W
28947 PUSH EAX
28948 CMP [EDI].TControl.fTextAlign, taRight
28949 JL @@chk_X
28950 JE @@alignR
28951 SUB ECX, EDX
28952 SAR ECX, 1
28953 JMP @@alignC
28954 @@alignR:
28955 ADD EAX, EDX
28956 @@alignC:
28957 SUB EAX, ECX
28958 @@chk_X:POP EDX
28959 CMP EAX, EDX
28960 JGE @@xOk
28961 XCHG EAX, EDX
28962 @@xOk: PUSH EAX // push X
28963 PUSH EBX // push hDC
28964 CALL ExtTextOut
28966 PUSH EBX
28967 CALL SetTextColor
28968 POP ECX
28969 JECXZ @@noRestoreFont
28970 PUSH ECX
28971 PUSH EBX
28972 CALL SelectObject
28973 @@noRestoreFont:
28974 POP ECX // Blend
28975 JECXZ @@restoreBk
28976 PUSH ECX
28977 PUSH EBX
28978 CALL SetBkColor
28979 POP ECX
28980 JMP @@delCaption
28981 @@restoreBk:
28982 PUSH EBX
28983 CALL SetBkMode
28984 @@delCaption:
28985 CALL RemoveStr
28987 @@noCaption:
28988 ADD ESP, 16
28990 @@exit_draw:
28991 POP ESI
28992 POP EDI
28993 POP EBX
28994 MOV AL, 1
28997 @@noCN_DRAWITEM:
28998 CMP word ptr [EDX].TMsg.message, WM_LBUTTONDOWN
28999 JZ @@doDown
29000 CMP word ptr [EDX].TMsg.message, WM_KEYDOWN
29001 JNZ @@noWM_LBUTTONDOWN
29002 CMP [EDX].TMsg.wParam, 32
29003 JNZ @@noWM_LBUTTONDOWN
29004 @@doDown:
29005 PUSH EDX
29006 XCHG EBX, EAX
29008 CALL @@fixed_proc
29009 MOV ECX, [EBX].TControl.fRepeatInterval
29010 JECXZ @@exit_LBUTTONDOWN
29011 //MOV EAX, EBX
29012 //CALL TControl.DoClick
29013 POP EDX
29014 PUSH EDX
29015 CMP word ptr [EDX].TMsg.message, WM_KEYDOWN
29016 JZ @@not_SetTimer
29017 PUSH 0
29018 PUSH [EBX].TControl.fRepeatInterval
29019 PUSH 1
29020 PUSH [EBX].TControl.fHandle
29021 CALL SetTimer
29022 @@exit_LBUTTONDOWN:
29023 @@not_SetTimer:
29024 POP EDX
29025 JMP @@invalidate
29027 @@noWM_LBUTTONDOWN:
29028 CMP word ptr [EDX].TMsg.message, WM_TIMER
29029 JNZ @@noWM_TIMER
29031 XCHG EBX, EAX
29032 PUSH 0
29033 PUSH 0
29034 PUSH BM_GETSTATE
29035 PUSH EBX
29036 CALL TControl.Perform
29037 {$IFDEF PARANOIA}
29038 DB $A8, 4
29039 {$ELSE}
29040 TEST AL, BST_PUSHED
29041 {$ENDIF}
29042 JNZ @@pushed
29043 PUSH 1
29044 PUSH [EBX].TControl.fHandle
29045 CALL KillTimer
29046 CALL ReleaseCapture
29047 JMP @@noWM_TIMER
29048 @@fixed_proc:
29049 TEST byte ptr [EBX].TControl.fBitBtnOptions, 8 // bboFixed
29050 JZ @@not_fixed
29051 XOR [EBX].TControl.fChecked, 1
29052 MOV ECX, [EBX].TControl.fOnChange.TMethod.Code
29053 JECXZ @@not_fixed
29054 MOV EAX, [EBX].TControl.fOnChange.TMethod.Data
29055 MOV EDX, EBX
29056 JMP ECX
29057 @@pushed:
29058 CALL @@fixed_proc
29059 MOV EAX, EBX
29060 CALL TControl.DoClick
29061 @@invalidate:
29062 XCHG EAX, EBX
29063 CALL TControl.Invalidate
29064 @@noWM_TIMER:
29065 XOR EAX, EAX
29066 POP EBX
29067 @@not_fixed:
29068 end;
29069 {$ELSE ASM_VERSION} //Pascal
29070 function WndProcBitBtn( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29071 var DIS: PDrawItemStruct;
29072 IsDown, IsDefault, IsDisabled: Boolean;
29073 Flags: Integer;
29074 X, Y, W, H, ImgW, ImgH, OutW, OutH, I, G, Bk, Blend: Integer;
29075 //BI: TBitmapInfo;
29076 //Dib: TDibSection;
29077 TxRect: TRect;
29078 OldFont: HFont;
29079 OldTextColor: TColor;
29080 CapText, CapTxtOrig: String;
29081 TextSz: TSize;
29082 DC: HDC;
29083 OldBmp: HBitmap;
29084 Handled: Boolean;
29085 //Br: HBrush;
29086 begin
29087 Result := False;
29088 if (Msg.message = WM_LBUTTONDBLCLK) then
29089 begin
29090 Rslt := Self_.Perform( WM_LBUTTONDOWN, Msg.wParam, Msg.lParam );
29091 Result := True;
29092 Exit;
29093 end;
29094 if (Msg.message = CN_DRAWITEM) then
29095 begin
29096 Result := True;
29097 Rslt := 1;
29098 DIS := Pointer( Msg.lParam );
29099 IsDown := DIS.itemState and ODS_SELECTED <> 0;
29100 IsDefault := DIS.itemState and ODS_FOCUS <> 0;
29101 IsDisabled := DIS.itemState and ODS_DISABLED <> 0;
29102 G := 0;
29103 if IsDown and not(bboFixed in Self_.fBitBtnOptions)
29104 or (bboFixed in Self_.fBitBtnOptions) and Self_.fChecked then
29105 G := 1;
29106 if IsDisabled then
29107 G := 2;
29108 if (G = 0) and IsDefault then
29109 G := 3;
29110 if ((G = 0) or (G = 3)) and Self_.MouseInControl then
29111 G := 4;
29112 if Assigned( Self_.fOnBitBtnDraw ) then
29113 begin
29114 if Assigned( Self_.fCanvas ) then
29115 Self_.fCanvas.SetHandle( DIS.hDC );
29116 Handled := Self_.fOnBitBtnDraw( Self_, G );
29117 if Assigned( Self_.fCanvas ) then
29118 Self_.fCanvas.SetHandle( 0 );
29119 if Handled then Exit;
29120 end;
29121 if not ( bboNoBorder in Self_.fBitBtnOptions ) then
29122 begin
29123 if IsDefault then
29124 begin
29125 Windows.FrameRect( DIS.hDC, DIS.rcItem, GetStockObject( BLACK_BRUSH ) );
29126 InflateRect( DIS.rcItem, -1, -1 );
29127 end;
29128 if not Self_.fFlat or Self_.fMouseInControl or IsDefault then
29129 begin
29130 if IsDown then
29131 Flags := BDR_SUNKENOUTER or BDR_SUNKENINNER
29132 else
29133 Flags := BDR_RAISEDOUTER or BDR_RAISEDINNER;
29134 DrawEdge( DIS.hDC, DIS.rcItem, Flags, BF_ADJUST or BF_RECT );
29135 InflateRect( DIS.rcItem, -1, -1 );
29136 end;
29137 end;
29138 TxRect := DIS.rcItem;
29139 if Self_.fGlyphBitmap <> 0 then
29140 begin
29141 ImgW := Self_.fGlyphWidth;
29142 ImgH := Self_.fGlyphHeight;
29143 if (ImgW > 0) and (ImgH > 0) then
29144 begin
29145 OutW := ImgW;
29146 OutH := ImgH;
29147 W := DIS.rcItem.Right - DIS.rcItem.Left;
29148 H := DIS.rcItem.Bottom - DIS.rcItem.Top;
29149 X := DIS.rcItem.Left;
29150 Y := DIS.rcItem.Top;
29151 if isDown and (Self_.fGlyphLayout <> glyphOver) then
29152 begin
29153 Inc( X, Self_.TextShiftX );
29154 Inc( Y, Self_.TextShiftY );
29155 end;
29156 case Self_.fGlyphLayout of
29157 glyphLeft:
29158 begin
29159 Y := Y + (H - OutH) div 2;
29160 TxRect.Left := X + OutW;
29161 end;
29162 glyphTop:
29163 begin
29164 X := X + (W - OutW) div 2;
29165 TxRect.Top := Y + OutH;
29166 end;
29167 glyphRight:
29168 begin
29169 X := DIS.rcItem.Right - OutW;
29170 TxRect.Right := X;
29171 Y := Y + (H - OutH) div 2;
29172 end;
29173 glyphBottom:
29174 begin
29175 Y := DIS.rcItem.Bottom - OutH;
29176 TxRect.Bottom := Y;
29177 X := X + (W - OutW) div 2;
29178 end;
29179 glyphOver:
29180 begin
29181 X := X + (W - OutW) div 2;
29182 Y := Y + (H - OutH) div 2;
29183 end;
29184 end;
29185 if X < DIS.rcItem.Left then
29186 X := DIS.rcItem.Left;
29187 if Y < DIS.rcItem.Top then
29188 Y := DIS.rcItem.Top;
29189 if X + OutW > DIS.rcItem.Right then
29190 OutW := DIS.rcItem.Right - X;
29191 if Y + OutH > DIS.rcItem.Bottom then
29192 OutH := DIS.rcItem.Bottom - Y;
29194 //Br := CreateSolidBrush( Color2RGB( Self_.fColor ) );
29195 //Windows.FillRect( DIS.hDC, MakeRect( X, DIS.rcItem.Top, X + OutW, DIS.rcItem.Bottom ), Br );
29196 //DeleteObject( Br );
29198 if bboImageList in Self_.fBitBtnOptions then
29199 begin
29200 I := LoWord( Self_.fGlyphCount );
29201 if //(HiWord( Self_.fGlyphCount ) > 1) and
29202 (HiWord( Self_.fGlyphCount ) > G) then
29203 I := I + G;
29204 Flags := 0; // ILD_NORMAL
29205 Blend := 0;
29206 if not Self_.fTransparent then
29207 Bk := Color2RGB( Self_.fColor )
29208 else
29209 begin
29210 Bk := Integer(CLR_NONE);
29211 Flags := ILD_TRANSPARENT;
29212 end;
29213 if HiWord( Self_.fGlyphCount ) = 1 then
29214 begin
29215 Blend := Integer(CLR_DEFAULT);
29216 if IsDefault then
29217 Flags := Flags or ILD_BLEND25;
29218 end;
29219 ImageList_DrawEx( Self_.fGlyphBitmap, I, DIS.hDC, X, Y, 0, 0,
29220 Bk, Blend, Flags );
29222 else
29223 begin
29224 DC := CreateCompatibleDC( 0 );
29225 OldBmp := SelectObject( DC, Self_.fGlyphBitmap );
29227 I := 0;
29228 if Self_.fGlyphCount > G then
29229 I := I + G * ImgW;
29230 StretchBlt( DIS.hDC, X, Y, OutW, OutH, DC, I, 0, ImgW, ImgH, SRCCOPY );
29232 SelectObject( DC, OldBmp );
29233 DeleteDC( DC );
29234 end;
29235 end;
29236 end;
29237 if not (bboNoCaption in Self_.fBitBtnOptions) then
29238 //if (Self_.Text <> '') then
29239 if (TxRect.Right > TxRect.Left) and (TxRect.Bottom > TxRect.Top) then
29240 begin
29241 CapText := Self_.Caption;
29242 ///////////////////////////////////////////// added 19 Nov 2001
29243 CapTxtOrig := CapText;
29244 if Assigned( Self_.FBitBtnGetCaption ) then
29245 CapText := Self_.FBitBtnGetCaption( Self_, CapText );
29246 /////////////////////////////////////////////
29248 Bk := 0;
29249 Blend := 0;
29250 Flags := ETO_CLIPPED;
29251 if Self_.fTransparent or (Self_.fGlyphLayout = glyphOver) then
29252 Bk := SetBkMode( DIS.hDC, TRANSPARENT )
29253 else
29254 begin
29255 Flags := Flags or ETO_OPAQUE;
29256 Blend := SetBkColor( DIS.hDC, Color2RGB( Self_.fColor ) );
29257 end;
29258 // Returned previous BkMode is either OPAQUE=1 or TRANSPARENT=2
29260 OldFont := 0;
29261 if assigned( Self_.fFont ) then
29262 OldFont := SelectObject( DIS.hDC, Self_.fFont.Handle );
29263 OldTextColor := SetTextColor( DIS.hDC, Color2RGB( Self_.fTextColor ) );
29265 Windows.GetTextExtentPoint32( DIS.hDC, PChar( CapText ), Length( CapText ),
29266 TextSz );
29267 W := TxRect.Right - TxRect.Left;
29268 H := TxRect.Bottom - TxRect.Top;
29269 Y := TxRect.Top + (H - TextSz.cy) div 2;
29270 case Self_.fTextAlign of
29271 taLeft: X := TxRect.Left;
29272 taCenter: X := TxRect.Left + (W - TextSz.cx) div 2;
29273 else {taRight:} X := TxRect.Right - TextSz.cx;
29274 end;
29275 if isDown then
29276 begin
29277 Inc( X, Self_.TextShiftX );
29278 Inc( Y, Self_.TextShiftY );
29279 end;
29280 if Y < 0 then
29281 Y := 0;
29282 if X < TxRect.Left then
29283 X := TxRect.Left;
29285 Windows.ExtTextOut( DIS.hDC, X, Y, Flags, @TxRect,
29286 PChar( CapText ), Length( CapText ), nil );
29288 //////////////////////////////////////////////////////////////////////////
29289 // added 19 Nov 2001 to provide underlying mnemonic characters
29290 if Assigned( Self_.FBitBtnExtDraw ) then
29291 Self_.FBitBtnExtDraw( Self_, DIS.hDC, X, Y, TxRect, CapText, CapTxtOrig,
29292 OldTextColor );
29293 //////////////////////////////////////////////////////////////////////////
29295 SetTextColor( DIS.hDC, OldTextColor );
29296 if OldFont <> 0 then
29297 SelectObject( DIS.hDC, OldFont );
29299 if Blend = 0 then
29300 SetBkMode( DIS.hDC, Bk )
29301 else
29302 SetBkColor( DIS.hDC, Blend );
29303 end;
29304 end;
29305 if (Msg.message = WM_LBUTTONDOWN) or (Msg.message = WM_KEYDOWN) and (Msg.wParam = 32) then
29306 begin
29307 if bboFixed in Self_.fBitBtnOptions then
29308 begin
29309 Self_.fChecked := not Self_.fChecked;
29310 if Assigned( Self_.fOnChange ) then
29311 Self_.fOnChange( Self_ );
29312 end;
29313 if Self_.fRepeatInterval > 0 then
29314 begin
29315 //Self_.DoClick;
29316 if Msg.message <> WM_KEYDOWN then
29317 SetTimer( Self_.fHandle, 1, Self_.fRepeatInterval, nil );
29318 Self_.Invalidate;
29319 end;
29320 end;
29322 // added 15 Aug 2002 to repaint when focus lost:
29323 if Msg.message = WM_KILLFOCUS then
29324 Self_.Invalidate;
29326 if Msg.message = WM_TIMER then
29327 begin
29328 if Self_.Perform( BM_GETSTATE, 0, 0 ) and BST_PUSHED = 0 then
29329 begin
29330 KillTimer( Self_.fHandle, 1 );
29331 ReleaseCapture;
29333 else
29334 begin
29335 if bboFixed in Self_.fBitBtnOptions then
29336 begin
29337 Self_.fChecked := not Self_.fChecked;
29338 if Assigned( Self_.fOnChange ) then
29339 Self_.fOnChange( Self_ );
29340 end;
29341 Self_.DoClick;
29342 Self_.Invalidate;
29343 end;
29344 end;
29345 end;
29346 {$ENDIF ASM_VERSION}
29347 //[END WndProcBitBtn]
29349 {$IFDEF USE_CONSTRUCTORS}
29350 //[function NewBitBtn]
29351 function NewBitBtn( AParent: PControl; const Caption: String;
29352 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap;
29353 GlyphCount: Integer ): PControl;
29354 begin
29355 new( Result, CreateBitBtn( AParent, Caption, Options, Layout, GlyphBitmap, GlyphCount ) );
29356 end;
29357 //[END NewBitBtn]
29358 {$ELSE not_USE_CONSTRUCTORS}
29360 //[FUNCTION NewBitBtn]
29361 {$IFDEF ASM_VERSION}
29362 function NewBitBtn( AParent: PControl; const Caption: String;
29363 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap; GlyphCount: Integer ): PControl;
29364 const szBitmapInfo = sizeof(TBitmapInfo);
29366 PUSH EBX
29367 PUSH EDX
29368 PUSH ECX
29370 PUSH 0
29371 PUSH offset[ButtonActions]
29372 MOV EDX, offset[ButtonClass]
29373 MOV ECX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or BS_OWNERDRAW
29374 CALL _NewControl
29375 XCHG EBX, EAX
29376 INC [EBX].TControl.fIgnoreDefault
29377 INC [EBX].TControl.fIsButton
29378 MOV byte ptr [EBX].TControl.fCommandActions.aAutoSzX, 8
29379 MOV byte ptr [EBX].TControl.fCommandActions.aAutoSzY, 8
29380 POP EAX
29381 MOV [EBX].TControl.fBitBtnOptions, AL
29382 MOVZX EDX, Layout
29383 MOV [EBX].TControl.fGlyphLayout, DL
29384 MOV ECX, GlyphBitmap
29385 MOV [EBX].TControl.fGlyphBitmap, ECX
29386 MOV EDX, [EBX].TControl.fBoundsRect.Top
29387 ADD EDX, 22
29388 MOV [EBX].TControl.fBoundsRect.Bottom, EDX
29389 TEST ECX, ECX
29390 JZ @@noGlyphWH
29391 {$IFDEF PARANOIA}
29392 DB $A8, 01
29393 {$ELSE}
29394 TEST AL, bboImageList
29395 {$ENDIF}
29396 JZ @@getBmpWH
29397 PUSH EAX
29398 MOV EAX, ESP
29399 PUSH EAX
29400 MOV EDX, ESP
29401 PUSH EAX
29402 PUSH EDX
29403 PUSH ECX
29404 CALL ImageList_GetIconSize
29405 POP EAX
29406 POP EDX
29407 MOV ECX, GlyphCount
29408 JMP @@WHready
29409 @@getBmpWH:
29410 ADD ESP, -szBitmapInfo
29411 PUSH ESP
29412 PUSH szBitmapInfo
29413 PUSH ECX
29414 CALL GetObject
29415 XCHG ECX, EAX
29416 POP EAX
29417 POP EAX
29418 POP EDX
29419 ADD ESP, szBitmapInfo-12
29420 TEST ECX, ECX
29421 JZ @@noGlyphWH
29422 MOV ECX, GlyphCount
29423 INC ECX
29424 LOOP @@GlyphCountOK
29425 PUSH EAX
29426 PUSH EDX
29427 XCHG EDX, ECX
29428 DIV ECX
29429 XCHG ECX, EAX
29430 POP EDX
29431 POP EAX
29432 @@GlyphCountOK:
29433 CMP ECX, 1
29434 JLE @@WHReady
29435 PUSH EDX
29437 IDIV ECX
29438 POP EDX
29439 @@WHReady:
29440 MOV [EBX].TControl.fGlyphWidth, EAX
29441 MOV [EBX].TControl.fGlyphHeight, EDX
29442 MOV [EBX].TControl.fGlyphCount, ECX
29443 POP ECX // ECX = @ Caption[ 1 ]
29444 PUSH ECX
29445 PUSH EDX
29446 PUSH EAX
29447 TEST EAX, EAX
29448 JLE @@noWidthResize
29449 JECXZ @@addWLeft
29450 CMP [Layout], glyphOver
29451 JE @@addWLeft
29452 MOVZX ECX, byte ptr[ECX]
29453 JECXZ @@addWLeft
29454 // else
29455 CMP [Layout], glyphLeft
29456 JZ @@addWRight
29457 CMP [Layout], glyphRight
29458 JNZ @@noWidthResize
29459 @@addWRight:
29460 ADD [EBX].TControl.fBoundsRect.Right, EAX
29461 ADD [EBX].TControl.fCommandActions.aAutoSzX, AX
29462 JMP @@noWidthResize
29463 @@addWLeft:
29464 // then
29465 ADD EAX, [EBX].TControl.fBoundsRect.Left
29466 MOV [EBX].TControl.fBoundsRect.Right, EAX
29467 MOV byte ptr [EBX].TControl.fCommandActions.aAutoSzX, 0
29468 @@noWidthResize:
29469 TEST EDX, EDX
29470 JLE @@noHeightResize
29471 CMP [Layout], glyphTop
29472 JE @@addHBottom
29473 CMP [Layout], glyphBottom
29474 JNE @@addHTop
29475 @@addHBottom:
29476 ADD [EBX].TControl.fBoundsRect.Bottom, EDX
29477 ADD [EBX].TControl.fCommandActions.aAutoSzY, DX
29478 JMP @@noHeightResize
29479 @@addHTop:
29480 ADD EDX, [EBX].TControl.fBoundsRect.Top
29481 MOV [EBX].TControl.fBoundsRect.Bottom, EDX
29482 MOV [EBX].TControl.fCommandActions.aAutoSzY, 0
29483 @@noHeightResize:
29484 POP ECX
29485 POP EAX
29487 MOV DL, 4
29488 TEST [EBX].TControl.fBitBtnOptions, 2 //1 shl bboNoBorder
29489 JNZ @@noBorderResize
29490 JECXZ @@noBorderWinc
29491 ADD [EBX].TControl.fBoundsRect.Right, EDX
29492 CMP [EBX].TControl.fCommandActions.aAutoSzX, 0
29493 JZ @@noBorderWinc
29494 ADD [EBX].TControl.fCommandActions.aAutoSzX, DX
29495 @@noBorderWinc:
29496 TEST EAX, EAX
29497 JLE @@noBorderResize
29498 ADD [EBX].TControl.fBoundsRect.Bottom, EDX
29499 CMP [EBX].TControl.fCommandActions.aAutoSzY, 0
29500 JZ @@noBorderResize
29501 ADD [EBX].TControl.fCommandActions.aAutoSzY, DX
29502 @@noBorderResize:
29503 @@noGlyphWH:
29504 MOV ECX, [EBX].TControl.fParent
29505 JECXZ @@notAttach2Parent
29506 XCHG EAX, ECX
29507 MOV EDX, offset[WndProc_DrawItem]
29508 CALL TControl.AttachProc
29509 @@notAttach2Parent:
29510 MOV EAX, EBX
29511 MOV EDX, offset[WndProcBitBtn]
29512 CALL TControl.AttachProc
29513 MOV EAX, EBX
29514 POP EDX
29515 CALL TControl.SetCaption
29516 MOV [EBX].TControl.fTextAlign, taCenter
29517 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
29518 MOV EAX, EBX
29519 MOV EDX, offset[WndProcBtnReturnClick]
29520 CALL TControl.AttachProc
29521 {$ENDIF}
29522 XCHG EAX, EBX
29523 POP EBX
29524 end;
29525 {$ELSE ASM_VERSION} //Pascal
29526 function NewBitBtn( AParent: PControl; const Caption: String;
29527 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap;
29528 GlyphCount: Integer ): PControl;
29530 B: TBitmapInfo;
29531 W, H: Integer;
29532 begin
29533 Result := _NewControl( AParent, 'BUTTON', WS_VISIBLE or WS_CHILD or
29534 WS_TABSTOP or BS_OWNERDRAW, False, @ButtonActions );
29535 Result.fIgnoreDefault := TRUE;
29536 Result.fIsButton := TRUE;
29537 Result.fCommandActions.aAutoSzX := 8;
29538 Result.fCommandActions.aAutoSzY := 8;
29539 //Result.fExStyle := Result.fExStyle and not WS_EX_CONTROLPARENT;
29540 Result.fBitBtnOptions := Options;
29541 Result.fGlyphLayout := Layout;
29542 Result.fGlyphBitmap := GlyphBitmap;
29543 with Result.fBoundsRect do
29544 begin
29545 Bottom := Top + 22;
29546 W := 0; H := 0;
29547 if GlyphBitmap <> 0 then
29548 begin
29549 if bboImageList in Options then
29550 ImageList_GetIconSize( GlyphBitmap, W, H )
29551 else
29552 begin
29553 if GetObject( GlyphBitmap, Sizeof(B), @B ) > 0 then
29554 begin
29555 W := B.bmiHeader.biWidth;
29556 H := B.bmiHeader.biHeight;
29557 if GlyphCount = 0 then
29558 GlyphCount := W div H;
29559 if GlyphCount > 1 then
29560 W := W div GlyphCount;
29561 end;
29562 end;
29563 if W > 0 then
29564 begin
29565 if (Caption = '') or (Layout = glyphOver) then
29566 begin
29567 Right := Left + W;
29568 Result.fCommandActions.aAutoSzX := 0;
29570 else
29571 if Layout in [ glyphLeft, glyphRight ] then
29572 begin
29573 Right := Right + W;
29574 Inc( Result.fCommandActions.aAutoSzX, W );
29575 end;
29576 end;
29577 if H > 0 then
29578 begin
29579 if Layout in [ glyphTop, glyphBottom ] then
29580 begin
29581 Bottom := Bottom + H;
29582 Inc( Result.fCommandActions.aAutoSzY, H );
29584 else
29585 begin
29586 Bottom := Top + H;
29587 Result.fCommandActions.aAutoSzY := 0;
29588 end;
29589 end;
29590 if not ( bboNoBorder in Options ) then
29591 begin
29592 if W > 0 then
29593 begin
29594 Inc( Right, 4 );
29595 if Result.fCommandActions.aAutoSzX > 0 then
29596 Inc( Result.fCommandActions.aAutoSzX, 4 );
29597 end;
29598 if H > 0 then
29599 begin
29600 Inc( Bottom, 4 );
29601 if Result.fCommandActions.aAutoSzY > 0 then
29602 Inc( Result.fCommandActions.aAutoSzY, 4 );
29603 end;
29604 end;
29605 end;
29606 Result.fGlyphWidth := W;
29607 Result.fGlyphHeight := H;
29608 end;
29609 Result.fGlyphCount := GlyphCount;
29610 if AParent <> nil then
29611 AParent.AttachProc( WndProc_DrawItem );
29612 Result.AttachProc( WndProcBitBtn );
29613 //Result.AttachProc( WndProcDoEraseBkgnd );
29614 Result.fTextAlign := taCenter;
29615 Result.Caption := Caption;
29616 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
29617 Result.AttachProc( WndProcBtnReturnClick );
29618 {$ENDIF}
29619 end;
29620 {$ENDIF ASM_VERSION}
29621 //[END NewBitBtn]
29623 {$ENDIF USE_CONSTRUCTORS}
29625 //===================== Check box ========================//
29627 {$IFDEF USE_CONSTRUCTORS}
29628 //[function NewCheckbox]
29629 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
29630 begin
29631 new( Result, CreateCheckbox( AParent, Caption ) );
29632 end;
29633 //[END NewCheckbox]
29634 {$ELSE not_USE_CONSTRUCTORS}
29636 //[FUNCTION NewCheckbox]
29637 {$IFDEF ASM_VERSION}
29638 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
29640 CALL NewButton
29641 MOV EDX, [EAX].TControl.fBoundsRect.Left
29642 ADD EDX, 72
29643 MOV [EAX].TControl.fBoundsRect.Right, EDX
29644 MOV [EAX].TControl.fStyle, WS_VISIBLE or WS_CHILD or BS_AUTOCHECKBOX or WS_TABSTOP
29645 MOV [EAX].TControl.fCommandActions.aAutoSzX, 24
29646 end;
29647 {$ELSE ASM_VERSION} //Pascal
29648 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
29649 begin
29650 Result := NewButton( AParent, Caption );
29651 with Result.fBoundsRect do
29652 begin
29653 Right := Left + 72;
29654 end;
29655 Result.fStyle := WS_VISIBLE or WS_CHILD or
29656 BS_AUTOCHECKBOX or WS_TABSTOP;
29657 Result.fCommandActions.aAutoSzX := 24;
29658 end;
29659 {$ENDIF ASM_VERSION}
29660 //[END NewCheckbox]
29662 {$ENDIF USE_CONSTRUCTORS}
29664 //[function NewCheckBox3State]
29665 function NewCheckBox3State( AParent: PControl; const Caption: String ): PControl;
29666 begin
29667 Result := NewCheckbox( AParent, Caption );
29668 Result.fStyle := Result.fStyle and not BS_AUTOCHECKBOX or BS_AUTO3STATE;
29669 end;
29671 //===================== Radiobox ========================//
29673 //[FUNCTION ClickRadio]
29674 {$IFDEF ASM_VERSION}
29675 procedure ClickRadio( Sender:PObj );
29677 MOV ECX, [EAX].TControl.fParent
29678 JECXZ @@exit
29679 PUSH [EAX].TControl.fMenu
29680 PUSH [ECX].TControl.fRadioLast
29681 PUSH [ECX].TControl.fRadio1st
29682 PUSH [ECX].TControl.fHandle
29683 CALL CheckRadioButton
29684 @@exit:
29685 end;
29686 {$ELSE ASM_VERSION} //Pascal
29687 procedure ClickRadio( Sender:PObj );
29688 var Self_:PControl;
29689 begin
29690 Self_ := PControl( Sender );
29691 if Self_.FParent <> nil then
29692 CheckRadioButton( Self_.fParent.fHandle,
29693 Self_.fParent.fRadio1st,
29694 Self_.fParent.fRadioLast,
29695 Self_.fMenu );
29696 end;
29697 {$ENDIF ASM_VERSION}
29698 //[END ClickRadio]
29700 {$IFDEF USE_CONSTRUCTORS}
29701 //[function NewRadiobox]
29702 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
29703 begin
29704 new( Result, CreateRadiobox( AParent, Caption ) );
29705 end;
29706 //[END NewRadiobox]
29707 {$ELSE not_USE_CONSTRUCTORS}
29709 //[FUNCTION NewRadiobox]
29710 {$IFDEF ASM_VERSION}
29711 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
29712 const
29713 RadioboxStyles = WS_VISIBLE or WS_CHILD or BS_RADIOBUTTON or
29714 WS_TABSTOP or WS_GROUP or BS_NOTIFY;
29716 PUSH EBX
29717 PUSH EAX
29718 CALL NewCheckbox
29719 XCHG EBX, EAX
29720 MOV [EBX].TControl.fStyle, RadioboxStyles
29721 MOV [EBX].TControl.fControlClick, offset[ClickRadio]
29722 POP ECX
29723 JECXZ @@exit
29724 MOV EDX, [EBX].TControl.fMenu
29725 MOV [ECX].TControl.fRadioLast, EDX
29726 MOV EAX, [ECX].TControl.fRadio1st
29727 TEST EAX, EAX
29728 JNZ @@exit
29729 MOV [ECX].TControl.fRadio1st, EDX
29730 MOV EAX, EBX
29731 CALL TControl.SetRadioChecked
29732 @@exit: XCHG EAX, EBX
29733 POP EBX
29734 end;
29735 {$ELSE ASM_VERSION} //Pascal
29736 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
29737 begin
29738 Result := NewCheckbox( AParent, Caption );
29739 Result.fStyle := WS_VISIBLE or WS_CHILD or
29740 BS_RADIOBUTTON or WS_TABSTOP or WS_GROUP or BS_NOTIFY;
29741 Result.fControlClick := ClickRadio;
29742 if AParent <> nil then
29743 begin
29744 AParent.fRadioLast := Result.fMenu;
29745 if AParent.fRadio1st = 0 then
29746 begin
29747 AParent.fRadio1st := Result.fMenu;
29748 Result.SetRadioChecked;
29749 end;
29750 end;
29751 end;
29752 {$ENDIF ASM_VERSION}
29753 //[END NewRadiobox]
29755 {$ENDIF USE_CONSTRUCTORS}
29757 //===================== Label ========================//
29759 {$IFNDEF USE_CONSTRUCTORS}
29760 {$IFDEF ASM_VERSION}
29761 const StaticClass: array[0..6]of Char=('S','T','A','T','I','C',#0);
29762 {$ENDIF ASM_VERSION}
29763 {$ENDIF USE_CONSTRUCTORS}
29765 {$IFDEF USE_CONSTRUCTORS}
29766 //[function NewLabel]
29767 function NewLabel( AParent: PControl; const Caption: String ): PControl;
29768 begin
29769 new( Result, CreateLabel( AParent, Caption ) );
29770 end;
29771 //[END NewLabel]
29772 {$ELSE not_USE_CONSTRUCTORS}
29774 //[FUNCTION NewLabel]
29775 {$IFDEF ASM_VERSION}
29776 function NewLabel( AParent: PControl; const Caption: String ): PControl;
29778 PUSH EDX
29780 PUSH 0
29781 PUSH offset[LabelActions]
29782 MOV ECX, WS_VISIBLE or WS_CHILD or SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY
29783 MOV EDX, offset[StaticClass]
29784 CALL _NewControl
29785 INC [EAX].TControl.fIsStaticControl
29786 INC [EAX].TControl.fSizeRedraw
29787 MOV EDX, [EAX].TControl.fBoundsRect.Top
29788 ADD EDX, 22
29789 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
29790 POP EDX
29791 PUSH EAX
29792 CALL TControl.SetCaption
29793 POP EAX
29794 end;
29795 {$ELSE ASM_VERSION} //Pascal
29796 function NewLabel( AParent: PControl; const Caption: String ): PControl;
29797 begin
29798 Result := _NewControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or
29799 SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY,
29800 False, @LabelActions );
29801 Result.fIsStaticControl := True;
29802 Result.fSizeRedraw := True;
29803 with Result.fBoundsRect do
29804 begin
29805 //Right := Left + 64;
29806 Bottom := Top + 22;
29807 end;
29808 Result.Caption := Caption;
29809 end;
29810 {$ENDIF ASM_VERSION}
29811 //[END NewLabel]
29813 {$ENDIF USE_CONSTRUCTORS}
29815 //===================== word wrap Label ========================//
29817 {$IFDEF USE_CONSTRUCTORS}
29818 //[function NewWordWrapLabel]
29819 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
29820 begin
29821 new( Result, CreateWordWrapLabel( AParent, Caption ) );
29822 end;
29823 //[END NewWordWrapLabel]
29824 {$ELSE not_USE_CONSTRUCTORS}
29826 //[FUNCTION NewWordWrapLabel]
29827 {$IFDEF ASM_VERSION}
29828 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
29830 CALL NewLabel
29831 MOV EDX, [EAX].TControl.fBoundsRect.Top
29832 ADD EDX, 44
29833 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
29834 INC [EAX].TControl.fWordWrap
29835 AND byte ptr [EAX].TControl.fStyle, not SS_LEFTNOWORDWRAP
29836 end;
29837 {$ELSE ASM_VERSION} //Pascal
29838 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
29839 begin
29840 Result := NewLabel( AParent, Caption );
29841 Result.fWordWrap := TRUE;
29842 with Result.fBoundsRect do
29843 begin
29844 Bottom := Top + 44;
29845 end;
29846 Result.fStyle := Result.fStyle and not SS_LEFTNOWORDWRAP;
29847 end;
29848 {$ENDIF ASM_VERSION}
29849 //[END NewWordWrapLabel]
29851 {$ENDIF USE_CONSTRUCTORS}
29853 //===================== Label Effect ========================//
29855 {$IFDEF USE_CONSTRUCTORS}
29856 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
29857 begin
29858 new( Result, CreateLabelEffect( AParent, Caption, ShadowDeep ) );
29859 end;
29860 {$ELSE not_USE_CONSTRUCTORS}
29862 //[FUNCTION NewLabelEffect]
29863 {$IFDEF ASM_VERSION}
29864 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
29866 PUSH EBX
29868 PUSH ECX
29869 PUSH EDX
29870 XOR EDX, EDX
29871 CALL NewLabel
29872 MOV EBX, EAX
29873 DEC [EBX].TControl.fIsStaticControl
29874 MOV EDX, offset[WndProcLabelEffect]
29875 CALL TControl.AttachProc
29877 //MOV EAX, EBX
29878 //CALL TControl.GetWindowHandle
29880 POP EDX
29881 MOV EAX, EBX
29882 CALL TControl.SetCaption
29884 MOV EDX, offset[WndProcDoEraseBkgnd]
29885 MOV EAX,EBX
29886 CALL TControl.AttachProc
29887 MOV [EBX].TControl.fTextAlign, taCenter
29888 MOV [EBX].TControl.fTextColor, clWindowText
29889 POP [EBX].TControl.fShadowDeep
29890 INC [EBX].TControl.fIgnoreWndCaption
29891 ADD [EBX].TControl.fBoundsRect.Bottom, 40 - 22
29892 MOV [EBX].TControl.fColor2, clNone
29894 XCHG EAX, EBX
29895 POP EBX
29896 end;
29897 {$ELSE ASM_VERSION} //Pascal
29898 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
29899 begin
29900 Result := NewLabel( AParent, '' );
29901 Result.fIsStaticControl := False;
29902 Result.AttachProc( WndProcLabelEffect );
29903 //Result.GetWindowHandle;
29904 Result.Caption := Caption;
29905 Result.AttachProc( WndProcDoEraseBkgnd );
29906 Result.fTextAlign := taCenter;
29907 Result.fTextColor := clWindowText;
29908 Result.fShadowDeep := ShadowDeep;
29909 Result.fIgnoreWndCaption := True;
29910 with Result.fBoundsRect do
29911 begin
29912 Bottom := Top + 40;
29913 end;
29914 Result.fColor2 := clNone;
29915 end;
29916 {$ENDIF ASM_VERSION}
29917 //[END NewLabelEffect]
29919 {$ENDIF USE_CONSTRUCTORS}
29921 //===================== Paint box ========================//
29923 {$IFDEF USE_CONSTRUCTORS}
29924 //[function NewPaintbox]
29925 function NewPaintbox( AParent: PControl ): PControl;
29926 begin
29927 new( Result, CreatePaintBox( AParent ) );
29928 end;
29929 {$ELSE not_USE_CONSTRUCTORS}
29931 //[FUNCTION NewPaintbox]
29932 {$IFDEF ASM_VERSION}
29933 function NewPaintbox( AParent: PControl ): PControl;
29935 XOR EDX, EDX
29936 CALL NewLabel
29937 //PUSH EAX
29938 //MOV EDX, offset[WndProcPaintBox]
29939 //CALL TControl.AttachProc
29940 //POP EAX
29941 ADD [EAX].TControl.fBoundsRect.Right, 40-64
29942 ADD [EAX].TControl.fBoundsRect.Bottom, 40-22
29943 end;
29944 {$ELSE ASM_VERSION} //Pascal
29945 function NewPaintbox( AParent: PControl ): PControl;
29946 begin
29947 Result := NewLabel( AParent, '' );
29948 //Result.AttachProc( WndProcPaintBox );
29949 with Result.fBoundsRect do
29950 begin
29951 Right := Left + 40;
29952 Bottom := Top + 40;
29953 end;
29954 end;
29955 {$ENDIF ASM_VERSION}
29956 //[END NewPaintbox]
29958 {$ENDIF USE_CONSTRUCTORS}
29960 {$IFDEF _D2}
29961 //[API SetBrushOrgEx]
29962 function SetBrushOrgEx(DC: HDC; X, Y: Integer; PrevPt: PPoint): BOOL; stdcall;
29963 external gdi32 name 'SetBrushOrgEx';
29964 {$ENDIF}
29966 //[FUNCTION WndProcDoEraseBkgnd]
29967 {$IFDEF ASM_VERSION}
29968 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29969 asm // //
29970 CMP word ptr [EDX].TMsg.message, WM_ERASEBKGND
29971 JNE @@ret_false
29972 MOV byte ptr [ECX], 1
29973 PUSH EBX
29974 PUSH EDI
29975 MOV EBX, EAX
29976 MOV EDI, [EDX].TMsg.wParam
29978 CALL TControl.CreateChildWindows
29979 CMP [EBX].TControl.fTransparent, 0
29980 JNE @@exit
29982 PUSH OPAQUE
29983 PUSH EDI
29984 CALL SetBkMode
29985 MOV EAX, [EBX].TControl.fColor
29986 CALL Color2RGB
29987 PUSH EAX
29988 PUSH EDI
29989 CALL SetBkColor
29990 XOR EAX, EAX
29991 PUSH EAX
29992 PUSH EAX
29993 PUSH EAX
29994 PUSH EDI
29995 CALL SetBrushOrgEx
29996 SUB ESP, 16
29997 PUSH ESP
29998 PUSH [EBX].TControl.fHandle
29999 CALL GetClientRect
30000 MOV EAX, EBX
30001 CALL dword ptr[Global_GetCtlBrushHandle]
30002 MOV EDX, ESP
30003 PUSH EAX
30004 PUSH EDX
30005 PUSH EDI
30006 CALL Windows.FillRect
30007 ADD ESP, 16
30008 @@exit: POP EDI
30009 POP EBX
30010 @@ret_false:
30011 XOR EAX, EAX
30012 end;
30013 {$ELSE ASM_VERSION PAS_VERSION}
30014 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30015 var DC: HDC;
30016 R: TRect;
30017 begin
30018 Result := FALSE;
30019 if Msg.message = WM_ERASEBKGND then
30020 begin
30021 Self_.CreateChildWindows;
30022 if Self_.Transparent then Exit;
30023 DC := Msg.wParam;
30024 SetBkMode( DC, OPAQUE );
30025 SetBkColor( DC, Color2RGB( Self_.fColor ) );
30026 SetBrushOrgEx( DC, 0, 0, nil );
30027 GetClientRect( Self_.fHandle, R );
30028 Windows.FillRect( DC, R, Global_GetCtlBrushHandle( Self_ ) );
30029 Rslt := 1;
30030 end;
30031 end;
30032 {$ENDIF ASM_VERSION}
30033 //[END WndProcDoEraseBkgnd]
30035 //[function WndProcImageShow]
30036 function WndProcImageShow( Sender: PControl; var Msg: TMsg;
30037 var Rslt: Integer ): Boolean;
30038 var PaintStruct: TPaintStruct;
30039 IL: PImageList;
30040 OldPaintDC: HDC;
30041 begin
30042 Result := FALSE;
30043 if (Msg.message = WM_PAINT) or (Msg.message = WM_PRINT) then
30044 begin
30045 OldPaintDC := Sender.fPaintDC;
30046 Sender.fPaintDC := Msg.wParam;
30047 if Sender.fPaintDC = 0 then
30048 Sender.fPaintDC := BeginPaint( Sender.fHandle, PaintStruct );
30049 //fOnPaint( Self_, fPaintDC );
30050 IL := Sender.ImageListNormal;
30051 if IL <> nil then
30052 begin
30053 IL.Draw( Sender.fCurIndex, Sender.fPaintDC, 0, 0 );
30054 Result := TRUE;
30055 end;
30056 if Msg.wParam = 0 then
30057 EndPaint( Sender.fHandle, PaintStruct );
30058 Sender.fPaintDC := OldPaintDC;
30059 Rslt := 0;
30060 //Result := True;
30061 Exit;
30062 end;
30063 end;
30065 //[function NewImageShow]
30066 function NewImageShow( AParent: PControl; AImgList: PImageList;
30067 ImgIdx: Integer ): PControl;
30068 var W, H: Integer;
30069 begin
30070 Result := NewLabel( AParent, '' );
30071 Result.ImageListNormal := AImgList;
30072 Result.AttachProc( WndProcImageShow );
30073 Result.AttachProc( WndProcDoEraseBkgnd );
30074 W := 32; H := 32;
30075 if AImgList <> nil then
30076 begin
30077 W := AImgList.ImgWidth;
30078 H := AImgList.ImgHeight;
30079 end;
30080 with Result.fBoundsRect do
30081 begin
30082 Right := Left + W;
30083 Bottom := Top + H;
30084 end;
30085 end;
30086 //[END NewImageShow]
30088 //===================== Scrollbar ========================//
30089 const
30090 KSB_INITIALIZE = WM_USER + 10000;
30091 KSB_KEY = $3232;
30093 //[function WndProcScrollBar]
30094 function WndProcScrollBar( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30095 begin
30096 Result := False;
30097 case Msg.message of
30098 WM_CREATE:
30099 PostMessage(Sender.Handle, KSB_INITIALIZE, KSB_KEY, KSB_KEY);
30101 KSB_INITIALIZE:
30102 if (Msg.wParam = Msg.lParam) and (Msg.wParam = KSB_KEY) then
30103 begin
30104 Sender.SBPageSize := Sender.fSBPageSize;
30105 Sender.SBMinMax := Sender.fSBMinMax;
30106 Sender.SBPosition := Sender.fSBPosition;
30107 end;
30108 end;
30109 end;
30110 //[END WndProcScrollBar]
30112 //[function WndProcScrollBarParent]
30113 function WndProcScrollBarParent( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30115 Bar: PControl;
30116 SI: TScrollInfo;
30117 NewPos: Integer;
30118 AllowChange: Boolean;
30119 Cmd: Word;
30121 begin
30122 Result := False;
30123 case Msg.message of
30124 WM_HSCROLL, WM_VSCROLL:
30125 if (Msg.lParam <> 0) then begin
30126 Bar := Pointer(GetProp(Msg.lParam, ID_SELF));
30127 if (Bar <> nil) then begin
30128 FillChar(SI, SizeOf(SI), 0);
30129 SI.cbSize := SizeOf(SI);
30130 SI.fMask := SIF_RANGE or SIF_POS or SIF_TRACKPOS or SIF_PAGE;
30131 Bar.SBGetScrollInfo(SI);
30133 Cmd := Msg.wParam and $0000FFFF;
30134 case Cmd of
30135 SB_BOTTOM: NewPos := SI.nMax;
30136 SB_TOP: NewPos := SI.nMin;
30137 SB_LINEDOWN: NewPos := SI.nPos + 1;
30138 SB_LINEUP: NewPos := SI.nPos - 1;
30139 SB_PAGEDOWN: NewPos := SI.nPos + Integer(SI.nPage);
30140 SB_PAGEUP: NewPos := SI.nPos - Integer(SI.nPage);
30141 SB_THUMBTRACK: NewPos := SI.nTrackPos;
30142 else
30143 Exit;
30144 end;
30146 if (NewPos > SI.nMax - Integer(SI.nPage) + 1) then
30147 NewPos := SI.nMax - Integer(SI.nPage) + 1;
30148 if (NewPos < SI.nMin) then
30149 NewPos := SI.nMin;
30151 AllowChange := True;
30152 if Assigned(Bar.OnSBBeforeScroll) then
30153 Bar.OnSBBeforeScroll(Bar, SI.nPos, NewPos, Cmd, AllowChange);
30154 if AllowChange then
30155 SI.nPos := NewPos
30156 else
30157 SI.nTrackPos := SI.nPos;
30158 Bar.fSBPosition := SI.nPos;
30159 Bar.fSBPosition := Bar.SBSetScrollInfo(SI);
30160 if AllowChange and Assigned(Bar.OnSBScroll) then
30161 Bar.OnSBScroll(Bar, Cmd);
30162 end;
30163 end;
30164 end;
30165 end;
30166 //[END WndProcScrollBarParent]
30168 //[function NewScrollBar]
30169 function NewScrollBar( AParent: PControl; BarSide: TScrollerBar ): PControl;
30170 const SBS_Directions: array[ TScrollerBar ] of DWORD = ( SBS_HORZ or SBS_BOTTOMALIGN,
30171 SBS_VERT or SBS_RIGHTALIGN );
30172 begin
30173 Result := _NewCommonControl(
30174 AParent,
30175 'SCROLLBAR',
30176 WS_VISIBLE or WS_CHILD or SBS_Directions[ BarSide ],
30177 False,
30180 Result.DetachProc(WndProcCtrl);
30181 Result.fLookTabKeys := [tkTab];
30182 Result.AttachProc(WndProcScrollBar);
30183 AParent.AttachProc(WndProcScrollBarParent);
30184 end;
30185 //[END NewScrollBar]
30187 //===================== Scrollbox ========================//
30188 //[function WndProcScrollBox]
30189 function WndProcScrollBox( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30190 var Bar: DWORD;
30191 SI: TScrollInfo;
30192 OldNotifyProc: pointer;
30193 begin
30195 case Msg.message of
30196 WM_HSCROLL: Bar := SB_HORZ;
30197 WM_VSCROLL: Bar := SB_VERT;
30198 WM_SIZE: begin
30199 if Assigned( Sender.fNotifyChild ) then
30200 Sender.fNotifyChild( Sender, nil );
30201 Result := FALSE;
30202 Exit;
30203 end;
30204 else begin
30205 Result := FALSE;
30206 Exit;
30207 end;
30208 end;
30210 SI.cbSize := Sizeof( SI );
30211 SI.fMask := SIF_RANGE or SIF_POS or SIF_PAGE or
30212 {$IFDEF F_P}$10{$ELSE}SIF_TRACKPOS{$ENDIF};
30213 {$IFDEF _D2}
30214 GetScrollInfo( Sender.fHandle, Bar, SI );
30215 {$ELSE}
30216 GetScrollInfo( Sender.fHandle, Bar, SI );
30217 {$ENDIF}
30218 SI.fMask := SIF_POS;
30219 case LoWord( Msg.wParam ) of
30220 SB_BOTTOM: SI.nPos := SI.nMax;
30221 SB_TOP: SI.nPos := SI.nMin;
30222 SB_LINEDOWN: Inc( SI.nPos, Sender.FScrollLineDist[ Bar ] );
30223 SB_LINEUP: Dec( SI.nPos, Sender.FScrollLineDist[ Bar ] );
30224 SB_PAGEDOWN: Inc( SI.nPos, Max( SI.nPage, 1 ) );
30225 SB_PAGEUP: Dec( SI.nPos, Max( SI.nPage, 1 ) );
30226 SB_THUMBTRACK:SI.nPos := SI.nTrackPos;
30227 end;
30228 if SI.nPos > SI.nMax { - Integer( SI.nPage ) } then
30229 SI.nPos := SI.nMax { - Integer( SI.nPage ) };
30230 if SI.nPos < SI.nMin then
30231 SI.nPos := SI.nMin;
30232 SetScrollInfo( Sender.fHandle, Bar, SI, TRUE );
30234 if Assigned( Sender.fScrollChildren ) then
30235 begin
30236 OldNotifyProc := @ Sender.fNotifyChild;
30237 Sender.fNotifyChild := nil;
30238 Sender.fScrollChildren( Sender );
30239 Sender.fNotifyChild := OldNotifyProc;
30240 end;
30242 SetScrollInfo( Sender.fHandle, Bar, SI, TRUE );
30243 Result := FALSE;
30244 end;
30245 //[END WndProcScrollBox]
30247 //[function NewScrollBox]
30248 function NewScrollBox( AParent: PControl; EdgeStyle: TEdgeStyle;
30249 Bars: TScrollerBars ): PControl;
30250 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 );
30251 var SBFlag: Integer;
30252 begin
30253 SBFlag := EdgeStyles[ EdgeStyle ];
30254 if sbHorizontal in Bars then
30255 SBFlag := SBFlag or WS_HSCROLL;
30256 if sbVertical in Bars then
30257 SBFlag := SBFlag or WS_VSCROLL;
30259 Result := _NewControl( AParent, 'ScrollBox', WS_VISIBLE or WS_CHILD or
30260 SBFlag, EdgeStyle = esLowered, nil );
30261 Result.AttachProc( WndProcForm ); //!!!
30262 Result.AttachProc( WndProcScrollBox );
30263 Result.AttachProc( WndProcDoEraseBkgnd );
30264 Result.fIsControl := TRUE;
30265 end;
30266 //[END NewScrollBox]
30268 //[function WndProcNotifyParentAboutResize]
30269 function WndProcNotifyParentAboutResize( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30270 var P: PControl;
30271 begin
30272 if (Msg.message = WM_SIZE) or (Msg.message = WM_MOVE) or (Msg.message = CM_SHOW) then
30273 begin
30274 P := Sender.Parent;
30275 if P <> nil then
30276 if Assigned( P.fNotifyChild ) then
30277 P.fNotifyChild( P, nil );
30279 else
30280 if Msg.message = WM_SHOWWINDOW then
30281 PostMessage( Sender.fHandle, CM_SHOW, 0, 0 );
30282 Result := FALSE;
30283 end;
30285 //[procedure CalcMinMaxChildren]
30286 procedure CalcMinMaxChildren( Self_: PControl; var SzR: TRect );
30287 var I: Integer;
30288 C: PControl;
30289 R: TRect;
30290 begin
30291 Szr := MakeRect( 0, 0, 0, 0 );
30292 for I := 0 to Self_.fChildren.fCount - 1 do
30293 begin
30294 C := Self_.fChildren.fItems[ I ];
30295 if C.ToBeVisible then
30296 begin
30297 R := C.BoundsRect;
30298 if (SzR.Left = SzR.Right) or (R.Left < SzR.Left) or (R.Right > SzR.Right) then
30299 begin
30300 if SzR.Left = SzR.Right then
30301 begin
30302 SzR.Left := R.Left;
30303 SzR.Right := R.Right;
30305 else
30306 begin
30307 if R.Left < SzR.Left then SzR.Left := R.Left;
30308 if R.Right > SzR.Right then SzR.Right := R.Right;
30309 end;
30310 end;
30311 if (SzR.Top = SzR.Bottom) or (R.Top < SzR.Top) or (R.Bottom > SzR.Bottom) then
30312 begin
30313 if SzR.Top = SzR.Bottom then
30314 begin
30315 SzR.Top := R.Top;
30316 SzR.Bottom := R.Bottom;
30318 else
30319 begin
30320 if R.Top < SzR.Top then SzR.Top := R.Top;
30321 if R.Bottom > SzR.Bottom then SzR.Bottom := R.Bottom;
30322 end;
30323 end;
30324 end;
30325 end;
30326 Dec( SzR.Left, Self_.Border );
30327 Inc( SzR.Right, Self_.Border - 1 );
30328 Dec( SzR.Top, Self_.Border );
30329 Inc( SzR.Bottom, Self_.Border - 1 );
30330 end;
30332 //[procedure NotifyScrollBox]
30333 procedure NotifyScrollBox( Self_, Child: PControl );
30334 var SI: TScrollInfo;
30336 procedure GetSetScrollInfo( SBar: DWORD; WH, R_RightBottom, SzR_LeftTop, SzR_RightBottom: Integer );
30337 var OldPos: Double;
30338 begin
30339 OldPos := 0;
30340 if not GetScrollInfo( Self_.fHandle, SBar, SI ) then
30341 begin
30342 SI.nMin := 0;
30343 SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );
30345 else
30346 begin
30347 if SI.nMax > SI.nMin then
30348 begin
30349 OldPos := (SI.nPos - SI.nMin) / (SI.nMax - SI.nMin);
30350 SI.nMin := 0;
30351 SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );
30352 if SzR_LeftTop < 0 then
30353 SI.nMax := Max( R_RightBottom - SzR_LeftTop - 1, WH - 1 );
30355 else
30356 begin
30357 SI.nMin := 0;
30358 SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );
30359 end;
30360 end;
30361 SI.nPos := SI.nMin + Round( (SI.nMax - SI.nMin) * OldPos );
30362 SI.nPage := R_RightBottom;
30363 SetScrollInfo( Self_.fHandle, SBar, SI, TRUE );
30364 end;
30366 var W, H: Integer;
30367 SzR: TRect;
30368 R: TRect;
30369 begin
30370 if Assigned( Child ) then
30371 begin
30372 Child.AttachProc( WndProcNotifyParentAboutResize );
30373 Exit;
30374 end;
30375 CalcMinMaxChildren( Self_, SzR );
30376 W := SzR.Right - SzR.Left;
30377 H := SzR.Bottom - SzR.Top;
30379 R := Self_.ClientRect;
30380 if (R.Right = 0) or (R.Bottom = 0) then Exit; // for case when form is minimized
30381 SI.cbSize := sizeof( SI );
30382 SI.fMask := SIF_RANGE or SIF_PAGE or SIF_POS;
30384 GetSetScrollInfo( SB_HORZ, W, R.Right, SzR.Left, SzR.Right );
30385 GetSetScrollInfo( SB_VERT, H, R.Bottom, SzR.Top, SzR.Bottom );
30387 end;
30389 //[procedure ScrollChildren]
30390 procedure ScrollChildren( _Self_: PControl );
30391 var SzR, R: TRect;
30392 I, Xpos, Ypos: Integer;
30393 OldNotifyProc: Pointer;
30394 C: PControl;
30395 DeltaX, DeltaY: Integer;
30397 begin
30399 CalcMinMaxChildren( _Self_, SzR );
30400 Xpos := GetScrollPos( _Self_.fHandle, SB_HORZ );
30401 Ypos := GetScrollPos( _Self_.fHandle, SB_VERT );
30403 DeltaX := -Xpos - SzR.Left;
30404 DeltaY := -Ypos - SzR.Top;
30406 if (DeltaX <> 0) or (DeltaY <> 0) then
30407 begin
30409 OldNotifyProc := @ _Self_.fNotifyChild;
30410 _Self_.fNotifyChild := nil;
30412 for I := 0 to _Self_.fChildren.fCount - 1 do
30413 begin
30414 C := _Self_.fChildren.fItems[ I ];
30415 R := C.BoundsRect;
30416 OffsetRect( R, DeltaX, DeltaY );
30417 C.BoundsRect := R;
30418 end;
30420 _Self_.fNotifyChild := OldNotifyProc;
30421 CalcMinMaxChildren( _Self_, R );
30422 if //(SzR.Left <> R.Left) or (SzR.Top <> R.Top) or
30423 //(Szr.Right <> R.Right) or (SzR.Bottom <> R.Bottom)
30424 ((SzR.Right - SzR.Left) <> (R.Right - R.Left)) or
30425 ((SzR.Bottom - SzR.Top) <> (R.Bottom - R.Top))
30426 then
30427 if Assigned( _Self_.fNotifyChild ) then
30428 _Self_.fNotifyChild( _Self_, nil );
30430 end;
30432 end;
30434 //[function NewScrollBoxEx]
30435 function NewScrollBoxEx( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
30436 begin
30437 Result := NewScrollBox( AParent, EdgeStyle, [ ] );
30438 Result.fNotifyChild := NotifyScrollBox;
30439 Result.fScrollChildren := ScrollChildren;
30440 Result.FScrollLineDist[ 0 ] := 16;
30441 Result.FScrollLineDist[ 1 ] := 16;
30442 end;
30444 //[function WndProcOnScroll]
30445 function WndProcOnScroll( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30446 var Bar: TScrollerBar;
30447 begin
30448 Bar := sbHorizontal; //0
30449 if Msg.message = WM_VSCROLL then
30450 Bar := sbVertical
30451 else
30452 if Msg.message <> WM_HSCROLL then
30453 begin
30454 Result := FALSE;
30455 Exit;
30456 end;
30458 if Assigned( Sender.OnScroll ) then
30459 Sender.OnScroll( Sender, Bar, LoWord( Msg.wParam ), HiWord( Msg.wParam ) );
30460 Result := FALSE;
30461 end;
30463 //[procedure TControl.SetOnScroll]
30464 procedure TControl.SetOnScroll(const Value: TOnScroll);
30465 begin
30466 FOnScroll := Value;
30467 AttachProc( @ WndProcOnScroll );
30468 end;
30470 //===================== Groupbox ========================//
30472 {$IFDEF USE_CONSTRUCTORS}
30473 //[function NewGroupbox]
30474 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
30475 begin
30476 new( Result, CreateGroupbox( AParent, Caption ) );
30477 end;
30478 //[END NewGroupbox]
30479 {$ELSE not_USE_CONSTRUCTORS}
30481 //[FUNCTION NewGroupbox]
30482 {$IFDEF ASM_VERSION}
30483 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
30485 PUSH EDX
30486 PUSH 0
30487 PUSH offset[ButtonActions]
30488 MOV EDX, offset[ButtonClass]
30489 MOV ECX, WS_VISIBLE or WS_CHILD or BS_GROUPBOX or WS_TABSTOP or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or WS_GROUP
30490 CALL _NewControl
30491 OR [EAX].TControl.fExStyle, WS_EX_CONTROLPARENT
30492 ADD [EAX].TControl.fBoundsRect.Right, 100-64
30493 ADD [EAX].TControl.fBoundsRect.Bottom, 100-22
30494 ADD [EAX].TControl.fClientTop, 22
30495 XOR EDX, EDX
30496 MOV [EAX].TControl.fTabstop, DL
30497 MOV DL, 2
30498 ADD [EAX].TControl.fClientBottom, EDX
30499 ADD [EAX].TControl.fClientLeft, EDX
30500 ADD [EAX].TControl.fClientRight, EDX
30501 POP EDX
30502 PUSH EAX
30503 CALL TControl.SetCaption
30504 POP EAX
30505 PUSH EAX
30506 MOV EDX, offset[WndProcDoEraseBkgnd]
30507 CALL TControl.AttachProc
30508 POP EAX
30509 end;
30510 {$ELSE ASM_VERSION} //Pascal
30511 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
30512 begin
30513 Result := _NewControl( AParent, 'BUTTON',
30514 WS_CHILD or
30515 WS_CLIPSIBLINGS or
30516 WS_CLIPCHILDREN or
30517 WS_TABSTOP or
30518 WS_VISIBLE or
30519 BS_NOTIFY or
30520 BS_GROUPBOX
30521 or WS_GROUP,
30522 FALSE, @ ButtonActions );
30523 Result.fExStyle := Result.fExStyle or WS_EX_CONTROLPARENT;
30524 Result.Caption := Caption;
30525 with Result.fBoundsRect do
30526 begin
30527 Right := Left + 100;
30528 Bottom := Top + 100;
30529 end;
30530 Result.fClientTop := 22;
30531 Result.fClientBottom := 2;
30532 Result.fClientLeft := 2;
30533 Result.fClientRight := 2;
30534 Result.fTabstop := False;
30535 Result.AttachProc( WndProcDoEraseBkgnd );
30536 end;
30537 {$ENDIF ASM_VERSION}
30538 //[END NewGroupbox]
30540 {$ENDIF USE_CONSTRUCTORS}
30542 //===================== Panel ========================//
30544 {$IFDEF USE_CONSTRUCTORS}
30545 //[function NewPanel]
30546 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
30547 begin
30548 new( Result, CreatePanel( AParent, EdgeStyle ) );
30549 end;
30550 //[END NewPanel]
30551 {$ELSE not_USE_CONSTRUCTORS}
30553 //[FUNCTION NewPanel]
30554 {$IFDEF ASM_VERSION}
30555 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
30557 PUSH EDX
30558 MOV EDX, offset[StaticClass]
30559 MOV ECX, WS_VISIBLE or WS_CHILD or SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY
30560 PUSH 0
30561 PUSH offset[LabelActions]
30562 CALL _NewControl
30563 ADD [EAX].TControl.fBoundsRect.Right, 100-64
30564 ADD [EAX].TControl.fBoundsRect.Bottom, 100-64
30565 OR byte ptr [EAX].TControl.fExStyle+2, 1
30566 POP ECX
30567 CMP CL, 1
30568 JG @@exit
30569 JE @@sunken
30570 OR byte ptr [EAX].TControl.fStyle+2, $40
30572 @@sunken:
30573 OR byte ptr [EAX].TControl.fStyle+1, $10
30574 @@exit:
30575 end;
30576 {$ELSE ASM_VERSION} //Pascal
30577 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
30578 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 );
30579 begin
30580 Result := _NewControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or SS_NOTIFY or
30581 SS_LEFTNOWORDWRAP or SS_NOPREFIX, False, @LabelActions );
30582 with Result.fBoundsRect do
30583 begin
30584 Right := Left + 100;
30585 Bottom := Top + 100;
30586 end;
30587 Result.Style := Result.Style or Edgestyles[ EdgeStyle ];
30588 Result.ExStyle := Result.fExStyle or WS_EX_CONTROLPARENT;
30589 Result.fVerticalAlign := vaTop;
30590 end;
30591 {$ENDIF ASM_VERSION}
30592 //[END NewPanel]
30594 {$ENDIF USE_CONSTRUCTORS}
30596 //===================== Splitter ==============================//
30598 //{$DEFINE USE_ASM_DODRAG}
30600 {$IFNDEF USE_ASM_DODRAG}
30601 {$DEFINE USE_PAS_DODRAG}
30602 {$ENDIF}
30603 {$IFNDEF ASM_VERSION}
30604 {$DEFINE USE_PAS_DODRAG}
30605 {$ENDIF}
30606 {$IFDEF USE_PAS_DODRAG}
30607 //[procedure DoDrag]
30608 procedure DoDrag( Self_: PControl; Cancel: Boolean );
30609 var NewSize1, NewSize2: Integer;
30610 MousePos: TPoint;
30611 R: TRect;
30612 Prev: PControl;
30613 I, M : Integer;
30614 begin
30615 if Self_.fDragging then
30616 begin
30617 I := Self_.fParent.fChildren.IndexOf( Self_ );
30618 Prev := Self_;
30619 if I > 0 then
30620 Prev := Self_.FParent.fChildren.fItems[ I - 1 ];
30621 GetCursorPos( MousePos );
30622 if Cancel then
30623 MousePos := Self_.fSplitStartPos;
30624 M := 1;
30625 if Self_.FAlign in [ caRight, caBottom ] then
30626 M := -1;
30627 if Self_.FAlign in [ caTop, caBottom ] then
30628 begin
30629 NewSize1 := (MousePos.y - Self_.fSplitStartPos.y)* M
30630 + Self_.fSplitStartSize;
30631 NewSize2 := Self_.fParent.ClientHeight - NewSize1
30632 - Self_.fBoundsRect.Bottom + Self_.fBoundsRect.Top
30633 - Self_.fParent.fMargin * 4;
30634 if Self_.fSecondControl <> nil then
30635 begin
30636 NewSize2 := Self_.fSecondControl.fBoundsRect.Bottom
30637 - Self_.fSecondControl.fBoundsRect.Top;
30638 if Self_.fSecondControl.FAlign = caClient then
30639 NewSize2 := Self_.fSplitStartPos2.y
30640 - (MousePos.y - Self_.fSplitStartPos.y)* M
30641 - Self_.fParent.fMargin * 4;
30642 end;
30644 else
30645 begin
30646 NewSize1 := (MousePos.x - Self_.fSplitStartPos.x)* M
30647 + Self_.fSplitStartSize;
30648 NewSize2 := Self_.fParent.ClientWidth - NewSize1
30649 - Self_.fBoundsRect.Right + Self_.fBoundsRect.Left
30650 - Self_.fParent.fMargin * 4;
30651 if Self_.fSecondControl <> nil then
30652 begin
30653 NewSize2 := Self_.fSecondControl.fBoundsRect.Right
30654 - Self_.fSecondControl.fBoundsRect.Left;
30655 if Self_.fSecondControl.FAlign = caClient then
30656 NewSize2 := Self_.fSplitStartPos2.x
30657 - (MousePos.x - Self_.fSplitStartPos.x)* M
30658 - Self_.fParent.Margin * 4;
30659 end;
30660 end;
30661 if {(Self_.fSplitMinSize1 <> 0) and} (NewSize1 < Self_.fSplitMinSize1) then
30662 begin
30663 Dec( NewSize2, Self_.fSplitMinSize1 - NewSize1 );
30664 NewSize1 := Self_.fSplitMinSize1;
30665 end;
30666 if {(Self_.fSplitMinSize2 <> 0) and} (NewSize2 < Self_.fSplitMinSize2) then
30667 begin
30668 Dec( NewSize1, Self_.fSplitMinSize2 - NewSize2 );
30669 NewSize2 := Self_.fSplitMinSize2;
30670 end;
30671 //if Self_.fSplitMinSize1 <> 0 then
30672 if NewSize1 < Self_.fSplitMinSize1 then Exit;
30673 //if Self_.fSplitMinSize2 <> 0 then
30674 if NewSize2 < Self_.fSplitMinSize2 then Exit;
30675 if assigned( Self_.fOnSplit ) then
30676 if not Self_.fOnSplit( Self_, NewSize1, NewSize2 ) then Exit;
30677 R := Prev.BoundsRect;
30678 case Self_.FAlign of
30679 caTop: R.Bottom := R.Top + NewSize1;
30680 caBottom: R.Top := R.Bottom - NewSize1;
30681 caRight: R.Left := R.Right - NewSize1;
30682 else R.Right := R.Left + NewSize1;
30683 end;
30684 Prev.BoundsRect := R;
30685 Global_Align( Self_.fParent );
30686 end;
30687 end;
30688 {$ENDIF}
30690 const
30691 chkLeft=2;
30692 chkTop=4;
30693 chkRight=8;
30694 chkBott=16;
30696 {$DEFINE USE!_ASM_DODRAG}
30698 //[FUNCTION WndProcSplitter]
30699 {$IFDEF ASM_VERSION}
30700 function WndProcSplitter( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30702 CMP word ptr [EDX].TMsg.message, WM_NCHITTEST
30703 JNE @@noWM_NCHITTEST
30704 PUSH ECX
30705 PUSH [EDX].TMsg.lParam
30706 PUSH [EDX].TMsg.wParam
30707 PUSH [EDX].TMsg.message
30708 PUSH [EAX].TControl.fHandle
30709 CALL DefWindowProc
30710 TEST EAX, EAX
30711 JLE @@htReady
30712 XOR EAX, EAX
30713 INC EAX
30714 @@htReady:
30715 POP ECX
30716 MOV [ECX], EAX
30717 MOV AL, 1
30720 @@noWM_NCHITTEST:
30721 PUSH EBX
30722 XCHG EBX, EAX
30723 CMP word ptr [EDX].TMsg.message, WM_MOUSEMOVE
30724 JNE @@noWM_MOUSEMOVE
30726 PUSH [EBX].TControl.fCursor
30727 CALL Windows.SetCursor
30729 XOR EDX, EDX
30731 {$IFDEF USE_ASM_DODRAG}
30732 CALL @@DoDrag
30733 {$ELSE}
30734 MOV EAX, EBX
30735 CALL DoDrag
30736 {$ENDIF}
30738 POP EBX
30741 {$IFDEF USE_ASM_DODRAG}
30742 @@DoDrag:
30743 PUSHAD
30744 MOVZX EDI, DL // EDI = 1 if Cancel, 0 otherwise
30745 CMP [EBX].TControl.fDragging, 0
30746 JZ @@e_DoDrag
30747 MOV EAX, [EBX].TControl.fParent
30748 MOV EAX, [EAX].TControl.fChildren
30749 PUSH EAX
30750 MOV EDX, EBX
30751 CALL TList.IndexOf
30752 POP EDX // EDX = Self_.fParent.fChildren:PList
30753 MOV EBP, EBX // Prev := Self_;
30754 TEST EAX, EAX
30755 JLE @@noPrev
30756 MOV EDX, [EDX].TList.fItems
30757 MOV EBP, [EDX+EAX*4-4] // Prev = Self_.fParent.fChildren.fItems[I-1]
30758 PUSH EBP // push Prev
30759 @@noPrev:
30760 PUSH EDX
30761 PUSH EDX
30762 PUSH ESP
30763 CALL GetCursorPos
30764 DEC EDI
30765 JNZ @@noCancel
30766 POP EDX
30767 POP EDX
30768 PUSH [EBX].TControl.fSplitStartPos.y
30769 PUSH [EBX].TControl.fSplitStartPos.x
30770 @@noCancel:
30771 OR EDI, -1
30772 MOV CL, [EBX].TControl.fAlign
30773 MOV AL, 1
30774 SHL EAX, CL
30775 {$IFDEF PARANOIA}
30776 DB $A8, chkRight or chkBott
30777 {$ELSE}
30778 TEST AL, chkRight or chkBott //fAlign in [ caRight, caBottom ] ?
30779 {$ENDIF}
30780 JNZ @@mReady
30781 INC EDI
30782 INC EDI
30783 @@mReady:
30784 MOV EDX, [EBX].TControl.fParent
30785 MOV EBP, [EDX].TControl.fMargin
30786 NEG EBP
30787 {$IFDEF PARANOIA}
30788 DB $A8, chkTop or chkBott
30789 {$ELSE}
30790 TEST AL, chkTop or chkBott // fAlign in [ caTop, caBottom ] ?
30791 {$ENDIF}
30792 XCHG EAX, EDX
30793 JZ @@noTopBottom
30795 CALL TControl.GetClientHeight
30796 XCHG EDX, EAX
30798 POP EAX
30799 POP ESI // MousePos.y
30800 MOV EAX, ESI
30801 PUSH EDX // Self_.fParent.ClientHeight
30802 SUB EAX, [EBX].TControl.fSplitStartPos.y
30803 IMUL EAX, EDI
30804 ADD EAX, [EBX].TControl.fSplitStartSize // EAX = NewSize1
30806 POP EDX
30807 SUB EDX, EAX
30808 SUB EDX, [EBX].TControl.fBoundsRect.Bottom
30809 ADD EDX, [EBX].TControl.fBoundsRect.Top
30810 LEA EDX, [EDX+EBP*4]
30812 MOV ECX, [EBX].TControl.fSecondControl
30813 JECXZ @@noSecondControl
30814 MOV EDX, [ECX].TControl.fBoundsRect.Bottom
30815 SUB EDX, [ECX].TControl.fBoundsRect.Top
30816 CMP [ECX].TControl.fAlign, caClient
30817 JNZ @@noSecondControl
30819 PUSH EAX
30820 MOV EAX, [EBX].TControl.fSplitStartPos.y
30821 SUB EAX, ESI
30822 IMUL EAX, EDI
30823 ADD EAX, [EBX].TControl.fSplitStartPos2.y
30824 LEA EDX, [EAX+EBP*4]
30825 POP EAX
30827 @@noSecondControl:
30828 JMP @@newSizesReady
30830 @@noTopBottom:
30831 CALL TControl.GetClientWidth
30832 XCHG EDX, EAX
30834 POP ESI // MousePos.x
30835 POP ECX
30836 MOV EAX, ESI
30837 PUSH EDX // Self_.fParent.ClientWidth
30838 SUB EAX, [EBX].TControl.fSplitStartPos.x
30839 IMUL EAX, EDI
30840 ADD EAX, [EBX].TControl.fSplitStartSize // EAX = NewSize1
30842 POP EDX
30843 SUB EDX, EAX
30844 SUB EDX, [EBX].TControl.fBoundsRect.Right
30845 ADD EDX, [EBX].TControl.fBoundsRect.Left
30846 LEA EDX, [EDX+EBP*4]
30848 MOV ECX, [EBX].TControl.fSecondControl
30849 JECXZ @@newSizesReady
30850 MOV EDX, [ECX].TControl.fBoundsRect.Right
30851 SUB EDX, [ECX].TControl.fBoundsRect.Left
30852 CMP [ECX].TControl.fAlign, caClient
30853 JNZ @@noSecondControl
30855 PUSH EAX
30856 MOV EAX, [EBX].TControl.fSplitStartPos.x
30857 SUB EAX, ESI
30858 IMUL EAX, EDI
30859 ADD EAX, [EBX].TControl.fSplitStartPos2.x
30860 LEA EDX, [EAX+EBP*4]
30861 POP EAX
30863 @@newSizesReady:
30864 MOV ECX, [EBX].TControl.fSplitMinSize1
30865 //JECXZ @@noCheckMinSize1
30866 SUB ECX, EAX
30867 JLE @@noCheckMinSize1
30868 SUB EDX, ECX
30869 ADD EAX, ECX
30871 @@noCheckMinSize1:
30872 MOV ECX, [EBX].TControl.fSplitMinSize2
30873 //JECXZ @@noCheckMinSize2
30874 SUB ECX, EDX
30875 JLE @@noCheckMinSize2
30876 SUB EAX, ECX
30877 ADD EDX, ECX
30879 @@noCheckMinSize2:
30880 MOV ECX, [EBX].TControl.fOnSplit.TMethod.Code
30881 JECXZ @@noOnSplit
30882 PUSHAD
30883 PUSH EDX
30884 MOV ESI, ECX
30885 XCHG ECX, EAX
30886 MOV EDX, EBX
30887 MOV EAX, [EBX].TControl.fOnSplit.TMethod.Data
30888 CALL ESI
30889 TEST AL, AL
30890 POPAD
30891 JZ @@e_DoDrag
30893 @@noOnSplit:
30894 XCHG ESI, EAX // NewSize1 -> ESI
30895 //MOV EDI, EDX // NewSize2 -> EDI
30896 POP EBP
30897 ADD ESP, -16
30898 MOV EAX, EBP
30899 MOV EDX, ESP
30900 CALL TControl.GetBoundsRect
30901 MOVZX ECX, [EBX].TControl.fAlign
30902 LOOP @@noPrev_caLeft
30903 ADD ESI, [ESP].TRect.Left
30904 MOV [ESP].TRect.Right, ESI
30905 @@noPrev_caLeft:
30906 LOOP @@noPrev_caTop
30907 ADD ESI, [ESP].TRect.Top
30908 MOV [ESP].TRect.Bottom, ESI
30909 @@noPrev_caTop:
30910 LOOP @@noPrev_caRight
30911 MOV EAX, [ESP].TRect.Right
30912 SUB EAX, ESI
30913 MOV [ESP].TRect.Left, EAX
30914 @@noPrev_caRight:
30915 LOOP @@noPrev_caBottom
30916 MOV EAX, [ESP].TRect.Bottom
30917 SUB EAX, ESI
30918 MOV [ESP].TRect.Top, EAX
30919 @@noPrev_caBottom:
30920 MOV EAX, EBP
30921 MOV EDX, ESP
30922 CALL TControl.SetBoundsRect
30923 ADD ESP, 16
30924 MOV EAX, [EBX].TControl.fParent
30925 //PUSH EAX
30926 CALL dword ptr[Global_Align]
30927 //POP EAX
30928 //CALL TControl.Update
30930 @@e_DoDrag:
30931 POPAD
30933 {$ENDIF USE_ASM_DODRAG}
30935 @@noWM_MOUSEMOVE:
30936 CMP word ptr [EDX].TMsg.message, WM_LBUTTONDOWN
30937 JNE @@noWM_LBUTTONDOWN
30938 MOV ECX, [EBX].TControl.fParent
30939 TEST ECX, ECX
30940 JZ @@noWM_LBUTTONDOWN
30941 //JECXZ @@noWM_LBUTTONDOWN
30943 MOV EAX, [ECX].TControl.fChildren
30944 PUSH EAX
30945 MOV EDX, EBX
30946 CALL TList.IndexOf
30947 POP ECX
30948 MOV EDX, EBX
30949 TEST EAX, EAX
30950 JLE @@noParent1
30951 MOV ECX, [ECX].TList.fItems
30952 MOV EDX, [ECX+EAX*4-4]
30953 @@noParent1:
30955 MOV CL, [EBX].TControl.fAlign
30956 MOV AL, 1
30957 SHL EAX, CL
30958 {$IFDEF PARANOIA}
30959 DB $A8, chkTop or chkBott
30960 {$ELSE}
30961 TEST AL, chkTop or chkBott // fAlign in [caTop,caBottom] ?
30962 {$ENDIF}
30963 XCHG EAX, EDX
30964 JZ @@no_caTop_caBottom
30965 CALL TControl.GetHeight
30966 JMP @@caTop_caBottom
30967 @@no_caTop_caBottom:
30968 CALL TControl.GetWidth
30969 @@caTop_caBottom:
30970 MOV [EBX].TControl.fSplitStartSize, EAX
30971 MOV ECX, [EBX].TControl.fSecondControl
30972 JECXZ @@noSecondControl1
30973 XCHG EAX, ECX
30974 PUSH EAX
30975 CALL TControl.GetWidth
30976 MOV [EBX].TControl.fSplitStartPos2.x, EAX
30977 POP EAX
30978 CALL TControl.GetHeight
30979 MOV [EBX].TControl.fSplitStartPos2.y, EAX
30980 @@noSecondControl1:
30981 PUSH [EBX].TControl.fHandle
30982 CALL SetCapture
30983 OR [EBX].TControl.fDragging, 1
30984 PUSH 0
30985 PUSH 100
30986 PUSH $7B
30987 PUSH [EBX].TControl.fHandle
30988 CALL SetTimer
30989 LEA EAX, [EBX].TControl.fSplitStartPos
30990 PUSH EAX
30991 CALL GetCursorPos
30992 JMP @@exit
30994 @@noWM_LBUTTONDOWN:
30995 CMP word ptr [EDX].TMsg.message, WM_LBUTTONUP
30996 JNE @@noWM_LBUTTONUP
30997 XOR EDX, EDX
30999 {$IFDEF USE_ASM_DODRAG}
31000 CALL @@DoDrag
31001 {$ELSE}
31002 MOV EAX, EBX
31003 CALL DoDrag
31004 {$ENDIF}
31006 JMP @@killtimer
31008 @@noWM_LBUTTONUP:
31009 CMP word ptr[EDX].TMsg.message, WM_TIMER
31010 JNE @@exit
31011 CMP [EBX].TControl.fDragging, 0
31012 JE @@exit
31013 PUSH VK_ESCAPE
31014 CALL GetAsyncKeyState
31015 TEST EAX, EAX
31016 JGE @@exit
31018 MOV DL, 1
31020 {$IFDEF USE_ASM_DODRAG}
31021 CALL @@DoDrag
31022 {$ELSE}
31023 MOV EAX, EBX
31024 CALL DoDrag
31025 {$ENDIF}
31027 @@killtimer:
31028 MOV [EBX].TControl.fDragging, 0
31029 PUSH $7B
31030 PUSH [EBX].TControl.fHandle
31031 CALL KillTimer
31032 CALL ReleaseCapture
31034 @@exit:
31035 POP EBX
31036 XOR EAX, EAX
31037 end;
31038 {$ELSE ASM_VERSION} //Pascal
31039 function WndProcSplitter( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31040 var I: Integer;
31041 Prev: PControl;
31043 procedure FinDrag;
31044 begin
31045 KillTimer( Self_.fHandle, $7B );
31046 Self_.fDragging := False;
31047 ReleaseCapture;
31048 end;
31049 begin
31050 case Msg.message of
31051 WM_NCHITTEST:
31052 begin
31053 Rslt := DefWindowProc( Self_.fHandle, Msg.message, Msg.wParam, Msg.lParam );
31054 if Rslt > 0 then
31055 Rslt := HTCLIENT;
31056 Result := True;
31057 Exit;
31058 end;
31059 WM_MOUSEMOVE:
31060 begin
31061 Windows.SetCursor( Self_.fCursor );
31062 DoDrag( Self_, False );
31063 end;
31064 WM_LBUTTONDOWN:
31065 begin
31066 if Self_.fParent <> nil then
31067 begin
31068 I := Self_.fParent.fChildren.IndexOf( Self_ );
31069 Prev := Self_;
31070 if I > 0 then
31071 Prev := Self_.FParent.fChildren.fItems[ I - 1 ];
31072 if Self_.fAlign in [ caTop, caBottom ] then
31073 Self_.fSplitStartSize := Prev.Height
31074 else
31075 Self_.fSplitStartSize := Prev.Width;
31076 if Self_.fSecondControl <> nil then
31077 Self_.fSplitStartPos2 :=
31078 MakePoint( Self_.fSecondControl.Width, Self_.fSecondControl.Height );
31079 SetCapture( Self_.fHandle );
31080 Self_.fDragging := True;
31081 SetTimer( Self_.fHandle, $7B, 100, nil );
31082 GetCursorPos( Self_.fSplitStartPos );
31083 end;
31084 end;
31085 WM_LBUTTONUP:
31086 begin
31087 DoDrag( Self_, False );
31088 FinDrag;
31089 end;
31090 WM_TIMER:
31091 if Self_.fDragging and (GetAsyncKeyState( VK_ESCAPE ) < 0) then
31092 begin
31093 DoDrag( Self_, True );
31094 FinDrag;
31095 end;
31096 end;
31097 Result := False;
31098 end;
31099 {$ENDIF ASM_VERSION}
31100 //[END WndProcSplitter]
31102 //[function NewSplitter]
31103 function NewSplitter( AParent: PControl; MinSizePrev, MinSizeNext: Integer ): PControl;
31104 begin
31105 Result := NewSplitterEx( AParent, MinSizePrev, MinSizeNext, esLowered );
31106 end;
31107 //[END NewSplitter]
31109 {$IFDEF USE_CONSTRUCTORS}
31110 //[function NewSplitterEx]
31111 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
31112 EdgeStyle: TEdgeStyle ): PControl;
31113 begin
31114 new( Result, CreateSplitter( AParent, MinSizePrev, MinSizeNext, EdgeStyle ) );
31115 end;
31116 //[END NewSplitterEx]
31117 {$ELSE not_USE_CONSTRUCTORS}
31119 //[FUNCTION NewSplitterEx]
31120 {$IFDEF ASM_VERSION}
31121 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
31122 EdgeStyle: TEdgeStyle ): PControl;
31123 const int_IDC_SIZEWE = integer( IDC_SIZEWE );
31125 PUSH EBX
31126 PUSH EAX // AParent
31127 PUSH ECX // MinSizePrev
31128 PUSH EDX // MinSizeNext
31129 MOV DL, EdgeStyle
31130 CALL NewPanel
31131 XCHG EBX, EAX
31132 POP [EBX].TControl.fSplitMinSize1
31133 POP [EBX].TControl.fSplitMinSize2
31134 XOR EDX, EDX
31135 MOV DL, 4
31136 MOV EAX, [EBX].TControl.fBoundsRect.Left
31137 ADD EAX, EDX
31138 MOV [EBX].TControl.fBoundsRect.Right, EAX
31139 ADD EDX, [EBX].TControl.fBoundsRect.Top
31140 MOV [EBX].TControl.fBoundsRect.Bottom, EDX
31142 POP ECX // ECX = AParent
31143 JECXZ @@noParent2
31144 MOV EAX, [ECX].TControl.fChildren
31145 MOV ECX, [EAX].TList.fCount
31146 CMP ECX, 1
31147 JLE @@noParent2
31149 MOV EAX, [EAX].TList.fItems
31150 MOV EAX, [EAX+ECX*4-8]
31151 MOV CL, [EAX].TControl.fAlign
31152 PUSH ECX
31153 MOV AL, 1
31154 SHL EAX, CL
31155 {$IFDEF PARANOIA}
31156 DB $A8, chkTop or chkBott
31157 {$ELSE}
31158 TEST AL, chkTop or chkBott
31159 {$ENDIF}
31160 MOV EAX, int_IDC_SIZEWE
31161 JZ @@TopBottom
31162 INC EAX
31163 @@TopBottom:
31164 PUSH EAX
31165 PUSH 0
31166 CALL LoadCursor
31167 MOV [EBX].TControl.fCursor, EAX
31168 POP EDX
31169 MOV EAX, EBX
31170 CALL TControl.SetAlign
31172 @@noParent2:
31173 MOV EAX, EBX
31174 MOV EDX, offset[WndProcSplitter]
31175 CALL TControl.AttachProc
31176 XCHG EAX, EBX
31177 POP EBX
31178 end;
31179 {$ELSE ASM_VERSION} //Pascal
31180 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
31181 EdgeStyle: TEdgeStyle ): PControl;
31182 var PrevCtrl: PControl;
31183 Sz0: Integer;
31184 begin
31185 Result := NewPanel( AParent, EdgeStyle );
31186 Result.fSplitMinSize1 := MinSizePrev;
31187 Result.fSplitMinSize2 := MinSizeNext;
31188 Sz0 := 4;
31189 with Result.fBoundsRect do
31190 begin
31191 Right := Left + Sz0;
31192 Bottom := Top + Sz0;
31193 end;
31194 if AParent <> nil then
31195 begin
31196 if AParent.fChildren.fCount > 1 then
31197 begin
31198 PrevCtrl := AParent.fChildren.fItems[ AParent.fChildren.fCount - 2 ];
31199 case PrevCtrl.FAlign of
31200 caLeft, caRight:
31201 begin
31202 Result.fCursor := LoadCursor( 0, IDC_SIZEWE );
31203 end;
31204 caTop, caBottom:
31205 begin
31206 Result.fCursor := LoadCursor( 0, IDC_SIZENS );
31207 end;
31208 end;
31209 Result.Align := PrevCtrl.FAlign;
31210 end;
31211 end;
31212 Result.AttachProc( WndProcSplitter );
31213 end;
31214 {$ENDIF ASM_VERSION}
31215 //[END NewSplitterEx]
31217 {$ENDIF USE_CONSTRUCTORS}
31219 //===================== MDI client window control =============//
31221 //[procedure DestroyMDIChildren]
31222 procedure DestroyMDIChildren( Form: PControl );
31223 var MDIClient: PControl;
31224 I: Integer;
31225 Ch: PControl;
31226 begin
31227 //Form.fDefWndProc := nil;
31228 MDIClient := Form.fMDIClient;
31229 MDIClient.fMDIDestroying := TRUE;
31230 if MDIClient = nil then Exit;
31231 if MDIClient.fMDIChildren <> nil then
31232 for I := MDIClient.fMDIChildren.Count - 1 downto 0 do
31233 begin
31234 Ch := MDIClient.fMDIChildren.fItems[ I ];
31235 if Ch.fHandle <> 0 then
31236 MDIClient.Perform( WM_MDIDESTROY, Ch.fHandle, 0 );
31237 end;
31238 MDIClient.fMDIChildren.Free;
31239 MDIClient.fMDIChildren := nil;
31240 if Form.fMenu <> 0 then
31241 begin
31242 MDIClient.Perform( WM_MDISETMENU, 0, 0 );
31243 MDIClient.Perform( WM_MDIREFRESHMENU, 0, 0 );
31244 DrawMenuBar( Form.fHandle );
31245 Form.fMenuObj.Free;
31246 Form.fMenuObj := nil;
31247 end;
31248 Form.fMDIClient := nil;
31249 MDIClient.Free;
31250 end;
31252 //[function ProcMDIAccel]
31253 function ProcMDIAccel( Applet: PControl; var Msg: TMsg ): Boolean;
31254 var Form: PControl;
31255 begin
31256 Result := FALSE;
31257 if (Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST) then
31258 begin
31259 Form := Applet.ActiveControl;
31260 if Form <> nil then
31261 begin
31262 if Form.IsMDIChild then
31263 Form := Form.Parent;
31264 Form := Form.ParentForm;
31265 if (Form <> nil) and (Form.MDIClient <> nil) then
31266 Result := TranslateMDISysAccel( Form.MDIClient.fHandle, Msg );
31267 end;
31268 end;
31269 end;
31271 //[function CallDefFrameProc]
31272 function CallDefFrameProc( Wnd: HWnd; Msg: Integer; wParam, lParam: Integer ): Integer;
31273 stdcall;
31274 var Form: PControl;
31275 begin
31276 Form := Pointer( GetProp( Wnd, ID_SELF ) );
31277 if Form <> nil then
31278 Form := Form.ParentForm;
31279 if (Form <> nil) and (Form.fMDIClient <> nil) then
31280 Result := DefFrameProc( Wnd, Form.fMDIClient.fHandle, Msg, wParam, lParam )
31281 else
31282 Result := DefWindowProc( Wnd, Msg, wParam, lParam );
31283 end;
31285 //[function WndFuncMDIClient]
31286 function WndFuncMDIClient( Wnd: HWnd; Msg, wParam, lParam: Integer ): Integer;
31287 stdcall;
31288 var C: PControl;
31289 M: TMsg;
31290 begin
31291 C := Pointer( GetProp( Wnd, ID_SELF ) );
31292 if C <> nil then
31293 begin
31294 M.hwnd := Wnd;
31295 M.message := Msg;
31296 M.wParam := wParam;
31297 M.lParam := lParam;
31298 Result := C.WndProc( M );
31300 else
31301 Result := DefWindowProc( Wnd, Msg, wParam, lParam );
31302 end;
31304 //[function ShowMDIClientEdge]
31305 function ShowMDIClientEdge( MDIClient: PControl ): Boolean;
31306 var ShowEdge: Boolean;
31307 I: Integer;
31308 Ch: PControl;
31309 ExStyle: Integer;
31310 begin
31311 Result := FALSE;
31312 ShowEdge := TRUE;
31313 if MDIClient.fMDIChildren.Count > 0 then
31314 for I := 0 to MDIClient.fMDIChildren.Count-1 do
31315 begin
31316 Ch := MDIClient.fMDIChildren.fItems[ I ];
31317 if IsZoomed( Ch.fHandle ) then
31318 begin
31319 ShowEdge := FALSE;
31320 break;
31321 end;
31322 end;
31323 ExStyle := MDIClient.ExStyle;
31324 if ShowEdge then
31325 if ExStyle and WS_EX_CLIENTEDGE = 0 then
31326 ExStyle := ExStyle or WS_EX_CLIENTEDGE
31327 else
31328 Exit
31329 else if ExStyle and WS_EX_CLIENTEDGE <> 0 then
31330 ExStyle := ExStyle and not WS_EX_CLIENTEDGE
31331 else
31332 Exit;
31333 MDIClient.ExStyle := ExStyle;
31334 Result := TRUE;
31335 end;
31337 //[function WndProcMDIClient]
31338 function WndProcMDIClient( MDIClient: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31339 {var I: Integer;
31340 Ch: PControl;}
31341 begin
31342 if not MDIClient.fMDIDestroying then
31343 case Msg.message of
31344 $3f:
31345 begin
31346 PostMessage( MDIClient.fHandle, CM_MDIClientShowEdge, 0, 0 );
31347 end;
31348 CM_MDIClientShowEdge:
31349 begin
31350 ShowMDIClientEdge( MDIClient );
31351 end;
31352 WM_NCHITTEST: // not necessary though
31353 begin
31354 Rslt := DefWindowProc( MDIClient.fHandle, WM_NCHITTEST, Msg.wParam, Msg.lParam );
31355 if Rslt = HTCLIENT then Rslt := HTTRANSPARENT;
31356 end;
31357 WM_WINDOWPOSCHANGING:
31358 begin
31359 MDIClient.Perform( WM_SETREDRAW, 0, 0 );
31360 end;
31361 WM_WINDOWPOSCHANGED:
31362 begin
31363 Global_Align( MDIClient.Parent );
31364 MDIClient.Invalidate;
31365 MDIClient.Parent.Invalidate;
31366 MDIClient.Perform( WM_SETREDRAW, 1, 0 );
31367 PostMessage( MDIClient.fHandle, CM_INVALIDATE, 0, 0 );
31368 end;
31369 CM_INVALIDATE:
31370 begin
31371 MDIClient.InvalidateNC( TRUE );
31372 MDIClient.InvalidateEx;
31373 {for I := 0 to MDIClient.fMDIChildren.Count-1 do
31374 begin
31375 Ch := MDIClient.fMDIChildren.fItems[ I ];
31376 Ch.InvalidateEx;
31377 Ch.Perform( WM_NCPAINT, 1, 0 );
31378 end;}
31379 end;
31380 end;
31381 Result := FALSE;
31382 end;
31384 // function added by Thaddy de Koning to fix MDI behaviour
31385 //[function WndProcParentNotifyMouseLDown]
31386 function WndProcParentNotifyMouseLDown( Sender: PControl; var Msg: TMsg;
31387 var Rslt: Integer ): Boolean;
31388 begin
31389 Result := FALSE;
31390 if (Sender.IsMDIChild) and (Msg.message = WM_PARENTNOTIFY) and
31391 (LOWORD(msg.wparam)=WM_LBUTTONDOWN) then
31392 BringWindowToTop( Sender.Handle );
31393 end;
31395 //[function NewMDIClient]
31396 function NewMDIClient( AParent: PControl; WindowMenu: THandle ): PControl;
31397 var F: PControl;
31398 CCS: TClientCreateStruct;
31399 PrntWin: HWnd;
31400 begin
31401 F := nil;
31402 PrntWin := 0;
31403 if AParent <> nil then
31404 begin
31405 F := AParent.ParentForm;
31406 if F <> nil then
31407 begin
31408 F.Add2AutoFreeEx( TObjectMethod( MakeMethod( F, @ DestroyMDIChildren ) ) );
31409 F.GetWindowHandle; // must be created before MDI client creation
31410 F.fDefWndProc := @CallDefFrameProc;
31411 end;
31412 PrntWin := AParent.GetWindowHandle;
31413 end;
31414 Applet.fExMsgProc := ProcMDIAccel;
31415 Result := _NewControl( AParent, 'MDICLIENT',
31416 WS_CHILD or WS_CLIPCHILDREN or WS_VSCROLL or WS_HSCROLL or
31417 WS_VISIBLE or WS_TABSTOP or MDIS_ALLCHILDSTYLES, TRUE, nil );
31418 {Result.fBoundsRect.Right := Result.fBoundsRect.Left + 300;
31419 Result.fBoundsRect.Bottom := Result.fBoundsRect.Top + 200;}
31420 Result.fMDIChildren := NewList;
31421 Result.fExStyle := WS_EX_CLIENTEDGE;
31423 CCS.hWindowMenu := WindowMenu;
31424 CCS.idFirstChild := $FF00;
31425 Result.fHandle := CreateWindowEx( WS_EX_CLIENTEDGE, 'MDICLIENT', nil,
31426 WS_CHILD or WS_CLIPCHILDREN or WS_VSCROLL or WS_HSCROLL or
31427 WS_VISIBLE or WS_TABSTOP,
31428 //or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX,
31429 0, 0, 0, 0, PrntWin, 0, hInstance, @ CCS );
31430 Result.fDefWndProc := Pointer( GetWindowLong( Result.fHandle, GWL_WNDPROC ) );
31431 SetWindowLong( Result.fHandle, GWL_WNDPROC, Integer( @WndFuncMDIClient ) );
31432 SetProp( Result.fHandle, ID_SELF, Integer( Result ) );
31433 if F <> nil then
31434 F.fMDIClient := Result;
31435 Result.AttachProc( WndProcMDIClient );
31436 Result.GetWindowHandle;
31438 Applet.AttachProc( WndProcParentNotifyMouseLDown );
31439 end;
31441 //===================== MDI child window object ==============//
31442 //[function MDIChildFunc]
31443 function MDIChildFunc( Wnd: HWnd; Msg: DWord; wParam, lParam: Integer ): Integer;
31444 stdcall;
31445 var C: PControl;
31446 M: TMsg;
31447 begin
31448 C := Pointer( GetProp( Wnd, ID_SELF ) );
31449 if C <> nil then
31450 begin
31451 M.hwnd := Wnd;
31452 M.message := Msg;
31453 M.wParam := wParam;
31454 M.lParam := lParam;
31455 Result := C.WndProc( M );
31457 else
31458 Result := DefMDIChildProc( Wnd, Msg, wParam, lParam );
31459 end;
31461 //[function Pass2DefMDIChildProc]
31462 function Pass2DefMDIChildProc( Sender_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31463 begin
31464 Result := FALSE;
31465 if Sender_ = nil then Exit;
31466 if Sender_.Parent = nil then Exit;
31467 if Sender_.Parent.fDestroying then Exit;
31468 if (Msg.message = WM_SYSCOMMAND) or (Msg.message = WM_CHILDACTIVATE) or
31469 (Msg.message = WM_SETFOCUS) or (Msg.message = WM_SIZE) or
31470 (Msg.message = WM_MOVE) or (Msg.message = WM_MENUCHAR) or
31471 (Msg.message = WM_GETMINMAXINFO) {and IsZoomed( Sender_.fHandle ) {and (Msg.hwnd = Sender_.fHandle) { -- doesn't work -- } then
31472 begin
31473 {if Msg.message = WM_GETMINMAXINFO then
31474 Rslt := DefWindowProc( Msg.hwnd, Msg.message, Msg.lParam, Msg.wParam )
31475 else}
31476 Rslt := DefMDIChildProc( Msg.hwnd, Msg.message, Msg.lParam, Msg.wParam );
31477 Result := TRUE;
31478 end;
31479 end;
31481 //[function WndProcMDIChild]
31482 function WndProcMDIChild( MDIChild: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31483 var ClientWnd: HWnd;
31484 MDIClient: PControl;
31485 MDIForm: PControl;
31486 begin
31487 Result := FALSE;
31488 MDIClient := MDIChild.Parent;
31489 if MDIClient = nil then Exit;
31490 ClientWnd := MDIClient.fHandle;
31491 if ClientWnd = 0 then Exit;
31492 case Msg.message of
31493 WM_DESTROY:
31494 begin
31495 MDIClient.fMDIChildren.Remove( MDIChild );
31496 MDIForm := MDIClient.ParentForm;
31497 if MDIForm <> nil then
31498 if MDIForm.fHandle <> 0 then
31499 DrawMenuBar( MDIForm.fHandle );
31500 MDIChild.Free;
31501 Result := TRUE;
31502 Exit;
31503 end;
31504 end;
31505 if MDIChild.fNotAvailable then
31506 begin
31507 MDIChild.fNotAvailable := FALSE;
31508 MDIChild.Invalidate;
31509 end;
31510 end;
31512 //[procedure CreateMDIChildExt]
31513 procedure CreateMDIChildExt( Sender: PControl );
31514 var F: PControl;
31515 begin
31516 F := Sender.Parent;
31517 if F <> nil then
31518 F := F.ParentForm;
31519 if F <> nil then
31520 DrawMenuBar( F.fHandle );
31521 end;
31523 //[function NewMDIChild]
31524 function NewMDIChild( AParent: PControl; const ACaption: String ): PControl;
31525 var MDIClient: PControl;
31526 begin
31527 Assert( (AParent <> nil) and (AParent.ParentForm <> nil) and
31528 (AParent.ParentForm.fMDIClient <> nil), 'Error creating MDI child' );
31529 MDIClient := AParent.ParentForm.fMDIClient;
31530 Result := NewForm( MDIClient, ACaption );
31531 Result.fIsMDIChild := TRUE;
31532 Result.fMenu := CtlIdCount;
31533 Inc( CtlIdCount );
31534 MDIClient.fMDIChildren.Add( Result );
31535 Result.fExStyle := Result.fExStyle or WS_EX_MDICHILD;
31536 Result.fWndFunc := @ MDIChildFunc;
31537 Result.fDefWndProc := @DefMDIChildProc;
31538 Result.fPass2DefProc := Pass2DefMDIChildProc;
31539 Result.AttachProc( WndProcMDIChild );
31541 Result.SubClassName := 'MDI_chld';
31542 Result.fNotAvailable := TRUE;
31543 Result.fCreateWndExt := CreateMDIChildExt;
31545 end;
31547 //===================== Gradient panel ========================//
31549 {$IFDEF USE_CONSTRUCTORS}
31550 //[function NewGradientPanel]
31551 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
31552 begin
31553 new( Result, CreateGradientPanel( AParent, Color1, Color2 ) );
31554 end;
31555 //[END NewGradientPanel]
31556 {$ELSE not_USE_CONSTRUCTORS}
31558 //[FUNCTION NewGradientPanel]
31559 {$IFDEF ASM_VERSION}
31560 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
31562 PUSH ECX
31563 PUSH EDX
31564 XOR EDX, EDX
31565 CALL NewLabel
31566 PUSH EAX
31567 MOV EDX, offset[WndProcGradient]
31568 CALL TControl.AttachProc
31569 POP EAX
31570 POP [EAX].TControl.fColor1
31571 POP [EAX].TControl.fColor2
31572 ADD [EAX].TControl.fBoundsRect.Right, 40-64
31573 ADD [EAX].TControl.fBoundsRect.Bottom, 40 - 22
31574 end;
31575 {$ELSE ASM_VERSION} //Pascal
31576 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
31577 begin
31578 Result := NewLabel( AParent, '' );
31579 Result.AttachProc( WndProcGradient );
31580 Result.fColor2 := Color2;
31581 Result.fColor1 := Color1;
31582 with Result.fBoundsRect do
31583 begin
31584 Right := Left + 40;
31585 Bottom := Top + 40;
31586 end;
31587 end;
31588 {$ENDIF ASM_VERSION}
31589 //[END NewGradientPanel]
31591 {$ENDIF USE_CONSTRUCTORS}
31593 {$IFDEF USE_CONSTRUCTORS}
31594 //[function NewGradientPanelEx]
31595 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
31596 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
31597 begin
31598 new( Result, CreateGradientPanelEx( AParent, Color1, Color2,
31599 Style, Layout ) );
31600 end;
31601 //[END NewGradientPanelEx]
31602 {$ELSE not_USE_CONSTRUCTORS}
31604 //[FUNCTION NewGradientPanelEx]
31605 {$IFDEF ASM_VERSION}
31606 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
31607 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
31609 PUSH ECX
31610 PUSH EDX
31611 XOR EDX, EDX
31612 CALL NewLabel
31613 PUSH EAX
31614 MOV EDX, offset[WndProcGradientEx]
31615 CALL TControl.AttachProc
31616 POP EAX
31617 POP [EAX].TControl.fColor1
31618 POP [EAX].TControl.fColor2
31619 ADD [EAX].TControl.fBoundsRect.Right, 40-100
31620 ADD [EAX].TControl.fBoundsRect.Bottom, 40 - 22
31621 MOV DL, Style
31622 MOV [EAX].TControl.fGradientStyle, DL
31623 MOV DL, Layout
31624 MOV [EAX].TControl.fGradientLayout, DL
31625 end;
31626 {$ELSE ASM_VERSION} //Pascal
31627 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
31628 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
31629 begin
31630 Result := NewLabel( AParent, '' );
31631 Result.AttachProc( WndProcGradientEx );
31632 Result.fColor2 := Color2;
31633 Result.fColor1 := Color1;
31634 Result.fGradientStyle := Style;
31635 Result.fGradientLayout := Layout;
31636 with Result.fBoundsRect do
31637 begin
31638 Right := Left + 40;
31639 Bottom := Top + 40;
31640 end;
31641 end;
31642 {$ENDIF ASM_VERSION}
31643 //[END NewGradientPanelEx]
31645 {$ENDIF USE_CONSTRUCTORS}
31647 //===================== Edit box ========================//
31649 const Editflags: array [ TEditOption ] of Integer = (
31650 not (ES_AUTOHSCROLL or WS_HSCROLL),
31651 not (es_AutoVScroll or WS_VSCROLL),
31652 es_Lowercase, es_Multiline,
31653 es_NoHideSel, es_OemConvert, es_Password, es_Readonly,
31654 es_UpperCase, es_WantReturn, 0, es_Number );
31656 {$IFDEF USE_CONSTRUCTORS}
31657 //[function NewEditbox]
31658 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;
31659 begin
31660 new( Result, CreateEditbox( AParent, Options ) );
31661 end;
31662 //[END NewEditbox]
31663 {$ELSE not_USE_CONSTRUCTORS}
31665 //[FUNCTION NewEditBox]
31666 {$IFDEF ASM_VERSION}
31667 const EditClass: array[0..4] of Char = ( 'E','D','I','T',#0 );
31668 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;
31669 const int_IDC_IBEAM = integer( IDC_IBEAM );
31670 const WS_flags = integer( WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER );
31671 const WS_clear = integer( not(WS_VSCROLL or WS_HSCROLL) );
31673 PUSH EBX
31674 XCHG EBX, EAX // EBX=AParent
31675 PUSH EDX
31676 MOV EAX, ESP
31677 XOR ECX, ECX
31678 MOV CL, 11
31679 MOV EDX, offset [EditFlags]
31680 CALL MakeFlags
31681 XCHG ECX, EAX // ECX = Flags
31682 POP EAX // Options
31683 PUSH EAX
31684 {$IFDEF PARANOIA}
31685 DB $A8, 8
31686 {$ELSE}
31687 TEST AL, 8
31688 {$ENDIF}
31689 JNZ @@1
31690 AND ECX, WS_clear
31691 @@1: OR ECX, WS_flags
31692 PUSH 1
31693 PUSH offset [EditActions]
31694 MOV EDX, offset [EditClass]
31695 XCHG EAX, EBX
31696 CALL _NewControl
31697 XCHG EBX, EAX
31698 { //YS
31699 PUSH int_IDC_IBEAM
31700 PUSH 0
31701 CALL LoadCursor
31702 MOV [EBX].TControl.fCursor, EAX
31704 LEA ECX, [EBX].TControl.fBoundsRect
31705 MOV EDX, [ECX].TRect.Left
31706 ADD EDX, 100
31707 MOV [ECX].TRect.Right, EDX
31708 MOV EDX, [ECX].TRect.Top
31709 ADD EDX, 22
31710 MOV [ECX].TRect.Bottom, EDX
31711 POP EAX // Options
31712 {$IFDEF PARANOIA}
31713 DB $A8, 8
31714 {$ELSE}
31715 TEST AL, 8
31716 {$ENDIF}
31717 MOV DL, $0D
31718 JZ @@2
31719 ADD [ECX].TRect.Right, 100
31720 ADD [ECX].TRect.Bottom, 200 - 22
31721 MOV DL, 1
31722 INC [EBX].TControl.fIgnoreDefault
31723 @@2: //MOV [EBX].TControl.fColor, clWindow
31724 TEST AH, 4
31725 JZ @@3
31726 AND DL, $FE
31727 @@3: MOV [EBX].TControl.fLookTabKeys, DL
31728 XCHG EAX, EBX
31729 POP EBX
31730 end;
31731 {$ELSE ASM_VERSION} //Pascal
31732 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;
31733 var Flags: Integer;
31734 begin
31735 Flags := MakeFlags( @Options, EditFlags );
31736 if not(eoMultiline in Options) then
31737 Flags := Flags and not(WS_HSCROLL or WS_VSCROLL);
31738 Result := _NewControl( AParent, 'EDIT', WS_VISIBLE or WS_CHILD or WS_TABSTOP
31739 or WS_BORDER or Flags, True, @EditActions );
31740 // Result.fCursor := LoadCursor( 0, IDC_IBEAM ); {YS}
31741 with Result.fBoundsRect do
31742 begin
31743 Right := Left + 100;
31744 Bottom := Top + 22;
31745 if eoMultiline in Options then
31746 begin
31747 Right := Right + 100;
31748 Bottom := Top + 200;
31749 Result.fIgnoreDefault := TRUE;
31750 end;
31751 end;
31752 Result.fLookTabKeys := [ tkTab, tkUpDown, tkPageUpPageDn ];
31753 if eoMultiline in Options then
31754 Result.fLookTabKeys := [ tkTab ];
31755 if eoWantTab in Options then
31756 Result.fLookTabKeys := Result.fLookTabKeys - [ tkTab ];
31757 end;
31758 {$ENDIF ASM_VERSION}
31759 //[END NewEditBox]
31761 {$ENDIF USE_CONSTRUCTORS}
31763 //===================== List box ========================//
31765 const ListFlags: array[TListOption] of Integer = (
31766 LBS_DISABLENOScroll, not LBS_ExtendedSel,
31767 LBS_MultiColumn or WS_HSCROLL,
31768 LBS_MultiPLESel,
31769 LBS_NoIntegralHeight, LBS_NoSel, LBS_Sort, LBS_USETabstops,
31770 not LBS_HASSTRINGS, LBS_NODATA, LBS_OWNERDRAWFIXED, LBS_OWNERDRAWVARIABLE );
31772 {$IFDEF USE_CONSTRUCTORS}
31773 //[function NewListbox]
31774 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
31775 begin
31776 new( Result, CreateListbox( AParent, Options ) );
31777 end;
31778 //[END NewListbox]
31779 {$ELSE not_USE_CONSTRUCTORS}
31781 //[FUNCTION NewListbox]
31782 {$IFDEF ASM_VERSION}
31783 const ListBoxClass : array[ 0..7 ] of Char = ( 'L','I','S','T','B','O','X',#0 );
31784 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
31786 PUSH EAX
31787 PUSH EDX
31788 MOV EAX, ESP
31789 MOV EDX, offset[ListFlags]
31790 XOR ECX, ECX
31791 MOV CL, 11
31792 CALL MakeFlags
31793 POP EDX
31794 OR EAX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER or WS_VSCROLL or LBS_NOTIFY
31795 XCHG ECX, EAX
31796 POP EAX
31797 PUSH 1
31798 PUSH offset[ListActions]
31799 MOV EDX, offset[ListBoxClass]
31800 CALL _NewControl
31801 ADD [EAX].TControl.fBoundsRect.Right, 100
31802 ADD [EAX].TControl.fBoundsRect.Bottom, 200-64
31803 MOV [EAX].TControl.fColor, clWindow
31804 MOV [EAX].TControl.fLookTabKeys, 3
31805 end;
31806 {$ELSE ASM_VERSION} //Pascal
31807 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
31808 var Flags: Integer;
31809 begin
31810 Flags := MakeFlags( @Options, ListFlags );
31811 Result := _NewControl( AParent, 'LISTBOX', WS_VISIBLE or WS_CHILD or WS_TABSTOP
31812 or WS_BORDER or WS_VSCROLL
31813 or LBS_NOTIFY or Flags, True, @ListActions );
31814 with Result.fBoundsRect do
31815 begin
31816 Right := Right + 100;
31817 Bottom := Top + 200;
31818 end;
31819 Result.fColor := clWindow;
31820 Result.fLookTabKeys := [ tkTab, tkLeftRight ];
31821 end;
31822 {$ENDIF ASM_VERSION}
31823 //[END NewListbox]
31825 {$ENDIF USE_CONSTRUCTORS}
31827 //===================== Combo box ========================//
31829 //[FUNCTION ComboboxDropDown]
31830 {$IFNDEF USE_DROPDOWNCOUNT}
31831 {$IFDEF ASM_VERSION}
31832 procedure ComboboxDropDown( Sender: PObj );
31834 PUSH EBX
31835 PUSH ESI
31836 MOV EBX, EAX
31837 CALL TControl.GetItemsCount
31838 CMP EAX, 1
31839 JGE @@1
31840 XOR EAX, EAX
31841 INC EAX
31842 @@1: CMP EAX, 8
31843 JLE @@2
31844 XOR EAX, EAX
31845 MOV AL, 8
31846 @@2: XOR ESI, ESI
31847 PUSH SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_SHOWWINDOW
31848 PUSH ESI
31849 PUSH ESI
31850 PUSH SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_HIDEWINDOW
31851 PUSH EAX
31852 MOV EAX, EBX
31853 CALL TControl.GetHeight
31854 POP ECX
31855 INC ECX
31856 IMUL ECX
31857 INC EAX
31858 INC EAX
31859 PUSH EAX
31860 MOV EAX, EBX
31861 CALL TControl.GetWidth
31862 PUSH EAX
31863 INC ESI
31864 @@3: XOR EDX, EDX
31865 PUSH EDX
31866 PUSH EDX
31867 PUSH EDX
31868 PUSH [EBX].TControl.fHandle
31869 CALL SetWindowPos
31870 DEC ESI
31871 JZ @@3
31872 MOV ECX, [EBX].TControl.fOnDropDown.TMethod.Code
31873 JECXZ @@exit
31874 MOV EAX, [EBX].TControl.fOnDropDown.TMethod.Data
31875 MOV EDX, EBX
31876 CALL ECX
31877 @@exit: POP ESI
31878 POP EBX
31879 end;
31880 {$ELSE ASM_VERSION} //Pascal
31881 procedure ComboboxDropDown( Sender: PObj );
31883 CB: PControl;
31884 IC: Integer;
31885 begin
31886 CB := PControl( Sender );
31887 IC := CB.Count;
31888 if IC > 8 then IC := 8;
31889 if IC < 1 then IC := 1;
31891 SetWindowPos( CB.Handle, 0, 0, 0, CB.Width, CB.Height * (IC + 1) + 2,
31892 SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_NOREDRAW +
31893 SWP_HIDEWINDOW);
31895 SetWindowPos( CB.Handle, 0, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE
31896 + SWP_NOZORDER + SWP_NOACTIVATE
31897 + SWP_NOREDRAW + SWP_SHOWWINDOW);
31899 if assigned( CB.fOnDropDown ) then
31900 CB.fOnDropDown( CB );
31902 end;
31903 {$ELSE newcode}
31904 {procedure ComboboxDropDown( Sender: PObj );
31906 CB: PControl;
31907 Count: Integer;
31908 DropDownCount: Integer;
31909 ItemHeight: Integer;
31910 begin
31911 CB := PControl(Sender);
31913 Count := CB.Count;
31914 DropDownCount := CB.DropDownCount;
31915 DropDownCount := 8;
31916 if (Count > DropDownCount) then
31917 Count := DropDownCount;
31918 if (Count < 1) then
31919 Count := 1;
31920 ItemHeight := CB.Perform(CB_GETITEMHEIGHT, 0, 0);
31921 SetWindowPos(
31922 CB.Handle, 0, 0, 0, CB.Width, ItemHeight * Count + CB.Height + 2,
31923 SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_HIDEWINDOW);
31924 SetWindowPos(
31925 CB.Handle, 0, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or
31926 SWP_NOACTIVATE or SWP_NOREDRAW or SWP_SHOWWINDOW);
31928 if Assigned(CB.fOnDropDown) then
31929 CB.fOnDropDown(CB);
31930 end;
31932 {$ENDIF USE_DROPDOWNCOUNT}
31933 {$ENDIF ASM_VERSION}
31934 //[END ComboboxDropDown]
31936 //[function WndFuncCombo]
31937 function WndFuncCombo( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
31938 : Integer; stdcall;
31939 var Combo, Form: PControl;
31940 ParentWnd : HWnd;
31941 MsgStruct: TMsg;
31942 //********************************************************** Added By M.Gerasimov
31944 PrevProc:Pointer;
31946 //********************************************************** Added By M.Gerasimov
31947 begin
31948 Combo := nil;
31950 ParentWnd := GetParent( W );
31951 if ParentWnd <> 0 then
31952 Combo := Pointer( GetProp( ParentWnd, ID_SELF ) );
31954 if Combo <> nil then
31955 begin
31956 MsgStruct.hwnd := Combo.fHandle;
31957 MsgStruct.message := Msg;
31958 MsgStruct.wParam := wParam;
31959 MsgStruct.lParam := lParam;
31960 Form := Combo.ParentForm;
31961 if fGlobalProcKeybd( Combo, MsgStruct, Result ) then Exit;
31962 if W <> Combo.FHandle then
31963 begin
31964 if Assigned( Applet ) and Assigned( Applet.OnMessage ) then
31965 if Applet.OnMessage( MsgStruct, Result ) then Exit;
31966 if (Applet <> Form) and (Form <> nil) then
31967 if Assigned( Form.OnMessage ) then
31968 if Form.OnMessage( MsgStruct, Result ) then Exit;
31969 end;
31970 if //(GetFocus = W) and
31971 (Msg = WM_KEYDOWN) or (Msg = WM_KEYUP) or (Msg = WM_CHAR) then
31972 begin
31973 Result := 0;
31974 if (wParam = VK_TAB) then
31975 begin
31976 case Msg of
31977 WM_KEYDOWN:
31978 if Assigned( Combo.fGotoControl ) and
31979 Combo.fGotoControl( Combo, wParam, FALSE ) then Exit;
31980 else Exit;
31981 end;
31983 else
31984 if (Msg = WM_CHAR) and ((wParam = VK_ESCAPE) or (wParam = VK_RETURN)) then
31985 begin
31986 if Combo.Perform( CB_GETDROPPEDSTATE, 0, 0 ) <> 0 then
31987 begin
31988 Combo.Perform( CB_SHOWDROPDOWN, 0, 0 );
31989 if wParam = VK_ESCAPE then
31990 Combo.Perform( CB_SETCURSEL, Combo.fCurIdxAtDrop, 0 );
31991 Combo.fWndProcKeybd( Combo, MsgStruct, Result );
31992 Exit;
31994 {$IFDEF ESC_CLOSE_DIALOGS}
31995 //---------------------------------Babenko Alexey--------------------------
31996 else
31997 if (wparam = VK_ESCAPE) then
31998 if (combo.ParentForm.ExStyle and WS_EX_DLGMODALFRAME) <> 0 then begin
31999 SendMessage(combo.ParentForm.Handle, WM_CLOSE, 0, 0);
32000 exit;
32001 end;
32002 //---------------------------------Babenko Alexey--------------------------
32003 {$ENDIF}
32004 end;
32005 Combo.fWndProcKeybd( Combo, MsgStruct, Result );
32007 else
32008 if Msg = WM_SETFOCUS then
32009 begin
32010 if Form <> nil then Form.fCurrentControl := Combo;
32011 end;
32012 MsgStruct.hwnd := W;
32013 //********************************************************** Added By M.Gerasimov
32015 PrevProc:=Pointer(GetProp( W, ID_PREVPROC ));
32016 if PrevProc <> Nil then
32017 Result := CallWindowProc( PrevProc , W, Msg, wParam, lParam )
32018 else
32019 Result:=0;
32021 //********************************************************** Added By M.Gerasimov
32022 // Result := CallWindowProc( //Combo.fPrevWndProc
32023 // Pointer( GetProp( W, 'PREV_PROC' ) )
32024 // , W, Msg, wParam, lParam );
32025 //**********************************************************
32027 else
32028 Result := DefWindowProc( W, Msg, wParam, lParam );
32029 end;
32031 //[PROCEDURE CreateComboboxWnd]
32032 {$IFDEF ASM_VERSION}
32033 procedure CreateComboboxWnd( Combo: PControl );
32034 //********************************************************** Remarked By M.Gerasimov
32035 //const PrevProcStr: PChar = 'PREV_PROC';
32036 //********************************************************** Remarked By M.Gerasimov
32038 PUSH EDI
32039 PUSH EBX
32040 XCHG EBX, EAX
32041 PUSH GW_CHILD
32042 PUSH [EBX].TControl.fHandle
32043 //XOR EDI, EDI
32044 @@getwindow:
32045 CALL GetWindow
32046 TEST EAX, EAX
32047 JZ @@fin
32048 {TEST EDI, EDI
32049 XCHG EDI, EAX
32050 JZ @@2getnext}
32051 PUSH offset[WndFuncCombo]
32052 PUSH GWL_WNDPROC
32053 PUSH EAX
32054 XCHG EDI, EAX
32055 CALL SetWindowLong
32056 PUSH EAX
32057 //********************************************* By M.Gerasimov
32058 // PUSH [PrevProcStr]
32059 //************************************************************
32060 PUSH offset [ID_PREVPROC] //
32061 //************************************************************
32062 PUSH EDI
32063 CALL SetProp
32064 @@2getnext:
32065 PUSH GW_HWNDNEXT
32066 PUSH EDI
32067 JMP @@getwindow
32068 @@fin: POP EBX
32069 POP EDI
32070 end;
32071 {$ELSE ASM_VERSION} //Pascal
32072 procedure CreateComboboxWnd( Combo: PControl );
32073 var W : HWND;
32074 PrevProc: DWORD;
32075 begin
32076 W := GetWindow( Combo.fHandle, GW_CHILD );
32077 {if W <> 0 then
32078 W := GetWindow( W, GW_HWNDNEXT );}
32079 while W <> 0 do
32080 begin
32081 PrevProc :=
32082 SetWindowLong( W, GWL_WNDPROC, Longint( @WndFuncCombo ) );
32083 //********************************************* By M.Gerasimov
32084 // SetProp( W, 'PREV_PROC', PrevProc );
32085 //************************************************************
32086 SetProp( W, ID_PREVPROC, PrevProc ); //
32087 //************************************************************
32088 W := GetWindow( W, GW_HWNDNEXT );
32089 end;
32090 end;
32091 {$ENDIF ASM_VERSION}
32092 //[END CreateComboboxWnd]
32094 //[procedure RemoveChldPrevProc]
32095 procedure RemoveChldPrevProc( fHandle: HWnd );
32096 var Chld: HWnd;
32097 begin
32098 Chld := GetWindow( fHandle, GW_CHILD );
32099 while Chld <> 0 do
32100 begin
32101 if GetProp( Chld, ID_PREVPROC ) <> 0 then
32102 RemoveProp(Chld, ID_PREVPROC);
32103 Chld := GetWindow( Chld, GW_HWNDNEXT );
32104 end;
32105 end;
32107 //[function WndProcCombo]
32108 function WndProcCombo( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32109 begin
32110 Result := FALSE;
32111 if (Msg.message >= WM_CTLCOLORMSGBOX) and (Msg.message <= WM_CTLCOLORSTATIC) then
32112 begin
32113 Rslt := Sender.Perform( Msg.message + CN_BASE, Msg.wParam, Msg.lParam );
32114 Result := TRUE;
32116 else
32117 if //(Msg.message = CN_CTLCOLOREDIT)
32118 (Msg.message >= CN_CTLCOLORMSGBOX) and (Msg.message <= CN_CTLCOLORSTATIC)
32119 {and not AppletTerminated} then
32120 begin
32121 if Sender.fTransparent then
32122 case Msg.message of
32123 CN_CTLCOLORLISTBOX:
32124 begin
32125 SetBkMode( Msg.wParam, Windows.OPAQUE );
32126 SetBkColor(Msg.WParam, Color2RGB( Sender.fColor ) );
32127 Rslt := Global_GetCtlBrushHandle( Sender );
32128 Result := TRUE;
32129 end;
32130 //********************************************************** Added By M.Gerasimov
32132 WM_DESTROY:
32133 RemoveChldPrevProc( Sender.Handle );
32135 //********************************************************** Added By M.Gerasimov
32136 else
32137 if not Sender.DblBufTopParent.fDblBufPainting then
32138 Sender.Invalidate;
32139 end;
32140 //Result := FALSE;
32142 else
32143 if Msg.message = CM_COMMAND then
32144 begin
32145 case HiWord( Msg.wParam ) of
32146 CBN_DROPDOWN:
32147 begin
32148 Sender.fDropped := True;
32149 Sender.fCurIdxAtDrop := Sender.CurIndex;
32150 Sender.fDropDownProc( Sender );
32151 end;
32152 CBN_CLOSEUP:
32153 begin
32154 Sender.fDropped := False;
32155 if Assigned( Sender.fOnCloseUp ) then Sender.fOnCloseUp( Sender );
32156 end;
32157 CBN_SELCHANGE:
32158 begin
32159 PostMessage( Sender.fHandle, CM_COMMAND, CM_CBN_SELCHANGE shl 16, 0 );
32160 end;
32161 end;
32162 end;
32163 end;
32165 const ComboFlags: array[ TComboOption ] of Integer = (
32166 CBS_DROPDOWNLIST, not CBS_AUTOHScroll,
32167 CBS_DISABLENOSCROLL, CBS_LowerCase, CBS_NoIntegralHeight,
32168 CBS_OemConvert, CBS_Sort, CBS_UpperCase,
32169 CBS_OWNERDRAWFIXED, CBS_OWNERDRAWVARIABLE, CBS_SIMPLE );
32171 {$IFDEF USE_CONSTRUCTORS}
32172 //[function NewCombobox]
32173 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
32174 begin
32175 new( Result, CreateCombobox( AParent, Options ) );
32176 end;
32177 {$ELSE not_USE_CONSTRUCTORS}
32179 //[FUNCTION NewCombobox]
32180 {$IFDEF ASM_VERSION}
32181 const ComboboxClass: array[0..8] of Char = ('C','O','M','B','O','B','O','X',#0 );
32182 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
32184 PUSH EDX
32185 PUSH EAX
32186 PUSH EDX
32187 MOV EAX, ESP
32188 MOV EDX, offset[ComboFlags]
32189 XOR ECX, ECX
32190 MOV CL, 10
32191 CALL MakeFlags
32192 POP EDX
32193 XCHG ECX, EAX
32194 POP EAX
32195 PUSH 1
32196 PUSH offset[ComboActions]
32197 MOV EDX, offset[ComboboxClass]
32198 OR ECX, WS_VISIBLE or WS_CHILD or WS_VSCROLL or CBS_HASSTRINGS or WS_TABSTOP
32199 TEST ECX, CBS_SIMPLE
32200 JNZ @@O
32201 OR ECX, CBS_DROPDOWN
32202 @@O:
32203 CALL _NewControl
32204 MOV [EAX].TControl.fCreateWndExt, offset[CreateComboboxWnd]
32205 MOV [EAX].TControl.fDropDownProc, offset[ComboboxDropDown]
32206 OR byte ptr [EAX].TControl.fClsStyle, CS_DBLCLKS
32207 ADD [EAX].TControl.fBoundsRect.Right, 100-64
32208 ADD [EAX].TControl.fBoundsRect.Bottom, 22-64
32209 //MOV [EAX].TControl.fColor, clWindow
32210 MOV CL, 1
32211 POP EDX
32212 TEST DL, 1
32213 JZ @@exit
32214 MOV CL, 3
32215 @@exit:
32216 MOV [EAX].TControl.fLookTabKeys, CL
32217 PUSH EAX
32218 MOV EDX, offset[ WndProcCombo ]
32219 CALL TControl.AttachProc
32220 POP EAX
32221 end;
32222 {$ELSE ASM_VERSION} //Pascal
32223 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
32224 var Flags: Integer;
32225 begin
32226 Flags := MakeFlags( @Options, ComboFlags );
32227 if not LongBool( Flags and CBS_SIMPLE ) then
32228 Flags := Flags or CBS_DROPDOWN;
32229 Result := _NewControl( AParent, 'COMBOBOX',
32230 WS_VISIBLE
32231 or WS_CHILD
32232 or WS_VSCROLL
32233 or CBS_HASSTRINGS or WS_TABSTOP
32234 or Flags
32235 , True, @ComboActions );
32236 //Result.fCannotDoubleBuf := TRUE;
32237 Result.fCreateWndExt := CreateComboboxWnd;
32238 Result.fDropDownProc := ComboboxDropDown;
32239 Result.fClsStyle := Result.fClsStyle or CS_DBLCLKS;
32240 with Result.fBoundsRect do
32241 begin
32242 Right := Left + 100;
32243 Bottom := Top + 22;
32244 end;
32245 Result.fLookTabKeys := [ tkTab ];
32246 if coReadOnly in Options then
32247 Result.fLookTabKeys := [ tkTab, tkLeftRight ];
32248 Result.AttachProc( @ WndProcCombo );
32249 {$IFDEF USE_DROPDOWNCOUNT}
32250 Result.DropDownCount := 8;
32251 {$ENDIF}
32252 end;
32253 {$ENDIF ASM_VERSION}
32254 //[END NewCombobox]
32256 {$ENDIF USE_CONSTRUCTORS}
32258 //[FUNCTION WndProcResiz]
32259 {$IFDEF ASM_VERSION}
32260 function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32262 PUSH ESI
32263 CMP word ptr [EDX].TMsg.message, WM_SIZE
32264 JNZ @@exit
32266 MOV ESI, [EAX].TControl.fChildren
32267 MOV ECX, [ESI].TList.fCount
32268 JECXZ @@exit
32269 MOV ESI, [ESI].TList.fItems
32270 @@loo: PUSH ECX
32271 LODSD
32272 PUSH EAX
32273 PUSH EAX
32274 PUSH CM_SIZE
32275 PUSH EAX
32276 CALL TControl.Perform
32277 POP ECX
32278 LOOP @@loo
32280 @@exit: XOR EAX, EAX
32281 POP ESI
32282 end;
32283 {$ELSE ASM_VERSION} //Pascal
32284 function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32285 var I: Integer;
32286 C: PControl;
32287 begin
32288 if Msg.message = WM_SIZE then
32289 begin
32290 for I:= 0 to Self_.fChildren.fCount - 1 do
32291 begin
32292 C := Self_.fChildren.fItems[ I ];
32293 C.Perform( CM_SIZE, 0, 0 );
32294 end;
32295 end;
32296 Result := False; // don't stop further processing
32297 end;
32298 {$ENDIF ASM_VERSION}
32299 //[END WndProcResiz]
32301 //[FUNCTION WndProcParentResize]
32302 {$IFDEF ASM_VERSION}
32303 function WndProcParentResize( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32305 CMP word ptr [EDX].TMsg.message, CM_SIZE
32306 JNZ @@exit
32307 PUSH 0
32308 PUSH 0
32309 PUSH WM_SIZE
32310 PUSH EAX
32311 CALL TControl.Perform
32312 @@exit: XOR EAX, EAX
32313 end;
32314 {$ELSE ASM_VERSION} //Pascal
32315 function WndProcParentResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32316 begin
32317 Result := False;
32318 case Msg.message of
32319 CM_SIZE:
32320 begin
32321 Self_.Perform( WM_SIZE, 0, 0 );
32322 end;
32323 end;
32324 end;
32325 {$ENDIF ASM_VERSION}
32326 //[END WndProcParentResize]
32328 //[procedure InitCommonControlCommonNotify]
32329 procedure InitCommonControlCommonNotify( Ctrl: PControl );
32330 var AParent: PControl;
32331 begin
32332 Ctrl.fIsCommonControl := True;
32333 AParent := Ctrl.Parent;
32334 if AParent <> nil then
32335 begin
32336 Ctrl.AttachProc( WndProcCommonNotify );
32337 AParent.AttachProc( WndProcNotify );
32338 end;
32339 end;
32341 //[procedure InitCommonControlSizeNotify]
32342 procedure InitCommonControlSizeNotify( Ctrl: PControl );
32343 var AParent: PControl;
32344 begin
32345 AParent := Ctrl.Parent;
32346 if AParent <> nil then
32347 begin
32348 Ctrl.AttachProc( WndProcParentResize );
32349 AParent.AttachProc( WndProcResize );
32350 end;
32351 end;
32353 //[function _NewCommonControl]
32354 function _NewCommonControl( AParent: PControl; ClassName: PChar; Style: DWORD;
32355 Ctl3D: Boolean; Actions: PCommandActions ): PControl;
32356 begin
32357 {*************} DoInitCommonControls( ICC_WIN95_CLASSES );
32358 Result := _NewControl( AParent, ClassName, Style, Ctl3D, Actions );
32359 //InitCommonControlSizeNotify( Result );
32360 InitCommonControlCommonNotify( Result );
32361 end;
32363 //==================== Progress bar ======================//
32365 {$IFDEF USE_CONSTRUCTORS}
32366 //[function NewProgressbar]
32367 function NewProgressbar( AParent: PControl ): PControl;
32368 begin
32369 new( Result, CreateProgressbar( AParent ) );
32370 end;
32371 //[END NewProgressbar]
32372 {$ELSE not_USE_CONSTRUCTORS}
32374 //[FUNCTION NewProgressbar]
32375 {$IFDEF ASM_VERSION}
32376 function NewProgressbar( AParent: PControl ): PControl;
32378 PUSH 1
32379 PUSH 0
32380 MOV EDX, offset[Progress_class]
32381 MOV ECX, WS_CHILD or WS_VISIBLE
32382 CALL _NewCommonControl
32383 LEA EDX, [EAX].TControl.fBoundsRect
32384 MOV ECX, [EDX].TRect.Left
32385 ADD ECX, 300
32386 MOV [EDX].TRect.Right, ECX
32387 MOV ECX, [EDX].TRect.Top
32388 ADD ECX, 20
32389 MOV [EDX].TRect.Bottom, ECX
32390 XOR EDX, EDX
32391 MOV [EAX].TControl.fMenu, EDX
32392 MOV [EAX].TControl.fTextColor, clHighlight
32393 MOV [EAX].TControl.fCommandActions.aSetBkColor, PBM_SETBKCOLOR
32394 end;
32395 {$ELSE ASM_VERSION} //Pascal
32396 function NewProgressbar( AParent: PControl ): PControl;
32397 begin
32398 Result := _NewCommonControl( AParent, PROGRESS_CLASS,
32399 WS_CHILD or WS_VISIBLE, True, nil );
32400 with Result.fBoundsRect do
32401 begin
32402 Right := Left + 300;
32403 Bottom := Top + 20;
32404 end;
32405 Result.fMenu := 0;
32406 Result.fTextColor := clHighlight;
32407 Result.fCommandActions.aSetBkColor := PBM_SETBKCOLOR;
32408 end;
32409 {$ENDIF ASM_VERSION}
32410 //[END NewProgressbar]
32412 {$ENDIF USE_CONSTRUCTORS}
32414 {$IFDEF USE_CONSTRUCTORS}
32415 //[function NewProgressbarEx]
32416 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
32417 begin
32418 new( Result, CreateProgressbarEx( AParent, Options ) );
32419 end;
32420 //[END NewProgressbarEx]
32421 {$ELSE not_USE_CONSTRUCTORS}
32423 //[FUNCTION NewProgressbarEx]
32424 {$IFDEF ASM_VERSION}
32425 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
32427 PUSH EDX
32428 CALL NewProgressbar
32429 POP ECX
32430 XOR EDX, EDX
32431 SHR ECX, 1
32432 JNC @@notVert
32433 MOV DL, 4
32434 @@notVert:
32435 SHR ECX, 1
32436 JNC @@notSmooth
32437 INC EDX
32438 @@notSmooth:
32439 OR [EAX].TControl.fStyle, EDX
32440 end;
32441 {$ELSE ASM_VERSION} //Pascal
32442 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
32443 const ProgressBarFlags: array[ TProgressbarOption ] of Integer =
32444 (PBS_VERTICAL, PBS_SMOOTH );
32445 begin
32446 Result := NewProgressbar( AParent );
32447 Result.fStyle := Result.fStyle or DWORD( MakeFlags( @Options, ProgressBarFlags ) );
32448 end;
32449 {$ENDIF ASM_VERSION}
32450 //[END NewProgressbarEx]
32452 {$ENDIF USE_CONSTRUCTORS}
32454 //===================== List view ========================//
32456 //[FUNCTION WndProcNotify]
32457 {$IFDEF ASM_VERSION}
32458 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32460 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
32461 JNE @@ret_false
32462 PUSH ECX
32463 PUSH EDX
32464 PUSH offset[ID_SELF]
32465 MOV ECX, [EDX].TMsg.lParam
32466 PUSH [ECX].TNMHdr.hwndFrom
32467 CALL GetProp
32468 POP EDX
32469 TEST EAX, EAX
32470 JZ @@ret_false_ECX
32471 MOV ECX, [EAX].TControl.fHandle
32472 MOV [EDX].TMsg.hwnd, ECX
32473 POP ECX
32474 JMP TControl.EnumDynHandlers
32475 @@ret_false_ECX:
32476 POP ECX
32477 @@ret_false:
32478 XOR EAX, EAX
32479 end;
32480 {$ELSE ASM_VERSION} //Pascal
32481 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32482 var NMhdr: PNMHdr;
32483 Child: PControl;
32484 begin
32485 Result := False;
32486 if Msg.message = WM_NOTIFY then
32487 begin
32488 NMhdr := Pointer( Msg.lParam );
32489 Child := Pointer( GetProp( NMhdr.hwndFrom, ID_SELF ) );
32490 if Child <> nil then
32491 begin
32492 {if Child = Self_ then
32493 begin
32494 Rslt := Self_.CallDefWndProc( Msg );
32495 Result := TRUE;
32497 else}
32498 begin
32499 Msg.hwnd := Child.fHandle;
32500 Result := EnumDynHandlers( Child, Msg, Rslt );
32501 end;
32502 end;
32503 end;
32504 end;
32505 {$ENDIF ASM_VERSION}
32506 //[END WndProcNotify]
32508 //[FUNCTION WndProcCommonNotify]
32509 {$IFDEF ASM_VERSION}
32510 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32512 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
32513 JNE @@ret_false
32514 PUSH EBX
32515 MOV EBX, [EDX].TMsg.lParam
32516 MOV EDX, [EBX].TNMHdr.code
32518 @@chk_nm_click:
32519 XOR ECX, ECX
32520 CMP EDX, NM_CLICK
32521 JZ @@click
32522 CMP EDX, NM_RCLICK
32523 JNE @@chk_killfocus
32524 INC ECX
32525 @@click:
32526 MOV [EAX].TControl.fRightClick, CL
32528 MOV ECX, [EAX].TControl.fOnClick.TMethod.Code
32529 JECXZ @@fin_false
32530 MOV EDX, [EAX].TControl.fOnClick.TMethod.Data
32531 JMP @@fin_event
32533 @@fin_false:
32534 POP EBX
32535 @@ret_false:
32536 XOR EAX, EAX
32539 @@chk_killfocus:
32540 CMP EDX, NM_KILLFOCUS
32541 JNE @@chk_setfocus
32542 MOV ECX, [EAX].TControl.fOnLeave.TMethod.Code
32543 JECXZ @@fin_false
32544 MOV EDX, [EAX].TControl.fOnLeave.TMethod.Data
32545 JMP @@fin_event
32546 @@chk_setfocus:
32547 CMP EDX, NM_RETURN
32548 JE @@set_focus
32549 CMP EDX, NM_SETFOCUS
32550 JNE @@fin_false
32552 @@set_focus:
32553 MOV ECX, [EAX].TControl.fOnEnter.TMethod.Code
32554 JECXZ @@fin_false
32555 MOV EDX, [EAX].TControl.fOnEnter.TMethod.Data
32557 @@fin_event:
32558 XCHG EAX, EDX
32559 CALL ECX
32560 POP EBX
32561 MOV AL, 1
32562 end;
32563 {$ELSE ASM_VERSION} //Pascal
32564 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32565 var NMhdr: PNMHdr;
32566 begin
32567 Result := False;
32568 if Msg.message = WM_NOTIFY then
32569 begin
32570 NMHdr := Pointer( Msg.lParam );
32571 case NMHdr.code of
32572 NM_RCLICK,
32573 NM_CLICK: if assigned( Self_.fOnClick ) then
32574 begin
32575 Self_.fRightClick := NMHdr.code=NM_RCLICK;
32576 Self_.fOnClick( Self_ );
32577 Result := TRUE;
32578 end;
32579 NM_KILLFOCUS: if assigned( Self_.fOnLeave ) then
32580 Self_.fOnLeave( Self_ );
32581 NM_RETURN,
32582 NM_SETFOCUS: if assigned( Self_.fOnEnter ) then
32583 Self_.fOnEnter( Self_ );
32584 end;
32585 end;
32586 end;
32587 {$ENDIF ASM_VERSION}
32588 //[END WndProcCommonNotify]
32590 const ListViewStyles: array[ TListViewStyle ] of DWORD = ( LVS_ICON, LVS_SMALLICON,
32591 LVS_LIST, LVS_REPORT, LVS_REPORT or LVS_NOCOLUMNHEADER );
32592 ListViewFlags: array[ TListViewOption ] of Integer = ( LVS_ALIGNLEFT, LVS_AUTOARRANGE,
32593 $400 {LVS_BUTTON}, LVS_EDITLABELS, LVS_NOLABELWRAP,
32594 LVS_NOSCROLL, LVS_NOSORTHEADER,
32595 not LVS_SHOWSELALWAYS, not LVS_SINGLESEL, LVS_SORTASCENDING,
32596 LVS_SORTDESCENDING, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
32597 LVS_OWNERDATA, LVS_OWNERDRAWFIXED );
32599 ListViewExFlags: array[ TListViewOption ] of Integer = ( 0, 0,
32600 0, 0, 0, 0, 0, 0, 0, 0, 0, LVS_EX_GRIDLINES,
32601 LVS_EX_SUBITEMIMAGES, LVS_EX_CHECKBOXES, LVS_EX_TRACKSELECT,
32602 LVS_EX_HEADERDRAGDROP, LVS_EX_FULLROWSELECT, LVS_EX_ONECLICKACTIVATE,
32603 LVS_EX_TWOCLICKACTIVATE, LVS_EX_FLATSB, LVS_EX_REGIONAL,
32604 LVS_EX_INFOTIP, LVS_EX_UNDERLINEHOT, LVS_EX_MULTIWORKAREAS, 0, 0 );
32607 //[FUNCTION ApplyImageLists2Control]
32608 {$IFDEF ASM_VERSION}
32609 procedure ApplyImageLists2Control( Sender: PControl );
32611 PUSHAD
32612 XCHG ESI, EAX
32613 MOVZX ECX, [ESI].TControl.fCommandActions.aSetImgList
32614 JECXZ @@fin
32615 MOV EBP, ECX
32616 XOR EBX, EBX
32617 MOV BL, 32
32618 XOR EDI, EDI
32619 @@loo:
32620 MOV EAX, ESI
32621 MOV EDX, EBX
32622 CALL TControl.GetImgListIdx
32623 TEST EAX, EAX
32624 JZ @@nx
32625 CALL TImageList.GetHandle
32626 PUSH EAX
32627 PUSH EDI
32628 PUSH EBP
32629 PUSH ESI
32630 CALL TControl.Perform
32631 @@nx:
32632 INC EDI
32633 SHR EBX, 1
32634 JZ @@fin
32635 CMP BL, 16
32636 JGE @@loo
32637 XOR EBX, EBX
32638 JMP @@loo
32639 @@fin:
32640 POPAD
32641 end;
32642 {$ELSE ASM_VERSION} //Pascal
32643 procedure ApplyImageLists2Control( Sender: PControl );
32644 var IL: PImageList;
32645 begin
32646 if Sender.fCommandActions.aSetImgList = 0 then Exit;
32647 IL := Sender.ImageListNormal;
32648 if IL <> nil then
32649 Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_NORMAL, IL.Handle );
32650 IL := Sender.ImageListSmall;
32651 if IL <> nil then
32652 Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_SMALL, IL.Handle );
32653 IL := Sender.ImageListState;
32654 if IL <> nil then
32655 Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_STATE, IL.Handle );
32656 end;
32657 {$ENDIF ASM_VERSION}
32658 //[END ApplyImageLists2Control]
32660 //[FUNCTION ApplyImageLists2ListView]
32661 {$IFDEF ASM_VERSION}
32662 procedure ApplyImageLists2ListView( Sender: PControl );
32664 PUSHAD
32666 XCHG ESI, EAX
32667 PUSH dword ptr [ESI].TControl.fLVOptions
32668 MOV EAX, ESP
32669 MOV EDX, offset[ListViewFlags]
32670 XOR ECX, ECX
32671 MOV CL, 25
32672 CALL MakeFlags
32673 POP ECX
32674 PUSH ECX
32676 MOV EDX, [ESI].TControl.fStyle
32677 //AND DH, 3
32678 AND DX, not $403F
32679 OR EDX, EAX
32681 MOVZX EAX, [ESI].TControl.fLVStyle
32682 OR EDX, [EAX*4 + offset ListViewStyles]
32684 MOV EAX, ESI
32685 CALL TControl.SetStyle
32687 MOV EAX, ESP
32688 MOV EDX, offset[ListViewExFlags]
32689 XOR ECX, ECX
32690 MOV CL, 23
32691 CALL MakeFlags
32692 POP EDX
32693 PUSH EAX
32694 PUSH $3FFF
32695 PUSH LVM_SETEXTENDEDLISTVIEWSTYLE
32696 PUSH ESI
32697 CALL TControl.Perform
32699 POPAD
32700 CALL ApplyImageLists2Control
32701 end;
32702 {$ELSE ASM_VERSION} //Pascal
32703 procedure ApplyImageLists2ListView( Sender: PControl );
32704 var Flags: DWORD;
32705 begin
32706 Flags := MakeFlags( @Sender.fLVOptions, ListViewFlags );
32707 Sender.Style := Sender.Style and not $403F
32708 or Flags or ListViewStyles[ Sender.fLVStyle ];
32709 Flags := MakeFlags( @Sender.fLVOptions, ListViewExFlags );
32710 Sender.Perform( LVM_SETEXTENDEDLISTVIEWSTYLE, $3FFF, Flags );
32711 ApplyImageLists2Control( Sender );
32712 end;
32713 {$ENDIF ASM_VERSION}
32714 //[END ApplyImageLists2ListView]
32716 {$IFDEF USE_CONSTRUCTORS}
32717 //[function NewListView]
32718 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
32719 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
32720 begin
32721 new( Result, CreateListView( AParent, Style, Options, ImageListSmall,
32722 ImageListNormal, ImageListState ) );
32723 end;
32724 //[END NewListView]
32725 {$ELSE not_USE_CONSTRUCTORS}
32727 //[FUNCTION NewListView]
32728 {$IFDEF ASM_VERSION}
32729 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
32730 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
32732 PUSH EDX
32733 PUSH ECX
32734 MOVZX EDX, DL
32735 MOV ECX, [EDX*4 + offset ListViewStyles]
32736 OR ECX, LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP
32737 MOV EDX, offset[WC_LISTVIEW]
32738 PUSH 1
32739 PUSH offset[ListViewActions]
32740 CALL _NewCommonControl
32742 MOV EDX, ESP
32743 PUSH EAX
32744 XCHG EAX, EDX
32745 MOV EDX, offset ListViewFlags
32746 XOR ECX, ECX
32747 MOV CL, 25
32748 CALL MakeFlags
32749 XCHG EDX, EAX
32750 POP EAX
32751 MOV ECX, [EAX].TControl.fStyle
32752 AND ECX, not LVS_TYPESTYLEMASK
32753 OR EDX, ECX
32754 MOV [EAX].TControl.fStyle, EDX
32756 POP [EAX].TControl.fLVOptions
32757 POP EDX
32758 MOV [EAX].TControl.fLVStyle, DL
32759 MOV [EAX].TControl.fCreateWndExt, offset[ApplyImageLists2ListView]
32760 ADD [EAX].TControl.fBoundsRect.Right, 200-64
32761 ADD [EAX].TControl.fBoundsRect.Bottom, 150-64
32762 MOV ECX, [ImageListState]
32763 XOR EDX, EDX
32764 PUSHAD
32765 CALL TControl.SetImgListIdx
32766 POPAD
32767 MOV ECX, [ImageListSmall]
32768 MOV DL, 16
32769 PUSHAD
32770 CALL TControl.SetImgListIdx
32771 POPAD
32772 MOV ECX, [ImageListNormal]
32773 ADD EDX, EDX
32774 PUSH EAX
32775 CALL TControl.SetImgListIdx
32776 POP EAX
32777 MOV [EAX].TControl.fLVTextBkColor, clWindow
32778 XOR EDX, EDX
32779 //MOV [EAX].TControl.fMargin, EDX
32780 INC EDX
32781 MOV [EAX].TControl.fLookTabKeys, DL
32782 end;
32783 {$ELSE ASM_VERSION} //Pascal
32784 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
32785 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
32786 begin
32787 Result := _NewCommonControl( AParent, WC_LISTVIEW, ListViewStyles[ Style ] or
32788 LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_CLIPCHILDREN,
32789 True, @ListViewActions );
32791 Result.fLVOptions := Options;
32792 Result.fLVStyle := Style;
32793 Result.fStyle := Result.fStyle and not LVS_TYPESTYLEMASK
32794 or DWORD( MakeFlags( @Options, ListViewFlags ) );
32795 Result.fCreateWndExt := ApplyImageLists2ListView;
32796 with Result.fBoundsRect do
32797 begin
32798 Right := Left + 200;
32799 Bottom := Top + 150;
32800 end;
32801 Result.ImageListSmall := ImageListSmall;
32802 Result.ImageListNormal := ImageListNormal;
32803 Result.ImageListState := ImageListState;
32804 Result.fLVTextBkColor := clWindow;
32805 Result.fLookTabKeys := [ tkTab ];
32806 //Result.fMargin := 0;
32807 end;
32808 {$ENDIF ASM_VERSION}
32809 //[END NewListView]
32811 {$ENDIF USE_CONSTRUCTORS}
32813 //===================== Tree view ========================//
32815 //[FUNCTION WndProcTreeView]
32816 {$IFDEF ASM_VERSION}
32817 function WndProcTreeView( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32818 asm //cmd //opd
32819 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
32820 JNZ @@ret_false
32821 PUSH EBX
32822 XCHG EBX, EAX
32823 MOV EDX, [EDX].TMsg.lParam
32824 LEA EAX, [EBX].TControl.fOnTVBeginDrag
32825 CMP word ptr [EDX].TNMTreeView.hdr.code, NM_RCLICK
32826 JNE @@chk_TVN_BEGINDRAG
32827 PUSH ECX
32828 PUSH ECX
32829 PUSH ESP
32830 CALL GetCursorPos
32831 MOV EAX, EBX
32832 MOV EDX, ESP
32833 MOV ECX, EDX
32834 CALL TControl.Screen2Client
32835 POP EAX
32836 AND EAX, $FFFF
32837 POP EDX
32838 SHL EDX, 16
32839 OR EAX, EDX
32840 PUSH EAX
32841 CALL GetShiftState
32842 PUSH EAX
32843 PUSH WM_RBUTTONUP
32844 PUSH [EBX].TControl.fHandle
32845 CALL PostMessage
32846 JMP @@2fin_false1
32848 @@chk_TVN_BEGINDRAG:
32849 {$IFDEF UNICODE_CTRLS}
32850 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINDRAGW
32851 JZ @@event_drag
32852 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINRDRAGW
32853 JZ @@event_drag
32854 {$ENDIF UNICODE_CTRLS}
32855 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINDRAG
32856 JZ @@event_drag
32857 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINRDRAG
32858 JNZ @@chk_BEGINLABELEDIT
32859 @@event_drag:
32860 MOV EDX, [EDX].TNMTreeView.itemNew.hItem
32861 @@event_call:
32862 MOV ECX, [EAX].TMethod.Code
32863 JECXZ @@2fin_false1
32864 MOV EAX, [EAX].TMethod.Data
32865 XCHG EBX, ECX
32866 XCHG EDX, ECX
32867 CALL EBX
32868 @@2fin_false1: JMP @@fin_false
32869 @@chk_BEGINLABELEDIT:
32870 LEA EAX, [EBX].TControl.fOnTVBeginEdit
32871 {$IFDEF UNICODE_CTRLS}
32872 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINLABELEDITW
32873 JZ @@beginlabeledit
32874 {$ENDIF UNICODE_CTRLS}
32875 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINLABELEDIT
32876 JNZ @@chk_ITEMEXPANDED //@@chk_DELETEITEM
32877 @@beginlabeledit:
32879 CMP [EBX].TControl.fDragging, 0
32880 JZ @@allow_LABELEDIT
32881 XOR EAX, EAX
32882 INC EAX
32883 MOV [ECX], EAX
32884 JMP @@ret_true
32886 @@allow_LABELEDIT:
32887 PUSH ECX // @Rslt
32889 MOV ECX, [EAX].TMethod.Code
32890 JECXZ @@2fin_false1
32891 PUSH EBX
32892 XCHG EBX, ECX
32893 MOV EDX, [EDX].TTVDispInfo.item.hItem
32894 XCHG EDX, ECX
32895 MOV EAX, [EAX].TMethod.Data
32896 CALL EBX
32897 TEST AL, AL
32898 SETZ AL // Rslt := not event result;
32899 POP EBX
32900 JZ @@ret_EAX
32901 INC [EBX].TControl.fEditing
32902 JMP @@ret_EAX
32904 @@call_EBX:
32905 CALL EBX
32906 @@2fin_false:
32907 JMP @@fin_false
32908 @@chk_ITEMEXPANDED:
32909 LEA EAX, [EBX].TControl.fOnTVExpanded
32910 {$IFDEF UNICODE_CTRLS}
32911 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDEDW
32912 JZ @@itemexpanded
32913 {$ENDIF UNICODE_CTRLS}
32914 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDED
32915 JNZ @@chk_SELCHANGING
32916 @@itemexpanded:
32917 MOV ECX, [EAX].TMethod.Code
32918 JECXZ @@2fin_false
32919 CMP [EDX].TNMTreeView.action, TVE_EXPAND
32920 PUSH ECX
32921 SETZ CL
32922 XCHG ECX, [ESP]
32923 JMP @@event_drag
32924 @@chk_SELCHANGING:
32925 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGING
32926 JNE @@chk_ITEMEXPANDING
32927 XCHG EAX, ECX
32928 MOV ECX, [EBX].TControl.fOnTVSelChanging.TMethod.Code
32929 @@2fin_false2:
32930 JECXZ @@2fin_false
32931 PUSH EAX //@Rslt
32932 PUSH [EDX].TNMTreeView.itemNew.hItem
32933 XCHG ECX, EBX //EBX=OnTVSelChanging.Code ECX=Sender
32934 XCHG ECX, EDX //EDX=Sender ECX=Msg
32935 MOV ECX, [ECX].TNMTreeView.itemOld.hItem
32936 MOV EAX, [EDX].TControl.fOnTVSelChanging.TMethod.Data
32937 JMP @@111
32939 @@chk_ITEMEXPANDING:
32940 {$IFDEF UNICODE_CTRLS}
32941 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDINGW
32942 JZ @@itemexpanding
32943 {$ENDIF UNICODE_CTRLS}
32944 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDING
32945 JNE @@chk_ENDLABELEDIT
32946 @@itemexpanding:
32947 XCHG EAX, ECX
32948 MOV ECX, [EBX].TControl.fOnTVExpanding.TMethod.Code
32949 JECXZ @@2fin_false2
32950 PUSH EAX // @Rslt
32951 CMP [EDX].TNMTreeView.action, TVE_EXPAND
32952 PUSH ECX
32953 SETZ CL
32954 XCHG ECX, [ESP]
32955 XCHG ECX, EBX //EBX=OnTVExpanding.Code ECX=Seneder
32956 XCHG EDX, ECX //ECX=Msg EDX=Sender
32957 MOV ECX, [ECX].TNMTreeView.itemNew.hItem //ECX=Item
32958 MOV EAX, [EDX].TControl.fOnTVExpanding.TMethod.Data //EAX=object
32959 @@111:
32960 CALL EBX
32961 TEST EAX, EAX
32962 SETZ AL // Rslt := not event result;
32963 @@ret_EAX:
32964 POP EDX //EDX=@Rslt
32965 MOVZX EAX, AL
32966 NEG EAX
32967 MOV [EDX], EAX
32968 @@ret_true:
32969 MOV AL, 1
32970 POP EBX
32972 @@chk_ENDLABELEDIT:
32973 {$IFDEF UNICODE_CTRLS}
32974 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ENDLABELEDITW
32975 JZ @@endlabeledit
32976 {$ENDIF UNICODE_CTRLS}
32977 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ENDLABELEDIT
32978 JNZ @@chk_SELCHANGED
32979 @@endlabeledit:
32980 MOV [EBX].TControl.fEditing, 0
32981 XCHG EAX, ECX
32982 MOV ECX, [EBX].TControl.fOnTVEndEdit.TMethod.Code
32983 JECXZ @@ret_1
32984 PUSH EAX
32985 PUSH EBX
32986 PUSH 0
32988 XCHG EDX, EBX
32989 MOV EAX, [EBX].TTVDispInfo.item.pszText
32990 PUSH EDX
32991 PUSH ECX
32992 XCHG EAX, EDX
32993 {$IFDEF UNICODE_CTRLS}
32994 CMP [EBX].TNMTreeView.hdr.code, TVN_ENDLABELEDITW
32995 JNZ @@endlabeleditA
32996 CALL TControl.TVGetItemTextW
32997 JMP @@NewTxt_ready
32998 @@endlabeleditA:
32999 {$ENDIF UNICODE_CTRLS}
33000 TEST EDX, EDX
33001 JNZ @@prepare_NewTxt
33002 // NewTxt := [EDX].TControl.TVItemText[ hItem ]
33003 LEA ECX, [ESP + 8]
33004 MOV EDX, [EBX].TTVDispInfo.item.hItem
33005 CALL TControl.TVGetItemText
33006 JMP @@NewTxt_ready
33007 @@prepare_NewTxt:
33008 LEA EAX, [ESP+8]
33009 CALL System.@LStrFromPChar
33010 @@NewTxt_ready:
33011 POP ECX
33012 POP EDX
33013 POP EAX
33014 PUSH EAX
33015 PUSH EAX
33016 MOV EAX, [EDX].TControl.fOnTVEndEdit.TMethod.Data
33017 MOV EBX, [EBX].TTVDispInfo.item.hItem
33018 XCHG ECX, EBX
33019 CALL EBX
33020 XCHG EBX, EAX
33021 CALL RemoveStr
33022 XCHG EAX, EBX
33023 POP EBX
33024 JMP @@ret_EAX
33025 @@ret_1:
33026 INC ECX
33027 MOV [EAX], ECX
33028 JMP @@ret_true
33030 @@chk_SELCHANGED:
33031 {$IFDEF UNICODE_CTRLS}
33032 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGEDW
33033 JZ @@selchanged
33034 {$ENDIF UNICODE_CTRLS}
33035 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGED
33036 JNZ @@fin_false
33037 @@selchanged:
33038 XCHG EAX, EBX
33039 CALL TControl.DoSelChange
33041 @@fin_false:
33042 POP EBX
33043 @@ret_false:
33044 XOR EAX, EAX
33045 end;
33046 {$ELSE ASM_VERSION} //Pascal
33047 function WndProcTreeView( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33048 var NM: PNMTreeView;
33049 DI: PTVDispInfo;
33050 P: TPoint;
33051 S: String;
33052 begin
33053 if Msg.message = WM_NOTIFY then
33054 begin
33055 NM := Pointer( Msg.lParam );
33056 case NM.hdr.code of
33057 NM_RCLICK:
33058 begin
33059 GetCursorPos( P );
33060 P := Self_.Screen2Client( P );
33061 PostMessage( Self_.fHandle, WM_RBUTTONUP, MK_RBUTTON or GetShiftState,
33062 (P.x and $FFFF) or (P.y shl 16) );
33063 end;
33065 {$IFDEF UNICODE_CTRLS}
33066 TVN_BEGINDRAGW, TVN_BEGINRDRAGW,
33067 {$ENDIF} TVN_BEGINDRAG, TVN_BEGINRDRAG:
33068 if Assigned( Self_.fOnTVBeginDrag ) then
33069 Self_.fOnTVBeginDrag( Self_, NM.itemNew.hItem );
33070 TVN_BEGINLABELEDIT {$IFDEF UNICODE_CTRLS}, TVN_BEGINLABELEDITW{$ENDIF}:
33071 begin
33072 if Self_.fDragging then
33073 begin
33074 Rslt := 1; // do not allow edit while dragging
33075 Result := TRUE;
33076 Exit;
33077 end;
33078 DI := Pointer( NM );
33079 if Assigned( Self_.fOnTVBeginEdit ) then
33080 begin
33081 Rslt := Integer( not Self_.fOnTVBeginEdit( Self_, DI.item.hItem ) );
33082 if Rslt = 0 then
33083 Self_.fEditing := TRUE;
33084 Result := TRUE;
33085 Exit;
33086 end;
33087 end;
33088 TVN_ENDLABELEDIT {$IFDEF UNICODE_CTRLS}, TVN_ENDLABELEDITW {$ENDIF}:
33089 begin
33090 DI := Pointer( NM );
33091 if Assigned( Self_.fOnTVEndEdit ) then
33092 begin
33093 S := DI.item.pszText;
33094 if DI.item.pszText = nil then
33095 begin
33096 {$IFDEF UNICODE_CTRLS}
33097 if NM.hdr.code = TVN_ENDLABELEDITW then
33098 S := Self_.TVItemTextW[ DI.item.hItem ]
33099 else
33100 {$ENDIF UNICODE_CTRLS}
33101 S := Self_.TVItemText[ DI.item.hItem ];
33102 end;
33103 if Self_.fOnTVEndEdit( Self_, DI.item.hItem, S )
33104 then Rslt := 1
33105 else Rslt := 0;
33107 else
33108 Rslt := 1;
33109 Self_.fEditing := FALSE;
33110 Result := True;
33111 Exit;
33112 end;
33113 TVN_ITEMEXPANDING {$IFDEF UNICODE_CTRLS}, TVN_ITEMEXPANDINGW {$ENDIF}:
33114 begin
33115 if Assigned( Self_.fOnTVExpanding ) then
33116 begin
33117 Rslt := Integer( not Self_.fOnTVExpanding( Self_, NM.itemNew.hItem,
33118 NM.action = TVE_EXPAND ) );
33119 Result := TRUE;
33120 Exit;
33121 end;
33122 end;
33123 TVN_ITEMEXPANDED {$IFDEF UNICODE_CTRLS}, TVN_ITEMEXPANDEDW {$ENDIF}:
33124 if Assigned( Self_.fOnTVExpanded ) then
33125 Self_.fOnTVExpanded( Self_, NM.itemNew.hItem, NM.action=TVE_EXPAND );
33126 {TVN_DELETEITEM:
33127 if Assigned( Self_.fOnTVDelete ) then
33128 Self_.fOnTVDelete( Self_, NM.itemOld.hItem );}
33129 //------------------ by Sergey Shisminzev:
33130 TVN_SELCHANGING {$IFDEF UNICODE_CTRLS}, TVN_SELCHANGINGW {$ENDIF}:
33131 begin
33132 if Assigned( Self_.fOnTVSelChanging ) then
33133 begin
33134 Rslt := Integer( not Self_.fOnTVSelChanging( Self_, NM.itemOld.hItem, NM.itemNew.hItem ) );
33135 Result := TRUE;
33136 Exit;
33137 end;
33138 end;
33139 //----------------------------------------
33140 TVN_SELCHANGED {$IFDEF UNICODE_CTRLS}, TVN_SELCHANGEDW {$ENDIF}:
33141 Self_.DoSelChange;
33142 end;
33143 end;
33144 Result := False;
33145 end;
33146 {$ENDIF ASM_VERSION}
33147 //[END WndProcTreeView]
33149 //[function ProcTVDeleteItem]
33150 function ProcTVDeleteItem( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33151 var NM: PNMTreeView;
33152 begin
33153 if Msg.message = WM_NOTIFY then
33154 begin
33155 NM := Pointer( Msg.lParam );
33156 case NM.hdr.code of
33157 TVN_DELETEITEM:
33158 if Assigned( Self_.fOnTVDelete ) then
33159 Self_.fOnTVDelete( Self_, NM.itemOld.hItem );
33160 end;
33161 end;
33162 Result := FALSE;
33163 end;
33165 //[procedure ClearTreeView]
33166 procedure ClearTreeView( TV: PControl );
33167 begin
33168 TV.TVDelete( TVI_ROOT );
33169 end;
33171 const
33172 TreeViewFlags: array[ TTreeViewOption ] of Integer = ( not TVS_HASLINES, TVS_LINESATROOT,
33173 not TVS_HASBUTTONS, TVS_EDITLABELS, not TVS_SHOWSELALWAYS,
33174 not TVS_DISABLEDRAGDROP, TVS_NOTOOLTIPS, TVS_CHECKBOXES,
33175 TVS_TRACKSELECT, TVS_SINGLEEXPAND, TVS_INFOTIP,
33176 TVS_FULLROWSELECT, TVS_NOSCROLL, TVS_NONEVENHEIGHT );
33178 {$IFDEF USE_CONSTRUCTORS}
33179 //[function NewTreeView]
33180 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
33181 ImgListNormal, ImgListState: PImageList ): PControl;
33182 begin
33183 new( Result, CreateTreeView( AParent, Options, ImgListNormal, ImgListState ) );
33184 end;
33185 {$ELSE not_USE_CONSTRUCTORS}
33187 //[FUNCTION NewTreeView]
33188 {$IFDEF ASM_VERSION}
33189 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
33190 ImgListNormal, ImgListState: PImageList ): PControl;
33191 asm //cmd //opd
33192 PUSH EBX
33193 PUSH ECX
33194 PUSH EAX
33195 PUSH EDX
33196 MOV EAX, ESP
33197 MOV EDX, offset[TreeViewFlags]
33198 XOR ECX, ECX
33199 MOV CL, 13
33200 CALL MakeFlags
33201 POP EDX
33202 OR EAX, WS_VISIBLE or WS_CHILD or WS_TABSTOP
33203 XCHG ECX, EAX
33204 POP EAX
33205 MOV EDX, offset[WC_TREEVIEW]
33206 PUSH 1
33207 PUSH offset[TreeViewActions]
33208 CALL _NewCommonControl
33209 MOV EBX, EAX
33210 MOV [EBX].TControl.fCreateWndExt, offset[ApplyImageLists2Control]
33211 MOV [EBX].TControl.fColor, clWindow
33212 MOV EDX, offset[WndProcTreeView]
33213 CALL TControl.AttachProc
33214 ADD [EBX].TControl.fBoundsRect.Right, 150-64
33215 ADD [EBX].TControl.fBoundsRect.Bottom, 200-64
33216 MOV EAX, EBX
33217 XOR EDX, EDX
33218 MOV DL, 32
33219 POP ECX // ImageListNormal
33220 CALL TControl.SetImgListIdx
33221 MOV EAX, EBX
33222 XOR EDX, EDX
33223 MOV ECX, [ImgListState]
33224 CALL TControl.SetImgListIdx
33225 MOV byte ptr [EBX].TControl.fLookTabKeys, 1
33226 XCHG EAX, EBX
33227 POP EBX
33228 end;
33229 {$ELSE ASM_VERSION} //Pascal
33230 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
33231 ImgListNormal, ImgListState: PImageList ): PControl;
33232 var Flags: Integer;
33233 begin
33234 Flags := MakeFlags( @Options, TreeViewFlags );
33235 Result := _NewCommonControl( AParent, WC_TREEVIEW, Flags or WS_VISIBLE or
33236 WS_CHILD or WS_TABSTOP, True, @TreeViewActions );
33237 Result.fCreateWndExt := ApplyImageLists2Control;
33238 Result.fColor := clWindow;
33239 Result.AttachProc( WndProcTreeView );
33240 with Result.fBoundsRect do
33241 begin
33242 Right := Left + 150;
33243 Bottom := Top + 200;
33244 end;
33245 Result.ImageListNormal := ImgListNormal;
33246 Result.ImageListState := ImgListState;
33247 //Result.fLVTextBkColor := clWindow;
33248 Result.fLookTabKeys := [ tkTab ];
33249 end;
33250 {$ENDIF ASM_VERSION}
33251 //[END NewTreeView]
33253 {$ENDIF USE_CONSTRUCTORS}
33255 //===================== Tab Control ========================//
33257 //[FUNCTION WndProcTabControl]
33258 {$IFDEF ASM_VERSION}
33259 function WndProcTabControl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33260 asm //cmd //opd
33261 PUSH EBP
33262 PUSH EBX
33263 PUSH ESI
33264 PUSH EDI
33265 MOV EBX, EAX
33266 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
33267 JNZ @@chk_WM_SIZE
33268 MOV EDX, [EDX].TMsg.lParam
33269 CMP word ptr [EDX].TNMHdr.code, TCN_SELCHANGE
33270 JNZ @@ret_false
33272 CALL TControl.GetCurIndex
33273 XCHG EDI, EAX
33274 CMP EDI, [EBX].TControl.fCurIndex
33275 PUSHFD // WasActive = ZF
33277 MOV [EBX].TControl.FCurIndex, EDI
33279 MOV EAX, EBX
33280 CALL TControl.GetItemsCount
33281 XCHG ESI, EAX // ESI := Self_.Count
33283 @@loo: DEC ESI
33284 JS @@e_loo
33285 MOV EDX, ESI
33286 MOV EAX, EBX
33287 CALL TControl.GetPages
33289 CMP ESI, EDI
33290 PUSH EAX
33291 SETZ DL
33292 CALL TControl.SetVisible
33293 POP EAX
33294 CMP ESI, EDI
33295 JNE @@nx_loo
33296 CALL TControl.BringToFront
33297 @@nx_loo:
33298 JMP @@loo
33299 @@e_loo:
33300 MOV EAX, EBX
33301 CALL TControl.ParentForm
33302 TEST EAX, EAX
33303 JZ @@1
33304 MOV ECX, [EAX].TControl.fCurrentControl
33305 JECXZ @@1
33306 MOV EAX, EBX
33307 MOV DL, 1
33308 CALL TControl.SetFocused
33309 MOV EAX, EBX
33310 CALL TControl.Invalidate
33311 TEST byte ptr [EBX].TControl.fStyle+1, $10
33312 JNZ @@1
33313 MOV EAX, EBX
33314 XOR EDX, EDX
33315 MOV DL, VK_TAB
33316 CALL TControl.GotoControl
33317 @@1:
33318 POPFD
33319 JZ @@ret_false
33321 MOV ECX, [EBX].TControl.fOnSelChange.TMethod.Code
33322 JECXZ @@ret_false
33323 MOV EDX, EBX
33324 MOV EAX, [EBX].TControl.fOnSelChange.TMethod.Data
33325 CALL ECX
33326 JMP @@ret_false
33327 @@chk_WM_SIZE:
33328 CMP word ptr [EDX].TMsg.message, WM_SIZE
33329 JNE @@ret_false
33330 ADD ESP, -16
33331 PUSH ESP
33332 PUSH [EBX].TControl.fHandle
33333 CALL Windows.GetClientRect
33334 PUSH ESP
33335 PUSH 0
33336 PUSH TCM_ADJUSTRECT
33337 PUSH EBX
33338 CALL TControl.Perform
33339 MOV EAX, EBX
33340 CALL TControl.GetItemsCount
33341 XCHG ESI, EAX
33342 @@loo2:
33343 DEC ESI
33344 JS @@e_loo2
33345 MOV EDX, ESI
33346 MOV EAX, EBX
33347 CALL TControl.GetPages
33348 MOV EDX, ESP
33349 CALL TControl.SetBoundsRect
33350 JMP @@loo2
33351 @@e_loo2:
33352 ADD ESP, 16
33353 @@ret_false:
33354 XOR EAX, EAX
33355 POP EDI
33356 POP ESI
33357 POP EBX
33358 POP EBP
33359 end;
33360 {$ELSE ASM_VERSION} //Pascal
33361 function WndProcTabControl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33362 var Hdr: PNMHdr;
33363 Page: PControl;
33364 I, A: Integer;
33365 R: TRect;
33366 Form: PControl;
33367 WasActive: Boolean;
33368 begin
33369 case Msg.message of
33370 WM_NOTIFY:
33371 begin
33372 Hdr := Pointer( Msg.lParam );
33373 case Hdr.code of
33374 TCN_SELCHANGE:
33375 begin
33376 A := Self_.Perform( TCM_GETCURSEL, 0, 0 );
33377 WasActive := Self_.fCurIndex = A;
33378 Self_.fCurIndex := A;
33379 for I := 0 to Self_.Count - 1 do
33380 begin
33381 Page := Self_.Pages[ I ];
33382 Page.Visible := A = I;
33383 if A = I then
33384 Page.BringToFront;
33385 end;
33386 Form := Self_.ParentForm;
33387 if Form <> nil then
33388 begin
33389 if Form.fCurrentControl <> nil then
33390 begin
33391 Self_.Focused := True;
33392 Self_.Invalidate;
33393 if not Longbool( Self_.fStyle and TCS_FOCUSONBUTTONDOWN ) then
33394 Self_.GotoControl( VK_TAB );
33395 end;
33396 end;
33397 if not WasActive then
33398 if Assigned( Self_.fOnSelChange ) then
33399 Self_.fOnSelChange( Self_ );
33400 //Result := True;
33401 end;
33402 end;
33403 end;
33404 WM_SIZE:
33405 begin
33406 GetClientRect( Self_.fHandle, R );
33407 Self_.Perform( TCM_ADJUSTRECT, 0, Integer( @R ) );
33408 for I := 0 to Self_.Count - 1 do
33409 begin
33410 Page := Self_.Pages[ I ];
33411 Page.BoundsRect := R;
33412 end;
33413 end;
33414 end;
33415 Result := False;
33416 end;
33417 {$ENDIF ASM_VERSION}
33418 //[END WndProcTabControl]
33420 const TabControlFlags: array[ TTabControlOption ] of Integer = ( TCS_BUTTONS,
33421 TCS_FIXEDWIDTH, not TCS_FOCUSNEVER,
33422 TCS_FIXEDWIDTH or TCS_FORCEICONLEFT, TCS_FIXEDWIDTH or TCS_FORCELABELLEFT,
33423 TCS_MULTILINE, TCS_MULTISELECT, TCS_RIGHTJUSTIFY, TCS_SCROLLOPPOSITE,
33424 TCS_BOTTOM, TCS_VERTICAL, TCS_FLATBUTTONS, TCS_HOTTRACK, 0, TCS_OWNERDRAWFIXED );
33426 {$IFDEF USE_CONSTRUCTORS}
33427 //[function NewTabControl]
33428 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
33429 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
33430 begin
33431 new( Result, CreateTabControl( AParent, Tabs, Options, ImgList, ImgList1stIdx ) );
33432 end;
33433 //[END NewTabControl]
33434 {$ELSE not_USE_CONSTRUCTORS}
33436 //[FUNCTION NewTabControl]
33437 {$IFDEF ASM_VERSION}
33438 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
33439 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
33440 asm //cmd //opd
33441 PUSH EBX
33442 PUSH ESI
33443 PUSH EDI
33444 XCHG EBX, EAX
33445 PUSH EDX
33446 PUSH ECX
33447 LEA EAX, [Options]
33448 MOV EDX, offset[TabControlFlags]
33449 XOR ECX, ECX
33450 MOV CL, 13
33451 CALL MakeFlags
33452 TEST byte ptr [Options], 4
33453 JZ @@0
33454 OR EAX, WS_TABSTOP or TCS_FOCUSONBUTTONDOWN
33455 @@0: OR EAX, WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_VISIBLE
33456 XCHG ECX, EAX
33457 XCHG EAX, EBX
33458 MOV EDX, offset[WC_TABCONTROL]
33459 PUSH 1
33460 PUSH offset[TabControlActions]
33461 CALL _NewCommonControl
33462 MOV EBX, EAX
33463 TEST [Options], 2 shl (tcoBorder - 1)
33464 JNZ @@borderfixed
33465 AND [EBX].TControl.fExStyle, not WS_EX_CLIENTEDGE
33466 @@borderfixed:
33467 MOV EDX, offset[WndProcTabControl]
33468 CALL TControl.AttachProc
33469 ADD [EBX].TControl.fBoundsRect.Right, 100-64
33470 ADD [EBX].TControl.fBoundsRect.Bottom, 100-64
33471 MOV ECX, [ImgList]
33472 JECXZ @@2
33473 XCHG EAX, ECX
33474 CALL TImageList.GetHandle
33475 PUSH EAX
33476 PUSH 0
33477 PUSH TCM_SETIMAGELIST
33478 PUSH EBX
33479 CALL TControl.Perform
33480 @@2:
33481 POP EDI // EDI = High(Tabs)
33482 POP ESI // ESI = Tabs
33483 XOR EDX, EDX // EBP := 0 (=I)
33484 MOV EAX, [ImgList1stIdx] //(=II)
33485 @@loop:
33486 CMP EDX, EDI
33487 JG @@e_loop
33488 PUSH EAX
33489 PUSH EDX
33490 PUSH EAX
33491 LODSD
33492 XCHG ECX, EAX
33493 MOV EAX, EBX
33494 CALL TControl.TC_Insert
33495 POP EDX
33496 POP EAX
33497 INC EAX
33498 INC EDX
33499 JMP @@loop
33500 @@e_loop:
33501 MOV byte ptr [EBX].TControl.fLookTabKeys, 1
33502 XCHG EAX, EBX
33503 POP EDI
33504 POP ESI
33505 POP EBX
33506 end;
33507 {$ELSE ASM_VERSION} //Pascal
33508 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
33509 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
33510 var I, II : Integer;
33511 Flags: Integer;
33512 begin
33513 Flags := MakeFlags( @Options, TabControlFlags );
33514 if tcoFocusTabs in Options then
33515 Flags := Flags or (WS_TABSTOP or TCS_FOCUSONBUTTONDOWN);
33516 Result := _NewCommonControl( AParent, WC_TABCONTROL,
33517 Flags or (WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_VISIBLE), True,
33518 @TabControlActions );
33519 //***
33520 if not( tcoBorder in Options ) then
33521 begin
33522 Result.fExStyle := Result.fExStyle and not WS_EX_CLIENTEDGE;
33523 end;
33524 Result.AttachProc( WndProcTabControl );
33525 with Result.fBoundsRect do
33526 begin
33527 Right := Left + 100;
33528 Bottom := Top + 100;
33529 end;
33530 if ImgList <> nil then
33531 Result.Perform( TCM_SETIMAGELIST, 0, ImgList.Handle );
33532 II := ImgList1stIdx;
33533 for I := 0 to High( Tabs ) do
33534 begin
33535 Result.TC_Insert( I, Tabs[ I ], II );
33536 Inc( II );
33537 end;
33538 Result.fLookTabKeys := [ tkTab ];
33539 end;
33540 {$ENDIF ASM_VERSION}
33541 //[END NewTabControl]
33543 {$ENDIF USE_CONSTRUCTORS}
33545 //===================== Tool bar ========================//
33547 //[FUNCTION WndProcToolbarCtr]
33548 {$IFDEF ASM_noVERSION} //TTN_NEEDTEXTW
33549 function WndProcToolbarCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
33551 CMP word ptr [EDX].TMsg.message, WM_WINDOWPOSCHANGED
33552 JNE @@chk_CM_COMMAND
33553 MOV dword ptr [ECX], 0 // Rslt := 0
33554 MOV ECX, [EAX].TControl.fOnResize.TMethod.Code
33555 JECXZ @@ret_true
33556 XCHG EDX, EAX // Sender := Self_
33557 MOV EAX, [EDX].TControl.fOnResize.TMethod.Data
33558 CALL ECX // Self_.fOnResize
33559 @@ret_true:
33560 MOV AL, 1 // Result := TRUE
33562 @@chk_CM_COMMAND:
33563 CMP word ptr [EDX].TMsg.message, CM_COMMAND
33564 JNE @@chk_WM_NOTIFY
33565 MOVZX ECX, word ptr [EDX].TMsg.wParam
33566 MOV [EAX].TControl.fCurItem, ECX
33567 PUSH EAX
33568 PUSH 0
33569 PUSH ECX
33570 PUSH TB_COMMANDTOINDEX
33571 PUSH EAX
33572 CALL TControl.Perform
33573 PUSH EAX
33575 PUSH VK_RETURN
33576 CALL GetKeyState
33577 TEST EAX, EAX
33578 SETL DL
33579 POP ECX
33580 POP EAX
33581 MOV [EAX].TControl.fCurIndex, ECX
33582 MOV [EAX].TControl.fRightClick, DL
33583 @@ret_false:
33584 XOR EAX, EAX
33587 @@chk_WM_NOTIFY:
33588 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
33589 JNE @@ret_false
33590 MOV EDX, [EDX].TMsg.lParam
33591 MOV ECX, [EDX].TTooltipText.hdr.code
33592 CMP ECX, TTN_NEEDTEXT
33593 JNE @@chk_NM_RCLICK
33594 PUSH EAX
33595 PUSH EDX
33596 MOV EDX, [EDX].TTooltipText.hdr.idFrom
33597 MOV ECX, [EAX].TControl.fTBttCmd
33598 OR EAX, -1
33599 JECXZ @@idxReady
33600 XCHG EAX, ECX
33601 CALL TList.IndexOf
33602 @@idxReady: // EAX = -1 or index of button tooltip
33603 TEST EAX, EAX
33604 POP EDX
33605 LEA EDX, [EDX].TTooltipText.szText
33606 MOV byte ptr [EDX], 0
33607 POP ECX
33608 JL @@ret_true
33609 MOV ECX, [ECX].TControl.fTBttTxt
33610 MOV ECX, [ECX].TStrList.fList
33611 MOV ECX, [ECX].TList.fItems
33612 MOV EAX, [ECX+EAX*4]
33613 XCHG EAX, EDX
33614 XOR ECX, ECX
33615 MOV CL, 79
33616 CALL StrLCopy
33617 JMP @@ret_true
33618 @@chk_NM_RCLICK:
33619 CMP ECX, NM_RCLICK
33620 JNE @@chk_NM_CLICK
33621 OR [EAX].TControl.fRightClick, 1
33622 MOV ECX, [EDX].TNMMouse.dwItemSpec
33623 MOV [EAX].TControl.fCurItem, -1
33624 PUSH EAX
33625 PUSH 0
33626 PUSH ECX
33627 PUSH TB_COMMANDTOINDEX
33628 PUSH EAX
33629 CALL TControl.Perform
33630 POP EDX
33631 MOV [EDX].TControl.fCurIndex, EAX
33632 XOR EAX, EAX
33634 @@chk_NM_CLICK:
33635 CMP ECX, NM_CLICK
33636 JNE @@chk_TBN_DROPDOWN
33637 MOV [EAX].TControl.fRightClick, 0
33638 OR [EAX].TControl.fCurItem, -1
33639 OR [EAX].TControl.fCurIndex, -1
33640 CMP [EDX].TTBNotify.iItem, -1
33641 SETNZ AL
33643 @@chk_TBN_DROPDOWN:
33644 CMP ECX, TBN_DROPDOWN
33645 JNE @@ret_false
33646 MOV EDX, [EDX].TTBNotify.iItem
33647 MOV [EAX].TControl.fCurItem, EDX
33648 PUSH EAX
33649 CALL TControl.TBItem2Index
33650 POP EDX
33651 MOV [EDX].TControl.fCurIndex, EAX
33652 MOV ECX, [EDX].TControl.fOnDropDown.TMethod.Code
33653 JECXZ @@ret_z
33654 MOV EAX, [EDX].TControl.fOnDropDown.TMethod.Data
33655 CALL ECX
33656 @@ret_z:
33657 XOR EAX, EAX
33658 end;
33659 {$ELSE ASM_VERSION} //Pascal
33660 function WndProcToolbarCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
33661 var lpttt: PTooltipText;
33662 idBtn, Idx: Integer;
33663 var Notify: PTBNotify;
33664 Mouse: PNMMouse;
33665 {$IFNDEF _FPC}
33666 {$IFNDEF _D2}
33667 var Wstr: WideString;
33668 {$ENDIF _D2}
33669 {$ENDIF _FPC}
33670 begin
33671 Result := False;
33672 if Msg.message = WM_WINDOWPOSCHANGED then
33673 begin
33674 if Assigned( Self_.fOnResize ) then
33675 Self_.fOnResize( Self_ );
33676 Result := TRUE;
33677 Rslt := 0;
33679 else if Msg.message = CM_COMMAND then
33680 begin
33681 Self_.fCurItem := Loword( Msg.wParam );
33682 Self_.fCurIndex := Self_.Perform( TB_COMMANDTOINDEX, Loword( Msg.wParam ), 0 );
33683 Self_.fRightClick := GetKeyState( VK_RBUTTON ) < 0;
33685 else if Msg.message = WM_NOTIFY then
33686 begin
33687 lpttt := Pointer( Msg.lParam );
33688 Notify := Pointer( Msg.lParam );
33689 case lpttt.hdr.code of
33690 TTN_NEEDTEXT:
33691 begin
33692 Result := True;
33693 idBtn := lpttt.hdr.idFrom;
33694 Idx := -1;
33695 if Self_.fTBttCmd <> nil then
33696 Idx := Self_.fTBttCmd.IndexOf( Pointer( idBtn ) );
33697 lpttt.szText[ 0 ] := #0;
33698 if Idx >= 0 then
33699 StrLCopy( lpttt.szText, Self_.fTBttTxt.fList.fItems[ Idx ], 79 );
33700 Exit;
33701 end;
33702 // for Windows XP
33703 {$IFNDEF _FPC}
33704 {$IFNDEF _D2}
33705 TTN_NEEDTEXTW:
33706 begin
33707 Result := True;
33708 idBtn := lpttt.hdr.idFrom;
33709 Idx := -1;
33710 if Self_.fTBttCmd <> nil then
33711 Idx := Self_.fTBttCmd.IndexOf( Pointer( idBtn ) );
33712 FillChar( lpttt.szText[ 0 ], 160, 0 );
33713 if Idx >= 0 then
33714 begin
33715 WStr := Self_.fTBttTxt.Items[ Idx ];
33716 if WStr <> '' then
33717 Move( Wstr[ 1 ], lpttt.szText, Min( 158, (Length( WStr ) + 1) * 2 ) );
33718 end;
33719 Exit;
33720 end;
33721 {$ENDIF _D2}
33722 {$ENDIF _FPC}
33723 NM_RCLICK:
33724 begin
33725 Mouse := Pointer( Msg.lParam );
33726 Self_.fCurItem := Mouse.dwItemSpec;
33727 Self_.fCurIndex := Self_.Perform( TB_COMMANDTOINDEX, Mouse.dwItemSpec, 0 );
33728 Self_.fRightClick := GetKeyState( VK_RBUTTON ) < 0;
33729 Self_.fRightClick := True;
33730 end;
33731 NM_CLICK:
33732 begin
33733 Self_.fCurItem := -1; // return CurItem = -1
33734 Self_.fCurIndex := -1;
33735 Self_.fRightClick := False;
33736 Result := Notify.iItem <> -1;
33737 // do not handle - if it will be handled in WM_COMMAND
33738 Exit;
33739 end;
33740 TBN_DROPDOWN:
33741 begin
33742 Self_.fCurItem := Notify.iItem;
33743 Self_.fCurIndex := Self_.TBItem2Index( Self_.fCurItem );
33744 if assigned( Self_.fOnDropDown ) then
33745 Self_.fOnDropDown( Self_ );
33746 end;
33747 end;
33748 end;
33749 end;
33750 {$ENDIF ASM_VERSION}
33751 //[END WndProcToolbarCtr]
33753 const ToolbarAligns: array[ TControlAlign ] of DWORD =
33754 ( 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,
33755 CCS_TOP );
33756 ToolbarOptions: array[ TToolbarOption ] of Integer = ( TBSTYLE_LIST, not TBSTYLE_LIST,
33757 TBSTYLE_FLAT, TBSTYLE_TRANSPARENT, TBSTYLE_WRAPABLE, CCS_NODIVIDER, 0 );
33759 {$IFDEF USE_CONSTRUCTORS}
33760 //[function NewToolbar]
33761 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
33762 Bitmap: HBitmap; Buttons: array of PChar;
33763 BtnImgIdxArray: array of Integer ) : PControl;
33764 begin
33765 new( Result, CreateToolbar( AParent, Align, Options, Bitmap, Buttons, BtnImgIdxArray ) );
33766 end;
33767 //[END NewToolbar]
33768 {$ELSE not_USE_CONSTRUCTORS}
33770 //[FUNCTION NewToolbar]
33771 {$IFDEF ASM_!VERSION}
33772 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
33773 Bitmap: HBitmap; Buttons: array of PChar;
33774 BtnImgIdxArray: array of Integer ) : PControl;
33775 const szTBButton = Sizeof( TTBButton );
33776 Option3DBorder = 1 shl Ord( tbo3DBorder );
33778 MOVZX EDX, DL
33779 PUSH EDX // Align
33780 PUSH EAX // AParent
33782 XOR EAX, EAX
33783 TEST CL, Option3DBorder
33784 SETNZ AL
33785 PUSH EAX
33787 PUSH ECX // Options
33789 MOV AL, ICC_BAR_CLASSES
33790 CALL DoInitCommonControls
33792 MOV EAX, ESP
33793 MOV EDX, offset[ToolbarOptions]
33794 XOR ECX, ECX
33795 MOV CL, 5
33796 CALL MakeFlags
33797 POP EDX
33799 PUSH 0
33800 XCHG ECX, EAX // ECX = MakeFlags(...)
33801 MOV EAX, [ESP+8] // EAX = AParent
33802 MOV EDX, [ESP+12] // EDX = Align
33803 OR ECX, [EDX*4+offset ToolbarAligns]
33804 OR ECX, WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS
33805 MOV EDX, offset[ TOOLBARCLASSNAME ]
33806 CALL _NewCommonControl
33807 MOV [EAX].TControl.fCommandActions.aClear, offset[ClearToolbar]
33808 MOV [EAX].TControl.fCommandActions.aGetCount, TB_BUTTONCOUNT
33809 INC [EAX].TControl.fIsButton
33810 POP EDX // pop AParent
33811 POP EDX // EDX = Align
33812 PUSH EDX
33813 TEST EDX, EDX
33814 JE @@zero_bounds
33815 ADD [EAX].TControl.fBoundsRect.Bottom, 26-64
33816 ADD [EAX].TControl.fBoundsRect.Right, 1000-64
33817 JMP @@bounds_ready
33818 @@zero_bounds:
33819 MOV [EAX].TControl.fBoundsRect.Left, EDX
33820 MOV [EAX].TControl.fBoundsRect.Top, EDX
33821 MOV [EAX].TControl.fBoundsRect.Right, EDX
33822 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
33823 @@bounds_ready:
33824 PUSH EBX
33825 PUSH ESI
33826 XCHG EBX, EAX
33827 MOV ESI, offset[TControl.Perform]
33828 PUSH 0
33829 PUSH 0
33830 PUSH TB_GETEXTENDEDSTYLE
33831 PUSH EBX
33832 CALL ESI
33833 OR EAX, TBSTYLE_EX_DRAWDDARROWS
33834 PUSH EAX
33835 PUSH 0
33836 PUSH TB_SETEXTENDEDSTYLE
33837 PUSH EBX
33838 CALL ESI
33839 MOV EDX, offset[WndProcToolbarCtrl]
33840 MOV EAX, EBX
33841 CALL TControl.AttachProc
33842 MOV EDX, offset[WndProcDoEraseBkgnd]
33843 MOV EAX, EBX
33844 CALL TControl.AttachProc
33845 PUSH 0
33846 PUSH szTBButton
33847 PUSH TB_BUTTONSTRUCTSIZE
33848 PUSH EBX
33849 CALL ESI
33850 PUSH 0
33851 PUSH [EBX].TControl.fMargin
33852 PUSH TB_SETINDENT
33853 PUSH EBX
33854 CALL ESI
33855 MOV EAX, [ESP+8] // Align
33856 {$IFDEF PARANOIA}
33857 DB $2C, 1
33858 {$ELSE}
33859 SUB AL, 1
33860 {$ENDIF}
33861 JL @@bounds_correct
33862 JE @@corr_right
33863 {$IFDEF PARANOIA}
33864 DB $2C, 2
33865 {$ELSE}
33866 SUB AL, 2
33867 {$ENDIF}
33868 JNE @@corr_bottom
33869 @@corr_right:
33870 MOV EDX, [EBX].TControl.fBoundsRect.Left
33871 ADD EDX, 24
33872 MOV [EBX].TControl.fBoundsRect.Right, EDX
33873 JMP @@bounds_correct
33874 @@corr_bottom:
33875 MOV EDX, [EBX].TControl.fBoundsRect.Top
33876 ADD EDX, 22
33877 MOV [EBX].TControl.fBoundsrect.Bottom, EDX
33878 @@bounds_correct:
33879 MOV EDX, [Bitmap]
33880 TEST EDX, EDX
33881 JZ @@bitmap_added
33882 MOV EAX, EBX
33883 CALL TControl.TBAddBitmap
33884 @@bitmap_added:
33886 PUSH dword ptr [BtnImgIdxArray]
33887 PUSH dword ptr [BtnImgIdxArray-4]
33888 MOV ECX, [Buttons-4]
33889 MOV EDX, [Buttons]
33890 MOV EAX, EBX
33891 CALL TControl.TBAddButtons
33893 PUSH 0
33894 PUSH 0
33895 PUSH WM_SIZE
33896 PUSH EBX
33897 CALL ESI
33899 XCHG EAX, EBX
33900 POP ESI
33901 POP EBX
33902 ///POP EDX ///!!! next command is MOV ESP,EBP
33903 end;
33904 {$ELSE ASM_VERSION} //Pascal
33905 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
33906 Bitmap: HBitmap; Buttons: array of PChar;
33907 BtnImgIdxArray: array of Integer ) : PControl;
33908 var Flags: DWORD;
33909 begin
33910 if not( tboTextBottom in Options ) then
33911 Options := Options + [ tboTextRight ];
33912 if tboTextRight in Options then
33913 Options := Options - [ tboTextBottom ];
33914 Flags := MakeFlags( @Options, ToolbarOptions );
33915 DoInitCommonControls( ICC_BAR_CLASSES );
33916 Result := _NewCommonControl( AParent, TOOLBARCLASSNAME,
33917 (ToolbarAligns[ Align ] or WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS or Flags),
33918 //(not (Align in [caNone])) and not (tboNoDivider in Options), nil );
33919 tbo3DBorder in Options, nil );
33920 Result.fCommandActions.aClear := ClearToolbar;
33921 Result.fCommandActions.aGetCount := TB_BUTTONCOUNT;
33922 Result.fIsButton := TRUE;
33923 with Result.fBoundsRect do
33924 begin
33925 if Align in [ caNone ] then
33926 begin
33927 Bottom := Top + 26;
33928 Right := Left + 1000;
33930 else
33931 begin
33932 Left := 0; Right := 0;
33933 Top := 0; Bottom := 0;
33934 end;
33935 end;
33936 Result.AttachProc( WndProcToolbarCtrl );
33937 Result.AttachProc( WndProcDoEraseBkgnd );
33938 Result.Perform(TB_SETEXTENDEDSTYLE, 0, Result.Perform(TB_GETEXTENDEDSTYLE, 0, 0) or
33939 TBSTYLE_EX_DRAWDDARROWS);
33941 Result.Perform( TB_BUTTONSTRUCTSIZE, Sizeof( TTBButton ), 0 );
33942 Result.Perform( TB_SETINDENT, Result.fMargin, 0 );
33943 with Result.fBoundsRect do
33944 begin
33945 if Align in [ caLeft, caRight ] then
33946 Right := Left + 24
33947 else if not (Align in [caNone]) then
33948 Bottom := Top + 22;
33949 end;
33950 if Bitmap <> 0 then
33951 Result.TBAddBitmap( Bitmap );
33952 Result.TBAddButtons( Buttons, BtnImgIdxArray );
33953 Result.Perform( WM_SIZE, 0, 0 );
33954 end;
33955 {$ENDIF ASM_VERSION}
33956 //[END NewToolbar]
33958 {$ENDIF USE_CONSTRUCTORS}
33960 //================== DateTimePicker =====================//
33962 function WndProcDateTimePickerNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33963 var NMhdr: PNMHdr;
33964 D: TDateTime;
33965 AllowChg: Boolean;
33966 NMDTString: PNMDateTimeString;
33967 begin
33968 Result := False;
33969 if Msg.message = WM_NOTIFY then
33970 begin
33971 NMHdr := Pointer( Msg.lParam );
33972 CASE NMHdr.code OF
33973 DTN_DROPDOWN: if Assigned( Self_.fOnDropDown ) then
33974 Self_.fOnDropDown( Self_ );
33975 DTN_CLOSEUP: if Assigned( Self_.fOnCloseUp ) then
33976 Self_.fOnCloseUp( Self_ );
33977 DTN_DATETIMECHANGE:
33978 if Assigned( Self_.fOnChange ) then
33979 Self_.fOnChange( Self_ );
33980 {DTN_FORMAT:
33981 Rslt := 0;}
33982 DTN_USERSTRING:
33983 if Assigned( Self_.fOnDTPUserString ) then
33984 begin
33985 NMDTString := Pointer( NMHdr );
33986 D := 0.0;
33987 AllowChg := TRUE;
33988 Self_.fOnDTPUserString( Self_, NMDTString.pszUserString, D, AllowChg );
33989 NMDTString.dwFlags := Integer( not AllowChg );
33990 end;
33991 END;
33992 end;
33993 end;
33995 const
33996 //( dtpoTime, dtpoDateLong, dtpoUpDown, dtpoRightAlign,
33997 // dtpoShowNone, dtpoParseInput )
33999 DateTimePickerOptions: array[ TDateTimePickerOption ] of Integer = (
34000 DTS_TIMEFORMAT, DTS_LONGDATEFORMAT, DTS_UPDOWN, DTS_RIGHTALIGN,
34001 DTS_SHOWNONE, DTS_APPCANPARSE );
34003 function NewDateTimePicker( AParent: PControl; Options: TDateTimePickerOptions )
34004 : PControl;
34005 var Flags: DWORD;
34006 const
34007 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS or
34008 CS_VREDRAW or CS_HREDRAW;
34009 begin
34010 DoInitCommonControls( ICC_DATE_CLASSES );
34011 Flags := MakeFlags( @Options, DateTimePickerOptions );
34012 Result := _NewCommonControl( AParent, DATETIMEPICK_CLASS,
34013 (WS_CHILD or WS_VISIBLE or WS_TABSTOP or Flags), TRUE, nil );
34014 //Result.ClsStyle := Result.ClsStyle and not CS_OFF;
34015 Result.SetSize( 110, 24 );
34016 Result.AttachProc( WndProcDateTimePickerNotify );
34017 end;
34019 procedure TControl.SetDateTime(Value: TDateTime);
34020 var ST: TSystemTime;
34021 begin
34022 DateTime2SystemTime( Value, ST );
34023 Perform( DTM_SETSYSTEMTIME, Integer( IsNAN( Value ) ) , Integer( @ ST ) );
34024 end;
34026 function TControl.GetDateTime: TDateTime;
34027 var ST: TSystemTime;
34028 begin
34029 if Perform( DTM_GETSYSTEMTIME, 0, Integer( @ ST ) ) = GDT_VALID then
34030 SystemTime2DateTime( ST, Result )
34031 else
34032 Result := NAN;
34033 end;
34035 function TControl.GetDate: TDateTime;
34036 begin
34037 Result := DateTime;
34038 if not IsNAN( Result ) then
34039 Result := Trunc( DateTime );
34040 end;
34042 function TControl.GetTime: TDateTime;
34043 begin
34044 Result := DateTime;
34045 if not IsNAN( Result ) then
34046 Result := Frac( Result );
34047 end;
34049 procedure TControl.SetDate(const Value: TDateTime);
34050 begin
34051 if IsNAN( Value ) then
34052 DateTime := Value
34053 else
34054 if not IsNAN( DateTime ) then
34055 DateTime := Trunc( Value ) + Frac( DateTime )
34056 else
34057 DateTime := Trunc( Value );
34058 end;
34060 procedure TControl.SetTime(const Value: TDateTime);
34061 begin
34062 if IsNAN( Value ) then
34063 DateTime := Value
34064 else
34065 if not IsNAN( DateTime ) then
34066 DateTime := Trunc( DateTime ) + Frac( Value )
34067 else
34068 DateTime := 1.0 + Frac( Value );
34069 end;
34071 function TControl.GetDateTimeRange: TDateTimeRange;
34072 var ST_R: array[ 0..1 ] of TSystemTime;
34073 begin
34074 Perform( DTM_GETRANGE, 0, Integer( @ ST_R[ 0 ] ) );
34075 SystemTime2DateTime( ST_R[ 0 ], Result[ 0 ] );
34076 SystemTime2DateTime( ST_R[ 1 ], Result[ 1 ] );
34077 end;
34079 procedure TControl.SetDateTimeRange(Value: TDateTimeRange);
34080 var ST_R: array[ 0..1 ] of TSystemTime;
34081 begin
34082 DateTime2SystemTime( Value[ 0 ], ST_R[ 0 ] );
34083 DateTime2SystemTime( Value[ 1 ], ST_R[ 1 ] );
34084 Perform( DTM_SETRANGE,
34085 Integer( IsNAN( Value[ 0 ] ) ) or
34086 (Integer( IsNAN( Value[ 1 ] ) ) shl 1),
34087 Integer( @ ST_R[ 0 ] ) );
34088 end;
34090 function TControl.GetDateTimePickerColor( Index: TDateTimePickerColor): TColor;
34091 begin
34092 Result := Perform( DTM_GETMCCOLOR, Integer( Index ), 0 );
34093 end;
34095 procedure TControl.SetDateTimePickerColor(
34096 Index: TDateTimePickerColor; Value: TColor);
34097 begin
34098 Perform( DTM_SETMCCOLOR, Integer( Index ), Color2RGB( Value ) );
34099 end;
34101 procedure TControl.SetDateTimeFormat(const Value: String);
34102 begin
34103 Perform( DTM_SETFORMAT, 0, Integer( PChar( Value ) ) );
34104 end;
34106 function MakeDateTimeRange( D1, D2: TDateTime ): TDateTimeRange;
34107 begin
34108 Result[ 0 ] := D1;
34109 Result[ 1 ] := D2;
34110 end;
34113 //===================== RichEdit ========================//
34115 type PENLink = ^TENLink;
34116 TENLink = packed record
34117 hdr: TNMHDR;
34118 msg: DWORD;
34119 wParam: Integer;
34120 lParam: Integer;
34121 chrg: TCHARRANGE;
34122 end;
34123 TEXTRANGEA = packed record
34124 chrg: TCharRange;
34125 lpstrText: PAnsiChar;
34126 end;
34128 //[FUNCTION WndProc_RE_LinkNotify]
34129 {$IFDEF ASM_VERSION}
34130 function WndProc_RE_LinkNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
34132 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
34133 JNE @@ret_false
34134 MOV EDX, [EDX].TMsg.lParam
34135 CMP [EDX].TNMHdr.code, EN_LINK
34136 JNE @@ret_false
34137 PUSH EBX
34138 PUSH EDX
34139 XCHG EBX, EAX
34140 XOR EAX, EAX
34141 MOV [ECX], EAX
34142 ADD ESP, -1020
34143 PUSH EAX
34144 PUSH ESP
34145 PUSH [EDX].TENLink.chrg.cpMax
34146 PUSH [EDX].TENLink.chrg.cpMin
34147 PUSH ESP
34148 PUSH 0
34149 PUSH EM_GETTEXTRANGE
34150 PUSH EBX
34151 CALL TControl.Perform
34152 ADD ESP, 12
34153 MOV EDX, ESP
34154 LEA EAX, [EBX].TControl.fREUrl
34155 CALL System.@LStrFromPChar
34156 ADD ESP, 1024
34157 POP EDX
34158 MOV ECX, [EDX].TENLink.msg
34159 LEA EAX, [EBX].TControl.fOnREOverURL
34160 CMP ECX, WM_MOUSEMOVE
34161 JE @@Url_event
34162 LEA EAX, [EBX].TControl.fOnREUrlClick
34163 CMP ECX, WM_LBUTTONDOWN
34164 JE @@Url_Event
34165 CMP ECX, WM_RBUTTONDOWN
34166 JNE @@after_Url_event
34167 @@Url_event:
34168 MOV ECX, [EAX].TMethod.Code
34169 JECXZ @@after_Url_event
34170 MOV EDX, EBX
34171 MOV EAX, [EAX].TMethod.Data
34172 CALL ECX
34173 @@after_Url_event:
34174 POP EBX
34175 MOV AL, 1
34177 @@ret_false:
34178 XOR EAX, EAX
34179 end;
34180 {$ELSE ASM_VERSION} //Pascal
34181 function WndProc_RE_LinkNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
34182 var Link: PENLink;
34183 Range: TextRangeA;
34184 Buffer: array[ 0..1023 ] of Char;
34185 begin
34186 Result := False;
34187 if (Msg.message = WM_NOTIFY) and (PNMHdr( Msg.lParam ).code = EN_LINK) then
34188 begin
34189 Link := Pointer( Msg.lParam );
34190 Range.chrg := Link.chrg;
34191 Range.lpstrText := @Buffer[ 0 ]; //Pchar( @Buffer[ 0 ] );
34192 Buffer[ 0 ] := #0;
34193 Self_.Perform( EM_GETTEXTRANGE, 0, Integer( @Range ) );
34194 Self_.fREUrl := Buffer;
34195 case Link.msg of
34196 WM_MOUSEMOVE:
34197 if assigned( Self_.fOnREOverURL ) then
34198 Self_.fOnREOverURL( Self_ );
34199 WM_LBUTTONDOWN, WM_RBUTTONDOWN:
34200 if assigned( Self_.fOnREUrlClick ) then
34201 Self_.fOnREUrlClick( Self_ );
34202 end;
34203 Rslt := 0;
34204 Result := TRUE;
34205 end;
34206 end;
34207 {$ENDIF ASM_VERSION}
34208 //[END WndProc_RE_LinkNotify]
34210 var Global_DisableParentCursor: Boolean;
34212 //[FUNCTION WndProcRichEditNotify]
34213 {$IFDEF ASM_noVERSION}
34214 function WndProcRichEditNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
34215 const int_IDC_ARROW = integer( IDC_ARROW );
34217 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
34218 JNE @@ret_false {YS}
34219 // JNE @@chk_WM_SETCURSOR {YS}
34220 MOV EDX, [EDX].TMsg.lParam
34221 CMP [EDX].TNMHdr.code, EN_SELCHANGE
34222 JNE @@ret_false
34223 //PUSH EAX
34224 CALL TControl.DoSelChange
34225 //POP EAX
34226 {CMP [EAX].TControl.fTransparent, 0
34227 JZ @@ret_false
34228 CALL TControl.Invalidate}
34229 @@ret_false:
34230 XOR EAX, EAX
34232 { //YS
34233 @@chk_WM_SETCURSOR:
34234 CMP word ptr [EDX].TMsg.message, WM_SETCURSOR
34235 JNE @@ret_false
34236 PUSH EBX
34237 MOV EBX, EAX
34238 PUSH ECX
34239 PUSH EDX
34240 INC [Global_DisableParentCursor]
34241 CALL TControl.CallDefWndProc
34242 DEC [Global_DisableParentCursor]
34243 POP EDX
34244 MOVZX EDX, word ptr [EDX].TMsg.lParam
34245 POP ECX
34246 MOV [ECX], EAX
34247 TEST EAX, EAX
34248 MOV EAX, [EBX].TControl.fCursor
34249 POP EBX
34250 JNZ @@ret_true
34251 INC dword ptr [ECX]
34252 CMP EDX, HTCLIENT
34253 JE @@set_cursor
34254 CMP EDX, HTVSCROLL
34255 JE @@set_arrow_cursor
34256 CMP EDX, HTHSCROLL
34257 JNE @@ret_false
34258 @@set_arrow_cursor:
34259 PUSH int_IDC_ARROW
34260 PUSH 0
34261 CALL LoadCursor
34262 @@set_cursor:
34263 PUSH EAX
34264 CALL Windows.SetCursor
34265 @@ret_true:
34266 MOV AL, 1
34268 end;
34269 {$ELSE ASM_VERSION} //Pascal
34270 function WndProcRichEditNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
34271 var NMhdr: PNMHdr;
34272 // TestCode: Integer;
34273 {FR: TFormatRange;
34274 I: Integer;
34275 R: TRect;
34276 LogX, LogY: Integer;}
34277 begin
34278 Result := False;
34279 if Msg.message = WM_NOTIFY then
34280 begin
34281 NMHdr := Pointer( Msg.lParam );
34282 case NMHdr.code of
34283 EN_SELCHANGE:
34284 begin
34285 Self_.DoSelChange;
34286 if Self_.fTransparent then
34287 Self_.Invalidate;
34288 end;
34289 end;
34291 { // YS
34292 else
34293 if Msg.message = WM_SETCURSOR then
34294 begin
34295 Result := True;
34296 TestCode := LoWord( Msg.lParam );
34297 Global_DisableParentCursor := True;
34298 Rslt := Self_.CallDefWndProc( Msg );
34299 Global_DisableParentCursor := False;
34300 if Rslt = 0 then
34301 begin
34302 Rslt := 1;
34303 case TestCode of
34304 HTVSCROLL, HTHSCROLL: Windows.SetCursor( LoadCursor( 0, IDC_ARROW ) );
34305 HTCLIENT: Windows.SetCursor( Self_.fCursor );
34306 else Result := False;
34307 end;
34308 end;
34309 end;
34311 end;
34312 {$ENDIF ASM_VERSION}
34313 //[END WndProcRichEditNotify]
34315 var FRichEditModule: Integer;
34316 RichEditClass: PChar = 'RichEdit20A';
34317 RichEditLib: PChar = 'RICHED32.DLL';
34319 const RichEditLibnames: array[ 0..2 ] of PChar =
34320 ( 'RICHED20.DLL', 'RICHED32.DLL', 'RICHED.DLL' );
34321 const RichEditflags: array [ TEditOption ] of Integer = (
34322 not (es_AutoHScroll or WS_HSCROLL),
34323 not (es_AutoVScroll or WS_VSCROLL),
34324 0 {es_Lowercase - not supported},
34325 0 {es_Multiline - RichEdit always multiline},
34326 es_NoHideSel,
34327 0 {es_OemConvert - not suppoted},
34328 0 {es_Password - not supported},
34329 es_Readonly,
34330 0 {es_UpperCase - not supported},
34331 es_WantReturn, 0, es_Number );
34333 {$IFDEF USE_CONSTRUCTORS}
34334 //[function NewRichEdit1]
34335 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
34336 begin
34337 new( Result, CreateRichEdit1( AParent, Options ) );
34338 end;
34339 //[END NewRichEdit1]
34340 {$ELSE not_USE_CONSTRUCTORS}
34342 //[FUNCTION NewRichEdit1]
34343 {$IFDEF ASM_VERSION}
34344 const RichEditClass10: array[0..8] of Char = ('R','i','c','h','E','d','i','t',#0);
34345 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
34347 PUSH EDX
34349 MOV ECX, [FRichEditModule]
34350 INC ECX
34351 LOOP @@loaded
34352 PUSHAD
34353 MOV BL, 3
34354 LEA ESI, [RichEditLibNames]
34355 @@loo:
34356 LODSD
34357 PUSH EAX
34358 CALL LoadLibrary
34359 CMP EAX, HINSTANCE_ERROR
34360 JG @@break
34361 MOV [RichEditClass], offset[RichEditClass10]
34362 DEC BL
34363 JNZ @@loo
34364 JMP @@fault
34365 @@break:
34366 MOV [FRichEditModule], EAX
34367 @@fault:
34368 POPAD
34369 @@loaded:
34370 PUSH EAX
34371 PUSH EDX
34372 MOV EAX, ESP
34373 MOV EDX, offset[RichEditFlags]
34374 XOR ECX, ECX
34375 MOV CL, 10
34376 CALL MakeFlags
34377 XCHG ECX, EAX
34378 POP EDX
34379 POP EAX
34380 PUSH 1
34381 PUSH offset[RichEditActions]
34382 MOV EDX, [RichEditClass]
34383 OR ECX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER or ES_MULTILINE
34384 CALL _NewCommonControl
34385 INC [EAX].TControl.fIgnoreDefault
34386 POP EDX
34387 TEST DH, 4 // is eoWantTab in Options ?
34388 SETZ DL
34389 MOV [EAX].TControl.fLookTabKeys, DL
34390 PUSH EBX
34391 MOV EBX, EAX
34392 MOV EDX, offset[WndProcRichEditNotify]
34393 CALL TControl.AttachProc
34394 MOV [EBX].TControl.fDoubleBuffered, 0
34395 INC [EBX].TControl.fCannotDoubleBuf
34396 ADD [EBX].TControl.fBoundsRect.Right, 100-64
34397 ADD [EBX].TControl.fBoundsRect.Bottom, 200-64
34398 PUSH ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or ENM_PROTECTED or $04000000
34399 PUSH 0
34400 PUSH EM_SETEVENTMASK
34401 PUSH EBX
34402 CALL TControl.Perform
34403 MOV EAX, clWindow
34404 MOV [EBX].TControl.fColor, EAX
34405 CALL Color2RGB
34406 PUSH EAX
34407 PUSH 0
34408 PUSH EM_SETBKGNDCOLOR
34409 PUSH EBX
34410 CALL TControl.Perform
34411 XCHG EAX, EBX
34412 POP EBX
34413 end;
34414 {$ELSE ASM_VERSION} //Pascal
34415 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
34416 var Flags, I: Integer;
34417 begin
34418 if FRichEditModule = 0 then
34419 begin
34420 for I := 0 to 2 do
34421 begin
34422 FRichEditModule := LoadLibrary( RichEditLibnames[ I ] );
34423 if FRichEditModule > HINSTANCE_ERROR then break;
34424 RichEditClass := 'RichEdit';
34425 end;
34426 if FRichEditModule <= HINSTANCE_ERROR then
34427 FRichEditModule := 0;
34428 end;
34429 Flags := MakeFlags( @Options, RichEditFlags );
34430 Result := _NewCommonControl( AParent, RichEditClass, WS_VISIBLE or WS_CHILD
34431 or WS_TABSTOP or WS_BORDER or ES_MULTILINE or Flags,
34432 True, @RichEditActions );
34433 Result.fIgnoreDefault := TRUE;
34434 Result.fLookTabKeys := [ tkTab ];
34435 if eoWantTab in Options then
34436 Result.fLookTabKeys := [ ];
34438 Result.AttachProc( WndProcRichEditNotify );
34439 Result.fDoubleBuffered := False;
34440 Result.fCannotDoubleBuf := True;
34441 with Result.fBoundsRect do
34442 begin
34443 Right := Right + 100;
34444 Bottom := Top + 200;
34445 end;
34446 Result.Perform( EM_SETEVENTMASK, 0,
34447 ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or
34448 ENM_PROTECTED or $04000000 {ENM_LINK} or ENM_KEYEVENTS {or ENM_MOUSEEVENTS} );
34449 Result.fColor := clWindow;
34450 Result.Perform( EM_SETBKGNDCOLOR, 0, Color2RGB(Result.fColor));
34451 //Result.Perform( WM_SIZE, 0, 0 );
34452 end;
34453 {$ENDIF ASM_VERSION}
34454 //[END NewRichEdit1]
34456 {$ENDIF USE_CONSTRUCTORS}
34458 //[API OleInitialize]
34459 function OleInitialize(pwReserved: Pointer): HResult; stdcall;
34460 external 'ole32.dll' name 'OleInitialize';
34461 procedure OleUninitialize; stdcall;
34462 external 'ole32.dll' name 'OleUninitialize';
34464 //[FUNCTION OleInit]
34465 {$IFDEF ASM_VERSION}
34466 function OleInit: Boolean;
34468 MOV ECX, [OleInitCount]
34469 INC ECX
34470 LOOP @@init1
34471 PUSH ECX
34472 CALL OleInitialize
34473 TEST EAX, EAX
34474 MOV AL, 0
34475 JNZ @@exit
34476 @@init1:
34477 INC [OleInitCount]
34478 MOV AL, 1
34479 @@exit:
34480 end;
34481 {$ELSE ASM_VERSION} //Pascal
34482 function OleInit: Boolean;
34483 begin
34484 if OleInitCount = 0 then
34485 begin
34486 Result := False;
34487 if OleInitialize( nil ) <> 0 then Exit;
34488 end;
34489 Inc( OleInitCount );
34490 Result := True;
34491 end;
34492 {$ENDIF ASM_VERSION}
34493 //[END OleInit]
34495 //[PROCEDURE OleUnInit]
34496 {$IFDEF ASM_VERSION}
34497 procedure OleUnInit;
34499 MOV ECX, [OleInitCount]
34500 JECXZ @@exit
34501 DEC [OleInitCount]
34502 JNZ @@exit
34503 CALL OleUninitialize
34504 @@exit:
34505 end;
34506 {$ELSE ASM_VERSION} //Pascal
34507 procedure OleUnInit;
34508 begin
34509 if OleInitCount > 0 then
34510 begin
34511 Dec( OleInitCount );
34512 if OleInitCount = 0 then
34513 OleUninitialize;
34514 end;
34515 end;
34516 {$ENDIF ASM_VERSION}
34517 //[END OleUnInit]
34519 //[API SysAllocStringLen]
34520 function SysAllocStringLen;
34521 external 'oleaut32.dll' name 'SysAllocStringLen';
34522 procedure SysFreeString( psz: PWideChar ); stdcall;
34523 external 'oleaut32.dll' name 'SysFreeString';
34526 //[function StringToOleStr]
34527 function StringToOleStr(const Source: string): PWideChar;
34529 SourceLen, ResultLen: Integer;
34530 Buffer: array[0..1023] of WideChar;
34531 begin
34532 SourceLen := Length(Source);
34533 if Length(Source) < SizeOf(Buffer) div 2 then
34534 Result := SysAllocStringLen(Buffer, MultiByteToWideChar(0, 0,
34535 PChar(Source), SourceLen, Buffer, SizeOf(Buffer) div 2))
34536 else
34537 begin
34538 ResultLen := MultiByteToWideChar(0, 0,
34539 Pointer(Source), SourceLen, nil, 0);
34540 Result := SysAllocStringLen(nil, ResultLen);
34541 MultiByteToWideChar(0, 0, Pointer(Source), SourceLen,
34542 Result, ResultLen);
34543 end;
34544 end;
34547 {$IFDEF USE_CONSTRUCTORS}
34548 //[function NewRichEdit]
34549 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
34550 begin
34551 new( Result, CreateRichEdit( AParent, Options ) );
34552 end;
34553 //[END NewRichEdit]
34554 {$ELSE not_USE_CONSTRUCTORS}
34556 //[FUNCTION NewRichEdit]
34557 {$IFDEF ASM_VERSION}
34558 const RichEdit20A: array[0..11] of Char = ('R','i','c','h','E','d','i','t','2','0','A',#0 );
34559 RichEd20_DLL: array[ 0..12] of Char = ('R','I','C','H','E','D','2','0','.','D','L','L',#0 );
34560 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
34561 const deltaChr = 24; // sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat );
34562 deltaPar = sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat );
34564 PUSHAD
34565 CALL OleInit
34566 TEST EAX, EAX
34567 POPAD
34568 JZ @@new1
34569 PUSH [RichEditClass]
34570 MOV [RichEditClass], offset[RichEdit20A]
34571 PUSH [RichEditLib]
34572 MOV [RichEditLib], offset[RichEd20_DLL]
34573 CALL NewRichEdit1
34574 POP [RichEditLib]
34575 POP [RichEditClass]
34576 MOV byte ptr [EAX].TControl.fCharFmtDeltaSz, deltaChr
34577 MOV byte ptr [EAX].TControl.fParaFmtDeltaSz, deltaPar
34579 @@new1: CALL NewRichEdit1
34580 end;
34581 {$ELSE ASM_VERSION} //Pascal
34582 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
34583 var OldRichEditClass, OldRichEditLib: PChar;
34584 begin
34585 if OleInit then
34586 begin
34587 OldRichEditClass := RichEditClass;
34588 RichEditClass := 'RichEdit20A';
34589 OldRichEditLib := RichEditLib;
34590 RichEditLib := 'RICHED20.DLL';
34591 Result := NewRichEdit1( AParent, Options );
34592 Result.fCharFmtDeltaSz := 24; //sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat );
34593 // sizeof( TCharFormat2 ) is calculated incorrectly
34594 Result.fParaFmtDeltaSz := sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat );
34595 RichEditClass := OldRichEditClass;
34596 RichEditLib := OldRichEditLib;
34598 else
34599 Result := NewRichEdit1( AParent, Options );
34600 end;
34601 {$ENDIF ASM_VERSION}
34602 //[END NewRichEdit]
34604 {$ENDIF USE_CONSTRUCTORS}
34606 //=====================================================================//
34627 { TControl }
34629 {$IFDEF ASM_VERSION}
34630 //[procedure TControl.Init]
34631 procedure TControl.Init;
34632 const
34633 IniStyle = WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
34634 WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
34635 WS_BORDER or WS_THICKFRAME;
34636 asm //cmd //opd
34637 PUSH EBX
34638 MOV EBX, EAX
34639 CALL TObj.Init
34640 MOV EDX, offset WndProcDummy
34641 MOV [EBX].fOnDynHandlers, EDX
34642 MOV [EBX].fWndProcKeybd, EDX
34643 MOV [EBX].fWndProcResizeFlicks, EDX
34644 MOV [EBX].fPass2DefProc, EDX
34645 //**** MOV [EBX].fDefWndProc, offset DefWindowProc
34646 MOV [EBX].fWndFunc, offset WndFunc
34647 MOV EDX, offset ClearText
34648 MOV [EBX].fCommandActions.aClear, EDX
34649 INC dword ptr [EBX].fWindowed
34650 MOV EDX, offset DummyObjProc
34651 MOV [EBX].fControlClick, EDX
34652 MOV EDX, clBtnFace
34653 MOV [EBX].fColor, EDX
34654 MOV DL, clWindowText and $FF
34655 MOV [EBX].fTextColor, EDX
34656 MOV byte ptr [EBX].fMargin, 2
34657 INC dword ptr [EBX].fCtl3D
34658 INC dword ptr [EBX].fCtl3Dchild
34659 DEC byte ptr [EBX].fAlphaBlend
34660 CALL NewList
34661 MOV [EBX].fChildren, EAX
34662 MOV byte ptr[EBX].fClsStyle, CS_OWNDC
34663 MOV [EBX].fStyle, IniStyle
34664 INC dword ptr[EBX].fExStyle+2
34665 INC dword ptr[EBX].fVisible
34666 INC dword ptr[EBX].fEnabled
34667 CALL NewList
34668 MOV [EBX].fDynHandlers, EAX
34669 POP EBX
34670 end;
34671 {$ELSE ASM_VERSION} //Pascal
34672 procedure TControl.Init;
34673 begin
34674 inherited;
34675 fOnDynHandlers := WndProcDummy;
34676 fWndProcKeybd := WndProcDummy;
34677 fWndProcResizeFlicks := WndProcDummy;
34678 fPass2DefProc := WndProcDummy;
34679 //**** fDefWndProc := @DefWindowProc;
34680 fWndFunc := @ WndFunc;
34681 fCommandActions.aClear := ClearText;
34682 fWindowed := True;
34683 fControlClick := DummyObjProc;
34684 fColor := clBtnFace;
34685 fTextColor := clWindowText;
34686 fMargin := 2;
34687 fCtl3D := True;
34688 fCtl3Dchild := True;
34689 fAlphaBlend := 255;
34690 fChildren := NewList;
34691 fClsStyle := CS_OWNDC;
34692 fStyle := WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
34693 WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
34694 WS_BORDER or WS_THICKFRAME;
34695 fExStyle := WS_EX_CONTROLPARENT;
34696 fVisible := True;
34697 fEnabled := True;
34698 fDynHandlers := NewList;
34699 end;
34700 {$ENDIF ASM_VERSION}
34702 {$IFDEF ASM_VERSION}
34703 //[PROCEDURE CallTControlInit]
34704 procedure CallTControlInit( Ctl: PControl );
34705 begin
34706 Ctl.Init;
34707 end;
34708 //[END CallTControlInit]
34710 //[procedure TControl.InitParented]
34711 procedure TControl.InitParented( AParent: PControl );
34712 const IStyle = WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
34713 WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
34714 WS_BORDER or WS_THICKFRAME;
34715 IExStyle = WS_EX_CONTROLPARENT;
34716 IClsStyle = CS_OWNDC;
34717 int_IDC_ARROW = integer( IDC_ARROW );
34719 PUSH EAX
34720 PUSH EDX
34721 CALL CallTControlInit
34722 POP EDX
34723 POP EAX
34724 TEST EDX, EDX
34725 JZ @@0
34726 MOV ECX, [EDX].fColor
34727 MOV [EAX].fColor, ECX
34728 @@0:
34729 CALL SetParent
34730 end;
34731 {$ELSE ASM_VERSION} //Pascal
34732 procedure TControl.InitParented( AParent: PControl );
34733 begin
34734 Init;
34735 if AParent <> nil then
34736 fColor := AParent.fColor;
34737 Parent := AParent;
34738 end;
34739 {$ENDIF ASM_VERSION}
34741 {$IFDEF ASM_VERSION}
34742 //[destructor TControl.Destroy]
34743 destructor TControl.Destroy;
34745 PUSH EBX
34746 MOV EBX, EAX
34747 CALL TControl.ParentForm
34748 TEST EAX, EAX
34749 JZ @@cur_ctl_removed
34750 CMP [EAX].TControl.fCurrentControl, EBX
34751 JNE @@cur_ctl_removed
34752 XOR EDX, EDX
34753 MOV [EAX].TControl.fCurrentControl, EDX
34754 @@cur_ctl_removed:
34756 MOV ECX, [EBX].fHandle
34757 JECXZ @@wndhidden
34758 PUSH SW_HIDE
34759 PUSH ECX
34760 CALL ShowWindow
34761 @@wndhidden:
34763 MOV EAX, EBX
34764 CALL Final
34765 MOV EAX, EBX
34766 CALL DestroyChildren
34768 XOR ECX, ECX
34769 CMP [EBX].fDestroying, CL
34770 JNZ @@destroyed
34772 XCHG CL, [EBX].fCtlClsNameChg
34773 JECXZ @@skip_free_clsname
34774 MOV EAX, [EBX].fControlClassName
34775 CALL System.@FreeMem
34776 @@skip_free_clsname:
34778 INC [EBX].fDestroying
34779 MOV EAX, [EBX].fFont
34780 CALL TObj.Free
34781 MOV EAX, [EBX].fBrush
34782 CALL TObj.Free
34783 MOV EAX, [EBX].fCanvas
34784 CALL TObj.Free
34786 XOR ECX, ECX
34788 MOV [EBX].fFont, ECX // +YS
34789 MOV [EBX].fBrush, ECX // +YS
34790 MOV [EBX].fCanvas, ECX // +YS
34792 XCHG ECX, [EBX].fCustomData
34793 JECXZ @@custfree
34794 XCHG EAX, ECX
34795 CALL System.@FreeMem
34796 @@custfree:
34797 MOV EAX, [EBX].fCustomObj
34798 CALL TObj.Free
34800 MOV EAX, [EBX].fHandle
34801 TEST EAX, EAX
34802 JZ @@free_fields
34804 XOR ECX, ECX
34805 XCHG ECX, [EBX].fAccelTable
34806 JECXZ @@accelTable_destroyed
34807 PUSH ECX
34808 CALL DestroyAcceleratorTable
34809 @@accelTable_destroyed:
34810 MOV EAX, [EBX].fMenuObj
34811 CALL TObj.Free
34812 @@destroy_img_list:
34813 MOV EAX, [EBX].fImageList
34814 TEST EAX, EAX
34815 JZ @@img_list_destroyed
34816 CALL TObj.Free
34817 JMP @@destroy_img_list
34818 @@img_list_destroyed:
34820 PUSH [EBX].fHandle
34821 CALL IsWindow
34822 TEST EAX, EAX
34823 JZ @@destroy2
34825 PUSH EAX
34826 PUSH 1
34827 PUSH WM_SETICON
34828 PUSH [EBX].fHandle
34829 CALL SendMessage
34830 TEST EAX, EAX
34831 JZ @@icoremoved
34832 CMP [EBX].fIconShared, 0
34833 JNZ @@icoremoved
34834 PUSH EAX
34835 CALL DestroyIcon
34836 @@icoremoved:
34837 //********************************************************** Remarked By M.Gerasimov
34838 // PUSH offset[ID_SELF]
34839 // PUSH [EBX].fHandle
34840 // CALL RemoveProp
34841 //********************************************************** Remarked By M.Gerasimov
34842 CMP [EBX].fNCDestroyed, 0
34843 JNZ @@destroy2
34844 PUSH [EBX].fHandle
34845 CALL DestroyWindow
34846 @@destroy2:
34847 XOR EAX, EAX
34848 MOV [EBX].fHandle, EAX
34850 @@free_fields:
34851 MOV EAX, [EBX].fCaption
34852 TEST EAX, EAX
34853 JZ @@caption_freed
34854 CALL System.@FreeMem
34855 @@caption_freed:
34856 MOV EAX, [EBX].fStatusTxt
34857 TEST EAX, EAX
34858 JZ @@statusTxt_freed
34859 CALL System.@FreeMem
34860 @@statusTxt_freed:
34861 MOV ECX, [EBX].fParent
34862 JECXZ @@removed_from_parent
34863 CMP [ECX].fCurrentControl, EBX
34864 JNE @@removefromParent
34865 XOR EAX, EAX
34866 MOV [ECX].fCurrentControl, EAX
34867 @@removefromParent:
34868 MOV EAX, [ECX].fChildren
34869 //PUSH EAX
34870 MOV EDX, EBX
34871 {CALL TList.IndexOf
34872 TEST EAX, EAX
34873 POP EDX
34874 JL @@removed_from_parent
34875 XCHG EAX, EDX
34876 CALL TList.Delete}
34877 CALL TList.Remove
34878 @@removed_from_parent:
34879 MOV ECX, [EBX].fTmpBrush
34880 JECXZ @@tmpBrush_deleted
34881 PUSH ECX
34882 CALL DeleteObject
34883 @@tmpBrush_deleted:
34885 PUSH EBX
34886 PUSH [EBX].fChildren
34887 PUSH [EBX].fTBttCmd
34888 PUSH [EBX].fTBttTxt
34889 PUSH [EBX].fTmpFont
34890 PUSH [EBX].fDynHandlers
34891 MOV BL, 5
34892 @@freeloo:
34893 POP EAX
34894 CALL TObj.Free
34895 DEC BL
34896 JNZ @@freeloo
34897 POP EBX
34898 LEA EAX, [EBX].fREUrl
34899 CALL System.@LStrClr
34900 XCHG EAX, EBX
34901 CALL TObj.Destroy
34902 @@destroyed:
34903 POP EBX
34904 end;
34905 {$ELSE ASM_VERSION} //Pascal
34906 destructor TControl.Destroy;
34907 var I: Integer;
34908 F: PControl;
34909 Ico: HIcon;
34910 begin
34911 {$IFDEF USE_MHTOOLTIP}
34912 {$DEFINE destroy}
34913 {$I KOLMHToolTip}
34914 {$UNDEF destroy}
34915 {$ENDIF USE_MHTOOLTIP}
34916 F := ParentForm; // or Applet - for form ???
34917 if F <> nil then
34918 if F.FCurrentControl = @Self then
34919 F.FCurrentControl := nil;
34921 if FHandle <> 0 then
34922 ShowWindow( fHandle, SW_HIDE );
34924 Final;
34925 DestroyChildren;
34927 if not fDestroying then
34928 begin
34929 fDestroying := True;
34931 if fCtlClsNameChg then
34932 begin
34933 FreeMem( fControlClassName );
34934 fCtlClsNameChg := FALSE;
34935 end;
34937 fFont.Free;
34938 fFont := nil;
34939 fBrush.Free;
34940 fBrush := nil;
34941 fCanvas.Free;
34942 fCanvas := nil;
34944 if fCustomData <> nil then
34945 FreeMem( fCustomData );
34946 fCustomData := nil;
34947 fCustomObj.Free;
34948 fCustomObj := nil;
34950 if fHandle <> 0 then
34951 begin
34952 {$IFNDEF NEW_MENU_ACCELL}
34953 if fAccelTable <> 0 then
34954 begin
34955 DestroyAcceleratorTable( fAccelTable );
34956 fAccelTable := 0;
34957 end;
34958 {$ENDIF}
34959 fMenuObj.Free;
34960 while fImageList <> nil do
34961 fImageList.Free;
34962 I := fHandle;
34963 if IsWindow( I ) then
34964 begin
34965 Ico := SendMessage( I, WM_SETICON, 1, 0 );
34966 if Ico <> 0 then
34967 if not fIconShared then
34968 DestroyIcon( Ico );
34969 //********************************************************** Remarked By M.Gerasimov
34970 // RemoveProp( I, ID_SELF );
34971 //********************************************************** Remarked By M.Gerasimov
34972 if not fNCDestroyed then
34973 begin
34974 {$IFDEF DEBUG_ENDSESSION}
34975 if EndSession_Initiated then
34976 LogFileOutput( GetStartDir + 'es_debug.txt',
34977 'DESTROYING HWND:' + Int2Str( I ) );
34978 {$ENDIF}
34979 DestroyWindow( I );
34980 end;
34982 {$IFDEF TEST_CLOSE}
34983 else
34985 int 3
34986 end;
34987 {$ENDIF}
34989 fHandle := 0;
34990 end;
34992 if fTmpBrush <> 0 then
34993 DeleteObject( fTmpBrush );
34994 fTmpBrush := 0;
34996 if FCaption <> nil then
34997 FreeMem( FCaption );
34998 if fStatusTxt <> nil then
34999 FreeMem( fStatusTxt );
35001 if fParent <> nil then
35002 begin
35003 {I := fParent.fChildren.IndexOf( @Self );
35004 if I >= 0 then
35005 fParent.fChildren.Delete( I );}
35006 fParent.fChildren.Remove( @Self );
35007 if fParent.fCurrentControl = @Self then
35008 fParent.fCurrentControl := nil;
35009 end;
35011 fChildren.Free;
35012 fTBttCmd.Free;
35013 fTBttTxt.Free;
35014 fTmpFont.Free;
35015 fDynHandlers.Free;
35016 fREUrl := '';
35017 inherited;
35018 end;
35019 end;
35020 {$ENDIF ASM_VERSION}
35022 {$IFDEF USE_MHTOOLTIP}
35023 {$DEFINE code}
35024 {$I KOLMHToolTip}
35025 {$UNDEF code}
35026 {$ENDIF}
35028 {$IFDEF ASM_VERSION}
35029 //[procedure TControl.SetEnabled]
35030 procedure TControl.SetEnabled( Value: Boolean );
35032 PUSH EBX
35033 MOV EBX, EAX
35034 MOVZX EDX, DL
35035 PUSH EDX
35036 CALL GetEnabled
35037 POP EDX
35038 CMP AL, DL
35039 JZ @@exit
35040 MOV [EBX].fEnabled, DL
35041 TEST EDX, EDX
35042 JNZ @@andnot
35043 OR byte ptr [EBX].fStyle + 3, 8
35044 JMP @@1
35045 @@andnot:
35046 AND byte ptr [EBX].fStyle + 3, $F7
35047 @@1:
35048 MOV ECX, [EBX].fHandle
35049 JECXZ @@exit
35051 PUSH EDX
35052 PUSH ECX
35053 CALL EnableWindow
35055 @@exit:
35056 POP EBX
35057 end;
35058 {$ELSE ASM_VERSION} //Pascal
35059 procedure TControl.SetEnabled( Value: Boolean );
35060 begin
35061 if GetEnabled = Value then Exit;
35062 fEnabled := Value;
35063 if Value then
35064 fStyle := fStyle and not WS_DISABLED
35065 else
35066 fStyle := fStyle or WS_DISABLED;
35067 if fHandle <> 0 then
35068 EnableWindow( fHandle, fEnabled );
35069 end;
35070 {$ENDIF ASM_VERSION}
35072 {$IFDEF ASM_VERSION}
35073 //[function TControl.GetParentWindow]
35074 function TControl.GetParentWindow: HWnd;
35076 MOV EAX, [EAX].fParent
35077 TEST EAX, EAX
35079 JZ @@exit
35081 CALL TControl.GetWindowHandle
35082 @@exit: --- replaced with following (6 bytes instead of 7):
35084 JNZ TControl.GetWindowHandle
35085 end;
35086 {$ELSE ASM_VERSION} //Pascal
35087 function TControl.GetParentWindow: HWnd;
35088 begin
35089 Result := 0;
35090 if fParent = nil then Exit;
35091 Result := fParent.GetWindowHandle;
35092 end;
35093 {$ENDIF ASM_VERSION}
35095 {$IFDEF ASM_VERSION}
35096 function TControl.GetWindowHandle: HWnd;
35098 MOV ECX, [EAX].fHandle
35099 JECXZ @@1
35100 XCHG EAX, ECX
35102 @@1:
35103 CMP [EAX].fCreateVisible, 0
35104 JNZ @@2
35106 PUSH EAX
35107 XOR EDX, EDX
35108 CALL TControl.Set_Visible
35109 POP EAX
35110 PUSH EAX
35111 //CALL TControl.CreateWindow
35112 CALL CallTControlCreateWindow
35113 { This is a call to Pascal piece of code, which
35114 calls virtual method TControl.CreateWindow }
35115 POP EAX
35117 INC [EAX].fCreateHidden
35118 JMP @@0
35120 @@2: PUSH EAX
35121 //CALL TControl.CreateWindow
35122 CALL CallTControlCreateWindow
35123 POP EAX
35124 @@0:
35125 MOV EAX, [EAX].fHandle
35126 end;
35127 {$ELSE ASM_VERSION} //Pascal
35128 function TControl.GetWindowHandle: HWnd;
35129 begin
35130 if fHandle = 0 then
35131 begin
35132 if not fCreateVisible then
35133 begin
35134 Set_Visible( False );
35135 CreateWindow; //virtual!!!
35136 fCreateHidden := True;
35138 else
35139 CreateWindow; //virtual!!!
35140 end;
35141 Result := fHandle;
35142 end;
35143 {$ENDIF ASM_VERSION}
35146 {$IFDEF _D7orHigher}
35147 // may be it was a good idea to replace CreateWindowEx,
35148 // but Inprise forget about stdcall... In result, asm-version became broken.
35149 //[API CreateWindowEx]
35150 function CreateWindowEx(dwExStyle: DWORD; lpClassName: PChar;
35151 lpWindowName: PChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;
35152 hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;
35153 stdcall; external user32 name 'CreateWindowExA';
35154 {$ENDIF}
35157 {$IFDEF ASM_VERSION}
35158 //[function TControl.CreateWindow]
35159 function TControl.CreateWindow: Boolean;
35160 const
35161 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;
35162 CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;
35163 szWndClass = sizeof( TWndClass );
35164 int_IDC_ARROW = integer( IDC_ARROW );
35166 PUSH EBX
35167 XCHG EBX, EAX
35168 MOV ECX, [EBX].fParent
35169 JECXZ @@chk_handle
35170 XCHG EAX, ECX
35171 CALL GetWindowHandle
35172 TEST EAX, EAX
35173 JZ @@ret_false
35174 @@chk_handle:
35175 MOV ECX, [EBX].fHandle
35176 JECXZ @@prepare_Params
35177 MOV DL, 0
35178 MOV EAX, EBX
35179 CMP [EBX].fCreateHidden, DL
35180 JZ @@create_children
35181 CALL CreateChildWindows
35182 MOV EAX, EBX
35183 MOV DL, 1
35184 CALL Set_Visible
35185 MOV [EBX].fCreateHidden, 0
35186 JMP @@ret_true
35187 @@create_children:
35188 CALL CreateChildWindows
35189 @@ret_true:
35190 MOV AL, 1
35191 POP EBX
35193 @@prepare_params:
35194 PUSH EBP
35195 MOV EBP, ESP
35197 PUSH ECX // Params.WindowClass.lpszClassName := nil
35198 PUSH ECX // Params.WindowClass.lpszMenuName := nil
35199 PUSH ECX // Params.WindowClass.hbrBackground := 0
35200 PUSH int_IDC_ARROW
35201 PUSH ECX
35202 CALL LoadCursor
35203 PUSH EAX // Params.WindowClass.hCursor := LoadCursor( 0, IDC_ARROW )
35204 XOR ECX, ECX
35205 PUSH ECX // Params.WindowClass.hIcon := 0
35206 PUSH [hInstance]// Params.WindowClass.hInstance := hInstance
35207 PUSH ECX // Params.WindowClass.cbWndExtra := 0
35208 PUSH ECX // Params.WindowClass.cbClsExtra := 0
35209 //PUSH offset DefWindowProc // Params.WindowClass.lpfnWndProc := @DefWindowProc
35210 PUSH [EBX].fDefWndProc // Params.WindowClass.lpfnWndProc := fDefWndProc
35211 PUSH [EBX].fClsStyle // Params.WindowClass.style := fStyle
35212 ADD ESP, -64
35213 PUSH ECX
35214 MOV EAX, EBX
35215 MOV EDX, ESP
35216 CALL get_ClassName
35217 POP EDX
35218 MOV EAX, ESP
35219 PUSH EDX
35220 //CALL StrPCopy // StrPCopy( Params.WinClsNamBuf, ClassName )
35221 CALL StrCopy
35222 CALL RemoveStr
35223 PUSH 0 // Params.Param := nil
35224 PUSH [hInstance] // Params.Inst := fInstance
35225 PUSH [EBX].fMenu // Params.Menu := fMenu
35226 MOV DL, 1
35227 MOV EAX, EBX
35228 CALL GetParentWnd
35229 PUSH EAX // Params.WndParent := GetParentWnd( True )
35231 MOV ECX, CW_USEDEFAULT
35232 MOV EAX, [EBX].fBoundsRect.Bottom
35233 MOV EDX, [EBX].fBoundsRect.Top
35234 SUB EAX, EDX
35235 JNZ @@1
35236 MOV EAX, ECX
35237 @@1: PUSH EAX // Params.Height := Height | CW_UseDefault
35238 MOV EAX, [EBX].fBoundsRect.Right
35239 SUB EAX, [EBX].fBoundsRect.Left
35240 {$IFDEF USE_CMOV}
35241 CMOVZ EAX, ECX
35242 {$ELSE}
35243 JNZ @@2
35244 MOV EAX, ECX
35245 @@2: {$ENDIF}
35247 PUSH EAX // Params.Width := Width | CW_UseDefault
35248 MOV EAX, [EBX].fBoundsRect.Left
35249 CMP [EBX].fIsControl, CL
35250 JNZ @@3
35251 TEST byte ptr [EBX].fChangedPosSz, 3
35252 JNZ @@3
35253 MOV EDX, ECX
35254 XCHG EAX, ECX
35255 @@3: PUSH EDX // Params.Y := Top | CW_UseDefault
35256 PUSH EAX // Params.X := Left | CW_UseDefault
35257 PUSH [EBX].fStyle // Params.Style := fStyle
35258 PUSH [EBX].fCaption // Params.Caption := fCaption
35259 LEA EAX, [ESP+40]
35260 PUSH EAX // Params.WinClassName := @Params.WinClsNamBuf
35261 PUSH [EBX].fExStyle // Params.ExStyle := fExStyle
35263 MOV ECX, [EBX].fControlClassName
35264 JECXZ @@registerClass
35265 LEA EAX, [ESP].TCreateWndParams.WindowClass
35266 PUSH EAX // @Params.WindowClass
35267 PUSH ECX // fControlClassName
35268 PUSH [hInstance] // hInstance
35269 CALL GetClassInfo
35270 MOV EAX, [ESP].TCreateWndParams.Inst
35271 MOV [ESP].TCreateWndParams.WindowClass.hInstance, EAX
35272 AND [ESP].TCreateWndParams.WindowClass.style, not CS_OFF
35273 @@registerClass:
35274 CMP [EBX].fDefWndProc, 0
35275 JNE @@fDefWndProc_ready
35276 MOV EAX, [ESP].TCreateWndParams.WindowClass.lpfnWndProc
35277 MOV [EBX].fDefWndProc, EAX
35278 @@fDefWndProc_ready:
35279 MOV ECX, [ESP].TCreateWndParams.WndParent
35280 INC ECX
35281 LOOP @@registerClass1
35282 TEST byte ptr [ESP].TCreateWndParams.Style+3, $40
35283 XCHG EAX, ECX
35284 JNZ @@fin
35285 @@registerClass1:
35286 MOV EAX, [ESP].TCreateWndParams.WinClassName
35287 MOV EDX, [ESP].TCreateWndParams.WindowClass.hInstance
35288 ADD ESP, -szWndClass
35289 PUSH ESP
35290 PUSH EAX
35291 PUSH EDX
35292 CALL GetClassInfo
35293 ADD ESP, szWndClass
35294 TEST EAX, EAX
35295 JNZ @@registered
35296 MOV EAX, [ESP].TCreateWndParams.WinClassName
35297 MOV [ESP].TCreateWndParams.WindowClass.lpszClassName, EAX
35298 MOV [ESP].TCreateWndParams.WindowClass.lpfnWndProc, offset WndFunc
35299 LEA EAX, [ESP].TCreateWndParams.WindowClass
35300 PUSH EAX
35301 CALL RegisterClass
35302 TEST EAX, EAX
35303 JZ @@fin
35304 @@registered:
35305 MOV [CreatingWindow], EBX
35306 CALL CreateWindowEx
35307 MOV [EBX].fHandle, EAX
35308 TEST EAX, EAX
35309 JZ @@fin
35310 PUSH EAX
35311 PUSH offset ID_SELF
35312 PUSH EAX
35314 //SendMessage(fHandle,WM_UPDATEUISTATE,UIS_CLEAR or (UISF_HIDEFOCUS shl 16),0);
35315 PUSH 0
35316 PUSH $10002 //UIS_CLEAR or (UISF_HIDEFOCUS shl 16)
35317 PUSH $0128 //WM_UPDATEUISTATE
35318 PUSH EAX
35319 CALL SendMessage
35321 CALL GetProp
35322 XCHG ECX, EAX
35323 POP EAX
35324 INC ECX
35325 LOOP @@propSet
35326 MOV [CreatingWindow], ECX
35327 PUSH EBX
35328 PUSH offset ID_SELF
35329 PUSH EAX
35330 CALL SetProp
35331 @@propSet:
35332 CMP [EBX].fIsControl, 0
35333 JNZ @@iconSet
35334 MOV EAX, EBX
35335 CALL GetIcon
35336 PUSH EAX
35337 PUSH 1
35338 PUSH WM_SETICON
35339 PUSH EBX
35340 CALL Perform
35341 @@iconSet:
35342 MOV ECX, [EBX].fCreateWndExt
35343 JECXZ @@dblbufcreate
35344 MOV EAX, EBX
35345 CALL ECX
35346 @@dblbufcreate:
35347 MOV EAX, EBX
35348 CALL Dword Ptr [ Global_DblBufCreateWnd ]
35349 @@applyfont:
35350 MOV EAX, EBX
35351 CALL ApplyFont2Wnd
35352 MOV EAX, EBX
35353 CALL ApplyFont2Wnd
35354 XCHG EAX, EBX
35355 CALL CreateChildWindows
35356 MOV AL, 1
35357 @@fin:
35358 MOV ESP, EBP
35359 POP EBP
35360 @@ret_false:
35361 POP EBX
35362 end;
35363 {$ELSE ASM_VERSION} //Pascal
35364 function TControl.CreateWindow: Boolean;
35365 const
35366 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;
35367 CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;
35368 var TempClass: TWndClass;
35369 Params: TCreateWndParams;
35370 ClassRegistered: Boolean;
35371 {$IFDEF _FPC}
35372 SClassName: String;
35373 {$ENDIF ASM_VERSION}
35374 begin
35375 {$IFDEF DEBUG_CREATEWINDOW}
35376 LogFileOutput( GetStartDir + 'Session.log', 'TControl.CreateWindow, ' +
35377 ' Self = ' + Int2Str( Integer( @ Self ) ) +
35378 ' Caption = ' + fCaption +
35379 ' fChildren = ' + Int2Hex( Integer( fChildren ), 4 ) +
35380 ' ChildCount = ' + Int2Str( ChildCount ) );
35381 {$ENDIF DEBUG_CREATEWINDOW}
35382 Result := False;
35383 if fParent <> nil then
35384 if fParent.GetWindowHandle = 0 then
35385 Exit;
35386 if fHandle <> 0 then
35387 begin
35388 if fCreateHidden then
35389 begin
35390 CreateChildWindows;
35391 Set_Visible( True );
35392 fCreateHidden := False;
35394 else
35395 begin
35396 CreateChildWindows;
35397 end;
35398 Result := True;
35399 Exit;
35400 end;
35402 FillChar( Params, Sizeof( Params ), 0 );
35403 Params.Caption := PChar( FCaption );
35404 Params.Style := FStyle;
35405 if not fEnabled then
35406 Params.Style := Params.Style or WS_DISABLED;
35407 Params.ExStyle := FExStyle;
35408 Params.WindowClass.style := FClsStyle;
35409 {Params.WindowClass.lpfnWndProc := @ DefWindowProc;
35410 if fDefWndProc <> nil then} //+-+
35411 Params.WindowClass.lpfnWndProc := FDefWndProc;
35412 Params.WindowClass.hCursor := LoadCursor( 0, IDC_ARROW );
35413 Params.WindowClass.hInstance := hInstance;
35414 Params.Inst := hInstance;
35415 {$IFDEF _FPC}
35416 SClassName := SubClassName;
35417 StrCopy( Params.WinClsNamBuf, @ SClassName[ 1 ] );
35418 {$ELSE}
35419 StrCopy( Params.WinClsNamBuf, @ SubClassName[ 1 ] );
35420 {$ENDIF}
35421 Params.WinClassName := @Params.WinClsNamBuf[ 0 ];
35422 Params.WndParent := GetParentWnd( True );
35423 Params.Menu := fMenu;
35424 Params.X := fBoundsRect.Left;
35425 Params.Y := fBoundsRect.Top;
35426 Params.Width := fBoundsRect.Right - fBoundsRect.Left;
35427 if Params.Width = 0 then
35428 Params.Width := CW_UseDefault;
35429 Params.Height := fBoundsRect.Bottom - fBoundsRect.Top;
35430 if Params.Height = 0 then
35431 Params.Height := CW_UseDefault;
35432 if not fIsControl then
35433 begin
35434 if not LongBool( fChangedPosSz and 3 ) then
35435 begin
35436 Params.X := CW_UseDefault;
35437 Params.Y := CW_UseDefault;
35438 end;
35439 end;
35441 if fControlClassName <> nil then
35442 begin // SUBCLASSING WINDOW
35443 GetClassInfo( Params.WindowClass.hInstance, fControlClassName,
35444 Params.WindowClass);
35445 Params.WindowClass.hInstance := Params.Inst;
35446 Params.WindowClass.style := Params.WindowClass.style
35447 and not CS_OFF or CS_ON;
35448 end;
35450 if FDefWndProc = nil then //+
35451 {$IFDEF F_P}
35452 Move( Params.WindowClass.lpfnWndProc, FDefWndProc, Sizeof( Pointer ) );
35453 {$ELSE}
35454 FDefWndProc := Params.WindowClass.lpfnWndProc;
35455 {$ENDIF}
35456 if (Params.WndParent = 0) and (Params.Style and WS_CHILD <> 0) then Exit;
35457 ClassRegistered := GetClassInfo( Params.WindowClass.hInstance,
35458 Params.WinClassName, TempClass );
35459 if not ClassRegistered then
35460 begin
35461 Params.WindowClass.lpszClassName := Params.WinClassName;
35462 Params.WindowClass.lpfnWndProc := fWndFunc;
35463 if RegisterClass( Params.WindowClass ) = 0 then Exit;
35464 end;
35465 {$IFDEF DEBUG_CREATEWINDOW}
35466 LogFileOutput( GetStartDir + 'Session.log',
35467 ' ExStyle=' + Int2Hex( Params.ExStyle, 4 ) +
35468 ' WinClassName=' + Params.WinClassName +
35469 ' Caption=' + Params.Caption +
35470 ' Style=' + Int2Hex( Params.Style, 4 ) +
35471 ' X=' + Int2Str( Params.X ) +
35472 ' Y=' + Int2Str( Params.Y ) +
35473 ' Width=' + Int2Str( Params.Width ) +
35474 ' Height=' + Int2Str( Params.Height ) +
35475 ' WndParent=' + Int2Str( Params.WndParent ) +
35476 ' Menu=' + Int2Str( Params.Menu ) +
35477 ' hInstance=' + Int2Str( Params.WindowClass.hInstance ) +
35478 ' Param=' + Int2Str( Integer( Params.Param ) )
35480 {$ENDIF}
35481 CreatingWindow := @Self;
35482 fHandle := CreateWindowEx( Params.ExStyle, Params.WinClassName,
35483 Params.Caption, Params.Style, Params.X, Params.Y,
35484 Params.Width, Params.Height, Params.WndParent,
35485 Params.Menu, Params.WindowClass.hInstance,
35486 Params.Param );
35487 if fHandle = 0 then Exit;
35488 SendMessage( fHandle, $0128 {WM_UPDATEUISTATE},
35489 2 {UIS_CLEAR} or (1 {UISF_HIDEFOCUS} shl 16),0);
35490 if GetProp(FHandle,ID_SELF) = 0 then
35491 begin
35492 CreatingWindow := nil;
35493 SetProp(FHandle, ID_SELF, THandle(@Self));
35494 end;
35495 //***
35496 if not fIsControl then
35497 SendMessage( fHandle, WM_SETICON, 1 {ICON_BIG}, GetIcon );
35498 if Assigned( FCreateWndExt ) then
35499 FCreateWndExt( @Self );
35500 Global_DblBufCreateWnd( @ Self );
35501 ApplyFont2Wnd;
35502 ApplyFont2Wnd;
35504 CreateChildWindows;
35505 Result := True;
35506 end;
35507 {$ENDIF}
35510 //[procedure TControl.CreateSubclass]
35511 procedure TControl.CreateSubclass(var Params: TCreateParams;
35512 ControlClassName: PChar);
35513 const
35514 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;
35515 CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;
35517 SaveInstance: THandle;
35518 begin
35519 if fControlClassName <> nil then
35520 with Params do
35521 begin
35522 SaveInstance := WindowClass.hInstance;
35523 if not GetClassInfo(HInstance, fControlClassName, WindowClass) and
35524 not GetClassInfo(0, fControlClassName, WindowClass)
35525 //and not GetClassInfo(HInstance {MainInstance}, fControlClassName, WindowClass)
35526 then
35527 GetClassInfo(WindowClass.hInstance, fControlClassName, WindowClass);
35528 WindowClass.hInstance := SaveInstance;
35529 WindowClass.style := WindowClass.style and not CS_OFF or CS_ON;
35530 end;
35531 end;
35533 //[FUNCTION WndProcMous]
35534 {$IFDEF ASM_VERSION}
35535 function WndProcMouse(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35537 PUSH EBX
35538 PUSH ESI
35539 XCHG EBX, EAX
35541 XOR ECX, ECX // Rslt not used. ECX <= Result = 0
35542 MOV EAX, [EDX].TMsg.message
35543 SUB AH, WM_MOUSEFIRST shr 8
35544 CMP EAX, $20A - WM_MOUSEFIRST //WM_MOUSELAST - WM_MOUSEFIRST
35545 JA @@exit
35547 PUSH dword ptr [EDX].TMsg.lParam // prepare X, Y
35549 PUSHAD
35551 PUSH VK_MENU
35552 CALL GetKeyState
35553 ADD EAX, EAX
35554 POPAD
35555 XCHG EAX, EDX
35556 MOV EAX, [EAX].TMsg.wParam
35558 JNC @@noset_MKALT
35559 {$IFDEF PARANOIA}
35560 DB $0C, MK_ALT
35561 {$ELSE}
35562 OR AL, MK_ALT
35563 {$ENDIF}
35564 @@noset_MKALT:
35566 PUSH EAX // prepare Shift
35568 LEA ESI, [EBX].TControl.fOnMouseDown
35569 CALL dword ptr [EDX*4 + @@jump_table]
35571 @@call_evnt:
35572 PUSH ECX // prepare Button, StopHandling
35573 MOV ECX, ESP // ECX = @MouseData
35575 CMP word ptr [ESI].TMethod.Code+2, 0
35576 JZ @@after_call
35578 MOV EDX, EBX // EDX = Self_
35579 MOV EAX, [ESI].TMethod.Data // EAX = Target_
35580 CALL dword ptr [ESI].TMethod.Code
35582 @@after_call:
35583 POP ECX
35584 POP EDX
35585 POP EDX
35586 MOV CL, CH // Result := StopHandling
35588 @@exit:
35589 XCHG EAX, ECX
35590 POP ESI
35591 POP EBX
35594 @@jump_table:
35595 DD Offset[@@MMove],Offset[@@LDown],Offset[@@LUp],Offset[@@LDblClk]
35596 DD Offset[@@RDown],Offset[@@RUp],Offset[@@RDblClk]
35597 DD Offset[@@MDown],Offset[@@MUp],Offset[@@MDblClk],Offset[@@MWheel]
35599 @@MDown: INC ECX
35600 @@RDown: INC ECX
35601 @@LDown: INC ECX
35602 //LEA ESI, [EBX].TControl.fOnMouseDown
35605 @@MUp: INC ECX
35606 @@RUp: INC ECX
35607 @@LUp: INC ECX
35608 //LEA ESI, [EBX].TControl.fOnMouseUp
35609 LODSD
35610 LODSD
35613 @@MMove: LEA ESI, [EBX].TControl.fOnMouseMove
35614 //ADD ESI, 16
35617 @@MDblClk: INC ECX
35618 @@RDblClk: INC ECX
35619 @@LDblClk: INC ECX
35620 LEA ESI, [EBX].TControl.fOnMouseDblClk
35621 //ADD ESI, 24
35624 @@MWheel:LEA ESI, [EBX].TControl.fOnMouseWheel
35625 //ADD ESI, 32
35626 //RET
35627 end;
35628 {$ELSE ASM_VERSION} //Pascal
35629 function WndProcMouse(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35630 var MouseData: TMouseEventData;
35631 begin
35632 Result := False;
35633 if (Msg.message >= WM_MOUSEFIRST) and (Msg.message <= $20A {WM_MOUSELAST}) and
35634 (Msg.hwnd = Self_.fHandle) then
35635 with MouseData do
35636 begin
35637 Shift := Msg.wParam;
35638 if GetKeyState( VK_MENU ) < 0 then
35639 Shift := Shift or MK_ALT;
35640 X := LoWord( Msg.lParam );
35641 Y := HiWord( Msg.lParam );
35642 Button := mbNone;
35643 StopHandling := FALSE;
35644 Rslt := 0; // needed ?
35645 case Msg.message of
35646 WM_LBUTTONDOWN:
35647 if Assigned( Self_.OnMouseDown ) then
35648 begin
35649 Button := mbLeft;
35650 Self_.OnMouseDown( Self_, MouseData );
35651 end;
35652 WM_RBUTTONDOWN:
35653 if Assigned( Self_.OnMouseDown ) then
35654 begin
35655 Button := mbRight;
35656 Self_.OnMouseDown( Self_, MouseData );
35657 end;
35658 WM_MBUTTONDOWN:
35659 if Assigned( Self_.OnMouseDown ) then
35660 begin
35661 Button := mbMiddle;
35662 Self_.OnMouseDown( Self_, MouseData );
35663 end;
35664 WM_LBUTTONUP:
35665 if Assigned( Self_.OnMouseUp ) then
35666 begin
35667 Button := mbLeft;
35668 Self_.OnMouseUp( Self_, MouseData );
35669 end;
35670 WM_RBUTTONUP:
35671 if Assigned( Self_.OnMouseUp ) then
35672 begin
35673 Button := mbRight;
35674 Self_.OnMouseUp( Self_, MouseData );
35675 end;
35676 WM_MBUTTONUP:
35677 if Assigned( Self_.OnMouseUp ) then
35678 begin
35679 Button := mbMiddle;
35680 Self_.OnMouseUp( Self_, MouseData );
35681 end;
35682 WM_MOUSEMOVE:
35683 if Assigned( Self_.OnMouseMove ) then
35684 Self_.OnMouseMove( Self_, MouseData );
35685 WM_LBUTTONDBLCLK:
35686 if Assigned( Self_.OnMouseDblClk ) then
35687 begin
35688 Button := mbLeft;
35689 Self_.OnMouseDblClk( Self_, MouseData );
35690 end;
35691 WM_RBUTTONDBLCLK:
35692 if Assigned( Self_.OnMouseDblClk ) then
35693 begin
35694 Button := mbRight;
35695 Self_.OnMouseDblClk( Self_, MouseData );
35696 end;
35697 WM_MBUTTONDBLCLK:
35698 if Assigned( Self_.OnMouseDblClk ) then
35699 begin
35700 Button := mbMiddle;
35701 Self_.OnMouseDblClk( Self_, MouseData );
35702 end;
35703 $020A {WM_MOUSEWHEEL}:
35704 if Assigned( Self_.OnMouseWheel ) then
35705 Self_.OnMouseWheel( Self_, MouseData );
35706 else
35707 Exit; //Result := False;
35708 end;
35709 Result := StopHandling;
35710 end;
35711 end;
35712 {$ENDIF ASM_VERSION}
35713 //[END WndProcMous]
35715 //[FUNCTION WndProcKeybd]
35716 {$IFDEF ASM_VERSION}
35717 function WndProcKeybd( Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35719 PUSH EBX
35720 MOV ECX, [EDX].TMsg.message
35721 SUB CX, $100
35722 CMP ECX, 5
35723 JA @@fin_false
35724 XCHG EBX, EAX // EBX = @Self
35725 XCHG EAX, ECX // EAX = message - WM_KEYFIRST
35726 LEA ECX, [EBX].TControl.fOnKeyUp
35727 JZ @@event
35728 {$IFDEF PARANOIA}
35729 DB $34, 1
35730 {$ELSE}
35731 XOR AL, 1
35732 {$ENDIF}
35733 JZ @@event
35734 LEA ECX, [EBX].TControl.fOnKeyDown
35735 {$IFDEF PARANOIA}
35736 DB $34, 1
35737 {$ELSE}
35738 XOR AL, 1
35739 {$ENDIF}
35740 JZ @@event
35741 {$IFDEF PARANOIA}
35742 DB $34, 4
35743 {$ELSE}
35744 XOR AL, 4
35745 {$ENDIF}
35746 JZ @@event
35747 LEA ECX, [EBX].TControl.fOnChar
35748 {$IFDEF PARANOIA}
35749 DB $34, 6
35750 {$ELSE}
35751 XOR AL, 2 xor 4
35752 {$ENDIF}
35753 JZ @@event
35754 {$IFDEF PARANOIA}
35755 DB $34, 4
35756 {$ELSE}
35757 XOR AL, 6 xor 2
35758 {$ENDIF}
35759 JNZ @@fin_false
35760 @@event:
35761 CMP word ptr [ECX].TMethod.Code+2, 0
35762 JZ @@fin_false
35763 PUSH EDX
35764 PUSH ECX
35765 LEA ECX, [EDX].TMsg.wParam
35766 PUSH ECX
35767 CALL GetShiftState
35768 POP ECX // @wParam
35769 XCHG EAX, [ESP] // ShiftState; EAX=@event
35770 MOV EDX, EBX // @Self
35771 MOV EBX, [EAX].TMethod.Code
35772 MOV EAX, [EAX].TMethod.Data
35773 CALL EBX
35775 POP EDX
35776 MOV ECX, [EDX].TMsg.wParam
35777 JECXZ @@fin_true
35779 @@fin_false:
35780 XOR EAX, EAX
35781 POP EBX
35784 @@fin_true:
35785 MOV AL, 1
35786 POP EBX
35787 end;
35788 {$ELSE ASM_VERSION} //Pascal
35789 function WndProcKeybd(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35790 var C : Char;
35791 begin
35792 Result := True;
35793 case Msg.message of
35794 WM_KEYDOWN, WM_SYSKEYDOWN:
35795 if assigned( Self_.fOnKeyDown ) then
35796 Self_.fOnKeyDown( Self_, Msg.wParam, GetShiftState );
35797 WM_KEYUP, WM_SYSKEYUP:
35798 if assigned( Self_.fOnKeyUp ) then
35799 Self_.fOnKeyUp( Self_, Msg.wParam, GetShiftState );
35800 WM_CHAR, WM_SYSCHAR:
35801 if assigned( Self_.fOnChar ) then
35802 begin
35803 C := Char( Msg.wParam );
35804 Self_.fOnChar( Self_, C, GetShiftState );
35805 Msg.wParam := Integer( C );
35806 end;
35807 else begin
35808 Result := False;
35809 Exit;
35810 end;
35811 end;
35812 if Msg.wParam <> 0 then
35813 Result := False;
35814 end;
35815 {$ENDIF ASM_VERSION}
35816 //[END WndProcKeybd]
35818 //[function WndProcDummy]
35819 function WndProcDummy(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35820 begin
35821 Result := False;
35822 end;
35824 //[procedure ExcludeCtlsWhichCannotDblBuf]
35825 procedure ExcludeCtlsWhichCannotDblBuf( Sender, ParentCtl: PControl; DC: HDC );
35826 var I: Integer;
35827 C: PControl;
35828 R, R1: TRect;
35829 begin
35830 for I := 0 to ParentCtl.fChildren.Count-1 do
35831 begin
35832 C := ParentCtl.fChildren.Items[ I ];
35833 if C.fCannotDoubleBuf then
35834 begin
35835 GetWindowRect( Sender.fHandle, R );
35836 GetWindowRect( C.fHandle, R1 );
35837 OffsetRect( R1, -R.Left, -R.Top );
35838 ExcludeClipRect(DC, R1.Left, R1.Top, R1.Right, R1.Bottom);
35840 else
35841 ExcludeCtlsWhichCannotDblBuf( Sender, C, DC );
35842 end;
35843 end;
35845 //[procedure DoReleaseDblBufBmp]
35846 procedure DoReleaseDblBufBmp( Sender: PControl );
35847 begin
35848 if Sender.fDblBufBmp <> 0 then
35849 DeleteObject( Sender.fDblBufBmp );
35850 end;
35852 //[procedure DoDrawChildrenDblBuffered]
35853 procedure DoDrawChildrenDblBuffered( DC: HDC; WndParent: HWnd; const RectParent: TRect;
35854 W: HWnd );
35855 var R, CR: TRect;
35856 Save: Integer;
35857 P, P0: TPoint;
35858 begin
35859 while W <> 0 do
35860 begin
35861 if IsWindowVisible( W ) then
35862 begin
35863 Save := SaveDC( DC );
35864 GetWindowRect( W, R );
35865 GetWindowOrgEx( DC, P );
35866 SetWindowOrgEx( DC, P.x - ( R.Left - RectParent.Left ), P.y - ( R.Top - RectParent.Top ), nil );
35867 IntersectClipRect( DC, 0, 0, R.Right - R.Left, R.Bottom - R.Top );
35868 SendMessage( W, WM_PRINT, DC, PRF_NONCLIENT );
35869 GetClientRect( W, CR );
35870 P0.x := 0; P0.y := 0;
35871 ClientToScreen( W, P0 );
35872 OffsetRect( CR, P0.x, P0.y );
35873 SetWindowOrgEx( DC, P.x - (CR.Left - RectParent.Left), P.y - (CR.Top - RectParent.Top), nil );
35874 IntersectClipRect( DC, 0, 0, CR.Right - CR.Left, CR.Bottom - CR.Top );
35875 SendMessage( W, WM_ERASEBKGND, DC, 0 );
35876 SendMessage( W, WM_PAINT, DC, 0 );
35877 DoDrawChildrenDblBuffered( DC, W, CR, GetWindow( W, GW_CHILD ) );
35878 RestoreDC( DC, Save );
35879 end;
35880 W := GetWindow( W, GW_HWNDNEXT );
35881 end;
35882 end;
35884 //[procedure DoDrawDblBuffered]
35885 procedure DoDrawDblBuffered( Sender: PControl );
35886 var R: TRect;
35887 DC0, DC1, DC2: HDC;
35888 OldBmp: HBitmap;
35889 R2: TRect;
35890 P1, P2: TPoint;
35891 ClientOnly: Boolean;
35892 OldPaintDC: HDC;
35893 {$IFDEF DEBUGDBLBUFF}
35894 Tmp: PBitmap;
35895 {$ENDIF}
35896 begin
35897 if not GetUpdateRect( Sender.fHandle, R, FALSE ) then
35898 Exit; // nothing to paint
35900 Sender.fDblBufPainting := TRUE;
35902 ClientOnly := Sender.fIsForm {and (WinVer < wvNT)};
35903 if ClientOnly then
35904 GetClientRect( Sender.fHandle, R )
35905 else
35906 begin
35907 GetWindowRect( Sender.fHandle, R );
35908 OffsetRect( R, -R.Left, -R.Top );
35909 end;
35911 DC0 := GetDC( Sender.fHandle );
35912 DC1 := CreateCompatibleDC( DC0 );
35913 if Sender.fDblBufBmp = 0 then
35914 Sender.Add2AutoFreeEx( TObjectMethod( MakeMethod( Sender, @ DoReleaseDblBufBmp ) ) );
35915 if (Sender.fDblBufW < R.Right) or (Sender.fDblBufH < R.Bottom) or
35916 (Sender.fDblBufW > R.Right + 32) or (Sender.fDblBufH > R.Bottom + 32) then
35917 if Sender.fDblBufBmp <> 0 then
35918 begin
35919 DeleteObject( Sender.fDblBufBmp );
35920 Sender.fDblBufBmp := 0;
35921 end;
35922 if Sender.fDblBufBmp = 0 then
35923 begin
35924 Sender.fDblBufBmp := CreateCompatibleBitmap( DC0, R.Right, R.Bottom );
35925 Sender.fDblBufW := R.Right;
35926 Sender.fDblBufH := R.Bottom;
35927 end;
35928 OldBmp := SelectObject( DC1, Sender.fDblBufBmp );
35930 OldPaintDC := Sender.fPaintDC;
35931 Sender.fPaintDC := DC1;
35932 if ClientOnly then
35933 begin
35934 GetClientRect( Sender.fHandle, R2 );
35935 P2.x := 0; P2.y := 0;
35936 ClientToScreen( Sender.fHandle, P2 );
35937 OffsetRect( R2, P2.x, P2.y );
35938 SendMessage( Sender.fHandle, WM_ERASEBKGND, DC1, 0 );
35939 SendMessage( Sender.fHandle, WM_PAINT, DC1, 0 );
35940 DoDrawChildrenDblBuffered( DC1, Sender.fHandle, R2,
35941 GetWindow( Sender.fHandle, GW_CHILD ) );
35943 else
35944 begin
35945 {Sender.Perform( WM_PRINT, DC1,
35946 PRF_CLIENT or PRF_NONCLIENT or PRF_ERASEBKGND or PRF_CHILDREN );}
35947 GetWindowRect( Sender.fHandle, R2 );
35948 DoDrawChildrenDblBuffered( DC1, Sender.fHandle, R2, Sender.fHandle );
35949 end;
35950 //Sender.fPaintDC := DC1;
35952 DC2 := GetWindowDC( Sender.fHandle );
35954 ExcludeCtlsWhichCannotDblBuf( Sender, Sender, DC2 );
35956 P1.x := 0; P1.y := 0;
35957 if ClientOnly then
35958 begin
35959 GetWindowRect( Sender.fHandle, R2 );
35960 ClientToScreen( Sender.fHandle, P1 );
35961 P1.x := P1.x - R2.Left;
35962 P1.y := P1.y - R2.Top;
35963 GetClientRect( Sender.fHandle, R );
35964 end;
35965 BitBlt( DC2, P1.x, P1.y, R.Right, R.Bottom, DC1, 0, 0, SRCCOPY );
35967 {$IFDEF DEBUGDBLBUFF}
35968 Tmp := NewDIBBitmap( R.Right, R.Bottom, pf16bit );
35969 BitBlt( Tmp.Canvas.Handle, 0, 0, R.Right, R.Bottom, DC1, 0, 0, SRCCopy );
35970 Tmp.SaveToFile( 'c:\tmp.bmp' );
35971 Tmp.Free;
35972 {$ENDIF}
35974 ReleaseDC( Sender.fHandle, DC2 );
35976 SelectObject( DC1, OldBmp );
35977 DeleteDC( DC1 );
35978 ReleaseDC( Sender.fHandle, DC0 );
35980 Sender.fPaintDC := OldPaintDC;
35981 ValidateRect( Sender.fHandle, nil );
35983 Sender.fDblBufPainting := FALSE;
35984 end;
35986 //[function WndProcBufferedDraw]
35987 function WndProcBufferedDraw( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
35988 var Self_DblBufTopParent: PControl;
35989 begin
35990 Result := False;
35991 //if AppletTerminated then Exit;
35992 case Msg.message of
35993 WM_ERASEBKGND:
35994 begin
35995 if Self_.fCannotDoubleBuf then Exit;
35996 if Self_.DblBufTopParent <> nil then
35997 // if the Control is not DoubleBuffered, and none of its Parent controls are
35998 // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work
35999 // as usual.
36000 begin // Call made in WndProcBufferedDraw of the top DoubleBuffered
36001 // Parent control, while processing WM_PAINT
36002 if Self_.fTransparent
36003 // Handle opaque control as usual.
36004 // For transparent (child) controls, do nothing at all
36005 // in responce to WM_ERASEBKGND (just tell to the system, that
36006 // the operation completed).
36008 // If DoubleBuffered control or control's DoubleBuffered parent
36009 // is not painting now through buffer, just ignore the message
36010 not Self_.DblBufTopParent.fDblBufPainting
36011 then
36012 begin
36013 if Self_.fParent <> nil then
36014 begin
36015 Rslt := 1;
36016 Result := TRUE;
36017 Exit;
36018 end;
36019 end;
36020 end;
36021 end;
36022 WM_PAINT:
36023 begin
36024 if Self_.fCannotDoubleBuf then Exit;
36025 Self_DblBufTopParent := Self_.DblBufTopParent;
36026 if Self_DblBufTopParent = nil then
36027 // if the Control is not DoubleBuffered, and none of its Parent controls are
36028 // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work
36029 // as usual.
36030 Exit;
36031 if Self_DblBufTopParent <> Self_ then
36032 // if one of the Parent controls is DoubleBuffered, than ignore this call
36033 // in Global_OnBufferedDraw, and work as usual (actually this allows to
36034 // paint children of the DoubleBuffered Parent control to be painted on
36035 // its buffer).
36036 begin
36037 if (not Self_DblBufTopParent.fDblBufPainting) or
36038 (Self_DblBufTopParent.fPaintDC = 0) then
36039 begin // Usual call. Ignore it.
36040 ValidateRect( Self_.fHandle, nil );
36041 //RedrawWindow( Self_.fHandle, nil, 0, RDW_VALIDATE ); experiment
36042 if not Self_DblBufTopParent.fDblBufPainting then
36043 begin
36044 Self_.DblBufTopParent.Invalidate;
36045 //RedrawWindow( Self_DblBufTopParent.fHandle, nil, 0, RDW_INVALIDATE ); exp.
36046 //RedrawWindow( Self_DblBufTopParent.fHandle, nil, 0, RDW_UPDATENOW ); exp.
36047 end;
36048 Rslt := 0;
36049 Result := True;
36050 end;
36051 Exit; // Call from DoDrawDblBuffered of the top doublebuffered Parent
36052 end;
36053 if Msg.wParam <> 0 then Exit;
36054 DoDrawDblBuffered( Self_ );
36055 Rslt := 0;
36056 Result := True;
36057 end;
36058 WM_NCPAINT:
36059 begin
36060 if Self_.fIsForm {and (WinVer < wvNT)} then Exit;
36061 if Self_.CannotDoubleBuf then Exit;
36062 Self_DblBufTopParent := Self_.DblBufTopParent;
36063 if Self_DblBufTopParent = nil then
36064 // if the Control is not DoubleBuffered, and none of its Parent controls are
36065 // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work
36066 // as usual.
36067 Exit;
36068 //if Self_.DblBufTopParent <> Self_ then
36069 // if one of the Parent controls is DoubleBuffered, than ignore this call
36070 // in Global_OnBufferedDraw, and work as usual (actually this allows to
36071 // paint children of the DoubleBuffered Parent control to be painted on
36072 // its buffer).
36073 begin
36074 if not Self_DblBufTopParent.fDblBufPainting
36075 then
36076 begin // Usual call. Ignore it.
36077 //ValidateRect( Self_.fHandle, nil );
36078 Rslt := 0;
36079 Result := True;
36080 end;
36081 end;
36082 end;
36083 WM_SETTEXT:
36084 begin
36085 if Self_.DblBufTopParent = nil then Exit;
36086 if not Self_.fIsStaticControl then Exit;
36087 ShowWindow( Self_.fHandle, SW_HIDE );
36088 Rslt := DefWindowProc( Self_.fHandle, WM_SETTEXT, Msg.wParam, Msg.lParam );
36089 ShowWindow( Self_.fHandle, SW_SHOWNA );
36090 UpdateWindow( Self_.fHandle ); // necessary!!!
36091 Result := True;
36092 end;
36093 WM_HSCROLL, WM_VSCROLL, WM_WINDOWPOSCHANGED:
36094 begin
36095 if Self_.DblBufTopParent = nil then Exit;
36096 Self_.Invalidate;
36097 end;
36098 WM_COMMAND:
36099 case HiWord( Msg.wParam ) of
36100 LBN_SELCHANGE {, CBN_SELCHANGE }:
36101 begin
36102 if Self_.DblBufTopParent = nil then Exit;
36103 Self_.Invalidate;
36104 end;
36105 end;
36106 end;
36107 end;
36109 const
36110 MM_MCINOTIFY = $3B9;
36112 {$IFDEF ASM_VERSION}
36114 {$DEFINE ASM_LOCAL}
36115 {$IFDEF NEW_MODAL}
36116 {$UNDEF ASM_LOCAL}
36117 {$ENDIF}
36119 {$ELSE}
36121 {$IFDEF ASM_LOCAL}
36122 {$UNDEF ASM_LOCAL}
36123 {$ENDIF}
36125 {$ENDIF}
36127 {$IFDEF ASM_LOCAL}
36128 //[function TControl.WndProc]
36129 function TControl.WndProc( var Msg: TMsg ): Integer;
36130 asm //cmd //opd
36131 PUSH EBX
36132 PUSH ESI
36133 PUSH EDI
36134 XCHG ESI, EAX
36135 MOV EDI, EDX
36136 XOR EAX, EAX
36137 CMP EAX, [EDX].TMsg.hWnd
36138 JNE @@1
36139 CMP EAX, [ESI].TControl.fHandle
36140 JNE @@1
36141 MOV EAX, [EDX].TMsg.hWnd
36142 MOV [ESI].TControl.fHandle, EAX
36143 @@1:
36144 PUSH 0
36145 MOV ECX, ESP
36146 MOV EAX, ESI
36147 CALL dword ptr [Global_OnBufferedDraw]
36148 TEST AL, AL
36149 POP EAX
36150 JNZ @@pass2defproc
36152 CMP [AppletRunning], 0
36153 JZ @@dyn2
36154 MOV ECX, [Applet]
36155 JECXZ @@dyn2
36156 CMP ECX, ESI
36157 JE @@dyn2
36159 CALL @@onmess
36161 @@dyn2: MOV ECX, ESI
36162 CALL @@onmess
36164 MOV EBX, [ESI].TControl.fOnDynHandlers
36165 MOV EAX, ESI
36166 CALL @@callonmes
36168 @@flicksproc:
36169 MOV EAX, ESI
36170 MOV EDX, EDI
36171 PUSH 0
36172 MOV ECX, ESP
36173 CALL dword ptr [ESI].TControl.fWndProcResizeFlicks
36174 TEST AL, AL
36175 POP EAX
36176 JNZ @@pass2defproc
36178 MOVZX EAX, word ptr [EDI].TMsg.message
36180 //CMP word ptr [EDI].TMsg.message, WM_CLOSE
36181 CMP AX, WM_CLOSE
36182 //********************************************************** Changed By M.Gerasimov
36183 // JNE @@chk_WM_NCDESTROY
36184 JNE @@chk_WM_DESTROY
36185 //********************************************************** Changed By M.Gerasimov
36187 MOV ECX, [ESI].TControl.fOnClose.TMethod.Code
36188 JECXZ @@wm_close1
36189 MOV EBX, ECX
36190 PUSH 1
36191 MOV ECX, ESP
36192 MOV EDX, ESI
36193 MOV EAX, [ESI].TControl.fOnClose.TMethod.Data
36194 CALL EBX
36195 POP ECX
36196 INC ECX
36197 LOOP @@wm_close0
36198 CMP [AppletRunning], CL
36199 JZ @@wm_close0
36200 //XOR EAX, EAX
36201 //MOV [ESI].TControl.fModalResult, 0
36202 JMP @@0pass2defproc
36204 /////////////////
36205 @@onmess:
36206 MOV EAX, [ECX].TControl.fOnMessage.TMethod.Data
36207 MOV EBX, [ECX].TControl.fOnMessage.TMethod.Code
36208 @@callonmes:
36209 TEST EBX, EBX
36210 JNZ @@onmess1 // @@dynmes1
36211 @@2onmessret:
36213 @@onmess1:
36214 PUSH 0
36216 MOV EDX, EDI
36217 MOV ECX, ESP
36218 CALL EBX
36219 TEST AL, AL
36221 POP EAX
36222 JZ @@2onmessret
36223 POP EDX // pop retaddr
36224 JMP @@pass2defproc
36225 /////////////////
36227 @@wm_close0:
36228 XOR EAX, EAX
36229 MOV [ESI].TControl.fOnClose.TMethod.Code, EAX
36230 @@wm_close1:
36231 MOV EAX, ESI
36232 CALL TControl.IsMainWindow
36233 TEST AL, AL
36234 MOV ECX, [Applet]
36235 JNZ @@wm_close2
36236 CMP ESI, ECX
36237 JNE @@calldef
36239 @@wm_close2:
36240 JECXZ @@postquit
36241 CMP ECX, ESI
36242 JE @@postquit
36243 PUSH 0
36244 PUSH 0
36245 PUSH WM_CLOSE
36246 PUSH ECX
36247 CALL TControl.Perform
36248 @@postquit:
36249 PUSH 0
36250 CALL PostQuitMessage
36251 //XOR EAX, EAX
36252 JMP @@0pass2defproc
36254 //********************************************************** Added By M.Gerasimov
36256 @@chk_WM_DESTROY:
36257 {CMP word ptr [EDI].TMsg.message, WM_DESTROY
36258 JNE @@chk_WM_NCDESTROY
36259 PUSH GW_CHILD
36260 PUSH [ESI].fHandle
36261 CALL GetWindow
36262 TEST EAX,EAX
36263 JZ @@chk_WM_NCDESTROY
36264 @@RmvNext:
36265 PUSH EAX
36266 PUSH offset[ID_PREVPROC]
36267 PUSH EAX
36268 CALL GetProp
36269 TEST EAX,EAX
36270 JZ @@GetNextChild
36271 POP EAX
36272 PUSH EAX
36273 PUSH offset[ID_PREVPROC]
36274 PUSH EAX
36275 CALL RemoveProp
36276 @@GetNextChild:
36277 POP EAX
36278 PUSH GW_HWNDNEXT
36279 PUSH EAX
36280 CALL GetWindow
36281 TEST EAX,EAX
36282 JNZ @@RmvNext}
36284 //********************************************************** Added By M.Gerasimov
36285 @@chk_WM_NCDESTROY:
36286 //CMP word ptr [EDI].TMsg.message, WM_NCDESTROY
36287 CMP AX, WM_NCDESTROY
36288 JNE @@chk_CM_RELEASE
36289 //********************************************************** Added By M.Gerasimov
36291 PUSH offset[ID_SELF]
36292 PUSH [ESI].fHandle
36293 CALL RemoveProp
36295 //********************************************************** Added By M.Gerasimov
36297 MOV ECX, [Applet]
36298 JECXZ @@nc_destroy1
36299 MOV EAX, [ESI].TControl.fHandle
36300 CMP EAX, [ECX].TControl.fHandle
36301 JE @@calldef
36302 @@nc_destroy1:
36303 MOV EAX, ESI
36304 CALL TControl.IsMainWindow
36305 TEST AL, AL
36306 JZ @@nc_destroy2
36307 PUSH 0
36308 PUSH 0
36309 PUSH CM_RELEASE
36310 PUSH [ESI].TControl.fHandle
36311 CALL PostMessage
36312 JMP @@calldef
36314 @@nc_destroy2:
36315 MOV EAX, [ESI].TControl.fParent
36316 CMP EAX, [Applet]
36317 JNE @@calldef
36319 MOV [ESI].TControl.fNCDestroyed, 1
36320 @@do_free:
36321 XCHG EAX, ESI
36322 CALL TObj.Free
36324 XOR EAX, EAX
36325 JMP @@exit // WM_NCDESTROY and CM_RELEASE
36326 // is not a subject to pass it
36327 // to fPass2DefProc
36329 @@chk_CM_RELEASE:
36330 //CMP word ptr [EDI].TMsg.message, CM_RELEASE
36331 CMP AX, CM_RELEASE
36332 JNE @@chk_WM_SIZE
36334 MOV [ESI].TControl.fDestroying, 1
36335 JMP @@do_free
36337 @@chk_WM_SIZE:
36338 //CMP word ptr [EDI].TMsg.message, WM_SIZE
36339 CMP AX, WM_SIZE
36340 JNE @@chk_WM_SHOWWINDOW
36342 MOV EDX, EDI
36343 MOV EAX, ESI
36344 CALL TControl.CallDefWndProc
36345 PUSH EAX
36347 MOV ECX, [EDI].TMsg.wParam
36348 MOV [ESI].TControl.fWindowState, CL
36350 CMP [ESI].TControl.fIsForm, 0
36351 JNZ @@doGlobalAlignSelf
36352 MOV EAX, [ESI].TControl.fParent
36353 TEST EAX, EAX
36354 JZ @@doGlobalAlignSelf
36355 CALL dword ptr [Global_Align]
36356 @@doGlobalAlignSelf:
36357 XCHG EAX, ESI
36358 CALL dword ptr [Global_Align]
36360 //POP EAX
36361 JMP @@popeax_exit
36362 // fPass2DefProc not needed,
36363 // CallDefWndProc already called
36365 @@chk_WM_SHOWWINDOW:
36366 //CMP word ptr [EDI].TMsg.message, WM_SHOWWINDOW
36367 CMP AX, WM_SHOWWINDOW
36368 JNE @@chk_WM_SYSCOMMAND
36370 MOV ECX, [EDI].TMsg.lParam
36371 LOOP @@chk_SW_PARENTOPENING
36373 PUSH [ESI].TControl.fHandle
36374 CALL IsIconic
36375 XOR EBX, EBX
36376 MOV BL, SW_SHOWMINNOACTIVE
36377 TEST EAX, EAX
36378 JNZ @@store_action
36380 PUSH [ESI].TControl.fHandle
36381 CALL IsZoomed
36382 MOV BL, SW_SHOWMAXIMIZED
36383 TEST EAX, EAX
36384 JNZ @@store_action
36386 MOV BL, SW_SHOWNOACTIVATE
36387 @@store_action:
36388 MOV [ESI].TControl.fShowAction, EBX
36389 @@2calldef:
36390 JMP @@calldef
36392 @@chk_SW_PARENTOPENING:
36393 DEC ECX
36394 LOOP @@2calldef
36396 MOV ECX, [ESI].TControl.fShowAction
36397 JECXZ @@ret_0
36399 PUSH ECX
36400 PUSH [ESI].TControl.fHandle
36401 CALL ShowWindow
36403 XOR EAX, EAX
36404 MOV [ESI].TControl.fShowAction, EAX
36405 @@ret_0:
36406 //XOR EAX, EAX
36407 JMP @@0pass2defproc
36409 @@chk_WM_SYSCOMMAND:
36410 //CMP word ptr [EDI].TMsg.message, WM_SYSCOMMAND
36411 CMP AX, WM_SYSCOMMAND
36412 JNE @@chk_WM_SETFOCUS
36414 MOV EAX, [EDI].TMsg.wParam
36415 {$IFDEF PARANOIA}
36416 DB $24, $F0
36417 {$ELSE}
36418 AND AL, $F0
36419 {$ENDIF}
36420 CMP AX, SC_MINIMIZE
36421 JNE @@calldef
36423 MOV EAX, ESI
36424 CALL TControl.IsMainWindow
36425 TEST AL, AL
36426 JZ @@calldef
36428 CMP ESI, [Applet]
36429 JE @@calldef
36431 PUSH 0
36432 PUSH SC_MINIMIZE
36433 PUSH WM_SYSCOMMAND
36434 MOV EAX, [Applet]
36435 PUSH [EAX].TControl.fHandle
36436 CALL PostMessage
36437 JMP @@ret_0
36439 @@chk_WM_SETFOCUS:
36440 //CMP word ptr [EDI].TMsg.message, WM_SETFOCUS
36441 CMP AX, WM_SETFOCUS
36442 JNE @@chk_WM_SETCURSOR
36444 MOV EAX, ESI
36445 CALL TControl.DoSetFocus
36446 TEST AL, AL
36447 JZ @@0pass2defproc
36449 //@@calldef_clickdisabled:
36450 INC [ESI].TControl.fClickDisabled
36452 MOV EAX, ESI
36453 MOV EDX, EDI
36454 CALL TControl.CallDefWndProc
36456 DEC [ESI].TControl.fClickDisabled
36457 JMP @@exit
36459 @@chk_WM_SETCURSOR:
36460 //CMP word ptr [EDI].TMsg.message, WM_SETCURSOR
36461 CMP AX, WM_SETCURSOR
36462 JNE @@chk_WM_CTLCOLOR
36464 CMP [Global_DisableParentCursor], 0
36465 JNE @@calldef
36467 CALL GetCapture
36468 TEST EAX, EAX
36469 JNZ @@calldef
36471 CMP word ptr [EDI].TMsg.lParam, HTCLIENT
36472 JNE @@calldef
36474 MOV ECX, [ScreenCursor]
36475 INC ECX
36476 LOOP @@setupCursor
36478 MOV ECX, [ESI].TControl.fCursor
36479 TEST ECX, ECX //YS
36480 JE @@calldef //YS
36481 @@setupCursor:
36482 PUSH ECX
36483 CALL Windows.SetCursor
36485 MOV AL, 1
36486 JMP @@exit
36488 @@chk_WM_CTLCOLOR:
36489 //MOV EAX, [EDI].TMsg.message
36490 MOV EDX, EAX
36491 SUB DX, WM_CTLCOLORMSGBOX
36492 CMP DX, WM_CTLCOLORSTATIC-WM_CTLCOLORMSGBOX
36493 JA @@chk_WM_COMMAND
36495 PUSH [EDI].TMsg.lParam
36496 PUSH [EDI].TMsg.wParam
36497 ADD AX, CN_BASE //+WM_CTLCOLORMSGBOX
36498 PUSH EAX
36499 PUSH [EDI].TMsg.lParam
36500 CALL SendMessage
36501 JMP @@pass2defproc
36503 @@chk_WM_COMMAND:
36504 //CMP word ptr [EDI].TMsg.message, WM_COMMAND
36505 CMP AX, WM_COMMAND
36506 JNE @@chk_WM_KEY
36508 PUSH offset[ID_SELF]
36509 PUSH [EDI].TMsg.lParam
36510 CALL GetProp
36511 TEST EAX, EAX
36512 JZ @@calldef
36514 PUSH [EDI].TMsg.lParam
36515 PUSH [EDI].TMsg.wParam
36516 PUSH CM_COMMAND
36517 PUSH [EDI].TMsg.lParam
36518 CALL SendMessage
36519 JMP @@pass2defproc
36521 @@chk_WM_KEY:
36522 //MOV EAX, [EDI].TMsg.message
36523 MOV EDX, EAX
36524 SUB DX, WM_KEYFIRST
36525 CMP DX, WM_KEYLAST-WM_KEYFIRST
36526 JA @@chk_CM_EXECPROC
36528 CALL GetFocus
36529 CMP EAX, [ESI].TControl.fFocusHandle
36530 JE @@in_focus
36531 CMP EAX, [ESI].TControl.fHandle
36532 JNE @@0pass2defproc
36534 @@in_focus:
36535 PUSH EAX
36537 MOV ECX, ESP
36538 MOV EDX, EDI
36539 MOV EAX, ESI
36540 CALL dword ptr [fGlobalProcKeybd]
36541 TEST AL, AL
36542 JNZ @@to_exit
36544 MOV ECX, ESP
36545 MOV EDX, EDI
36546 MOV EAX, ESI
36547 CALL [ESI].fWndProcKeybd
36548 TEST AL, AL
36549 @@to_exit:
36550 POP EAX
36551 JNZ @@pass2defproc
36553 PUSH VK_CONTROL
36554 CALL GetKeyState
36555 XCHG EBX, EAX
36556 PUSH VK_MENU
36557 CALL GetKeyState
36558 OR EAX, EBX
36559 ADD EAX, EAX
36560 JC @@calldef
36562 CMP word ptr [EDI].TMsg.message, WM_CHAR
36563 JNE @@to_fGotoControl
36565 CMP byte ptr [EDI].TMsg.wParam, 9
36566 JE @@clear_wParam
36567 JMP @@calldef
36569 @@to_fGotoControl:
36570 MOV EAX, ESI
36571 CALL TControl.ParentForm
36572 TEST EAX, EAX
36573 JZ @@calldef
36575 MOV ECX, [EAX].fGotoControl
36576 JECXZ @@calldef
36578 MOV EBX, ECX
36579 CMP [EDI].TMsg.message, WM_KEYDOWN
36580 SETNE CL
36581 MOV EDX, [EDI].TMsg.wParam
36582 MOV EAX, ESI
36583 CALL EBX
36584 TEST AL, AL
36585 JZ @@calldef
36587 @@clear_wParam:
36588 XOR EAX, EAX
36589 MOV [EDI].TMsg.wParam, EAX
36590 JMP @@pass2defproc
36592 @@chk_CM_EXECPROC:
36593 //CMP word ptr [EDI].TMsg.message, CM_EXECPROC
36594 CMP AX, CM_EXECPROC
36595 JNE @@chk_MM_MCINOTIFY
36597 MOV EAX, [EDI].TMsg.lParam
36598 MOV EDX, [EDI].TMsg.wParam
36599 CALL [Global_Synchronized]
36600 JMP @@0pass2defproc
36602 @@chk_MM_MCINOTIFY:
36603 //CMP word ptr [EDI].TMsg.message, MM_MCINOTIFY
36604 CMP AX, MM_MCINOTIFY
36605 JNE @@calldef
36607 MOV ECX, [FMMNotify]
36608 JECXZ @@ret_0_MM
36610 XCHG EAX, EDI
36611 CALL ECX
36612 @@ret_0_MM:
36613 XOR EAX, EAX
36614 JMP @@exit
36616 @@calldef:
36617 XCHG EAX, ESI
36618 MOV EDX, EDI
36619 CALL TControl.CallDefWndProc
36620 JMP @@exit
36622 @@0pass2defproc:
36623 XOR EAX, EAX
36624 @@pass2defproc:
36625 PUSH EAX
36626 @@1pass2defproc:
36627 CMP [AppletTerminated], 0 //
36628 JNZ @@popeax_exit // uncommented 25-Oct-2003
36629 CMP [ESI].fNCDestroyed, 0 //
36630 JNZ @@popeax_exit //
36632 MOV ECX, ESP
36633 XCHG EAX, ESI
36634 MOV EDX, EDI
36635 CALL dword ptr[EAX].fPass2DefProc
36636 @@popeax_exit:
36637 POP EAX
36639 @@exit:
36640 POP EDI
36641 POP ESI
36642 POP EBX
36643 end;
36644 {$ELSE ASM_LOCAL} //Pascal
36646 {$IFDEF DEBUG_CREATEWINDOW}
36647 var DbgCWCount: Integer = 0;
36648 {$ENDIF DEBUG_CREATEWINDOW}
36649 function TControl.WndProc( var Msg: TMsg ): Integer;
36650 var Accept: Boolean;
36651 C : PControl;
36652 F {, Chld}: HWnd;
36653 Cur: HCURSOR; // YS
36654 PassFun: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
36656 procedure Default;
36657 begin
36658 Result := CallDefWndProc( Msg );
36659 end;
36661 begin
36662 {$IFDEF DEBUG_CREATEWINDOW}
36663 Inc( DbgCWCount );
36664 if DbgCWCount < 10 then
36665 LogFileOutput( GetStartDir + 'Session.log', 'TControl.WndProc: ' +
36666 ' Msg.hwnd=' + Int2Str( Msg.hwnd ) +
36667 ' Msg.message=' + Int2Hex( Msg.message, 2 ) +
36668 ' Msg.wParam=' + Int2Str( Msg.wParam ) + '=$' + Int2Hex( Msg.wParam, 4 ) +
36669 ' Msg.lParam=' + Int2Str( Msg.lParam ) + '=$' + Int2Hex( Msg.lParam, 4 ) );
36670 {$ENDIF DEBUG_CREATEWINDOW}
36671 if (Msg.hwnd <> 0) and (fHandle = 0) then
36672 fHandle := Msg.hwnd;
36674 PassFun := fPass2DefProc;
36675 if not Global_OnBufferedDraw( @Self, Msg, Result ) then
36676 if not (AppletRunning and (Applet <> @Self) and Assigned( Applet ) and
36677 Assigned( Applet.OnMessage ) and Applet.OnMessage( Msg, Result )) then
36678 if not (Assigned( OnMessage ) and OnMessage( Msg, Result )) then
36679 if not fOnDynHandlers( @Self, Msg, Result ) then
36680 begin
36681 if not fWndProcResizeFlicks( @Self, Msg, Result ) then
36682 case Msg.message of
36683 {$IFDEF NEW_MODAL}
36684 // version of code by Alexander Pravdin
36685 WM_CLOSE:
36686 begin
36687 Accept := True;
36688 if Assigned( fOnClose ) then begin
36689 fOnClose( @Self, Accept );
36690 if AppletRunning then
36691 if Accept then
36692 if fModal > 0 then begin
36693 if ModalResult = 0 then
36694 fModalResult := Integer($80000000);
36695 Msg.message := 0;
36696 Exit;
36698 else
36699 fOnClose := nil
36700 else begin
36701 Result := 0;
36702 fModalResult := 0;
36704 else
36705 fOnClose := nil;
36707 else begin
36708 if fModal > 0 then begin
36709 if ModalResult = 0 then
36710 fModalResult := Integer($80000000);
36711 Exit;
36712 end;
36713 end;
36715 if Accept then begin
36716 if IsMainWindow or ( Applet = @Self ) then begin
36717 if Assigned( Applet ) and ( Applet <> @Self ) then
36718 Applet.Perform( WM_CLOSE, 0, 0 );
36719 PostQuitMessage( 0 );
36720 Result := 0;
36722 else
36723 Default;
36724 end;
36725 end;
36726 {$ELSE}
36727 WM_CLOSE: begin
36728 Accept := True;
36729 if Assigned( fOnClose ) then
36730 begin
36731 fOnClose( @Self, Accept );
36732 if (not Accept) and (AppletRunning) then
36733 begin
36734 Result := 0;
36735 //ModalResult := 0;
36736 //Exit; //?????????????????
36738 else //+-+
36739 fOnClose := nil;
36740 end;
36741 if Accept then
36742 begin
36743 if IsMainWindow or (Applet = @Self) then
36744 begin
36745 if Assigned( Applet ) and (Applet <> @Self) then
36746 Applet.Perform( WM_CLOSE, 0, 0 );
36747 PostQuitMessage( 0 );
36748 Result := 0;
36749 //Exit; //???????????????
36751 else
36752 Default;
36753 end;
36754 end;
36755 {$ENDIF}
36756 {//********************************************************** Added By M.Gerasimov
36758 WM_DESTROY:
36759 begin
36760 Chld := GetWindow( fHandle, GW_CHILD );
36761 while Chld <> 0 do
36762 begin
36763 if GetProp( Chld, ID_PREVPROC ) <> 0 then
36764 RemoveProp(Chld, ID_PREVPROC);
36765 Chld := GetWindow( Chld, GW_HWNDNEXT );
36766 end;
36767 end;
36769 //********************************************************** Added By M.Gerasimov}
36770 WM_NCDESTROY:
36771 begin
36772 //********************************************************** Added By M.Gerasimov
36774 RemoveProp( fHandle, ID_SELF );
36776 //********************************************************** Added By M.Gerasimov
36777 if (Applet = nil) or (Handle <> Applet.Handle) then
36778 begin
36779 if IsMainWindow then
36780 begin
36781 PostMessage( fHandle, CM_RELEASE, 0, 0 );
36782 Default;
36784 else
36785 if fParent = Applet then
36786 begin
36787 fNCDestroyed := True;
36788 Free;
36789 Result := 0;
36790 Exit; //!!!!!!!!!!!!!!!!!!!!!!!!!
36792 else
36793 Default;
36794 end;
36795 end;
36797 CM_RELEASE: begin
36798 fDestroying := True;
36799 Free;
36800 Result := 0;
36801 //Exit; //??????????????????????????
36802 end;
36804 WM_SIZE: begin
36805 Default;
36806 case Msg.wParam of
36807 SIZENORMAL: fWindowState := wsNormal;
36808 SIZEICONIC: fWindowState := wsMinimized;
36809 SIZEFULLSCREEN: fWindowState := wsMaximized;
36810 end;
36811 if not fIsForm and (fParent <> nil) then
36812 Global_Align( fParent );
36813 Global_Align( @Self );
36814 Exit;
36815 end;
36816 WM_SHOWWINDOW:
36817 begin
36818 case Msg.lParam of
36819 SW_PARENTCLOSING:
36820 begin
36821 if IsIconic( fHandle ) then
36822 fShowAction := SW_SHOWMINNOACTIVE
36823 else
36824 if IsZoomed( fHandle ) then
36825 fShowAction := SW_SHOWMAXIMIZED
36826 else
36827 fShowAction := SW_SHOWNOACTIVATE;
36828 Default;
36829 end;
36830 SW_PARENTOPENING:
36831 begin
36832 if fShowAction <> 0 then
36833 begin
36834 ShowWindow( Handle, fShowAction );
36835 fShowAction := 0;
36836 end;
36837 Result := 0;
36838 //Exit; //?????????????????????????
36839 end;
36840 else Default;
36841 end;
36842 end;
36843 WM_SysCommand:
36844 begin
36845 if ((Msg.wParam and $FFF0) = SC_MINIMIZE) and
36846 IsMainWindow and (@Self <> Applet) then
36847 begin
36848 PostMessage( Applet.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
36849 Result := 0;
36850 //Exit; //???????????????????????????
36852 else Default;
36853 end;
36854 WM_SETFOCUS:
36855 begin
36856 if not DoSetFocus then
36857 begin
36858 Result := 0;
36859 //Exit; //???????????????????????????
36861 else
36862 begin
36863 Inc( fClickDisabled );
36864 Default;
36865 Dec( fClickDisabled );
36866 Exit;
36867 end;
36868 end;
36869 WM_SETCURSOR:
36870 if not Global_DisableParentCursor then
36871 begin
36872 if (GetCapture = 0) and
36873 (LOWORD( Msg.lParam ) = HTCLIENT) then
36874 begin
36875 if ScreenCursor <> 0 then //YS
36876 Cur := ScreenCursor //YS
36877 else //YS
36878 Cur := fCursor; //YS
36879 if Cur <> 0 then //YS
36880 begin //YS
36881 Windows.SetCursor( Cur ); //YS
36882 Result := 1; //YS
36883 end //YS
36884 else //YS
36885 Default; //YS
36886 //Exit; //?????????????????????
36888 else Default;
36890 else Default;
36891 WM_CTLCOLORMSGBOX..WM_CTLCOLORSTATIC:
36892 begin
36893 Result := SendMessage(Msg.LParam, CN_BASE + Msg.message, Msg.WParam, Msg.LParam);
36894 //exit; //???????????????????????
36895 end;
36896 WM_COMMAND:
36897 begin
36898 C := Pointer( GetProp( Msg.lParam, ID_SELF ) );
36899 if C <> nil then
36900 begin
36901 Result := SendMessage( Msg.lParam, CM_COMMAND, Msg.wParam, Msg.lParam );
36902 //Exit; //???????????????????????
36904 else Default;
36905 end;
36906 WM_KEYFIRST..WM_KEYLAST:
36907 begin
36908 F := GetFocus;
36909 if (F <> fFocusHandle) and (F <> fHandle) then
36910 begin
36911 Result := 0;
36912 // Jump to PassFun here. Prevents beep in case when WM_KEYDOWN
36913 // called another form and focus is changed, so WM_KEYUP failed
36914 // to handle.
36916 else
36917 begin
36918 if fGlobalProcKeybd( @Self, Msg, Result ) then Exit; //??????????????????
36919 //else
36920 if fWndProcKeybd( @Self, Msg, Result ) then Exit; //???????????????????
36921 //else
36922 if ((GetKeystate( VK_CONTROL ) or GetKeyState( VK_MENU )) >= 0) then
36923 begin
36924 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36925 if (Msg.message <> WM_CHAR) // v1.02 Tabulate AND " in EditBox fix
36926 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36927 then
36928 begin
36929 C := ParentForm;
36930 if (C <> nil) and Assigned(C.fGotoControl) and
36931 C.fGotoControl( @Self, Msg.wParam, Msg.message <> WM_KEYDOWN ) then
36932 begin
36933 Msg.wParam := 0;
36934 Result := 0;
36935 //+-+exit;
36937 else Default;
36939 //+++++++++++++++++++++++++++++++++++++++++++++//
36940 else //
36941 if Msg.wParam = 9 then // prevent system beep //
36942 begin //
36943 Msg.wParam := 0; //
36944 Result := 0; //
36945 //+-+exit; //
36946 end //
36947 //+++++++++++++++++++++++++++++++++++++++++++++//
36948 else Default;
36950 else Default;
36951 end;
36952 end;
36953 CM_EXECPROC: begin
36954 Global_Synchronized( Pointer( Msg.lParam ), Pointer( Msg.wParam ) );
36955 Result := 0;
36956 //Exit; //???????????????????
36957 end;
36958 MM_MCINOTIFY: begin
36959 if Assigned( FMMNotify ) then
36960 FMMNotify( Msg );
36961 Result := 0;
36962 exit;
36963 end;
36964 else begin
36965 Default; //+-+
36966 Exit; //+-+
36967 end;
36968 end;
36969 end;
36971 if not AppletTerminated and not fNCDestroyed then
36972 PassFun( @Self, Msg, Result ); //+-+
36973 end;
36974 {$ENDIF ASM_LOCAL}
36975 //[END TContro]
36977 {$UNDEF ASM_LOCAL}
36979 //[procedure SetMouseEvent]
36980 procedure SetMouseEvent( Self_: PControl );
36981 begin
36982 Self_.AttachProc( WndProcMouse );
36983 end;
36985 //[procedure TControl.SetMouseDown]
36986 procedure TControl.SetMouseDown(const Value: TOnMouse);
36987 begin
36988 fOnMouseDown := Value;
36989 SetMouseEvent( @Self );
36990 end;
36992 //[procedure TControl.SetMouseMove]
36993 procedure TControl.SetMouseMove(const Value: TOnMouse);
36994 begin
36995 fOnMouseMove := Value;
36996 SetMouseEvent( @Self );
36997 end;
36999 //[procedure TControl.SetMouseUp]
37000 procedure TControl.SetMouseUp(const Value: TOnMouse);
37001 begin
37002 fOnMouseUp := Value;
37003 SetMouseEvent( @Self );
37004 end;
37006 //[procedure TControl.SetMouseDblClk]
37007 procedure TControl.SetMouseDblClk(const Value: TOnMouse);
37008 begin
37009 fOnMouseDblClk := Value;
37010 SetMouseEvent( @Self );
37011 end;
37013 //[procedure TControl.SetMouseWheel]
37014 procedure TControl.SetMouseWheel(const Value: TOnMouse);
37015 begin
37016 fOnMouseWheel := Value;
37017 SetMouseEvent( @Self );
37018 end;
37020 {$IFDEF ASM_VERSION}
37021 //[procedure TControl.SetClsStyle]
37022 procedure TControl.SetClsStyle( Value: DWord );
37023 asm //cmd //opd
37024 CMP EDX, [EAX].TControl.fClsStyle
37025 JE @@exit
37026 MOV [EAX].TControl.fClsStyle, EDX
37027 MOV ECX, [EAX].TControl.fHandle
37028 JECXZ @@exit
37029 PUSH EDX
37030 PUSH GCL_STYLE
37031 PUSH ECX
37032 CALL SetClassLong
37033 @@exit:
37034 end;
37035 {$ELSE ASM_VERSION} //Pascal
37036 procedure TControl.SetClsStyle( Value: DWord );
37037 begin
37038 if fClsStyle = Value then Exit;
37039 fClsStyle := Value;
37040 if fHandle = 0 then Exit;
37041 SetClassLong( fHandle, GCL_STYLE, Value );
37042 end;
37043 {$ENDIF ASM_VERSION}
37045 {$IFDEF ASM_VERSION}
37046 //[procedure TControl.SetStyle]
37047 procedure TControl.SetStyle( Value: DWord );
37048 const SWP_FLAGS = SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
37049 SWP_NOZORDER or SWP_FRAMECHANGED;
37051 CMP EDX, [EAX].fStyle
37052 JZ @@exit
37053 MOV [EAX].fStyle, EDX
37054 MOV ECX, [EAX].fHandle
37055 JECXZ @@exit
37057 PUSH EAX
37059 PUSH SWP_FLAGS
37060 XOR EAX, EAX
37061 PUSH EAX
37062 PUSH EAX
37063 PUSH EAX
37064 PUSH EAX
37065 PUSH EAX
37066 PUSH ECX
37068 PUSH EDX
37069 PUSH GWL_STYLE
37070 PUSH ECX
37071 CALL SetWindowLong
37073 CALL SetWindowPos
37075 POP EAX
37076 CALL Invalidate
37077 @@exit:
37078 end;
37079 {$ELSE ASM_VERSION} //Pascal
37080 procedure TControl.SetStyle( Value: DWord );
37081 begin
37082 if fStyle = Value then Exit;
37083 fStyle := Value;
37084 if fHandle = 0 then Exit;
37085 SetWindowLong( fHandle, GWL_STYLE, Value );
37087 SetWindowPos( fHandle, 0, 0, 0, 0, 0,
37088 SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
37089 SWP_NOZORDER or SWP_FRAMECHANGED );
37090 Invalidate;
37091 end;
37092 {$ENDIF ASM_VERSION}
37094 {$IFDEF ASM_VERSION}
37095 //[procedure TControl.SetExStyle]
37096 procedure TControl.SetExStyle( Value: DWord );
37097 const SWP_FLAGS = SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
37098 SWP_NOZORDER or SWP_FRAMECHANGED;
37100 CMP EDX, [EAX].fExStyle
37101 JZ @@exit
37102 MOV [EAX].fExStyle, EDX
37103 MOV ECX, [EAX].fHandle
37104 JECXZ @@exit
37106 PUSH EAX
37108 PUSH SWP_FLAGS
37109 XOR EAX, EAX
37110 PUSH EAX
37111 PUSH EAX
37112 PUSH EAX
37113 PUSH EAX
37114 PUSH EAX
37115 PUSH ECX
37117 PUSH EDX
37118 PUSH GWL_EXSTYLE
37119 PUSH ECX
37120 CALL SetWindowLong
37122 CALL SetWindowPos
37124 POP EAX
37125 CALL Invalidate
37126 @@exit:
37127 end;
37128 {$ELSE ASM_VERSION} //Pascal
37129 procedure TControl.SetExStyle( Value: DWord );
37130 begin
37131 if fExStyle = Value then Exit;
37132 fExStyle := Value;
37133 if fHandle = 0 then Exit;
37134 SetWindowLong( fHandle, GWL_EXSTYLE, Value );
37136 SetWindowPos( fHandle, 0, 0, 0, 0, 0,
37137 SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
37138 SWP_NOZORDER or SWP_FRAMECHANGED );
37139 Invalidate;
37140 end;
37141 {$ENDIF ASM_VERSION}
37143 {$IFDEF ASM_VERSION}
37144 //[procedure TControl.SetCursor]
37145 procedure TControl.SetCursor( Value: HCursor );
37146 asm //cmd //opd
37147 CMP EDX, [EAX].TControl.fCursor
37148 JE @@exit
37149 MOV [EAX].TControl.fCursor, EDX
37150 MOV ECX, [EAX].TControl.fHandle
37151 JECXZ @@exit
37152 TEST EDX, EDX //YS
37153 JE @@exit //YS
37154 MOV ECX, [ScreenCursor]
37155 INC ECX
37156 LOOP @@exit
37158 PUSH EBX
37159 XCHG EBX, EAX
37160 PUSH EDX
37161 PUSH EAX
37162 PUSH EAX
37163 PUSH ESP
37164 CALL GetCursorPos
37165 MOV EDX, ESP
37166 MOV ECX, EDX
37167 MOV EAX, EBX
37168 CALL Screen2Client
37169 ADD ESP, -16
37170 MOV EDX, ESP
37171 MOV EAX, EBX
37172 CALL TControl.ClientRect
37173 MOV EDX, ESP
37174 LEA EAX, [ESP+16]
37175 CALL PointInRect
37176 ADD ESP, 24
37177 TEST AL, AL
37178 JZ @@fin
37179 CALL Windows.SetCursor
37180 PUSH EAX
37181 @@fin: POP EAX
37182 POP EBX
37183 @@exit:
37184 end;
37185 {$ELSE ASM_VERSION} //Pascal
37186 procedure TControl.SetCursor( Value: HCursor );
37187 var P: TPoint;
37188 begin
37189 if fCursor = Value then Exit;
37190 fCursor := Value;
37191 if (fHandle = 0) or (fCursor = 0) then Exit; //YS
37192 if ScreenCursor <> 0 then Exit;
37193 GetCursorPos( P );
37194 P := Screen2Client( P );
37195 if PointInRect( P, ClientRect ) then
37196 Windows.SetCursor( Value );
37197 end;
37198 {$ENDIF ASM_VERSION}
37200 //[procedure TControl.CursorLoad]
37201 procedure TControl.CursorLoad(Inst: Integer; ResName: PChar);
37202 begin
37203 Cursor := LoadCursor( Inst, ResName );
37204 fCursorShared := TRUE;
37205 end;
37207 {$IFDEF ASM_VERSION}
37208 //[procedure TControl.SetIcon]
37209 procedure TControl.SetIcon( Value: HIcon );
37210 asm //cmd //opd
37211 CMP EDX, [EAX].TControl.fIcon
37212 JE @@exit
37213 MOV [EAX].TControl.fIcon, EDX
37214 INC EDX
37215 JZ @@1
37216 DEC EDX
37217 @@1:
37218 PUSH EDX
37219 PUSH 1 //ICON_BIG
37220 PUSH WM_SETICON
37221 PUSH EAX
37222 CALL Perform
37223 TEST EAX, EAX
37224 JZ @@exit
37225 PUSH EAX
37226 CALL DestroyIcon
37227 @@exit:
37228 end;
37229 {$ELSE ASM_VERSION} //Pascal
37230 procedure TControl.SetIcon( Value: HIcon );
37231 var OldIco: HIcon;
37232 begin
37233 if fIcon = Value then Exit;
37234 fIcon := Value;
37235 if Value = THandle(-1) then
37236 Value := 0;
37237 OldIco := Perform( WM_SETICON, 1 {ICON_BIG}, Value );
37238 if OldIco <> 0 then
37239 DestroyIcon( OldIco );
37240 end;
37241 {$ENDIF ASM_VERSION}
37243 {$IFDEF ASM_VERSION}
37244 //[procedure TControl.SetMenu]
37245 procedure TControl.SetMenu( Value: HMenu );
37247 PUSH EBX
37248 XCHG EBX, EAX
37249 CMP [EBX].fMenu, EDX
37250 JZ @@exit
37251 PUSH EDX
37252 MOV ECX, [EBX].fMenuObj
37253 JECXZ @@no_free_menuctl
37254 XCHG EAX, EDX
37255 CALL TObj.Free
37256 @@no_free_menuctl:
37257 MOV ECX, [EBX].fMenu
37258 JECXZ @@no_destroy
37259 PUSH ECX
37260 CALL DestroyMenu
37261 @@no_destroy:
37262 POP EDX
37263 MOV [EBX].fMenu, EDX
37264 MOV ECX, [EBX].fHandle
37265 JECXZ @@exit
37266 PUSH EDX
37267 PUSH ECX
37268 CALL Windows.SetMenu
37269 @@exit:
37270 POP EBX
37271 end;
37272 {$ELSE ASM_VERSION} //Pascal
37273 procedure TControl.SetMenu( Value: HMenu );
37274 begin
37275 if fMenu = Value then Exit;
37276 if fMenuObj <> nil then
37277 fMenuObj.Free;
37278 if fMenu <> 0 then
37279 DestroyMenu( fMenu );
37280 fMenu := Value;
37281 if fHandle = 0 then Exit;
37282 Windows.SetMenu( fHandle, Value );
37283 end;
37284 {$ENDIF ASM_VERSION}
37286 //[procedure CallWinHelp]
37287 procedure CallWinHelp( Context: Integer; CtxCtl: PControl );
37288 var Cmd: Integer;
37289 Form: PControl;
37290 Popup: Boolean;
37291 begin
37292 Cmd := HELP_CONTEXT;
37293 if CtxCtl <> nil then
37294 begin
37295 Form := CtxCtl.ParentForm;
37296 if Form <> nil then
37297 if Assigned( Form.OnHelp ) then
37298 begin
37299 Popup := FALSE;
37300 Form.OnHelp( CtxCtl, Context, Popup );
37301 if Popup then
37302 Cmd := HELP_CONTEXTPOPUP;
37303 if CtxCtl = nil then Exit;
37304 end;
37306 else
37307 if Context = 0 then
37308 Cmd := HELP_CONTENTS;
37309 WinHelp( Applet.Handle, PChar( Applet.GetHelpPath ), Cmd, Context );
37310 end;
37312 var HHCtrl: THandle;
37313 HtmlHelp: procedure( Wnd: HWnd; Path: PChar; Cmd, Data: Integer ); stdcall;
37315 //[procedure HtmlHelpCommand]
37316 procedure HtmlHelpCommand( Wnd: HWnd; const HelpFilePath: String; Cmd, Data: Integer );
37317 begin
37318 if HHCtrl = 0 then
37319 HHCtrl := LoadLibrary( 'HHCTRL.OCX' );
37320 if HHCtrl = 0 then Exit;
37321 if not Assigned( HtmlHelp ) then
37322 HtmlHelp := GetProcAddress( HHCtrl, 'HtmlHelpA' );
37323 if not Assigned( HtmlHelp ) then Exit;
37324 HtmlHelp( Wnd, PChar( HelpFilePath ), Cmd, Data );
37325 end;
37327 //[procedure CallHtmlHelp]
37328 procedure CallHtmlHelp( Context: Integer; CtxCtl: PControl );
37329 var Cmd: Integer;
37330 Form: PControl;
37331 Popup: Boolean;
37332 Ids: array[ 0..2 ] of DWORD;
37333 begin
37335 Cmd := $F; // HH_HELP_CONTEXT;
37336 if CtxCtl <> nil then
37337 begin
37338 Form := CtxCtl.ParentForm;
37339 if Form <> nil then
37340 if Assigned( Form.OnHelp ) then
37341 begin
37342 Popup := FALSE;
37343 Form.OnHelp( CtxCtl, Context, Popup );
37344 if Popup then
37345 begin
37346 Cmd := $10; //HH_TP_HELPCONTEXTMENU;
37347 Ids[ 0 ] := CtxCtl.fMenu;
37348 Ids[ 1 ] := Context;
37349 Ids[ 2 ] := 0;
37350 Context := Integer( @ Ids );
37351 end;
37352 if CtxCtl = nil then Exit;
37353 end;
37355 else
37356 if Context = 0 then
37357 Cmd := 1; // HH_DISPLAY_TOC;
37358 HtmlHelpCommand( Applet.Handle, HelpFilePath, Cmd, Context );
37359 end;
37362 Global_HelpProc: procedure( Context: Integer; CtxCtl: PControl ) = CallWinHelp;
37364 //[function WndProcHelp]
37365 function WndProcHelp( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
37366 var HI: PHelpInfo;
37367 Ctx: Integer;
37368 Ctl: PControl;
37369 begin
37370 Result := FALSE;
37371 if Msg.message = WM_HELP then
37372 begin
37373 Ctx := 0;
37374 Ctl := nil;
37375 HI := Pointer( Msg.lParam );
37376 if HI.iContextType = HELPINFO_WINDOW then
37377 begin
37378 Ctl := Pointer( GetProp( HI.hItemHandle, ID_SELF ) );
37379 while Ctl <> nil do
37380 begin
37381 Ctx := Ctl.fHelpContext;
37382 if Ctx <> 0 then break;
37383 Ctl := Ctl.Parent;
37384 end;
37386 else
37387 //if HI.iContextType = HELPINFO_MENUITEM then
37388 Ctx := GetMenuContextHelpID( HI.hItemHandle );
37389 Applet.CallHelp( Ctx, Ctl );
37390 Rslt := 1;
37391 Result := TRUE;
37393 {$IFDEF AUTO_CONTEXT_HELP}
37394 else
37395 if (Msg.message = WM_CONTEXTMENU) then
37396 begin
37397 Ctl := Pointer( GetProp( Msg.wParam, ID_SELF ) );
37398 if (Ctl <> nil) and (Ctl.fHelpContext <> 0) then
37399 //if (Ctl.fAutoPopupMenu = nil) then // seems not working
37400 begin
37401 Applet.CallHelp( Ctl.fHelpContext, Ctl );
37402 Rslt := 1;
37403 Result := TRUE;
37404 end;
37406 {$ENDIF}
37408 end;
37410 //[procedure TControl.SetHelpContext]
37411 procedure TControl.SetHelpContext(Value: Integer);
37412 var F: PControl;
37413 begin
37414 fHelpContext := Value;
37415 F := ParentForm;
37416 if F = nil then Exit;
37417 F.AttachProc( WndProcHelp );
37418 SetWindowContextHelpId( GetWindowHandle, Value );
37419 end;
37421 //[function TControl.AssignHelpContext]
37422 function TControl.AssignHelpContext(Context: Integer): PControl;
37423 begin
37424 SetHelpContext( Context );
37425 Result := @ Self;
37426 end;
37428 //[procedure AssignHtmlHelp]
37429 procedure AssignHtmlHelp( const HtmlHelpPath: String );
37430 begin
37431 Assert( (HtmlHelpPath <> '') and (Applet <> nil), 'Error parameters' );
37432 if HelpFilePath <> '' then
37433 FreeMem( HelpFilePath );
37434 GetMem( HelpFilePath, Length( HtmlHelpPath ) + 1 );
37435 StrCopy( HelpFilePath, @ HtmlHelpPath[ 1 ] );
37436 Global_HelpProc := CallHtmlHelp;
37437 Applet.AttachProc( WndProcHelp );
37438 end;
37440 //[procedure TControl.CallHelp]
37441 procedure TControl.CallHelp(Context: Integer; CtxCtl: PControl {; CtlID: Integer} );
37442 begin
37443 Global_HelpProc( Context, CtxCtl {, CtlID} );
37444 end;
37446 //[function TControl.GetHelpPath]
37447 function TControl.GetHelpPath: String;
37448 begin
37449 Result := HelpFilePath;
37450 if Result = '' then
37451 begin
37452 Result := ParamStr( 0 );
37453 Result := ReplaceFileExt( Result, '.hlp' );
37454 end;
37455 end;
37457 //[procedure TControl.SetHelpPath]
37458 procedure TControl.SetHelpPath(const Value: String);
37459 begin
37460 Assert( Value <> '', 'Error parameter' );
37461 if HelpFilePath <> '' then
37462 FreeMem( HelpFilePath );
37463 GetMem( HelpFilePath, Length( Value ) + 1 );
37464 StrCopy( HelpFilePath, @ Value[ 1 ] );
37465 end;
37467 {$IFDEF ASM_VERSION}
37468 //[function TControl.GetCaption]
37469 function TControl.GetCaption: String;
37471 XCHG EAX, EDX
37472 MOVZX ECX, [EDX].fIgnoreWndCaption
37473 JECXZ @@getwndcaption
37475 @@ret_fCaption:
37476 MOV EDX, [EDX].fCaption
37477 JMP System.@LStrFromPChar
37479 @@getwndcaption:
37480 MOV ECX, [EDX].fHandle
37481 JECXZ @@ret_fCaption
37483 PUSH EBX
37484 PUSH ESI
37485 XCHG EBX, EAX
37487 MOV ESI, ECX
37488 PUSH ESI
37489 CALL GetWindowTextLength
37490 MOV EDX, EAX
37491 INC EAX
37492 PUSH EAX // MaxLen
37494 MOV EAX, EBX
37495 CALL System.@LStrSetLength
37497 POP EDX
37498 MOV ECX, [EBX]
37499 JECXZ @@exit
37500 PUSH EDX // MaxLen = Length(Result) + 1
37502 PUSH ECX //@Result[1]
37503 PUSH ESI // fHandle
37504 CALL GetWindowText
37506 @@exit:
37507 POP ESI
37508 POP EBX
37509 end;
37510 {$ELSE ASM_VERSION} //Pascal
37511 function TControl.GetCaption: String;
37512 var Buf: PChar;
37513 Sz: Integer;
37514 begin
37515 if not fIgnoreWndCaption and (FHandle <> 0) then
37516 begin
37517 Sz := GetWindowTextLength( FHandle );
37518 if Sz = 0 then
37519 Buf := nil
37520 else
37521 begin
37522 GetMem( Buf, Sz + 1 );
37523 GetWindowText( FHandle, Buf, Sz + 1 );
37524 end;
37525 Result := Buf;
37526 if Buf <> nil then
37527 FreeMem( Buf );
37528 Exit;
37529 end;
37530 Result := FCaption;
37531 end;
37532 {$ENDIF ASM_VERSION}
37534 {$IFDEF ASM_VERSION}
37535 //[procedure TControl.SetCaption]
37536 procedure TControl.SetCaption( const Value: String );
37538 PUSH EBX
37539 XCHG EBX, EAX
37540 PUSH EDX
37541 MOV EAX, [EBX].fCaption
37542 TEST EAX, EAX
37543 JZ @@store_Caption
37544 CALL System.@FreeMem
37545 @@store_Caption:
37546 POP EAX
37547 CALL EAX2PChar
37548 PUSH EAX
37549 CALL StrLen
37550 INC EAX
37551 CALL System.@GetMem
37552 MOV [EBX].fCaption, EAX
37553 POP EDX
37554 CALL StrCopy
37555 MOV ECX, [EBX].fHandle
37556 JECXZ @@exit
37557 PUSH [EBX].fCaption
37558 PUSH ECX
37559 CALL SetWindowText
37560 CMP [EBX].fIsStaticControl, 0
37561 JZ @@1
37562 MOV EAX, EBX
37563 CALL Invalidate
37564 @@1:
37565 XCHG EAX, EBX
37566 MOV ECX, [EAX].fAutoSize
37567 JECXZ @@exit
37568 CALL ECX
37569 @@exit: POP EBX
37570 end;
37571 {$ELSE ASM_VERSION} //Pascal
37572 procedure TControl.SetCaption( const Value: String );
37573 var L: DWORD;
37574 begin
37575 //if fHandle = 0 then
37576 begin
37577 if fCaption <> nil then
37578 FreeMem( fCaption );
37579 L := Length( Value ) + 1;
37580 GetMem( fCaption, L );
37581 StrCopy( fCaption, PChar( Value ) );
37582 //Exit;
37583 end;
37584 if fHandle = 0 then Exit;
37585 SetWindowText( fHandle, @Value[ 1 ] );
37586 if not fIsStaticControl then
37587 Invalidate;
37588 if Assigned( fAutoSize ) then
37589 fAutoSize( @Self );
37590 end;
37591 {$ENDIF ASM_VERSION}
37593 {$IFDEF ASM_VERSION}
37594 //[function TControl.GetVisible]
37595 function TControl.GetVisible: Boolean;
37597 MOV ECX, [EAX].fHandle
37598 JECXZ @@check_fStyle
37600 {CMP [EAX].fIsControl, 0
37601 JNE @@check_fStyle}
37603 PUSH EAX
37604 PUSH ECX
37605 CALL IsWindowVisible
37606 TEST EAX, EAX
37607 POP EAX
37608 JMP @@checked // Z if not visible
37610 @@check_fStyle:
37611 TEST byte ptr [EAX].fStyle+3, 10h // WS_VISIBLE shr 3
37612 @@checked:
37613 SETNZ DL
37614 MOV [EAX].fVisible, DL
37615 XCHG EAX, EDX
37616 end;
37617 {$ELSE ASM_VERSION}
37618 function TControl.GetVisible: Boolean;
37619 begin
37620 if (fHandle <> 0)
37621 //and (not fIsControl or (ParentForm <> nil) and ParentForm.Visible)
37622 //and not fIsControl
37623 then
37624 fVisible :=
37625 //LongBool( GetWindowLong( fHandle, GWL_STYLE ) and WS_VISIBLE )
37626 IsWindowVisible( fHandle )
37627 else
37628 fVisible := (FStyle and WS_VISIBLE) <> 0;
37629 Result := fVisible;
37630 end;
37631 {$ENDIF ASM_VERSION}
37633 {$IFDEF ASM_VERSION}
37634 //[function TControl.Get_Visible]
37635 function TControl.Get_Visible: Boolean;
37636 asm // //
37637 MOV ECX, [EAX].fHandle
37638 JECXZ @@ret_fVisible
37639 CMP [EAX].fIsControl, 0
37640 JNZ @@ret_fVisible
37641 PUSH EAX
37642 PUSH ECX
37643 CALL IsWindowVisible
37644 XCHG EDX, EAX
37645 POP EAX
37646 MOV [EAX].fVisible, DL
37647 @@ret_fVisible:
37648 MOVZX EAX, [EAX].fVisible
37649 end;
37650 {$ELSE ASM_VERSION} // Pascal
37651 function TControl.Get_Visible: Boolean;
37652 begin
37653 if (fHandle <> 0)
37654 //and (not fIsControl or (ParentForm <> nil) and ParentForm.Visible)
37655 and not fIsControl
37656 then
37657 fVisible :=
37658 //LongBool( GetWindowLong( fHandle, GWL_STYLE ) and WS_VISIBLE )
37659 IsWindowVisible( fHandle );
37660 Result := fVisible;
37661 end;
37662 {$ENDIF ASM_VERSION}
37664 {$IFDEF ASM_VERSION}
37665 //[procedure TControl.Set_Visible]
37666 procedure TControl.Set_Visible( Value: Boolean );
37667 const wsVisible = $10;
37669 PUSH EBX
37670 PUSH ESI
37671 //MOV ESI, EAX
37672 XCHG ESI, EAX
37673 MOVZX EBX, DL
37674 {CALL Get_Visible
37675 CMP AL, BL
37676 JE @@reset_fCreateHidden}
37678 MOV AL, byte ptr [ESI].fStyle + 3
37679 TEST EBX, EBX
37680 JZ @@reset_WS_VISIBLE
37681 OR AL, wsVisible
37682 PUSH SW_SHOW
37683 JMP @@store_Visible
37684 @@reset_WS_VISIBLE:
37685 AND AL, not wsVisible
37686 PUSH SW_HIDE
37688 @@store_Visible:
37689 MOV byte ptr [ESI].fStyle + 3, AL
37690 MOV [ESI].fVisible, BL
37691 MOV ECX, [ESI].fHandle
37692 JECXZ @@after_showwindow
37694 PUSH ECX
37695 CALL ShowWindow
37696 PUSH ECX
37697 @@after_showwindow:
37698 POP ECX
37700 MOV ECX, [ESI].fParent
37701 JECXZ @@chk_align_Self
37702 XCHG EAX, ECX
37703 CALL dword ptr [Global_Align]
37705 @@chk_align_Self:
37706 TEST EBX, EBX
37707 JZ @@reset_fCreateHidden
37708 MOV EAX, ESI
37709 CALL dword ptr [Global_Align]
37712 @@reset_fCreateHidden:
37713 MOV ECX, [ESI].fHandle
37714 JECXZ @@exit
37715 TEST BL, BL
37716 JNZ @@exit
37717 MOV [ESI].fCreateHidden, 0 { +++ }
37718 @@exit:
37719 POP ESI
37720 POP EBX
37721 end;
37722 {$ELSE ASM_VERSION} // Pascal
37723 procedure TControl.Set_Visible( Value: Boolean );
37724 var CmdShow: DWORD;
37725 begin
37726 //if Get_Visible <> Value then // commented to allow to set up controls visibility
37727 begin // on invisible form (Vladimir Piven)
37728 if Value then
37729 begin
37730 fStyle := fStyle or WS_VISIBLE;
37731 CmdShow := SW_SHOW;
37733 else
37734 begin
37735 fStyle := fStyle and not WS_VISIBLE;
37736 CmdShow := SW_HIDE;
37737 end;
37738 fVisible := Value;
37739 if fHandle = 0 then Exit;
37740 ShowWindow( fHandle, CmdShow );
37741 if fParent <> nil then
37742 Global_Align( fParent );
37743 //else
37744 if Value then
37745 Global_Align( @Self );
37746 end;
37747 if not Value and (fHandle <> 0) then
37748 fCreateHidden := FALSE; // { +++ }
37749 end;
37750 {$ENDIF ASM_VERSION}
37752 //[procedure TControl.SetVisible]
37753 procedure TControl.SetVisible( Value: Boolean );
37754 begin
37755 fCreateVisible := TRUE;
37756 Set_Visible( Value );
37757 end;
37759 {$IFDEF ASM_VERSION}
37760 //[function TControl.GetBoundsRect]
37761 function TControl.GetBoundsRect: TRect;
37763 PUSH ESI
37764 PUSH EDI
37765 LEA ESI, [EAX].fBoundsRect
37766 MOV EDI, EDX
37768 PUSH EDX
37770 MOVSD
37771 MOVSD
37772 MOVSD
37773 MOVSD
37775 POP EDI
37777 XCHG ESI, EAX
37778 MOV ECX, [ESI].fHandle
37779 JECXZ @@exit
37781 PUSH EDI
37782 PUSH ECX
37783 CALL GetWindowRect
37785 CMP [ESI].fIsControl, 0
37786 JZ @@storeBounds
37788 MOV EAX, [ESI].fParent
37790 TEST EAX, EAX
37791 JZ @@exit
37793 XOR EDX, EDX
37794 PUSH EDX
37795 PUSH EDX
37796 MOV ECX, ESP
37797 PUSH EDX
37798 PUSH EDX
37799 MOV EDX, ESP
37800 CALL TControl.Client2Screen
37801 POP EAX
37802 POP EAX
37804 POP EAX
37805 NEG EAX
37806 POP ECX
37807 NEG ECX
37808 PUSH ECX
37809 PUSH EAX
37810 PUSH EDI
37811 CALL OffsetRect
37813 @@storeBounds:
37814 XCHG ESI, EDI
37815 LEA EDI, [EDI].fBoundsRect
37816 MOVSD
37817 MOVSD
37818 MOVSD
37819 MOVSD
37821 @@exit:
37822 POP EDI
37823 POP ESI
37824 end;
37825 {$ELSE ASM_VERSION} //Pascal
37826 function TControl.GetBoundsRect: TRect;
37827 var W: PControl;
37828 P: TPoint;
37829 begin
37830 Result := fBoundsRect;
37831 if fHandle <> 0 then
37832 begin
37833 GetWindowRect( fHandle, Result );
37834 if fIsControl then
37835 begin
37836 W := fParent; // WindowedParent;
37837 if W <> nil then
37838 begin
37839 P.x := 0; P.y := 0;
37840 P := W.Client2Screen( P );
37841 OffsetRect( Result, -P.x, -P.y );
37842 end;
37843 end;
37844 fBoundsRect := Result;
37845 end;
37846 end;
37847 {$ENDIF ASM_VERSION}
37849 //[PROCEDURE HelpGetBoundsRect]
37850 {$IFDEF ASM_VERSION}
37851 procedure HelpGetBoundsRect;
37853 POP ECX
37854 ADD ESP, - size_TRect
37855 MOV EDX, ESP
37856 PUSH ECX
37857 PUSH EAX
37858 CALL TControl.GetBoundsRect
37859 POP EAX
37860 end;
37861 {$ENDIF ASM_VERSION}
37862 //[END HelpGetBoundsRect]
37864 {$IFDEF ASM_VERSION}
37865 //[procedure TControl.SetBoundsRect]
37866 procedure TControl.SetBoundsRect( const Value: TRect );
37867 const swp_flags = SWP_NOZORDER or SWP_NOACTIVATE;
37869 PUSH EDI
37870 MOV EDI, EAX
37872 PUSH ESI
37873 MOV ESI, EDX
37875 CALL HelpGetBoundsRect
37877 MOV EAX, ESI
37878 MOV EDX, ESP
37879 CALL RectsEqual
37880 TEST AL, AL
37881 JNZ @@exit
37883 POP EDX // left
37884 POP ECX // top
37885 POP EAX // right
37886 PUSH EAX
37887 PUSH ECX
37888 PUSH EDX
37890 SUB EAX, EDX // EAX = width
37891 CMP EDX, [ESI].TRect.Left
37892 MOV DL, 0
37893 JE @@1
37894 INC EDX
37895 @@1: CMP ECX, [ESI].TRect.Top
37896 JE @@2
37897 OR DL, 2
37898 @@2: OR [EDI].fChangedPosSz, DL
37900 PUSH EAX // W saved
37902 MOV EAX, [EDI].fBoundsRect.Bottom
37903 SUB EAX, ECX
37904 PUSH EAX // H saved
37906 PUSH EDI // @Self saved
37908 LEA EDI, [EDI].fBoundsRect
37909 MOVSD
37910 MOVSD
37911 MOVSD
37912 MOVSD
37914 MOV ESI, EDI
37915 POP EDI // @ Self restored
37916 MOV ECX, [EDI].fHandle
37917 JECXZ @@fin
37921 PUSH swp_flags
37923 LODSD
37924 LODSD
37925 XCHG EDX, EAX // EDX = bottom
37926 LODSD
37927 XCHG ECX, EAX // ECX = right
37928 LODSD
37929 SUB EDX, EAX // EAX = bottom - top
37930 PUSH EDX // push HEIGHT
37931 XCHG EDX, EAX // EDX = top
37932 LODSD // EAX = left
37935 SUB ECX, EAX
37936 PUSH ECX // push WIDTH
37938 PUSH EDX // push TOP
37939 PUSH EAX // push LEFT
37940 PUSH 0
37942 PUSH [EDI].fHandle
37943 CALL SetWindowPos
37945 CMP [EDI].fSizeRedraw, 0
37946 JE @@fin
37947 XCHG EAX, EDI
37948 CALL Invalidate // *MUST* be called?
37950 @@fin:
37951 POP EDX // H restored
37952 POP EAX // W restored
37954 @@exit:
37955 ADD ESP, size_TRect
37956 POP ESI
37957 POP EDI
37958 end;
37959 {$ELSE ASM_VERSION} //Pascal
37960 procedure TControl.SetBoundsRect( const Value: TRect );
37961 var Rect: TRect;
37962 begin
37963 Rect := GetBoundsRect;
37964 if RectsEqual( Value, Rect ) then Exit;
37965 if Value.Left <> fBoundsRect.Left then fChangedPosSz := fChangedPosSz or 1;
37966 if Value.Top <> fBoundsRect.Top then fChangedPosSz := fChangedPosSz or 2;
37967 fBoundsRect := Value;
37968 Rect := Value;
37970 if fHandle <> 0 then
37971 begin
37972 SetWindowPos( fHandle, 0, Rect.Left, Rect.Top, Rect.Right - Rect.Left,
37973 Rect.Bottom - Rect.Top, SWP_NOZORDER or SWP_NOACTIVATE );
37974 if fSizeRedraw then
37975 Invalidate;
37976 end;
37977 end;
37978 {$ENDIF ASM_VERSION}
37980 const
37981 WindowStateShowCommands: array[TWindowState] of Byte =
37982 (SW_SHOWNOACTIVATE, SW_SHOWMINNOACTIVE, SW_SHOWMAXIMIZED);
37983 {$IFDEF ASM_VERSION}
37984 //[procedure TControl.SetWindowState]
37985 procedure TControl.SetWindowState( Value: TWindowState );
37986 asm //cmd //opd
37987 CMP [EAX].TControl.fWindowState, DL
37988 JE @@exit
37989 MOV [EAX].TControl.fWindowState, DL
37990 XCHG EAX, EDX
37992 CWDE
37993 MOV AL, byte ptr [WindowStateShowCommands+EAX]
37994 PUSH EAX
37995 XCHG EAX, EDX
37996 CALL TControl.GetWindowHandle
37997 PUSH EAX
37998 CALL ShowWindow
37999 @@exit:
38000 end;
38001 {$ELSE ASM_VERSION} //Pascal
38002 procedure TControl.SetWindowState( Value: TWindowState );
38003 begin
38004 if fWindowState <> Value then
38005 begin
38006 fWindowState := Value;
38007 ShowWindow(GetWindowHandle, WindowStateShowCommands[Value]);
38008 end;
38009 end;
38010 {$ENDIF ASM_VERSION}
38012 {$IFDEF ASM_VERSION}
38013 //[procedure TControl.Show]
38014 procedure TControl.Show;
38016 PUSH EBX
38017 MOV EBX, EAX
38018 CALL CreateWindow
38019 MOV DL, 1
38020 MOV EAX, EBX
38021 CALL SetVisible
38022 PUSH [EBX].fHandle
38023 CALL SetForegroundWindow
38024 XCHG EAX, EBX
38025 CALL DoSetFocus
38026 POP EBX
38027 end;
38028 {$ELSE ASM_VERSION} //Pascal
38029 procedure TControl.Show;
38030 begin
38031 CreateWindow;
38032 SetVisible( True );
38033 SetForegroundWindow( Handle );
38034 DoSetFocus;
38035 end;
38036 {$ENDIF ASM_VERSION}
38038 //[procedure TControl.Hide]
38039 procedure TControl.Hide;
38040 begin
38041 SetVisible( False );
38042 end;
38044 {$IFDEF ASM_VERSION}
38045 //[function TControl.Client2Screen]
38046 function TControl.Client2Screen( const P: TPoint ): TPoint;
38048 PUSH ESI
38049 PUSH EDI
38051 MOV ESI, EDX
38052 MOV EDI, ECX
38054 MOVSD
38055 MOVSD
38057 PUSH ECX
38058 MOV ECX, [EAX].fHandle
38059 JECXZ @@exit
38061 PUSH ECX
38062 CALL ClientToScreen
38063 PUSH ECX
38065 @@exit: POP ECX
38066 POP EDI
38067 POP ESI
38068 end;
38069 {$ELSE ASM_VERSION} //Pascal
38070 function TControl.Client2Screen( const P: TPoint ): TPoint;
38071 begin
38072 Result := P;
38073 if fHandle <> 0 then
38074 Windows.ClientToScreen( fHandle, Result );
38075 end;
38076 {$ENDIF ASM_VERSION}
38078 {$IFDEF ASM_VERSION}
38079 //[function TControl.Screen2Client]
38080 function TControl.Screen2Client( const P: TPoint ): TPoint;
38082 PUSH ESI
38083 PUSH EDI
38085 MOV ESI, EDX
38086 MOV EDI, ECX
38088 MOVSD
38089 MOVSD
38091 PUSH ECX
38092 MOV ECX, [EAX].fHandle
38093 JECXZ @@exit
38095 PUSH ECX
38096 CALL ScreenToClient
38097 PUSH ECX
38099 @@exit: POP ECX
38100 POP EDI
38101 POP ESI
38102 end;
38103 {$ELSE ASM_VERSION} //Pascal
38104 function TControl.Screen2Client( const P: TPoint ): TPoint;
38105 begin
38106 Result := P;
38107 if Handle <> 0 then
38108 Windows.ScreenToClient( Handle, Result );
38109 end;
38110 {$ENDIF ASM_VERSION}
38112 {$IFDEF ASM_VERSION}
38113 //[function TControl.ClientRect]
38114 function TControl.ClientRect: TRect;
38116 PUSH [EAX].fClientLeft
38117 PUSH [EAX].fClientRight
38118 PUSH [EAX].fClientTop
38119 PUSH [EAX].fClientBottom
38120 PUSH EDX
38121 PUSH EDX // prepare 'dest' for GetClientRect
38123 PUSH EAX
38124 LEA EAX, [EAX].fBoundsRect
38126 XOR ECX, ECX
38127 MOV CL, size_TRect
38129 CALL System.Move
38130 POP EAX // EAX = @Self
38132 CALL TControl.GetWindowHandle
38134 // this version is more correct ?:
38135 //------------------------------
38136 {PUSH EAX
38137 CALL CallTControlCreateWindow
38138 POP EAX
38139 MOV EAX, [EAX].fHandle}
38140 //-------------------------------
38142 TEST EAX, EAX
38143 JZ @@exit
38145 PUSH EAX // prepare 'handle' for GetClientRect
38146 CALL GetClientRect
38147 PUSH EAX
38149 @@exit: POP EDX
38150 POP EDX // EDX = @Result
38151 POP EAX // EAX = fClientBottom
38152 SUB [EDX].TRect.Bottom, EAX
38153 POP EAX // EAX = fClientTop
38154 ADD [EDX].TRect.Top, EAX // Correct Result.Top
38155 POP EAX // EAX = fClientRight
38156 SUB [EDX].TRect.Right, EAX
38157 POP EAX // EAX = fClientLeft
38158 ADD [EDX].TRect.Left, EAX
38159 end;
38160 {$ELSE ASM_VERSION} //Pascal
38161 function TControl.ClientRect: TRect;
38162 const BorderParams: array[ 0..5 ] of DWORD =
38163 ( SM_CXBORDER, SM_CXFRAME, SM_CXSIZEFRAME, SM_CYBORDER, SM_CYFRAME, SM_CYSIZEFRAME );
38164 begin
38165 Result := fBoundsRect;
38166 GetWindowHandle;
38167 //CreateWindow; //virtual!!!
38168 if (fHandle <> 0) then
38169 GetClientRect( fHandle, Result );
38170 Inc( Result.Top, fClientTop );
38171 Dec( Result.Bottom, fClientBottom );
38172 Inc( Result.Left, fClientLeft );
38173 Dec( Result.Right, fClientRight );
38174 end;
38175 {$ENDIF ASM_VERSION}
38177 {$IFDEF ASM_VERSION}
38178 //[procedure TControl.Invalidate]
38179 procedure TControl.Invalidate;
38181 XOR EDX, EDX
38182 CMP [AppletTerminated], DL
38183 JNZ @@exit
38184 MOV ECX, [EAX].fHandle
38185 JECXZ @@exit
38186 PUSH EAX
38187 PUSH 1
38188 PUSH EDX //=0
38189 PUSH ECX
38190 CALL Windows.InvalidateRect
38191 POP EAX
38192 CALL dword ptr[Global_Invalidate]
38193 @@exit:
38194 end;
38195 {$ELSE ASM_VERSION} //Pascal
38196 procedure TControl.Invalidate;
38197 begin
38198 if AppletTerminated then Exit;
38199 if fHandle = 0 then Exit;
38200 InvalidateRect( fHandle, nil, True );
38202 Global_Invalidate( @Self );
38203 end;
38204 {$ENDIF ASM_VERSION}
38206 {$IFDEF ASM_VERSION}
38207 //[function TControl.GetIcon]
38208 function TControl.GetIcon: HIcon;
38210 PUSH EBX
38211 XCHG EBX, EAX
38212 MOV EAX, [EBX].fIcon
38213 INC EAX
38214 JZ @@exit
38215 DEC EAX
38216 JNZ @@exit
38218 MOV ECX, [Applet]
38219 JECXZ @@load
38220 CMP ECX, EBX
38221 JZ @@load
38223 XCHG EAX, ECX
38224 CALL TControl.GetIcon
38225 TEST EAX, EAX
38226 JZ @@exit
38228 XOR EDX, EDX
38229 PUSH EDX
38230 PUSH EDX
38231 PUSH EDX
38232 INC EDX // IMAGE_ICON = 1
38233 PUSH EDX
38234 PUSH EAX
38235 CALL CopyImage
38236 JMP @@store_fIcon
38238 @@main_icon:
38239 DB 'MAINICON',0
38241 @@load:
38242 PUSH offset @@main_icon
38243 PUSH [hInstance]
38244 CALL LoadIcon
38245 @@store_fIcon:
38246 MOV [EBX].fIcon, EAX
38247 @@exit:
38248 POP EBX
38249 end;
38250 {$ELSE ASM_VERSION} //Pascal
38251 function TControl.GetIcon: HIcon;
38252 begin
38253 Result := fIcon;
38254 if Result = THandle( -1 ) then
38255 begin
38256 Result := 0;
38257 Exit;
38258 end;
38259 if Result = 0 then
38260 if (Assigned( Applet )) and
38261 (@Self <> Applet) then
38262 begin
38263 Result := Applet.Icon;
38264 if Result <> 0 then
38265 Result := CopyImage( Result, IMAGE_ICON, 0, 0, 0 );
38267 else
38268 begin
38269 //if Result = 0 then
38270 Result := LoadIcon( hInstance, 'MAINICON' );
38271 //Result := LoadImage( hInstance, 'MAINICON', IMAGE_ICON, 16, 16, LR_SHARED );
38272 end;
38273 fIcon := Result;
38274 end;
38275 {$ENDIF ASM_VERSION}
38278 //[procedure TControl.IconLoad]
38279 procedure TControl.IconLoad(Inst: Integer; ResName: PChar);
38280 begin
38281 Icon := LoadIcon( Inst, ResName );
38282 fIconShared := TRUE;
38283 end;
38285 //[procedure TControl.IconLoadCursor]
38286 procedure TControl.IconLoadCursor(Inst: Integer; ResName: PChar);
38287 begin
38288 Icon := LoadCursor( Inst, ResName );
38289 fIconShared := TRUE;
38290 end;
38292 {$IFDEF ASM_VERSION}
38293 //[function TControl.CallDefWndProc]
38294 function TControl.CallDefWndProc(var Msg: TMsg): Integer;
38296 PUSH [EDX].TMsg.lParam
38297 PUSH [EDX].TMsg.wParam
38298 PUSH [EDX].TMsg.message
38300 MOV ECX, [EAX].fDefWndProc
38301 JECXZ @@defwindowproc
38303 PUSH [EAX].fHandle
38304 PUSH ECX
38305 CALL CallWindowProc
38308 @@defwindowproc:
38309 PUSH [EDX].TMsg.hwnd
38310 CALL DefWindowProc
38311 end;
38312 {$ELSE ASM_VERSION} //Pascal
38313 function TControl.CallDefWndProc(var Msg: TMsg): Integer;
38314 begin
38315 if FDefWndProc <> nil then
38316 Result := CallWindowProc( FDefWndProc, FHandle, Msg.message, Msg.wParam, Msg.lParam )
38317 else
38318 Result := DefWindowProc( Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam );
38319 end;
38320 {$ENDIF ASM_VERSION}
38322 {$IFDEF ASM_VERSION}
38323 //[function TControl.GetWindowState]
38324 function TControl.GetWindowState: TWindowState;
38325 asm //cmd //opd
38326 PUSH EBX
38327 PUSH ESI
38328 XCHG ESI, EAX
38329 MOVZX EBX, [ESI].TControl.fWindowState
38330 MOV ECX, [ESI].TControl.fHandle
38331 JECXZ @@ret_EBX
38332 MOV BL, 2
38333 MOV ESI, ECX
38334 PUSH ESI
38335 CALL IsZoomed
38336 TEST EAX, EAX
38337 JNZ @@ret_EBX
38338 DEC EBX
38339 PUSH ESI
38340 CALL IsIconic
38341 TEST EAX, EAX
38342 JNZ @@ret_EBX
38343 DEC EBX
38344 @@ret_EBX:
38345 XCHG EAX, EBX
38346 POP ESI
38347 POP EBX
38348 end;
38349 {$ELSE ASM_VERSION} //Pascal
38350 function TControl.GetWindowState: TWindowState;
38351 begin
38352 Result := fWindowState;
38353 if Handle <> 0 then
38354 begin
38355 if IsIconic( Handle ) then
38356 Result := wsMinimized
38357 else
38358 if IsZoomed( Handle ) then
38359 Result := wsMaximized
38360 else
38361 Result := wsNormal;
38362 fWindowState := Result;
38363 end;
38364 end;
38365 {$ENDIF ASM_VERSION}
38367 {$IFDEF ASM_VERSION}
38368 //[function TControl.DoSetFocus]
38369 function TControl.DoSetFocus: Boolean;
38371 PUSH ESI
38372 MOV ESI, EAX
38374 {MOV EDX, [ESI].fStyle
38375 TEST EDX, WS_TABSTOP
38376 JZ @@exit}
38378 CALL GetEnabled
38379 TEST AL, AL
38380 JZ @@exit
38382 XOR EAX, EAX
38383 CMP [ESI].fTabstop, AL
38384 JZ @@exit
38386 INC [ESI].TControl.fClickDisabled
38388 PUSH [ESI].fHandle
38389 CALL SetFocus
38391 DEC [ESI].TControl.fClickDisabled
38393 MOV AL, 1
38395 @@exit:
38396 POP ESI
38397 end;
38398 {$ELSE ASM_VERSION} //Pascal
38399 function TControl.DoSetFocus: Boolean;
38400 begin
38401 Result := False;
38402 if Enabled and fTabstop {and (fStyle and WS_TABSTOP <> 0)} then
38403 begin
38404 Inc( fClickDisabled );
38405 SetFocus( fHandle );
38406 Dec( fClickDisabled );
38407 Result := True;
38408 end;
38409 end;
38410 {$ENDIF ASM_VERSION}
38412 //[function TControl.HandleAllocated]
38413 function TControl.HandleAllocated: Boolean;
38414 begin
38415 Result := FHandle <> 0;
38416 end;
38418 {$IFDEF ASM_VERSION}
38419 //[function TControl.GetEnabled]
38420 function TControl.GetEnabled: Boolean;
38422 MOV ECX, [EAX].fHandle
38423 JECXZ @@get_field
38425 PUSH ECX
38426 CALL IsWindowEnabled
38427 { but 00000001 is returned anywhere...
38428 NEG EAX
38429 SBB EAX, EAX
38430 NEG EAX
38434 @@get_field:
38435 TEST byte ptr [EAX].fStyle + 3, 8 //WS_DISABLED shr 3
38436 SETZ AL
38437 end;
38438 {$ELSE ASM_VERSION} //Pascal
38439 function TControl.GetEnabled: Boolean;
38440 begin
38441 if FHandle = 0 then
38442 Result := (Style and WS_DISABLED) = 0
38443 else
38444 Result := IsWindowEnabled( FHandle );
38445 end;
38446 {$ENDIF ASM_VERSION}
38448 {$IFDEF ASM_VERSION}
38449 //[function TControl.IsMainWindow]
38450 function TControl.IsMainWindow: Boolean;
38452 CMP [EAX].fIsControl, 0
38453 JNZ @@no_notmain
38455 XCHG EDX, EAX
38456 MOV EAX, [EDX].fParent
38458 TEST EAX, EAX
38459 JZ @@1
38461 MOV ECX, [EAX].fParent
38462 INC ECX
38463 LOOP @@no_notmain
38465 MOV EAX, [EAX].fChildren
38467 MOV ECX, [EAX].TList.fCount
38468 JECXZ @@no_notmain
38470 MOV EAX, [EAX].TList.fItems
38471 CMP EDX, [EAX]
38472 MOV AL, 1
38473 JMP @@2
38474 @@1:
38475 INC EAX
38476 MOVZX ECX, [AppButtonUsed]
38477 JECXZ @@yes_main
38478 CMP EDX, [Applet]
38479 @@2:
38480 JZ @@yes_main
38482 @@no_notmain:
38483 XOR EAX, EAX
38484 @@yes_main:
38485 end;
38486 {$ELSE ASM_VERSION} //Pascal
38487 function TControl.IsMainWindow: Boolean;
38488 var A: PControl;
38489 begin
38490 Result := False;
38491 if fIsControl then Exit;
38492 A := fParent; // WindowedParent;
38493 if A = nil then
38494 begin
38495 Result := (@Self = Applet) or not AppButtonUsed;
38496 Exit;
38498 else
38499 if A.fParent <> nil then Exit;
38500 //--------------------------------------------------------------------------------
38501 if A.fChildren.fCount = 0 then Exit; // by ECM, fixes AV when user changed (logoff)
38502 //--------------------------------------------------------------------------------
38503 Result := A.fChildren.fItems[ 0 ] = @Self;
38504 end;
38505 {$ENDIF ASM_VERSION}
38507 {$IFDEF ASM_VERSION}
38508 //[function TControl.get_ClassName]
38509 function TControl.get_ClassName: String;
38511 PUSH EBX
38512 XCHG EBX, EAX
38513 XCHG EAX, EDX
38514 MOV EDX, [EBX].fControlClassName
38515 PUSH EAX
38516 CALL System.@LStrFromPChar
38517 POP EAX
38518 CMP [EBX].fCtlClsNameChg, 0
38519 JNZ @@exit
38520 MOV ECX, [EAX]
38521 MOV EDX, offset[ @@obj ]
38522 CALL System.@LStrCat3
38523 JMP @@exit
38525 DD -1, 4
38526 @@obj: DB 'obj_', 0
38528 @@exit:
38529 POP EBX
38530 end;
38531 {$ELSE ASM_VERSION} //Pascal
38532 function TControl.get_ClassName: String;
38533 begin
38534 if not fCtlClsNameChg then
38535 Result := 'obj_' + fControlClassName
38536 else
38537 Result := fControlClassName;
38538 end;
38539 {$ENDIF ASM_VERSION}
38541 //[procedure TControl.set_ClassName]
38542 procedure TControl.set_ClassName(const Value: String);
38543 begin
38544 if fCtlClsNameChg then
38545 FreeMem( fControlClassName );
38546 GetMem( fControlClassName, Length( Value ) + 1 );
38547 StrCopy( fControlClassName, @ Value[ 1 ] );
38548 fCtlClsNameChg := TRUE;
38549 end;
38551 //[function WndProcQueryEndSession]
38552 function WndProcQueryEndSession( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
38553 var Accept: Boolean;
38554 begin
38555 Result := FALSE;
38556 if Msg.message = WM_QUERYENDSESSION then
38557 begin
38558 if Assigned( Sender.fOnQueryEndSession ) then
38559 begin
38560 Accept := TRUE;
38561 Sender.fCloseQueryReason := qShutdown;
38562 if LongBool(Msg.lParam and {ENDSESSION_LOGOFF} DWORD($80000000)) then
38563 Sender.fCloseQueryReason := qLogoff;
38564 Sender.fOnQueryEndSession( Sender, Accept );
38565 Sender.fCloseQueryReason := qClose;
38566 Rslt := Integer( Accept );
38567 // Äîáàâèòü. Íóæíî äëÿ òîãî, ÷òîáû îòìåíèëîñü çàâåðøåíèå ñåàíñà,
38568 // åñëè Accept óñòàíîâëåí â False è ñåàíñ çàâåðøèëñÿ ïðè Accept = True
38569 // Add (YS). To cancel ending session if Accept=FALSE but allow ending
38570 // session if Accept=TRUE.
38571 Result := True; // {YS}: no further processing
38572 end;
38573 end;
38574 end;
38576 //[procedure TControl.SetOnQueryEndSession]
38577 procedure TControl.SetOnQueryEndSession(const Value: TOnEventAccept);
38578 begin
38579 AttachProc( WndProcQueryEndSession );
38580 fOnQueryEndSession := Value;
38581 end;
38583 //[function WndProcMinMaxRestore]
38584 function WndProcMinMaxRestore( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
38585 begin
38586 Result := FALSE;
38587 if Msg.message = WM_SYSCOMMAND then
38588 begin
38589 case Msg.wParam of
38590 SC_MINIMIZE: if Assigned( Sender.fOnMinimize ) then
38591 Sender.fOnMinimize( Sender );
38592 SC_MAXIMIZE: if Assigned( Sender.fOnMaximize ) then
38593 Sender.fOnMaximize( Sender );
38594 SC_RESTORE: if Assigned( Sender.fOnRestore ) then
38595 Sender.fOnRestore( Sender );
38596 end;
38597 end;
38598 end;
38600 //[procedure TControl.SetOnMinMaxRestore]
38601 procedure TControl.SetOnMinMaxRestore(const Index: Integer;
38602 const Value: TOnEvent);
38603 type POnEvent = ^TOnEvent;
38604 {$IFDEF F_P}
38605 var Ptr1: Pointer;
38606 {$ELSE DELPHI}
38607 var Ev: POnEvent;
38608 {$ENDIF F_P/DELPHI}
38609 begin
38610 AttachProc( WndProcMinMaxRestore );
38611 {$IFDEF F_P}
38612 Ptr1 := Self;
38614 MOV EAX, [Ptr1]
38615 LEA EAX, [EAX].TControl.fOnMinimize
38616 ADD EAX, [Index]
38617 MOV EDX, [Value]
38618 MOV [EAX], EDX
38619 MOV EDX, [Value+4]
38620 MOV [EAX+4], EDX
38621 end [ 'EAX', 'EDX' ];
38622 {$ELSE DELPHI}
38623 Ev := Pointer( Integer( @ TMethod( fOnMinimize ).Code ) + Index );
38624 //Ev := Pointer( Integer( @ fOnMinimize ) + Index );
38625 Ev^ := Value;
38626 {$ENDIF}
38627 end;
38629 {$IFDEF F_P}
38630 //[function TControl.GetOnMinMaxRestore]
38631 function TControl.GetOnMinMaxRestore(const Index: Integer): TOnEvent;
38632 begin
38633 CASE Index OF
38634 0: Result := fOnMinimize;
38635 8: Result := fOnMaximize;
38636 16: Result := fOnRestore;
38637 END;
38638 end;
38639 {$ENDIF F_P}
38641 {$IFDEF INPACKAGE}
38642 {$IFDEF ASM_LOCAL}
38643 {$UNDEF ASM_LOCAL}
38644 {$ENDIF}
38645 {$ELSE}
38646 {$IFDEF ASM_VERSION}
38647 {$DEFINE ASM_LOCAL}
38648 {$ENDIF}
38649 {$ENDIF}
38651 {$IFDEF ASM_LOCAL}
38652 //[procedure TControl.SetParent]
38653 procedure TControl.SetParent( Value: PControl );
38655 PUSH EBX
38656 PUSH EDI
38657 XCHG EBX, EAX
38658 MOV EDI, [EBX].fParent
38660 CMP EDX, EDI
38661 JZ @@exit
38663 PUSH EDX
38664 TEST EDI, EDI
38665 JZ @@set_another_parent
38667 MOV EAX, [EDI].fChildren
38668 MOV EDX, EBX
38669 CALL TList.Remove
38671 MOV ECX, [EDI].fNotifyChild
38672 JECXZ @@set_another_parent
38674 MOV EAX, EDI
38675 XOR EDX, EDX
38676 CALL ECX
38678 @@set_another_parent:
38679 POP EDI
38680 MOV [EBX].fParent, EDI
38681 TEST EDI, EDI
38682 JZ @@exit
38684 MOV EAX, [EDI].fChildren
38685 MOV EDX, EBX
38686 CALL TList.Add
38688 {$IFNDEF INPACKAGE}
38689 MOV ECX, [EBX].FHandle
38690 JECXZ @@parentwnd_assigned
38691 PUSH ECX
38692 MOV EAX, EDI
38693 CALL GetWindowHandle
38694 POP ECX
38695 PUSH EAX
38696 PUSH ECX
38697 CALL Windows.SetParent
38699 @@parentwnd_assigned:
38700 {$ENDIF}
38702 MOV ECX, [EDI].fNotifyChild
38703 JECXZ @@exit
38705 MOV EAX, EDI
38706 MOV EDX, EBX
38707 CALL ECX
38709 @@exit:
38710 POP EDI
38711 POP EBX
38712 end;
38713 {$ELSE ASM_VERSION} //Pascal
38714 procedure TControl.SetParent( Value: PControl );
38715 begin
38716 if Value = fParent then Exit;
38717 if fParent <> nil then
38718 begin
38719 fParent.fChildren.Remove( @Self );
38720 if Assigned( fParent.fNotifyChild ) then
38721 fParent.fNotifyChild( fParent, nil );
38722 end;
38723 fParent := Value;
38724 if fParent <> nil then
38725 begin
38726 fParent.fChildren.Add( @Self );
38727 {$IFNDEF INPACKAGE}
38728 if FHandle <> 0 then
38729 Windows.SetParent( FHandle, Value.GetWindowHandle );
38730 {$ENDIF}
38731 if Assigned( fParent.fNotifyChild ) then
38732 fParent.fNotifyChild( fParent, @ Self );
38733 end;
38734 end;
38735 {$ENDIF ASM_VERSION}
38737 //[function TControl.ChildIndex]
38738 function TControl.ChildIndex(Child: PControl): Integer;
38739 begin
38740 Result := fChildren.IndexOf( Child );
38741 end;
38744 //[procedure TControl.MoveChild]
38745 procedure TControl.MoveChild(Child: PControl; NewIdx: Integer);
38746 var I: Integer;
38747 begin
38748 I := ChildIndex( Child );
38749 Assert( I>=0, 'TControl.MoveChild: index out of bounds' );
38750 fChildren.MoveItem( I, NewIdx );
38751 end;
38753 //[procedure TControl.EnableChildren]
38754 procedure TControl.EnableChildren(Enable, Recursive: Boolean);
38755 var I: Integer;
38756 C: PControl;
38757 begin
38758 for I := 0 to ChildCount-1 do
38759 begin
38760 C := Children[ I ];
38761 C.Enabled := Enable;
38762 if Recursive then
38763 C.EnableChildren( Enable, TRUE );
38764 end;
38765 end;
38767 {$IFDEF ASM_VERSION}
38768 //[constructor TControl.CreateParented]
38769 constructor TControl.CreateParented(AParent: PControl);
38770 asm //cmd //opd
38771 //CALL System.@ObjSetup // generated automatically
38772 //JZ @@exit // generated automatically
38773 PUSH EAX
38774 MOV EDX, ECX
38775 MOV ECX, [EAX]
38776 CALL dword ptr [ECX+8]
38777 POP EAX
38778 @@exit:
38779 end;
38780 {$ELSE ASM_VERSION} //Pascal
38781 constructor TControl.CreateParented(AParent: PControl);
38782 begin
38783 InitParented( AParent );
38784 end;
38785 {$ENDIF ASM_VERSION}
38787 {$IFDEF ASM_VERSION}
38788 //[function TControl.GetLeft]
38789 function TControl.GetLeft: Integer;
38791 CALL HelpGetBoundsRect
38792 POP EAX
38794 POP ECX
38795 POP ECX
38796 POP ECX
38797 end;
38798 {$ELSE ASM_VERSION} //Pascal
38799 function TControl.GetLeft: Integer;
38800 begin
38801 Result := BoundsRect.Left;
38802 end;
38803 {$ENDIF ASM_VERSION}
38805 {$IFDEF ASM_VERSION}
38806 //[procedure TControl.SetLeft]
38807 procedure TControl.SetLeft( Value: Integer );
38809 PUSH EDI
38811 PUSH EDX
38812 CALL HelpGetBoundsRect
38813 POP EDX // EDX = Left
38814 POP ECX // ECX = Top
38815 POP EDI // EDI = Right
38817 SUB EDI, EDX // EDI = width
38818 MOV EDX, [ESP+4] // EDX = Left'
38819 ADD EDI, EDX // EDI = Right'
38821 PUSH EDI
38822 PUSH ECX
38823 PUSH EDX
38824 MOV EDX, ESP
38826 CALL SetBoundsRect
38827 ADD ESP, size_TRect + 4
38829 POP EDI
38831 end;
38832 {$ELSE ASM_VERSION} //Pascal
38833 procedure TControl.SetLeft( Value: Integer );
38834 var R: TRect;
38835 begin
38836 R := BoundsRect;
38837 R.Left := Value;
38838 R.Right := Value + Width;
38839 SetBoundsRect( R );
38840 end;
38841 {$ENDIF ASM_VERSION}
38843 {$IFDEF ASM_VERSION}
38844 //[function TControl.GetTop]
38845 function TControl.GetTop: Integer;
38847 CALL HelpGetBoundsRect
38848 POP EDX
38849 POP EAX
38850 POP EDX
38851 POP EDX
38852 end;
38853 {$ELSE ASM_VERSION} //Pascal
38854 function TControl.GetTop: Integer;
38855 begin
38856 Result := BoundsRect.Top;
38857 end;
38858 {$ENDIF ASM_VERSION}
38860 {$IFDEF ASM_VERSION}
38861 //[procedure TControl.SetTop]
38862 procedure TControl.SetTop( Value: Integer );
38864 PUSH ESI
38865 PUSH EDI
38867 PUSH EDX
38868 CALL HelpGetBoundsRect
38869 POP EDX // EDX = Left
38870 POP ECX // ECX = Top
38871 POP EDI // EDI = Right
38872 POP ESI // ESI = Bottom
38874 SUB ESI, ECX // ESI = Height'
38875 POP ECX // ECX = Top'
38876 ADD ESI, ECX // ESI = Bottom'
38878 PUSH ESI
38879 PUSH EDI
38880 PUSH ECX
38881 PUSH EDX
38882 MOV EDX, ESP
38884 CALL SetBoundsRect
38885 ADD ESP, size_TRect
38887 POP EDI
38888 POP ESI
38889 end;
38890 {$ELSE ASM_VERSION} //Pascal
38891 procedure TControl.SetTop( Value: Integer );
38892 var R: TRect;
38893 begin
38894 R := BoundsRect;
38895 R.Top := Value;
38896 R.Bottom := Value + Height;
38897 SetBoundsRect( R );
38898 end;
38899 {$ENDIF ASM_VERSION}
38901 {$IFDEF ASM_VERSION}
38902 //[function TControl.GetWidth]
38903 function TControl.GetWidth: Integer;
38905 CALL HelpGetBoundsRect
38906 POP EDX
38907 POP ECX
38908 POP EAX
38909 SUB EAX, EDX
38910 POP ECX
38911 end;
38912 {$ELSE ASM_VERSION} //Pascal
38913 function TControl.GetWidth: Integer;
38914 begin
38915 with BoundsRect do
38916 Result := Right - Left;
38917 end;
38918 {$ENDIF ASM_VERSION}
38920 {$IFDEF ASM_VERSION}
38921 //[procedure TControl.SetWidth]
38922 procedure TControl.SetWidth( Value: Integer );
38924 PUSH EDX
38926 CALL HelpGetBoundsRect
38927 POP EDX
38928 PUSH EDX
38929 ADD EDX, [ESP].size_TRect
38930 MOV [ESP].TRect.Right, EDX
38932 MOV EDX, ESP
38933 CALL SetBoundsRect
38935 ADD ESP, size_TRect + 4
38936 end;
38937 {$ELSE ASM_VERSION} //Pascal
38938 procedure TControl.SetWidth( Value: Integer );
38939 var R: TRect;
38940 begin
38941 R := BoundsRect;
38942 with R do
38943 Right := Left + Value;
38944 SetBoundsRect( R );
38945 end;
38946 {$ENDIF ASM_VERSION}
38948 {$IFDEF ASM_VERSION}
38949 //[function TControl.GetHeight]
38950 function TControl.GetHeight: Integer;
38952 CALL HelpGetBoundsRect
38953 POP ECX
38954 POP EDX // EDX = top
38955 POP ECX
38956 POP EAX // EAX = bottom
38957 SUB EAX, EDX // result = height
38958 end;
38959 {$ELSE ASM_VERSION} //Pascal
38960 function TControl.GetHeight: Integer;
38961 begin
38962 with BoundsRect do
38963 Result := Bottom - Top;
38964 end;
38965 {$ENDIF ASM_VERSION}
38967 {$IFDEF ASM_VERSION}
38968 //[procedure TControl.SetHeight]
38969 procedure TControl.SetHeight( Value: Integer );
38971 PUSH EDX
38973 CALL HelpGetBoundsRect
38974 MOV EDX, [ESP].TRect.Top
38975 ADD EDX, [ESP].size_TRect
38976 MOV [ESP].TRect.Bottom, EDX
38978 MOV EDX, ESP
38979 CALL SetBoundsRect
38981 ADD ESP, size_TRect + 4
38982 end;
38983 {$ELSE ASM_VERSION} //Pascal
38984 procedure TControl.SetHeight( Value: Integer );
38985 var R: TRect;
38986 begin
38987 R := BoundsRect;
38988 with R do
38989 Bottom := Top + Value;
38990 SetBoundsRect( R );
38991 end;
38992 {$ENDIF ASM_VERSION}
38994 {$IFDEF ASM_VERSION}
38995 //[function TControl.GetPosition]
38996 function TControl.GetPosition: TPoint;
38998 PUSH EDX
38999 CALL HelpGetBoundsRect
39000 POP EAX // EAX = left
39001 POP ECX // ECX = top
39002 POP EDX
39003 POP EDX
39004 POP EDX // EDX = @Result
39005 MOV [EDX], EAX
39006 MOV [EDX+4], ECX
39007 end;
39008 {$ELSE ASM_VERSION} //Pascal
39009 function TControl.GetPosition: TPoint;
39010 begin
39011 Result.x := BoundsRect.Left;
39012 Result.y := BoundsRect.Top;
39013 end;
39014 {$ENDIF ASM_VERSION}
39016 {$IFDEF ASM_VERSION}
39017 //[procedure TControl.Set_Position]
39018 procedure TControl.Set_Position( Value: TPoint );
39020 PUSH ESI
39021 PUSH EDI
39023 PUSH EAX
39024 PUSH EDX
39025 CALL HelpGetBoundsRect
39026 POP EDX // left
39027 POP EAX // top
39028 POP ECX // right
39029 SUB ECX, EDX // ECX = width
39030 POP EDX // bottom
39031 SUB EDX, EAX // EDX = height
39032 POP EAX // EAX = @Value
39033 POP ESI // ESI = @Self
39035 MOV EDI, [EAX+4] // top'
39036 ADD EDX, EDI
39037 PUSH EDX // bottom'
39039 MOV EAX, [EAX] // left'
39040 ADD ECX, EAX
39041 PUSH ECX // right'
39043 PUSH EDI // top'
39044 PUSH EAX // left'
39046 MOV EAX, ESI
39047 MOV EDX, ESP
39048 CALL SetBoundsRect
39050 ADD ESP, size_TRect
39052 POP EDI
39053 POP ESI
39054 end;
39055 {$ELSE ASM_VERSION} //Pascal
39056 procedure TControl.Set_Position( Value: TPoint );
39057 var R: TRect;
39058 begin
39059 R.Top := Value.y;
39060 R.Left := Value.x;
39061 R.Right := R.Left + Width;
39062 R.Bottom := R.Top + Height;
39063 BoundsRect := R;
39064 end;
39065 {$ENDIF ASM_VERSION}
39067 //[function WndProcConstraints]
39068 function WndProcConstraints( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39069 var MMI: PMinMaxInfo;
39070 begin
39071 Result := FALSE;
39072 if Msg.message = WM_GETMINMAXINFO then
39073 begin
39074 Rslt := Sender.CallDefWndProc( Msg );
39075 MMI := Pointer( Msg.lParam );
39076 if Sender.FMaxWidth > 0 then
39077 begin
39078 MMI.ptMaxSize.x := Sender.FMaxWidth;
39079 MMI.ptMaxTrackSize.x := Sender.FMaxWidth;
39080 end;
39081 if Sender.FMaxHeight > 0 then
39082 begin
39083 MMI.ptMaxSize.y := Sender.FMaxHeight;
39084 MMI.ptMaxTrackSize.y := Sender.FMaxHeight;
39085 end;
39086 MMI.ptMinTrackSize := MakePoint( Sender.FMinWidth, Sender.FMinHeight );
39087 Rslt := 0;
39088 Result := TRUE;
39089 end;
39090 end;
39092 {$IFDEF USE_MHTOOLTIP}
39093 {$DEFINE implementation}
39094 {$I KOLMHToolTip}
39095 {$UNDEF implementation}
39096 {$ENDIF}
39098 //[procedure TControl.SetConstraint]
39099 procedure TControl.SetConstraint(const Index, Value: Integer);
39100 begin
39101 AttachProc( WndProcConstraints );
39102 case Index of
39103 0: FMinWidth := Value;
39104 1: FMinHeight := Value;
39105 2: FMaxWidth := Value;
39106 3: FMaxHeight := Value;
39107 end;
39108 end;
39110 {$IFDEF F_P}
39111 //[function TControl.GetConstraint]
39112 function TControl.GetConstraint(const Index: Integer): Integer;
39113 begin
39114 CASE Index OF
39115 0: Result := FMinWidth;
39116 1: Result := FMinHeight;
39117 2: Result := FMaxWidth;
39118 3: Result := FMaxHeight;
39119 END;
39120 end;
39121 {$ENDIF F_P}
39124 //[function TControl.ControlRect]
39125 function TControl.ControlRect: TRect;
39126 var C: PControl;
39127 R: TRect;
39128 begin
39129 Result := BoundsRect;
39130 C := Parent;
39131 if C <> nil then
39132 begin
39133 //DoScrollOffset( @Result );
39135 if not C.fIsControl then Exit;
39137 R := C.ControlRect;
39138 OffsetRect( Result, R.Left, R.Top );
39140 if C.fChildren <> nil then
39141 if C.FChildren.IndexOf( @Self ) >= C.MembersCount then
39142 begin
39143 R := C.ClientRect;
39144 Dec( R.Top, C.fClientTop );
39145 Dec( R.Left, C.fClientLeft );
39146 OffsetRect( Result, R.Left, R.Top );
39147 end;
39148 end;
39149 end;
39152 //[function TControl.ControlAtPos]
39153 function TControl.ControlAtPos( X, Y: Integer;
39154 IgnoreDisabled: Boolean ): PControl;
39155 var I: Integer;
39156 C: PControl;
39157 CR, VR: TRect;
39158 begin
39159 Result := nil;
39160 CR := ControlRect;
39161 if Windowed then
39162 CR := MakeRect( 0, 0, 0, 0 );
39163 X := X + CR.Left; // - R.Left;
39164 Y := Y + CR.Top; // - R.Top;
39165 for I := ChildCount { + MembersCount } - 1 downto 0 do
39166 begin
39167 C := Children[ I ]; //Members[ I ];
39168 if C.Visible then
39169 if (not IgnoreDisabled) or IgnoreDisabled and C.Enabled then
39170 begin
39171 VR := C.ControlRect;
39172 if (X >= VR.Left) and (X < VR.Right) and
39173 (Y >= VR.Top) and (Y < VR.Bottom) then
39174 begin
39175 Result := C;
39176 Exit;
39177 end;
39178 end;
39179 end;
39180 end;
39182 //[PROCEDURE DefaultPaintBackground]
39183 {$IFDEF ASM_VERSION}
39184 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );
39186 PUSH EDI
39188 PUSH EDI
39189 MOV EDI, ESP
39191 PUSH ECX
39192 PUSH EDX
39194 MOV EAX, [EAX].TControl.fColor
39195 CALL Color2RGB
39196 PUSH EAX
39197 CALL CreateSolidBrush
39198 STOSD
39199 MOV EDI, EAX
39200 CALL windows.FillRect
39201 PUSH EDI
39202 CALL DeleteObject
39203 POP EDI
39204 end;
39205 {$ELSE ASM_VERSION} //Pascal
39206 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );
39207 var B: HBrush;
39208 begin
39209 B := CreateSolidBrush( Color2Rgb( Sender.Color ) );
39210 Windows.FillRect( DC, Rect^, B );
39211 DeleteObject( B );
39212 end;
39213 {$ENDIF ASM_VERSION}
39214 //[END DefaultPaintBackground]
39216 //[procedure TControl.PaintBackground]
39217 procedure TControl.PaintBackground( DC: HDC; Rect: PRect );
39218 begin
39219 Global_OnPaintBkgnd( @Self, DC, Rect );
39220 end;
39222 //[procedure TControl.SetCtlColor]
39223 {$IFDEF ASM_VERSION}
39224 procedure TControl.SetCtlColor( Value: TColor );
39226 PUSH EBX
39227 MOV EBX, EAX
39229 {$IFNDEF INPACKAGE}
39230 PUSH EDX
39232 CALL GetWindowHandle
39233 XCHG ECX, EAX
39235 POP EDX
39236 {$ELSE}
39237 MOV ECX, [EBX].fHandle
39238 {$ENDIF}
39240 JECXZ @@1
39242 MOVZX ECX, [EBX].fCommandActions.aSetBkColor
39243 JECXZ @@1
39245 PUSH EDX
39247 XCHG EAX, EDX
39248 PUSH ECX
39249 CALL Color2RGB
39250 POP ECX
39252 PUSH EAX // Color2RGB( Value )
39253 PUSH 0 // 0
39254 PUSH ECX // fCommandActions.aSetBkColor
39255 PUSH EBX // @ Self
39256 CALL TControl.Perform
39258 POP EDX
39260 @@1:
39261 CMP EDX, [EBX].fColor
39262 JZ @@exit
39264 MOV [EBX].fColor, EDX
39266 XOR ECX, ECX
39267 XCHG ECX, [EBX].fTmpBrush
39268 JECXZ @@setbrushcolor
39270 PUSH EDX
39271 PUSH ECX
39272 CALL DeleteObject
39273 POP EDX
39275 @@setbrushcolor:
39276 MOV ECX, [EBX].fBrush
39277 JECXZ @@invldte
39279 XCHG EAX, ECX
39280 MOV ECX, EDX
39281 //MOV EDX, go_Color
39282 XOR EDX, EDX
39283 CALL TGraphicTool.SetInt
39285 @@invldte:
39286 XCHG EAX, EBX
39287 CALL TControl.Invalidate
39288 @@exit:
39289 POP EBX
39290 end;
39291 {$ELSE ASM_VERSION} //Pascal
39292 procedure TControl.SetCtlColor( Value: TColor );
39293 begin
39294 {$IFNDEF INPACKAGE}
39295 if GetWindowHandle <> 0 then
39296 {$ELSE}
39297 if fHandle <> 0 then
39298 {$ENDIF}
39299 if fCommandActions.aSetBkColor <> 0 then
39300 Perform( fCommandActions.aSetBkColor, 0, Color2RGB( Value ) );
39301 if fColor = Value then Exit;
39302 fColor := Value;
39303 if fTmpBrush <> 0 then
39304 begin
39305 DeleteObject( fTmpBrush );
39306 fTmpBrush := 0;
39307 end;
39308 if fBrush <> nil then
39309 fBrush.Color := Value;
39310 Invalidate;
39311 end;
39312 {$ENDIF ASM_VERSION}
39314 {$IFDEF ASM_VERSION}
39315 //[function TControl.GetParentWnd]
39316 function TControl.GetParentWnd( NeedHandle: Boolean ): HWnd;
39318 MOV ECX, [EAX].fParent
39319 JECXZ @@exit
39321 PUSH ECX
39322 TEST DL, DL
39323 JZ @@load_handle
39325 XCHG EAX, ECX
39326 CALL GetWindowHandle
39328 @@load_handle:
39329 POP ECX
39330 MOV ECX, [ECX].fHandle
39332 @@exit: XCHG EAX, ECX
39334 end;
39335 {$ELSE ASM_VERSION} //Pascal
39336 function TControl.GetParentWnd( NeedHandle: Boolean ): HWnd;
39337 var C: PControl;
39338 begin
39339 Result := 0;
39340 C := fParent; // WindowedParent;
39341 if C <> nil then
39342 begin
39343 if NeedHandle then
39344 C.GetWindowHandle;
39345 Result := C.fHandle;
39346 end;
39347 end;
39348 {$ENDIF ASM_VERSION}
39350 {$IFDEF ASM_VERSION}
39351 //[procedure TControl.CreateChildWindows]
39352 procedure TControl.CreateChildWindows;
39354 PUSH ESI
39355 MOV ESI, [EAX].TControl.fChildren
39356 MOV ECX, [ESI].TList.fCount
39357 MOV ESI, [ESI].TList.fItems
39358 JECXZ @@exit
39360 @@loop: PUSH ECX
39361 LODSD
39362 CALL CallTControlCreateWindow
39363 //CALL TControl.GetWindowHandle
39364 POP ECX
39365 LOOP @@loop
39367 @@exit: POP ESI
39368 end;
39369 {$ELSE ASM_VERSION} //Pascal
39370 procedure TControl.CreateChildWindows;
39371 var I: Integer;
39372 C: PControl;
39373 begin
39374 for I := 0 to fChildren.Count - 1 do
39375 begin
39376 C := fChildren.fItems[ I ];
39377 //C.GetWindowHandle;
39378 C.CreateWindow; //virtual!!!
39379 end;
39380 end;
39381 {$ENDIF ASM_VERSION}
39383 //[function TControl.GetMembers]
39384 function TControl.GetMembers(Idx: Integer): PControl;
39385 begin
39386 Result := fChildren.fItems[ Idx ];
39387 end;
39389 {$IFDEF ASM_VERSION}
39390 //[procedure TControl.DestroyChildren]
39391 procedure TControl.DestroyChildren;
39393 PUSH ESI
39395 MOV EAX, [EAX].fChildren
39396 PUSH EAX
39397 MOV ECX, [EAX].TList.fCount
39398 JECXZ @@clear
39399 MOV ESI, [EAX].TList.fItems
39400 LEA ESI, [ESI + ECX*4 - 4] // is order really important ?
39402 @@loop: STD //
39403 LODSD
39404 CLD //
39406 PUSH ECX
39407 CALL TObj.Free
39408 POP ECX
39410 LOOP @@loop
39412 @@clear:
39413 POP EAX
39414 CALL TList.Clear
39416 POP ESI
39417 end;
39418 {$ELSE ASM_VERSION} //Pascal
39419 procedure TControl.DestroyChildren;
39420 var I: Integer;
39421 W: PControl;
39422 begin
39423 for I := fChildren.fCount - 1 downto 0 do
39424 begin
39425 W := fChildren.fItems[ I ];
39426 W.Free;
39427 end;
39428 fChildren.Clear;
39429 end;
39430 {$ENDIF ASM_VERSION}
39432 {//-
39433 //[function TControl.WindowedParent]
39434 function TControl.WindowedParent: PControl;
39435 begin
39436 Result := fParent;
39437 end;}
39439 {$IFDEF ASM_VERSION}
39440 //[function TControl.ProcessMessage]
39441 function TControl.ProcessMessage: Boolean;
39442 const size_TMsg = sizeof( TMsg );
39444 PUSH EBX
39445 XCHG EBX, EAX
39447 ADD ESP, -size_TMsg-4
39449 MOV EDX, ESP
39450 PUSH 1
39451 XOR ECX, ECX
39452 PUSH ECX
39453 PUSH ECX
39454 PUSH ECX
39455 PUSH EDX
39456 CALL PeekMessage
39458 TEST EAX, EAX
39459 JZ @@exit
39461 MOV EDX, [ESP].TMsg.message
39462 CMP DX, WM_QUIT
39463 JNZ @@tran_disp
39464 MOV [AppletTerminated], 1
39465 JMP @@fin
39467 @@tran_disp:
39468 MOV ECX, [EBX].fExMsgProc
39469 JECXZ @@do_tran_disp
39470 MOV EAX, EBX
39471 MOV EDX, ESP
39472 CALL ECX
39473 TEST AL, AL
39474 JNZ @@fin
39476 @@do_tran_disp:
39477 MOV EAX, ESP
39478 PUSH EAX
39479 PUSH EAX
39480 CALL TranslateMessage
39481 CALL DispatchMessage
39483 @@fin:
39484 MOV AX, word ptr [ESP].TMsg.message
39485 TEST AX, AX
39486 SETNZ AL
39488 @@exit: ADD ESP, size_TMsg+4
39489 POP EBX
39490 end;
39491 {$ELSE ASM_VERSION} //Pascal
39492 function TControl.ProcessMessage: Boolean;
39493 var Msg: TMsg;
39494 begin
39495 Result := False;
39496 if PeekMessage( Msg, 0, 0, 0, PM_REMOVE ) then
39497 begin
39498 Result := Msg.message <> 0;
39499 if (Msg.message = WM_QUIT) then
39500 AppletTerminated := True
39501 else
39502 begin
39503 if not(Assigned( fExMsgProc ) and fExMsgProc( @Self, Msg )) then
39504 begin
39505 TranslateMessage( Msg );
39506 DispatchMessage( Msg );
39507 end;
39508 end;
39509 end;
39510 end;
39511 {$ENDIF ASM_VERSION}
39513 {$IFDEF ASM_VERSION}
39514 //[procedure TControl.ProcessMessages]
39515 procedure TControl.ProcessMessages;
39517 @@loo: PUSH EAX
39518 CALL ProcessMessage
39519 DEC AL
39520 POP EAX
39521 JZ @@loo
39522 end;
39523 {$ELSE ASM_VERSION} //Pascal
39524 procedure TControl.ProcessMessages;
39525 begin
39526 while ProcessMessage do ;
39527 end;
39528 {$ENDIF ASM_VERSION}
39530 //[procedure TControl.ProcessMessagesEx]
39531 procedure TControl.ProcessMessagesEx;
39532 begin
39533 PostMessage( GetWindowHandle, CM_PROCESS, 0, 0 );
39534 ProcessMessages;
39535 end;
39537 //[FUNCTION WndProcForm]
39538 {$IFDEF ASM_VERSION}
39539 function WndProcForm(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39540 const szPaintStruct = sizeof(TPaintStruct);
39541 asm //cmd //opd
39542 CMP word ptr [EDX].TMsg.message, WM_ENDSESSION
39543 JNE @@chk_WM_SETFOCUS
39545 CMP [EDX].TMsg.wParam, 0
39546 JZ @@ret_false
39548 CALL TObj.RefDec
39549 XOR EAX, EAX
39550 MOV [AppletRunning], AL
39551 XCHG EAX, [Applet]
39552 INC [AppletTerminated]
39554 CALL TObj.Free
39555 CALL System.@Halt0
39556 //-------
39558 @@chk_WM_SETFOCUS:
39559 CMP word ptr [EDX].TMsg.message, WM_SETFOCUS
39560 JNE @@ret_false
39562 PUSH EBX
39563 PUSH ESI
39564 XOR EBX, EBX
39565 XCHG ESI, EAX
39566 {$IFDEF FIX_MODAL_SETFOCUS}
39567 MOV ECX, [ESI].TControl.fModalForm
39568 JECXZ @@no_fix_modal_setfocus
39569 PUSH [ECX].TControl.fHandle
39570 CALL SetFocus
39571 @@no_fix_modal_setfocus:
39572 {$ENDIF}
39574 MOV ECX, [ESI].TControl.FCurrentControl
39575 JECXZ @@1
39576 INC EBX
39577 XCHG EAX, ECX
39579 // or CreateForm?
39580 PUSH EAX
39581 CALL CallTControlCreateWindow
39582 POP EAX
39583 PUSH [EAX].TControl.fHandle
39585 CALL SetFocus
39586 @@1: MOV ECX, [Applet]
39587 JECXZ @@ret_EBX
39588 CMP ECX, ESI
39589 JE @@ret_EBX
39590 MOV [ECX].TControl.FCurrentControl, ESI
39591 @@ret_EBX:
39592 XCHG EAX, EBX
39593 POP ESI
39594 POP EBX
39597 @@ret_false:
39598 XOR EAX, EAX
39599 end;
39600 {$ELSE ASM_VERSION} //Pascal
39601 function WndProcForm(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39602 var App: PControl;
39603 begin
39604 Result := True;
39605 with Self_{-}^{+} do
39606 case Msg.message of
39607 WM_ENDSESSION:
39608 begin
39609 if Msg.wParam <> 0 then
39610 begin
39611 Self_.RefDec;
39612 { Normally, WM_ENDSESSION is sent to a main form, not to Applet.
39613 Since we do not plan further working after handling this message,
39614 we decrease RefCount for the form (in was increased in EnumDynHandlers
39615 to prevent object destroying while its message processing is not
39616 finished). }
39617 App := Applet;
39618 //Rslt := 0; { We will not return any result at all. }
39619 {$IFDEF DEBUG_ENDSESSION}
39620 EndSession_Initiated := TRUE;
39621 LogFileOutput( GetStartDir + 'es_debug.txt',
39622 'Self_=' + Int2Hex( DWORD( Self_ ), 8 ) +
39623 ' Self_.Handle=' + Int2Str( Self_.FHandle ) );
39624 {$ENDIF}
39625 AppletTerminated := TRUE;
39626 AppletRunning := FALSE;
39627 Applet := nil;
39628 App.Free; { We provide OnDestroy handlers to be called for any objects here }
39629 Halt; { Stop further executing. }
39630 end else Result := FALSE;
39631 end;
39632 WM_SETFOCUS:
39633 begin
39634 {$IFDEF NEW_MODAL}
39635 if fModalForm <> nil then
39636 SetFocus( fModalForm.fHandle )
39637 else if ( FCurrentControl <> nil ) and not ( fCurrentControl.IsForm xor fIsApplet ) then
39638 {$ELSE not NEW_MODAL}
39639 if FCurrentControl <> nil then
39640 {$ENDIF}
39641 begin
39642 FCurrentControl.CreateWindow; //virtual!!!
39643 SetFocus( FCurrentControl.fHandle );
39645 else
39646 Result := False;
39647 if assigned( Applet ) and (Applet <> Self_) then
39648 Applet.FCurrentControl := Self_;
39649 end;
39650 else Result := False;
39651 end;
39652 end;
39653 {$ENDIF ASM_VERSION}
39654 //[END WndProcForm]
39656 //[FUNCTION GetPrevCtrlBoundsRect]
39657 {$IFDEF ASM_VERSION}
39658 function GetPrevCtrlBoundsRect( P: PControl; var R: TRect ): Boolean;
39660 MOV EDX, EBX
39661 MOV EAX, [EBX].TControl.fParent
39662 TEST EAX, EAX
39663 JZ @@exit
39664 PUSH EAX
39665 CALL TControl.ChildIndex
39666 TEST EAX, EAX
39667 XCHG EDX, EAX
39668 POP EAX
39669 JZ @@exit
39670 DEC EDX
39671 CALL TControl.GetMembers
39673 POP ECX // retaddr
39674 ADD ESP, -size_TRect
39675 MOV EDX, ESP
39676 PUSH ECX
39677 CALL TControl.GetBoundsRect
39678 STC // return CARRY
39679 @@exit:
39680 end;
39681 {$ELSE ASM_VERSION} //Pascal
39682 function GetPrevCtrlBoundsRect( P: PControl; var R: TRect ): Boolean;
39683 var Idx: Integer;
39684 begin
39685 Result := False;
39686 if P.FParent = nil then Exit;
39687 Idx := P.FParent.ChildIndex( P ) - 1;
39688 if Idx < 0 then Exit;
39689 Result := True;
39690 R := P.FParent.Children[ Idx ].BoundsRect;
39691 end;
39692 {$ENDIF ASM_VERSION}
39693 //[END GetPrevCtrlBoundsRect]
39695 {$IFDEF ASM_VERSION}
39696 //[function TControl.PlaceUnder]
39697 function TControl.PlaceUnder: PControl;
39699 PUSH EBX
39700 XCHG EBX, EAX
39701 CALL GetPrevCtrlBoundsRect
39702 JNC @@exit
39703 POP EDX // EDX = Left
39704 MOV EAX, EBX
39705 CALL TControl.SetLeft
39707 POP EDX
39708 POP EDX
39709 POP EDX // EDX = Bottom
39711 MOV EAX, [EBX].fParent
39712 ADD EDX, [EAX].fMargin
39714 MOV EAX, EBX
39715 CALL TControl.SetTop
39716 @@exit:
39717 XCHG EAX, EBX
39718 POP EBX
39719 end;
39720 {$ELSE ASM_VERSION} //Pascal
39721 function TControl.PlaceUnder: PControl;
39722 var R: TRect;
39723 begin
39724 Result := @Self;
39725 if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;
39726 Top := R.Bottom + fParent.fMargin;
39727 Left := R.Left;
39728 end;
39729 {$ENDIF ASM_VERSION}
39731 {$IFDEF ASM_VERSION}
39732 //[function TControl.PlaceDown]
39733 function TControl.PlaceDown: PControl;
39735 PUSH EBX
39736 XCHG EBX, EAX
39737 CALL GetPrevCtrlBoundsRect
39738 JNC @@exit
39739 POP EDX
39740 POP EDX
39741 POP EDX
39742 POP EDX // EDX = Bottom
39744 MOV EAX, [EBX].fParent
39745 ADD EDX, [EAX].fMargin
39747 MOV EAX, EBX
39748 CALL TControl.SetTop
39749 @@exit:
39750 XCHG EAX, EBX
39751 POP EBX
39752 end;
39753 {$ELSE ASM_VERSION} //Pascal
39754 function TControl.PlaceDown: PControl;
39755 var R: TRect;
39756 begin
39757 Result := @Self;
39758 if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;
39759 Top := R.Bottom + fParent.fMargin;
39760 end;
39761 {$ENDIF ASM_VERSION}
39763 {$IFDEF ASM_VERSION}
39764 //[function TControl.PlaceRight]
39765 function TControl.PlaceRight: PControl;
39767 PUSH EBX
39768 XCHG EBX, EAX
39769 CALL GetPrevCtrlBoundsRect
39770 JNC @@exit
39771 POP EDX
39772 POP EDX // EDX = Top
39773 MOV EAX, EBX
39774 CALL TControl.SetTop
39775 POP EDX // EDX = Right
39777 MOV EAX, [EBX].fParent
39778 ADD EDX, [EAX].fMargin
39780 POP ECX
39781 MOV EAX, EBX
39782 CALL TControl.SetLeft
39783 @@exit:
39784 XCHG EAX, EBX
39785 POP EBX
39786 end;
39787 {$ELSE ASM_VERSION} //Pascal
39788 function TControl.PlaceRight: PControl;
39789 var R: TRect;
39790 begin
39791 Result := @Self;
39792 if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;
39793 Top := R.Top;
39794 Left := R.Right + fParent.fMargin;
39795 end;
39796 {$ENDIF ASM_VERSION}
39798 {$IFDEF ASM_VERSION}
39799 //[function TControl.SetSize]
39800 function TControl.SetSize(W, H: Integer): PControl;
39802 PUSH EBX
39803 XCHG EBX, EAX
39804 SUB ESP, 16
39805 XCHG EAX, EDX
39806 MOV EDX, ESP
39807 PUSH ECX // save H
39808 PUSH EAX // save W
39809 MOV EAX, EBX
39810 CALL GetBoundsRect
39811 POP ECX // pop W
39812 JECXZ @@nochg_W
39813 ADD ECX, [ESP+4].TRect.Left
39814 MOV [ESP+4].TRect.Right, ECX
39815 @@nochg_W:
39816 POP ECX // pop H
39817 JECXZ @@nochg_H
39818 ADD ECX, [ESP].TRect.Top
39819 MOV [ESP].TRect.Bottom, ECX
39820 @@nochg_H:
39821 MOV EAX, EBX
39822 MOV EDX, ESP
39823 CALL TControl.SetBoundsRect
39824 ADD ESP, 16
39825 XCHG EAX, EBX
39826 POP EBX
39827 end;
39828 {$ELSE ASM_VERSION} //Pascal
39829 function TControl.SetSize(W, H: Integer): PControl;
39830 var R: TRect;
39831 begin
39832 R := BoundsRect;
39833 if W > 0 then R.Right := R.Left + W;
39834 if H > 0 then R.Bottom := R.Top + H;
39835 SetBoundsRect( R );
39836 Result := @Self;
39837 end;
39838 {$ENDIF ASM_VERSION}
39840 //[function TControl.SetClientSize]
39841 function TControl.SetClientSize(W, H: Integer): PControl;
39842 begin
39843 if W > 0 then ClientWidth := W;
39844 if H > 0 then ClientHeight := H;
39845 Result := @Self;
39846 end;
39848 {$IFDEF ASM_VERSION}
39849 //[function TControl.AlignLeft]
39850 function TControl.AlignLeft(P: PControl): PControl;
39852 PUSH EAX
39853 MOV EAX, EDX
39854 CALL TControl.GetLeft
39855 MOV EDX, EAX
39856 POP EAX
39857 PUSH EAX
39858 CALL TControl.SetLeft
39859 POP EAX
39860 end;
39861 {$ELSE ASM_VERSION} //Pascal
39862 function TControl.AlignLeft(P: PControl): PControl;
39863 begin
39864 Result := @Self;
39865 Left := P.Left;
39866 end;
39867 {$ENDIF ASM_VERSION}
39869 {$IFDEF ASM_VERSION}
39870 //[function TControl.AlignTop]
39871 function TControl.AlignTop(P: PControl): PControl;
39873 PUSH EAX
39874 MOV EAX, EDX
39875 CALL TControl.GetTop
39876 MOV EDX, EAX
39877 POP EAX
39878 PUSH EAX
39879 CALL TControl.SetTop
39880 POP EAX
39881 end;
39882 {$ELSE ASM_VERSION} //Pascal
39883 function TControl.AlignTop(P: PControl): PControl;
39884 begin
39885 Result := @Self;
39886 Top := P.Top;
39887 end;
39888 {$ENDIF ASM_VERSION}
39890 //[FUNCTION WndProcCtrl]
39891 {$IFDEF ASM_VERSION} // see addition for combobox in pas version
39892 function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
39893 asm //cmd //opd
39894 PUSH EBX
39895 XCHG EBX, EAX
39896 PUSH ESI
39897 PUSH EDI
39898 MOV EDI, EDX
39899 MOV EDX, [EDI].TMsg.message
39901 SUB DX, CN_CTLCOLORMSGBOX
39902 CMP DX, CN_CTLCOLORSTATIC-CN_CTLCOLORMSGBOX
39903 JA @@chk_CM_COMMAND
39904 @@2:
39905 PUSH ECX
39906 MOV EAX, [EBX].TControl.fTextColor
39907 CALL Color2RGB
39908 XCHG ESI, EAX
39909 PUSH ESI
39910 PUSH [EDI].TMsg.wParam
39911 CALL SetTextColor
39912 CMP [EBX].TControl.fTransparent, 0
39913 JZ @@opaque
39915 PUSH Windows.TRANSPARENT
39916 PUSH [EDI].TMsg.wParam
39917 CALL SetBkMode
39918 PUSH NULL_BRUSH
39919 CALL GetStockObject
39920 JMP @@ret_rslt
39922 @@opaque:
39923 MOV EAX, [EBX].TControl.fColor
39924 CALL Color2RGB
39925 XCHG ESI, EAX
39926 PUSH OPAQUE
39927 PUSH [EDI].TMsg.wParam
39928 CALL SetBkMode
39929 PUSH ESI
39930 PUSH [EDI].TMsg.wParam
39931 CALL SetBkColor
39933 MOV EAX, EBX
39934 CALL Global_GetCtlBrushHandle
39935 @@ret_rslt:
39936 XCHG ECX, EAX
39937 @@tmpbrushready:
39938 POP EAX
39939 MOV [EAX], ECX
39940 @@ret_true:
39941 MOV AL, 1
39943 JMP @@ret_EAX
39945 @@chk_CM_COMMAND:
39946 CMP word ptr [EDI].TMsg.message, CM_COMMAND
39947 JNE @@chk_WM_SETFOCUS
39949 PUSH ECX
39951 MOVZX ECX, word ptr [EDI].TMsg.wParam+2
39952 CMP CX, [EBX].TControl.fCommandActions.aClick
39953 JNE @@chk_aEnter
39955 CMP [EBX].TControl.fClickDisabled, 0
39956 JG @@calldef
39957 MOV EAX, EBX
39958 CALL TControl.DoClick
39959 JMP @@calldef
39961 @@chk_aEnter:
39962 LEA EAX, [EBX].TControl.fOnEnter
39963 CMP CX, [EBX].TControl.fCommandActions.aEnter
39964 JE @@goEvent
39965 LEA EAX, [EBX].TControl.fOnLeave
39966 CMP CX, [EBX].TControl.fCommandActions.aLeave
39967 JE @@goEvent
39968 LEA EAX, [EBX].TControl.fOnChange
39969 CMP CX, [EBX].TControl.fCommandActions.aChange
39970 JNE @@chk_aSelChange
39971 @@goEvent:
39972 MOV ECX, [EAX].TMethod.Code
39973 JECXZ @@2calldef
39974 MOV EAX, [EAX].TMethod.Data
39975 MOV EDX, EBX
39976 CALL ECX
39977 @@2calldef:
39978 JMP @@calldef
39980 @@chk_aSelChange:
39981 CMP CX, [EBX].TControl.fCommandActions.aSelChange
39982 JNE @@chk_WM_SETFOCUS_1
39983 MOV EAX, EBX
39984 CALL TControl.DoSelChange
39986 @@calldef:
39987 XCHG EAX, EBX
39988 MOV EDX, EDI
39989 CALL TControl.CallDefWndProc
39990 JMP @@ret_rslt
39992 @@chk_WM_SETFOCUS_1:
39993 POP ECX
39994 @@chk_WM_SETFOCUS:
39995 XOR EAX, EAX
39996 CMP word ptr [EDI].TMsg.message, WM_SETFOCUS
39997 JNE @@ret_EAX
39999 MOV [ECX], EAX
40000 MOV EAX, EBX
40001 CALL TControl.ParentForm
40002 TEST EAX, EAX
40003 JZ @@ret_true
40005 MOV [EAX].TControl.FCurrentControl, EBX
40006 XOR EAX, EAX
40008 PUSH EDX
40009 @@2ret_EAX:
40010 POP EDX
40012 @@ret_EAX:
40013 POP EDI
40014 POP ESI
40015 POP EBX
40016 end;
40017 {$ELSE ASM_VERSION} //Pascal
40018 function WndProcCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
40019 var F: PControl;
40020 Cmd : DWORD;
40021 begin
40022 //Result := FALSE;
40023 with Self_{-}^{+} do
40024 case Msg.message of
40025 CN_CTLCOLORMSGBOX..CN_CTLCOLORSTATIC:
40026 begin
40027 SetTextColor(Msg.WParam, Color2RGB(fTextColor));
40028 if fTransparent {AND (fPaintDC = Msg.wParam)} then
40029 begin
40030 SetBkMode( Msg.wParam, Windows.TRANSPARENT );
40031 Rslt := GetStockObject( NULL_BRUSH );
40033 else
40034 begin
40035 SetBkMode( Msg.wParam, Windows.OPAQUE );
40036 SetBkColor(Msg.WParam, Color2RGB( fColor ) );
40037 Rslt := Global_GetCtlBrushHandle( Self_ );
40038 end;
40039 Result := TRUE;
40040 end;
40041 CM_COMMAND:
40042 begin
40043 Result := True;
40044 Cmd := HiWord( Msg.wParam );
40045 if Cmd = fCommandActions.aClick then
40046 begin
40047 if Integer( fClickDisabled ) <= 0 then
40048 DoClick;
40049 end else
40050 if Cmd = fCommandActions.aEnter then
40051 begin
40052 if Assigned( fOnEnter ) then fOnEnter( Self_ );
40053 end else
40054 if Cmd = fCommandActions.aLeave then
40055 begin
40056 if Assigned( fOnLeave ) then fOnLeave( Self_ );
40057 end else
40058 if Integer(Cmd) = fCommandActions.aChange then
40059 begin
40060 if Assigned( fOnChange ) then fOnChange( Self_ );
40061 //if fTransparent then Invalidate;
40062 end else
40063 if Integer(Cmd) = fCommandActions.aSelChange then
40064 begin
40065 DoSelChange;
40066 // if fTransparent then Invalidate;
40068 else Result := False;
40070 if Result then
40071 Rslt := CallDefWndProc( Msg );
40073 end;
40075 WM_SETFOCUS:
40076 begin
40077 Rslt := 0;
40078 Result := TRUE;
40079 F := ParentForm;
40080 if F <> nil then
40081 begin
40082 F.fCurrentControl := Self_;
40083 Result := False; // go further handling
40084 end;
40085 end;
40086 {$IFDEF ESC_CLOSE_DIALOGS}
40087 //---------------------------------Babenko Alexey--------------------------
40088 WM_KEYDOWN:
40089 begin
40090 if (Self_.ParentForm.ExStyle and WS_EX_DLGMODALFRAME) <> 0 then
40091 if Msg.wParam = 27 then SendMessage(Self_.ParentForm.Handle, WM_CLOSE, 0, 0);
40092 result:=false;
40093 end;
40094 //---------------------------------Babenko Alexey--------------------------
40095 {$ENDIF ESC_CLOSE_DIALOGS}
40096 else Result := False;
40097 end;
40098 end;
40099 {$ENDIF ASM_VERSION}
40100 //[END WndProcCtrl]
40102 //[FUNCTION WndProcPaint]
40103 {$IFDEF ASM_noVERSION}
40104 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40105 const szPaintStruct = sizeof(TPaintStruct);
40106 asm //cmd //opd
40107 CMP word ptr [EDX].TMsg.message, WM_PRINT
40108 JE @@print
40109 CMP word ptr [EDX].TMsg.message, WM_PAINT
40110 JNE @@ret_false
40111 @@print:
40112 CMP word ptr [EAX].TControl.fOnPaint.TMethod.Code+2, 0
40113 JE @@ret_false
40114 PUSH EBX
40115 PUSH ESI
40117 XCHG EBX, EAX
40118 MOV ESI, EDX
40119 XOR EAX, EAX
40120 PUSH ECX
40121 PUSH EAX
40122 PUSH EAX
40123 PUSH EAX
40124 PUSH EAX
40125 CALL CreateRectRgn
40126 MOV [EBX].TControl.fUpdRgn, EAX
40128 MOVSX EDX, [EBX].TControl.fEraseUpdRgn
40129 PUSH EDX
40130 PUSH EAX
40131 PUSH [EBX].TControl.fHandle
40132 CALL GetUpdateRgn
40134 CMP EAX, 1
40135 JA @@collectUpdRgn
40137 XOR EAX, EAX
40138 XCHG EAX, [EBX].TControl.fUpdRgn
40139 PUSH EAX
40140 CALL DeleteObject
40142 @@collectUpdRgn:
40143 MOV ECX, [EBX].TControl.fCollectUpdRgn
40144 JECXZ @@asg_fPaintDC
40145 XCHG EAX, ECX
40146 MOV ECX, [EBX].TControl.fUpdRgn
40147 JECXZ @@asg_fPaintDC
40149 PUSH RGN_OR
40150 PUSH ECX
40151 PUSH EAX
40152 PUSH EAX
40153 CALL CombineRgn
40155 DEC EAX
40156 JNZ @@invalidateRgn
40158 ADD ESP, -16
40159 PUSH ESP
40160 PUSH [EBX].TControl.fHandle
40161 CALL Windows.GetClientRect
40163 PUSH [EBX].TControl.fCollectUpdRgn
40164 CALL DeleteObject
40165 CALL CreateRectRgn
40166 MOV [EBX].TControl.fCollectUpdRgn, EAX
40168 @@invalidateRgn:
40169 MOVSX EDX, [EBX].TControl.fEraseUpdRgn
40170 PUSH EDX
40171 PUSH [EBX].TControl.fCollectUpdRgn
40172 PUSH [EBX].TControl.fHandle
40173 CALL InvalidateRgn
40176 @@asg_fPaintDC:
40177 MOV ECX, [ESI].TMsg.wParam
40178 INC ECX
40179 LOOP @@storePaintDC
40181 ADD ESP, -szPaintStruct
40182 PUSH ESP
40183 PUSH [EBX].TControl.fHandle
40184 CALL BeginPaint
40185 XCHG ECX, EAX
40186 @@storePaintDC:
40187 MOV [EBX].TControl.fPaintDC, ECX
40188 XCHG EAX, ECX
40190 MOV ECX, [EBX].TControl.fCollectUpdRgn
40191 JECXZ @@doOnPaint
40193 PUSH ECX
40194 PUSH EAX
40195 CALL SelectClipRgn
40197 @@doOnPaint:
40198 MOV ECX, [EBX].TControl.fPaintDC
40199 MOV EDX, EBX
40200 MOV EAX, [EBX].TControl.fOnPaint.TMethod.Data
40201 CALL dword ptr [EBX].TControl.fOnPaint.TMethod.Code
40203 MOV ECX, [EBX].TControl.fCanvas
40204 JECXZ @@e_paint
40206 XCHG EAX, ECX
40207 XOR EDX, EDX
40208 CALL TCanvas.SetHandle
40210 @@e_paint:
40211 MOV ECX, [ESI].TMsg.wParam
40212 INC ECX
40213 LOOP @@zero_fPaintDC
40215 PUSH ESP
40216 PUSH [EBX].TControl.fHandle
40217 CALL EndPaint
40218 ADD ESP, szPaintStruct
40220 @@zero_fPaintDC:
40221 XOR ECX, ECX
40222 MOV [EBX].TControl.fPaintDC, ECX
40224 POP EAX
40225 MOV [EAX], ECX
40227 XCHG ECX, [EBX].TControl.fUpdRgn
40228 JECXZ @@exit_True
40230 PUSH ECX
40231 CALL DeleteObject
40233 @@exit_True:
40234 POP ESI
40235 POP EBX
40236 MOV AL, 1
40239 @@ret_false:
40240 XOR EAX, EAX
40241 end;
40242 {$ELSE ASM_VERSION} //Pascal
40243 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40244 var PaintStruct: TPaintStruct;
40245 CR: TRect;
40246 Cplxity: Integer;
40247 OldPaintDC: HDC;
40248 begin
40249 with Self_{-}^{+} do
40250 case Msg.message of
40251 WM_PRINT,
40252 WM_PAINT: if assigned( fOnPaint ) then
40253 begin
40254 fUpdRgn := CreateRectRgn( 0, 0, 0, 0 );
40255 Cplxity := Integer( GetUpdateRgn( fHandle, fUpdRgn, fEraseUpdRgn ) );
40256 if (Cplxity = NULLREGION) or (Cplxity = ERROR) then
40257 begin
40258 DeleteObject( fUpdRgn );
40259 fUpdRgn := 0;
40260 end;
40262 if (fCollectUpdRgn <> 0) and (fUpdRgn <> 0) then
40263 begin
40264 if CombineRgn( fCollectUpdRgn, fCollectUpdRgn, fUpdRgn, RGN_OR )
40265 = COMPLEXREGION then
40266 begin
40267 windows.GetClientRect( Self_.fHandle, CR );
40268 DeleteObject( fCollectUpdRgn );
40269 fCollectUpdRgn := CreateRectRgnIndirect( CR );
40270 end;
40271 InvalidateRgn( fHandle, fCollectUpdRgn, fEraseUpdRgn );
40272 end;
40274 OldPaintDC := fPaintDC;
40275 fPaintDC := Msg.wParam;
40276 if fPaintDC = 0 then
40277 fPaintDC := BeginPaint( fHandle, PaintStruct );
40279 if fCollectUpdRgn <> 0 then
40280 SelectClipRgn( fPaintDC, fCollectUpdRgn );
40282 fOnPaint( Self_, fPaintDC );
40284 if assigned( Self_.fCanvas ) then
40285 Self_.fCanvas.SetHandle( 0 );
40287 if Msg.wParam = 0 then
40288 EndPaint( fHandle, PaintStruct );
40289 fPaintDC := OldPaintDC;
40291 Rslt := 0;
40293 Result := True;
40294 if fUpdRgn <> 0 then
40295 DeleteObject( fUpdRgn );
40296 fUpdRgn := 0;
40297 Exit;
40298 end;
40299 end;
40300 Result := FALSE;
40301 end;
40302 {$ENDIF ASM_VERSION}
40303 //[END WndProcPaint]
40305 //[procedure TControl.SetOnPaint]
40306 procedure TControl.SetOnPaint( const Value: TOnPaint );
40307 begin
40308 fOnPaint := Value;
40309 AttachProc( WndProcPaint );
40310 end;
40313 //[function WndProcEraseBkgnd]
40314 function WndProcEraseBkgnd( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40315 var PaintStruct: TPaintStruct;
40316 OldPaintDC: HDC;
40317 begin
40318 Result := FALSE;
40319 if Msg.message = WM_ERASEBKGND then
40320 begin
40321 if Assigned( Sender.OnEraseBkgnd ) then
40322 begin
40323 OldPaintDC := Sender.fPaintDC;
40324 Sender.fPaintDC := Msg.wParam;
40325 if Sender.fPaintDC = 0 then
40326 Sender.fPaintDC := BeginPaint( Sender.fHandle, PaintStruct );
40327 Sender.OnEraseBkgnd( Sender, Msg.wParam );
40328 if Msg.wParam = 0 then
40329 EndPaint( Sender.fHandle, PaintStruct );
40330 if Assigned( Sender.fCanvas ) then
40331 Sender.fCanvas.SetHandle( 0 );
40332 Sender.fPaintDC := OldPaintDC;
40333 Rslt := 0;
40334 Result := TRUE;
40336 else
40337 Rslt := 0;
40338 end;
40339 end;
40341 //[procedure TControl.SetOnEraseBkgnd]
40342 procedure TControl.SetOnEraseBkgnd(const Value: TOnPaint);
40343 begin
40344 fOnEraseBkgnd := Value;
40345 AttachProc( WndProcEraseBkgnd );
40346 end;
40348 //[FUNCTION WndProcGradient]
40349 {$IFDEF ASM_noVERSION}
40350 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40351 const szPaintStruct = sizeof( TPaintStruct );
40352 asm //cmd //opd
40353 CMP word ptr [EDX].TMsg.message, WM_PRINTCLIENT
40354 JE @@print
40355 CMP word ptr [EDX].TMsg.message, WM_PAINT
40356 JNE @@ret_false
40357 @@print:
40358 PUSHAD
40359 XCHG EDI, EAX
40360 MOV ESI, EDX
40361 XOR EAX, EAX
40362 MOV [ECX], EAX
40363 OR EAX, [ESI].TMsg.wParam
40364 JNZ @@1
40365 ADD ESP, -szPaintStruct
40366 PUSH ESP
40367 PUSH [EDI].TControl.fHandle
40368 CALL BeginPaint
40369 @@1: MOV [EDI].TControl.fPaintDC, EAX
40370 ADD ESP, -16
40371 MOV EDX, ESP
40372 MOV EAX, EDI
40373 CALL TControl.ClientRect
40374 MOV EAX, [EDI].TControl.fColor1
40375 CALL Color2RGB
40376 XCHG EBX, EAX
40377 MOV EAX, [EDI].TControl.fColor2
40378 CALL Color2RGB
40379 MOV EBP, [ESP].TRect.Bottom
40380 @@loo:
40381 MOV EDX, [ESP].TRect.Top
40382 CMP EBP, EDX
40383 JLE @@e_loo
40384 INC EDX
40385 MOV [ESP].TRect.Bottom, EDX
40387 INC EBP
40388 PUSH EAX
40390 PUSH EAX
40391 {SUB AL, BL
40392 MOV AH, 0
40394 CWDE}
40395 AND EAX, $FF
40396 MOV EDX, EBX
40397 AND EDX, $FF
40398 SUB EAX, EDX
40401 MOV ECX, [ESP+8].TRect.Top
40402 IMUL ECX
40403 IDIV EBP
40404 XOR EDX, EDX
40405 ADD AL, BL
40406 MOV AH, 0
40407 CWDE
40408 XCHG [ESP], EAX
40410 PUSH EAX
40411 {SUB AH, BH
40412 MOV AL, AH
40413 MOV AH, 0
40415 CWDE}
40416 SHR EAX, 8
40417 AND EAX, $FF
40418 MOV EDX, EBX
40419 SHR EDX, 8
40420 AND EDX, $FF
40421 SUB EAX, EDX
40423 IMUL ECX
40424 IDIV EBP
40425 ADD AL, BH
40426 AND EAX, $FF
40427 SHL EAX, 8
40428 XCHG [ESP], EAX
40430 SHR EAX, 16
40431 MOV EDX, EBX
40432 SHR EDX, 16
40433 PUSH EDX
40434 SUB EAX, EDX
40435 IMUL ECX
40436 IDIV EBP
40437 POP EDX
40438 //AND EAX, $FF00
40439 ADD EAX, EDX
40440 SHL EAX, 16
40442 POP EDX
40443 MOV AH, DH
40444 POP EDX
40445 MOV AL, DL
40447 PUSH EAX
40448 CALL CreateSolidBrush
40450 PUSH EAX
40452 PUSH EAX
40453 LEA EDX, [ESP+12]
40454 PUSH EDX
40455 PUSH [EDI].TControl.fPaintDC
40456 CALL Windows.FillRect
40458 CALL DeleteObject
40460 POP EAX
40461 DEC EBP
40462 INC [ESP].TRect.Top
40463 JMP @@loo
40464 @@e_loo:
40465 ADD ESP, 16
40466 MOV ECX, [ESI].TMsg.wParam
40467 INC ECX
40468 LOOP @@2
40469 PUSH ESP
40470 PUSH [EDI].TControl.fHandle
40471 CALL EndPaint
40472 ADD ESP, szPaintStruct
40473 @@2: XOR EAX, EAX
40474 MOV [EDI].TControl.fPaintDC, EAX
40475 POPAD
40476 MOV Al, 1
40478 @@ret_false:
40479 XOR EAX, EAX
40480 end;
40481 {$ELSE ASM_VERSION} //Pascal
40482 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40483 var PaintStruct: TPaintStruct;
40484 Bmp: PBitmap;
40485 CR: TRect;
40486 I: Integer;
40487 R, G, B: Integer;
40488 R1, G1, B1: Integer;
40489 C: TColor;
40490 W, H, WH: Integer;
40491 W9x: Boolean;
40492 Br: HBrush;
40493 //Save: Integer;
40494 OldPaintDC: HDC;
40495 begin
40496 case Msg.message of
40497 WM_PAINT, WM_PRINTCLIENT:
40498 begin
40499 OldPaintDC := Self_.fPaintDC;
40500 Self_.fPaintDC := Msg.wParam;
40501 if Self_.fPaintDC = 0 then
40502 Self_.fPaintDC := BeginPaint( Self_.fHandle, PaintStruct );
40503 CR := Self_.ClientRect;
40504 W9x := WinVer < wvNT;
40505 W := 1;
40506 H := CR.Bottom;
40507 WH := H;
40508 Bmp := nil;
40509 if Self_.fGradientStyle = gsHorizontal then
40510 begin
40511 W := CR.Right;
40512 H := 1;
40513 WH := W;
40514 end;
40515 if not W9x then
40516 Bmp := NewDIBBitmap( W, H, pf32bit );
40517 C := Color2RGB( Self_.fColor1 );
40518 R := C shr 16;
40519 G := (C shr 8) and $FF;
40520 B := C and $FF;
40521 C := Color2RGB( Self_.fColor2 );
40522 R1 := C shr 16;
40523 G1 := (C shr 8) and $FF;
40524 B1 := C and $FF;
40525 for I := 0 to WH-1 do
40526 begin
40527 C := ((( R + (R1 - R) * I div WH ) and $FF) shl 16) or
40528 ((( G + (G1 - G) * I div WH ) and $FF) shl 8) or
40529 ( B + (B1 - B) * I div WH ) and $FF;
40530 if W9x then
40531 begin
40532 if Self_.fGradientStyle = gsVertical then
40533 CR.Bottom := CR.Top + 1
40534 else
40535 CR.Right := CR.Left + 1;
40536 Br := CreateSolidBrush( C );
40537 Windows.FillRect( Self_.fPaintDC, CR, Br );
40538 DeleteObject( Br );
40539 if Self_.fGradientStyle = gsVertical then
40540 Inc( CR.Top )
40541 else
40542 Inc( CR.Left );
40544 else
40545 begin
40546 if Self_.fGradientStyle = gsVertical then
40547 Bmp.DIBPixels[ 0, I ] := C
40548 else
40549 Bmp.DIBPixels[ I, 0 ] := C;
40550 end;
40551 end;
40552 if not W9x then
40553 begin
40554 SetStretchBltMode( Self_.fPaintDC, HALFTONE );
40555 SetBrushOrgEx( Self_.fPaintDC, 0, 0, nil );
40556 StretchBlt( Self_.fPaintDC, 0, 0, CR.Right, CR.Bottom, Bmp.Canvas.Handle,
40557 0, 0, W, H, SRCCOPY );
40558 Bmp.Free;
40559 end;
40560 if Msg.wParam = 0 then
40561 EndPaint( Self_.fHandle, PaintStruct );
40562 Self_.fPaintDC := OldPaintDC;
40563 Rslt := 0;
40564 Result := True;
40565 Exit;
40566 end;
40567 end;
40568 Result := False;
40569 end;
40570 {$ENDIF ASM_VERSION}
40571 //[END WndProcGradient]
40573 //[function WndProcGradientEx]
40574 function WndProcGradientEx( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40575 function Ceil( X: Double ): Integer;
40576 begin
40577 Result := Round( X ) + 1;
40578 end;
40579 const
40580 SQRT2 = 1.4142135623730950488016887242097;
40582 RC, R0: TRect;
40583 C, C2: TColor;
40584 R1, G1, B1: Integer;
40585 R2, G2, B2: Integer;
40586 DX1, DX2, DY1, DY2, DR, DG, DB, K: Double;
40587 PaintStruct: TPaintStruct;
40588 I: Integer;
40589 Br: HBrush;
40590 Rgn: HRgn;
40591 Poly: array[ 0..3 ] of TPoint;
40592 OldPaintDC: HDC;
40593 fX1, fX2, fY1, fY2: Double;
40595 procedure OffsetF( DX, DY: Double );
40596 begin
40597 fX1 := fX1 + DX;
40598 fX2 := fX2 + DX;
40599 fY1 := fY1 + DY;
40600 fY2 := fY2 + DY;
40601 end;
40602 begin
40603 Result := FALSE;
40604 if (Msg.message <> WM_PAINT) and (Msg.message <> WM_PRINTCLIENT) then Exit;
40605 if Self_.fGradientStyle in [ gsHorizontal, gsVertical ] then
40606 begin
40607 Result := WndProcGradient( Self_, Msg, Rslt );
40608 Exit;
40609 end;
40610 C := Color2RGB( Self_.fColor2 );
40611 R2 := C and $FF;
40612 G2 := (C shr 8) and $FF;
40613 B2 := (C shr 16) and $FF;
40614 C := Color2RGB( Self_.fColor1 );
40615 R1 := C and $FF;
40616 G1 := (C shr 8) and $FF;
40617 B1 := (C shr 16) and $FF;
40618 DR := (R2 - R1) / 256;
40619 DG := (G2 - G1) / 256;
40620 DB := (B2 - B1) / 256;
40621 OldPaintDC := Self_.fPaintDC;
40622 Self_.fPaintDC := Msg.wParam;
40623 if Self_.fPaintDC = 0 then
40624 Self_.fPaintDC := BeginPaint( Self_.fHandle, PaintStruct );
40625 RC := Self_.ClientRect;
40626 fX1 := 0;
40627 fY1 := 0;
40628 case Self_.fGradientStyle of
40629 gsRombic:
40630 //RF := MakeRect( 0, 0, RC.Right div 128, RC.Bottom div 128 );
40631 begin
40632 fX2 := RC.Right / 128;
40633 fY2 := RC.Bottom / 128;
40634 end;
40635 gsElliptic:
40636 //RF := MakeRect( 0, 0, Ceil( RC.Right / 256 * SQRT2 ), Ceil( RC.Bottom / 256 * SQRT2 ) );
40637 begin
40638 fX2 := RC.Right / 256 * SQRT2;
40639 fY2 := RC.Bottom / 256 * SQRT2;
40640 end;
40641 else
40642 //RF := MakeRect( 0, 0, RC.Right div 256, RC.Bottom div 256 );
40643 begin
40644 fX2 := RC.Right / 256;
40645 fY2 := RC.Bottom / 256;
40646 end;
40647 end;
40648 case Self_.fGradientStyle of
40649 gsRectangle, gsRombic, gsElliptic:
40650 begin
40651 case Self_.FGradientLayout of
40652 glCenter, glTop, glBottom:
40653 //OffsetRect( RF, (RC.Right - RF.Right) div 2, 0 );
40654 OffsetF( (RC.Right - fX2) / 2, 0 );
40655 glTopRight, glBottomRight, glRight:
40656 //OffsetRect( RF, RC.Right - RF.Right div 2, 0 );
40657 OffsetF( RC.Right - fX2 / 2, 0 );
40658 glTopLeft, glBottomLeft, glLeft:
40659 //OffsetRect( RF, -RF.Right div 2, 0 );
40660 OffsetF( -fX2 / 2, 0 );
40661 end;
40662 case Self_.FGradientLayout of
40663 glCenter, glLeft, glRight:
40664 //OffsetRect( RF, 0, (RC.Bottom - RF.Bottom) div 2 );
40665 OffsetF( 0, (RC.Bottom - fY2) / 2 );
40666 glBottom, glBottomLeft, glBottomRight:
40667 //OffsetRect( RF, 0, RC.Bottom - RF.Bottom div 2 );
40668 OffsetF( 0, RC.Bottom - fY2 / 2 );
40669 glTop, glTopLeft, glTopRight:
40670 //OffsetRect( RF, 0, -RF.Bottom div 2 );
40671 OffsetF( 0, -fY2 / 2 )
40672 end;
40673 end;
40674 end;
40675 DX1 := -fX1 / 255; //(-RF.Left) / 255;
40676 DY1 := -fY1 / 255; // (-RF.Top) / 255;
40677 DX2 := (RC.Right - fX2) / 255; //(RC.Right - RF.Right) / 255;
40678 DY2 := (RC.Bottom - fY2) / 255;
40679 case Self_.fGradientStyle of
40680 gsRombic, gsElliptic:
40681 begin
40682 if DX2 < -DX1 then DX2 := -DX1;
40683 if DY2 < -DY1 then DY2 := -DY1;
40684 K := 2;
40685 if Self_.fGradientStyle = gsElliptic then K := SQRT2;
40686 DX2 := DX2 * K;
40687 DY2 := DY2 * K;
40688 DX1 := -DX2;
40689 DY1 := -DY2;
40690 end;
40691 end;
40692 C2 := C;
40693 for I := 0 to 255 do
40694 begin
40695 if (I < 255) then
40696 begin
40697 C2 := TColor( (( Ceil( B1 + DB * (I+1) ) and $FF) shl 16) or
40698 (( Ceil( G1 + DG * (I+1) ) and $FF) shl 8) or
40699 Ceil( R1 + DR * (I+1) ) and $FF );
40700 if (Self_.fGradientStyle in [gsRombic,gsElliptic,gsRectangle]) and
40701 (C2 = C) then continue;
40702 end;
40703 Br := CreateSolidBrush( C );
40704 R0 := MakeRect( Ceil( fX1 + DX1 * I ),
40705 Ceil( fY1 + DY1 * I ),
40706 Ceil( fX2 + DX2 * I ) + 1,
40707 Ceil( fY2 + DY2 * I ) + 1 );
40708 Rgn := 0;
40709 case Self_.fGradientStyle of
40710 gsRectangle:
40711 Rgn := CreateRectRgnIndirect( R0 );
40712 gsRombic:
40713 begin
40714 Poly[ 0 ].x := R0.Left;
40715 Poly[ 0 ].y := R0.Top + (R0.Bottom - R0.Top) div 2;
40716 Poly[ 1 ].x := R0.Left + (R0.Right - R0.Left) div 2;
40717 Poly[ 1 ].y := R0.Top;
40718 Poly[ 2 ].x := R0.Right;
40719 Poly[ 2 ].y := Poly[ 0 ].y;
40720 Poly[ 3 ].x := Poly[ 1 ].x;
40721 Poly[ 3 ].y := R0.Bottom;
40722 Rgn := CreatePolygonRgn( Poly[ 0 ].x, 4, ALTERNATE );
40723 end;
40724 gsElliptic:
40725 Rgn := CreateEllipticRgnIndirect( R0 );
40726 end;
40727 if Rgn <> 0 then
40728 begin
40729 if Rgn <> NULLREGION then
40730 begin
40731 Windows.FillRgn( Self_.fPaintDC, Rgn, Br );
40732 ExtSelectClipRgn( Self_.fPaintDC, Rgn, RGN_DIFF );
40733 end;
40734 DeleteObject( Rgn );
40735 end;
40736 DeleteObject( Br );
40737 C := C2;
40738 end;
40739 if Self_.fPaintDC <> HDC( Msg.wParam ) then
40740 EndPaint( Self_.fHandle, PaintStruct );
40741 Self_.fPaintDC := OldPaintDC;
40742 Rslt := 0;
40743 Result := True;
40744 end;
40747 //[function WndProcLabelEffect]
40748 function WndProcLabelEffect( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40750 Sz: TSize;
40751 P0: TPoint;
40752 CR: TRect;
40753 B : Boolean;
40754 CShadow: TColor;
40755 Target: PCanvas;
40756 Txt: String;
40757 LCaption: PChar;
40758 OldPaintDC: HDC;
40760 procedure doTextOut( shfx, shfy: Integer; col: TColor );
40761 begin
40762 SetTextColor( Target.fHandle, col );
40763 Windows.ExtTextOut( Target.fHandle, P0.x + shfx, P0.y + shfy,
40764 ETO_CLIPPED, @CR,
40765 PChar(Txt), Length(Txt), nil );
40766 //GDIFlush; // for test only
40767 end;
40769 var I, J, Istp : Integer;
40770 PS: TPaintStruct;
40771 //DoEndPaint: Boolean;
40772 begin
40773 Result := False;
40775 case Msg.message of
40777 WM_SETTEXT:
40778 begin
40779 LCaption := PChar( Msg.lParam );
40780 if LCaption <> Self_.fCaption then
40781 begin
40782 if Self_.fCaption <> nil then
40783 FreeMem( Self_.fCaption );
40784 GetMem( Self_.fCaption, StrLen( LCaption ) + 1 );
40785 StrCopy( Self_.fCaption, LCaption );
40786 end;
40787 Result := True;
40788 Rslt := 1;
40789 Exit;
40790 end;
40792 WM_PRINTCLIENT, WM_PAINT:
40793 begin
40794 OldPaintDC := Self_.fPaintDC;
40795 Self_.fPaintDC := Msg.wParam;
40796 if Self_.fPaintDC = 0 then
40797 Self_.fPaintDC := BeginPaint( Self_.fHandle, PS );
40798 begin
40799 Target := Self_.Canvas;
40800 Txt := Self_.fCaption;
40801 Target.TextArea( Txt, Sz, P0 );
40802 if Self_.fShadowDeep <> 0 then
40803 begin
40804 for B := False to Self_.fCtl3D do
40805 begin
40806 Inc( Sz.cx, Abs( Self_.fShadowDeep ) );
40807 Inc( Sz.cy, Abs( Self_.fShadowDeep ) );
40808 end;
40809 end;
40810 CR := Self_.ClientRect;
40811 case Self_.fTextAlign of
40812 taCenter: P0.x := P0.x + (CR.Right - Sz.cx) div 2;
40813 taRight: P0.x := P0.x + (CR.Right - Sz.cx);
40814 end;
40815 case Self_.fVerticalAlign of
40816 vaCenter: P0.y := P0.y + (CR.Bottom - Sz.cy) div 2;
40817 vaBottom: P0.y := P0.y + (CR.Bottom - Sz.cy);
40818 end;
40819 if Self_.fShadowDeep <> 0 then
40820 begin
40821 if Self_.fColor2 = clNone then
40822 CShadow := ColorsMix(Color2RGB(Self_.fTextColor),Color2RGB(Self_.fColor2))
40823 else
40824 CShadow := Color2RGB( Self_.fColor2 );
40825 if not Self_.fTransparent then
40826 Target.FillRect( CR ); // GDIFlush; for test only
40827 //Target.DeselectHandles;
40828 Target.RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
40829 SetBkMode( Target.fHandle, Windows.TRANSPARENT );
40830 if Self_.fCtl3D then
40831 begin
40832 I := - Self_.fShadowDeep;
40833 Istp := 1;
40834 if Self_.ShadowDeep > 0 then Istp := -1;
40835 repeat
40836 J := - Self_.fShadowDeep;
40837 repeat
40838 if not ( (I=0) and (J=0) ) then
40839 begin
40840 if (I * Istp < 0) and (J * Istp < 0) then
40841 begin
40842 doTextOut( I, J, CShadow );
40843 end;
40844 end;
40845 J := J - Istp;
40846 until J = Self_.fShadowDeep - IStp;
40847 I := I - Istp;
40848 until I = Self_.fShadowDeep - IStp;
40850 else
40851 doTextout( Self_.fShadowDeep, Self_.fShadowdeep, CShadow );
40852 doTextout( 0, 0, Color2RGB(Self_.fTextColor) );
40854 else
40855 begin
40856 //Target.DeselectHandles;
40857 Target.RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
40858 SetBkMode( Target.fHandle, Windows.TRANSPARENT );
40859 //Target.TextRect( CR, P0.x, P0.y, Txt );
40860 doTextout( 0, 0, Color2RGB(Self_.fTextColor) );
40861 end;
40862 end;
40863 if assigned( Self_.fCanvas ) then
40864 Self_.fCanvas.SetHandle( 0 );
40865 if MSg.wParam = 0 then
40866 EndPaint( Self_.fHandle, PS );
40867 Self_.fPaintDC := OldPaintDC;
40868 Rslt := 0;
40869 Result := True;
40870 Exit;
40871 end;
40872 end;
40873 end;
40875 {$IFDEF ASM_VERSION}
40876 //[procedure TControl.DoClick]
40877 procedure TControl.DoClick;
40879 PUSH EAX
40880 CALL [EAX].fControlClick
40881 POP EDX
40883 MOV ECX, [EDX].fOnClick.TMethod.Code
40884 JECXZ @@exit
40885 MOV EAX, [EDX].fOnClick.TMethod.Data
40886 CALL ECX
40887 @@exit:
40888 end;
40889 {$ELSE ASM_VERSION} //Pascal
40890 procedure TControl.DoClick;
40891 begin
40892 fControlClick( @Self );
40893 if Assigned( fOnClick ) then
40894 fOnClick( @Self );
40895 end;
40896 {$ENDIF ASM_VERSION}
40898 {$IFDEF ASM_VERSION}
40899 //[function TControl.ParentForm]
40900 function TControl.ParentForm: PControl;
40902 @@1: CMP [EAX].fIsControl, 0
40903 JZ @@exit
40904 MOV EAX, [EAX].fParent
40905 TEST EAX, EAX
40906 JNZ @@1
40907 @@exit:
40908 end;
40909 {$ELSE ASM_VERSION} //Pascal
40910 function TControl.ParentForm: PControl;
40911 begin
40912 Result := @Self;
40913 if Result.fIsControl then
40914 repeat
40915 Result := Result.fParent;
40916 until (Result = nil) or not Result.fIsControl;
40917 end;
40918 {$ENDIF ASM_VERSION}
40920 {$IFDEF ASM_VERSION}
40921 //[procedure TControl.SetProgressColor]
40922 procedure TControl.SetProgressColor(const Value: TColor);
40924 PUSH EDX
40925 PUSH EAX
40926 MOV EAX, EDX
40927 CALL Color2RGB
40928 POP EDX
40929 PUSH EDX
40930 PUSH EAX
40931 PUSH 0
40932 PUSH PBM_SETBARCOLOR
40933 PUSH EDX
40934 CALL Perform
40935 TEST EAX, EAX
40936 POP EAX
40937 POP EDX
40938 JZ @@exit
40939 MOV [EAX].fTextColor, EDX
40940 @@exit:
40941 end;
40942 {$ELSE ASM_VERSION} //Pascal
40943 procedure TControl.SetProgressColor(const Value: TColor);
40944 begin
40945 if Perform( PBM_SETBARCOLOR, 0, Color2RGB(Value) ) <> 0 then
40946 fTextColor := Value;
40947 end;
40948 {$ENDIF ASM_VERSION}
40950 //[procedure TControl.SetShadowDeep]
40951 procedure TControl.SetShadowDeep(const Value: Integer);
40952 begin
40953 fShadowDeep := Value;
40954 Invalidate;
40955 end;
40957 {$IFDEF ASM_VERSION}
40958 //[function TControl.GetFont]
40959 function TControl.GetFont: PGraphicTool;
40961 MOV ECX, [EAX].FFont
40962 INC ECX
40963 LOOP @@exit
40964 PUSH EAX
40965 CALL NewFont
40966 POP EDX
40967 MOV [EDX].FFont, EAX
40968 MOV ECX, [EDX].fTextColor
40969 MOV [EAX].TGraphicTool.fData.Color, ECX
40970 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[FontChanged]
40971 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
40973 @@exit: XCHG EAX, ECX
40974 end;
40975 {$ELSE ASM_VERSION} //Pascal
40976 function TControl.GetFont: PGraphicTool;
40977 begin
40978 if FFont = nil then
40979 begin
40980 FFont := NewFont;
40981 FFont.fData.Color := fTextColor;
40982 FFont.OnChange := FontChanged;
40983 end;
40984 Result := FFont;
40985 end;
40986 {$ENDIF ASM_VERSION}
40988 {$IFDEF ASM_VERSION}
40989 //[function TControl.GetBrush]
40990 function TControl.GetBrush: PGraphicTool;
40992 MOV ECX, [EAX].FBrush
40993 INC ECX
40994 LOOP @@exit
40995 PUSH EAX
40996 CALL NewBrush
40997 POP EDX
40998 MOV [EDX].FBrush, EAX
40999 MOV ECX, [EDX].fColor
41000 MOV [EAX].TGraphicTool.fData.Color, ECX
41001 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[BrushChanged]
41002 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
41004 @@exit: XCHG EAX, ECX
41005 end;
41006 {$ELSE ASM_VERSION} //Pascal
41007 function TControl.GetBrush: PGraphicTool;
41008 begin
41009 if FBrush = nil then
41010 begin
41011 FBrush := NewBrush;
41012 FBrush.fData.Color := fColor;
41013 FBrush.OnChange := BrushChanged;
41014 end;
41015 Result := FBrush;
41016 end;
41017 {$ENDIF ASM_VERSION}
41019 {$IFDEF ASM_VERSION}
41020 //[procedure TControl.FontChanged]
41021 procedure TControl.FontChanged(Sender: PGraphicTool);
41023 MOV ECX, [EDX].TGraphicTool.fData.Color
41024 MOV [EAX].fTextColor, ECX
41025 PUSH EAX
41026 CALL ApplyFont2Wnd
41027 POP EAX
41028 CALL Invalidate
41029 end;
41030 {$ELSE ASM_VERSION} //Pascal
41031 procedure TControl.FontChanged(Sender: PGraphicTool);
41032 begin
41033 fTextColor := Sender.fData.Color;
41034 ApplyFont2Wnd;
41035 Invalidate;
41036 end;
41037 {$ENDIF ASM_VERSION}
41039 {$IFDEF ASM_VERSION}
41040 //[procedure TControl.BrushChanged]
41041 procedure TControl.BrushChanged(Sender: PGraphicTool);
41043 MOV ECX, [EDX].TGraphicTool.fData.Color
41044 MOV [EAX].fColor, ECX
41045 XOR ECX, ECX
41046 XCHG ECX, [EAX].fTmpBrush
41047 JECXZ @@inv
41048 PUSH EAX
41049 PUSH ECX
41050 CALL DeleteObject
41051 POP EAX
41052 @@inv: CALL Invalidate
41053 end;
41054 {$ELSE ASM_VERSION} //Pascal
41055 procedure TControl.BrushChanged(Sender: PGraphicTool);
41056 begin
41057 fColor := Sender.fData.Color;
41058 if fTmpBrush <> 0 then
41059 begin
41060 DeleteObject( fTmpBrush );
41061 fTmpBrush := 0;
41062 end;
41063 if fPaintDC = 0 then
41064 // only if not in painting already :
41065 Invalidate;
41066 end;
41067 {$ENDIF ASM_VERSION}
41069 {$IFDEF ASM_VERSION}
41070 //[procedure TControl.ApplyFont2Wnd]
41071 procedure TControl.ApplyFont2Wnd;
41073 PUSH EBX
41074 XCHG EBX, EAX
41076 MOV ECX, [EBX].fFont
41077 JECXZ @@exit
41078 XCHG EAX, ECX
41080 MOV ECX, [EBX].fHandle
41081 JECXZ @@0
41083 MOV EDX, [EAX].TGraphicTool.fData.Color
41084 MOV [EBX].fTextColor, EDX
41086 PUSH $FFFF
41087 CALL TGraphicTool.GetHandle
41088 PUSH EAX
41089 PUSH WM_SETFONT
41090 PUSH EBX
41091 CALL Perform
41093 @@0:
41094 XOR ECX, ECX
41095 XCHG ECX, [EBX].fCanvas
41096 JECXZ @@1
41098 XCHG EAX, ECX
41099 CALL TObj.Free
41100 @@1:
41101 MOV ECX, [EBX].fAutoSize
41102 JECXZ @@exit
41103 XCHG EAX, EBX
41104 CALL ECX
41105 @@exit:
41106 POP EBX
41107 end;
41108 {$ELSE ASM_VERSION} //Pascal
41109 procedure TControl.ApplyFont2Wnd;
41110 begin
41111 if fFont <> nil then
41112 begin
41113 if fHandle <> 0 then
41114 begin
41115 fTextColor := fFont.fData.Color;
41116 Perform( WM_SETFONT, FFont.Handle, 1 );
41117 end;
41119 if fCanvas <> nil then
41120 begin
41121 fCanvas.Free;
41122 fCanvas := nil;
41123 end;
41125 if Assigned( fAutoSize ) then
41126 fAutoSize( @Self );
41127 //if assigned( fCanvas ) then
41128 // {fCanvas.fFont :=} fCanvas.fFont.Assign( fFont );
41129 end;
41130 end;
41131 {$ENDIF ASM_VERSION}
41133 {$IFDEF ASM_VERSION}
41134 //[function TControl.ResizeParent]
41135 function TControl.ResizeParent: PControl;
41137 LEA EDX, [TControl.ResizeParentRight]
41138 PUSH EDX
41139 CALL EDX
41140 CALL TControl.ResizeParentBottom
41141 end;
41142 {$ELSE ASM_VERSION} //Pascal
41143 function TControl.ResizeParent: PControl;
41144 begin
41145 ResizeParentBottom;
41146 ResizeParentRight;
41147 // Once again, to fix Windows (or my???) bug with
41148 // incorrect calculating of GetClientRect after
41149 // SetWindowLong( GWL_[EX}STYLE,... )
41150 Result := ResizeParentBottom;
41151 end;
41152 {$ENDIF ASM_VERSION}
41154 {$IFDEF ASM_VERSION}
41155 //[function TControl.ResizeParentBottom]
41156 function TControl.ResizeParentBottom: PControl;
41158 PUSH EAX
41159 PUSH EBX
41160 MOV EBX, [EAX].fParent
41161 TEST EBX, EBX
41162 JZ @@exit
41164 MOV EDX, [EAX].fBoundsRect.Bottom
41165 ADD EDX, [EBX].fMargin
41167 TEST [EBX].fChangedPosSz, 20h
41168 JZ @@1
41170 PUSH EDX
41171 MOV EAX, EBX
41172 CALL GetClientHeight
41173 POP EDX
41175 CMP EDX, EAX
41176 JLE @@exit
41177 @@1:
41178 MOV EAX, EBX
41179 CALL TControl.SetClientHeight
41180 OR [EBX].fChangedPosSz, 20h
41181 @@exit:
41182 POP EBX
41183 POP EAX
41184 end;
41185 {$ELSE ASM_VERSION} //Pascal
41186 function TControl.ResizeParentBottom: PControl;
41187 var NewCH: Integer;
41188 begin
41189 Result := @Self;
41190 if fParent <> nil then
41191 begin
41192 NewCH := BoundsRect.Bottom + fParent.fMargin;
41193 if (fParent.fChangedPosSz and $20) <> 0 then
41194 if NewCH < fParent.ClientHeight then Exit;
41195 fParent.ClientHeight := NewCH;
41196 fParent.fChangedPosSz := fParent.fChangedPosSz or $20;
41197 end;
41198 end;
41199 {$ENDIF ASM_VERSION}
41201 {$IFDEF ASM_VERSION}
41202 //[function TControl.ResizeParentRight]
41203 function TControl.ResizeParentRight: PControl;
41205 PUSH EAX
41206 PUSH EBX
41207 MOV EBX, [EAX].fParent
41208 TEST EBX, EBX
41209 JZ @@exit
41211 MOV EDX, [EAX].fBoundsRect.Right
41212 ADD EDX, [EBX].fMargin
41214 TEST [EBX].fChangedPosSz, 10h
41215 JZ @@1
41217 PUSH EDX
41218 MOV EAX, EBX
41219 CALL GetClientWidth
41220 POP EDX
41222 CMP EDX, EAX
41223 JLE @@exit
41224 @@1:
41225 MOV EAX, EBX
41226 CALL TControl.SetClientWidth
41227 OR [EBX].fChangedPosSz, 10h
41228 @@exit:
41229 POP EBX
41230 POP EAX
41231 end;
41232 {$ELSE ASM_VERSION} //Pascal
41233 function TControl.ResizeParentRight: PControl;
41234 var NewCW: Integer;
41235 begin
41236 Result := @Self;
41237 if fParent <> nil then
41238 begin
41239 NewCW := fBoundsRect.Right + fParent.fMargin;
41240 if (fParent.fChangedPosSz and $10) <> 0 then
41241 if NewCW < fParent.ClientWidth then Exit;
41242 fParent.ClientWidth := NewCW;
41243 fParent.fChangedPosSz := fParent.fChangedPosSz or $10;
41244 end;
41245 end;
41246 {$ENDIF ASM_VERSION}
41248 {$IFDEF ASM_VERSION}
41249 //[function TControl.GetClientHeight]
41250 function TControl.GetClientHeight: Integer;
41252 ADD ESP, -size_TRect
41253 MOV EDX, ESP
41254 CALL TControl.ClientRect
41255 POP EDX
41256 POP ECX // Top
41257 POP EDX
41258 POP EAX // Bottom
41259 SUB EAX, ECX // Result = Bottom - Top
41260 end;
41261 {$ELSE ASM_VERSION} //Pascal
41262 function TControl.GetClientHeight: Integer;
41263 begin
41264 with ClientRect do
41265 Result := Bottom - Top;
41266 end;
41267 {$ENDIF ASM_VERSION}
41269 {$IFDEF ASM_VERSION}
41270 //[function TControl.GetClientWidth]
41271 function TControl.GetClientWidth: Integer;
41273 ADD ESP, -size_TRect
41274 MOV EDX, ESP
41275 CALL TControl.ClientRect
41276 POP ECX // Left
41277 POP EDX
41278 POP EAX // Right
41279 SUB EAX, ECX // Result = Right - Left
41280 POP EDX
41281 end;
41282 {$ELSE ASM_VERSION} //Pascal
41283 function TControl.GetClientWidth: Integer;
41284 begin
41285 with ClientRect do
41286 Result := Right - Left;
41287 end;
41288 {$ENDIF ASM_VERSION}
41290 {$IFDEF ASM_VERSION}
41291 //[procedure TControl.SetClientHeight]
41292 procedure TControl.SetClientHeight(const Value: Integer);
41294 PUSH EBX
41295 PUSH EDX
41297 MOV EBX, EAX
41298 CALL TControl.GetClientHeight
41299 PUSH EAX
41300 MOV EAX, EBX
41301 CALL TControl.GetHeight // EAX = Height
41303 POP EDX // EDX = ClientHeight
41304 SUB EAX, EDX // EAX = Delta
41305 POP EDX // EDX = Value
41306 ADD EDX, EAX // EDX = Value + Delta
41307 XCHG EAX, EBX // EAX = @Self
41308 CALL TControl.SetHeight
41309 POP EBX
41310 end;
41311 {$ELSE ASM_VERSION} //Pascal
41312 procedure TControl.SetClientHeight(const Value: Integer);
41313 var Delta: Integer;
41314 begin
41315 Delta := ClientHeight;
41316 Delta := Height - Delta;
41317 Height := Value + Delta;
41318 end;
41319 {$ENDIF ASM_VERSION}
41321 {$IFDEF ASM_VERSION}
41322 //[procedure TControl.SetClientWidth]
41323 procedure TControl.SetClientWidth(const Value: Integer);
41325 PUSH EBX
41326 PUSH EDX
41328 MOV EBX, EAX
41329 CALL TControl.GetClientWidth
41330 PUSH EAX
41331 MOV EAX, EBX
41332 CALL TControl.GetWidth // EAX = Width
41334 POP EDX // EDX = ClientWidth
41335 SUB EAX, EDX // EAX = Width - ClientWidth
41336 POP EDX // EDX = Value
41337 ADD EDX, EAX // EDX = Value + Delta
41338 XCHG EAX, EBX // EAX = @Self
41339 CALL TControl.SetWidth
41340 POP EBX
41341 end;
41342 {$ELSE ASM_VERSION} //Pascal
41343 procedure TControl.SetClientWidth(const Value: Integer);
41344 var Delta: Integer;
41345 begin
41346 Delta := ClientWidth;
41347 Delta := Width - Delta;
41348 Width := Value + Delta;
41349 end;
41350 {$ENDIF ASM_VERSION}
41352 {$IFDEF ASM_VERSION}
41353 //[function TControl.CenterOnParent]
41354 function TControl.CenterOnParent: PControl;
41356 PUSHAD
41358 XCHG ESI, EAX
41359 MOV ECX, [ESI].fParent
41360 JECXZ @@1
41361 CMP [ESI].fIsControl, 0
41362 JNZ @@2
41364 @@1:
41365 PUSH SM_CYSCREEN
41366 CALL GetSystemMetrics
41367 PUSH EAX
41369 PUSH SM_CXSCREEN
41370 CALL GetSystemMetrics
41371 PUSH EAX
41373 PUSH 0
41374 PUSH 0 // ESP -> Rect( 0, 0, CX, CY )
41376 JMP @@3
41378 @@2: ADD ESP, -size_TRect
41379 MOV EDX, ESP
41380 XCHG EAX, ECX
41381 CALL TControl.ClientRect
41382 // ESP -> ClientRect
41383 @@3: MOV EAX, ESI
41384 CALL GetWindowHandle
41386 MOV EAX, ESI
41387 CALL GetWidth
41389 POP EDX // left
41390 ADD EAX, EDX // + width
41392 POP EDI // top
41393 POP EDX // right
41395 SUB EDX, EAX
41396 SAR EDX, 1
41398 MOV EAX, ESI
41399 CALL SetLeft
41401 MOV EAX, ESI
41402 CALL GetHeight
41404 ADD EAX, EDI // height + top
41406 POP EDX // bottom
41407 SUB EDX, EAX
41408 SAR EDX, 1
41410 XCHG EAX, ESI
41411 CALL SetTop
41413 POPAD
41414 end;
41415 {$ELSE ASM_VERSION} //Pascal
41416 function TControl.CenterOnParent: PControl;
41417 var PCR: TRect;
41418 begin
41419 Result := @Self;
41420 if (fParent = nil) or not fIsControl then
41421 PCR := MakeRect( 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) )
41422 else
41423 PCR := fParent.ClientRect;
41424 GetWindowHandle;
41425 Left := (PCR.Right - PCR.Left - Width) div 2;
41426 Top := (PCR.Bottom - PCR.Top - Height) div 2;
41427 end;
41428 {$ENDIF ASM_VERSION}
41430 {$IFDEF ASM_noVERSION}
41431 //[function TControl.GetHasBorder]
41432 function TControl.GetHasBorder: Boolean;
41433 const style_mask = WS_BORDER or WS_THICKFRAME or WS_DLGFRAME;
41435 CALL UpdateWndStyles
41436 MOV EAX, [EAX].fStyle
41437 AND EAX, style_mask
41438 SETNZ AL
41439 end;
41440 {$ELSE ASM_VERSION} //Pascal
41441 function TControl.GetHasBorder: Boolean;
41442 begin
41443 UpdateWndStyles;
41444 Result := LongBool( fStyle and (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME))
41445 or LongBool( fExStyle and WS_EX_CLIENTEDGE );
41446 end;
41447 {$ENDIF ASM_VERSION}
41449 {$IFDEF ASM_noVERSION} // YS
41450 //[procedure TControl.SetHasBorder]
41451 procedure TControl.SetHasBorder(const Value: Boolean);
41452 const style_mask = WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION
41453 or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU;
41454 exstyle_mask = not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME
41455 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);
41458 PUSH EAX
41459 PUSH EDX
41461 CALL GetHasBorder
41462 POP ECX
41463 CMP AL, CL
41465 POP EAX
41466 JZ @@exit
41468 MOV EDX, [EAX].fStyle
41469 DEC CL
41470 MOVZX ECX, [EAX].fIsControl
41471 JNZ @@1
41473 OR EDX, WS_THICKFRAME
41474 INC ECX
41475 LOOP @@set_style
41476 OR EDX, style_mask
41477 JMP @@set_style
41479 @@1: AND EDX, not style_mask
41480 INC ECX
41481 LOOP @@2
41482 OR EDX, WS_POPUP
41484 @@2: PUSH EDX
41486 MOV EDX, [EAX].fExStyle
41487 AND EDX, exstyle_mask
41489 PUSH EAX
41490 CALL SetExStyle
41491 POP EAX
41493 POP EDX
41494 @@set_style:
41495 CALL SetStyle
41496 @@exit:
41497 end;
41498 {$ELSE ASM_VERSION} //Pascal
41499 procedure TControl.SetHasBorder(const Value: Boolean);
41500 var NewStyle: DWORD;
41501 begin
41502 if Value = GetHasBorder then Exit;
41503 {if Value then
41504 begin
41505 NewStyle := fStyle or WS_THICKFRAME;
41506 if not fIsControl then
41507 NewStyle := NewStyle or WS_BORDER or
41508 WS_DLGFRAME or WS_CAPTION or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
41509 WS_SYSMENU;
41510 Style := NewStyle;
41511 end}
41512 if Value then
41513 begin
41514 if not fIsControl then
41515 Style := fStyle or WS_THICKFRAME or WS_BORDER or
41516 WS_DLGFRAME or WS_CAPTION or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
41517 WS_SYSMENU
41518 else
41519 if fCtl3D then
41520 ExStyle := fExStyle or WS_EX_CLIENTEDGE
41521 else
41522 Style := fStyle or WS_BORDER;
41524 else
41525 begin
41526 NewStyle := fStyle and not (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION
41527 or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU);
41528 if not fIsControl then NewStyle := NewStyle or WS_POPUP;
41529 Style := NewStyle;
41530 ExStyle := fExStyle and not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME
41531 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);
41532 end;
41533 end;
41534 {$ENDIF ASM_VERSION}
41536 {$IFDEF ASM_VERSION}
41537 //[function TControl.GetHasCaption]
41538 function TControl.GetHasCaption: Boolean;
41539 const style_mask1 = (WS_POPUP or WS_DLGFRAME) shr 16;
41540 style_mask2 = WS_CAPTION shr 16;
41542 CALL UpdateWndStyles
41543 MOV ECX, [EAX].fStyle + 2
41544 MOV EDX, ECX
41545 MOV AL, 1
41546 AND DX, style_mask1
41547 JZ @@1
41548 AND CX, style_mask2
41549 JNZ @@1
41550 XOR EAX, EAX
41551 @@1:
41552 end;
41553 {$ELSE ASM_VERSION} //Pascal
41554 function TControl.GetHasCaption: Boolean;
41555 begin
41556 UpdateWndStyles;
41557 Result := not LongBool( fStyle and (WS_POPUP or WS_DLGFRAME))
41558 or LongBool( fStyle and WS_CAPTION);
41559 end;
41560 {$ENDIF ASM_VERSION}
41562 {$IFDEF ASM_VERSION}
41563 //[procedure TControl.SetHasCaption]
41564 procedure TControl.SetHasCaption(const Value: Boolean);
41565 const style_mask = not (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION
41566 or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU);
41567 exstyle_mask = not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME
41568 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);
41570 PUSH EAX
41571 PUSH EDX
41573 CALL GetHasCaption
41574 POP ECX
41575 CMP AL, CL
41577 POP EAX
41578 JZ @@exit // Value = HasCaption
41580 MOV EDX, [EAX].fStyle
41581 DEC CL
41582 JNZ @@1 // if not Value -> @@1
41584 AND EDX, not WS_POPUP
41585 OR EDX, WS_CAPTION
41586 JMP @@set_style
41588 @@1:
41589 CMP [EAX].fIsControl, 0
41590 JNZ @@2 // if fIsControl -> @@2
41592 AND EDX, not (WS_CAPTION or WS_SYSMENU)
41593 OR EDX, WS_POPUP
41594 JMP @@3
41596 @@2:
41597 AND EDX, not WS_CAPTION
41598 OR EDX, WS_DLGFRAME
41600 @@3:
41601 PUSH EDX
41603 MOV EDX, [EAX].fExStyle
41604 OR EDX, WS_EX_DLGMODALFRAME
41606 PUSH EAX
41607 CALL SetExStyle
41608 POP EAX
41610 POP EDX
41611 @@set_style:
41612 CALL SetStyle
41613 @@exit:
41614 end;
41615 {$ELSE ASM_VERSION} //Pascal
41616 procedure TControl.SetHasCaption(const Value: Boolean);
41617 begin
41618 if Value = GetHasCaption then Exit;
41619 if Value then
41620 begin
41621 Style := fStyle and not (WS_POPUP or WS_DLGFRAME) or WS_CAPTION;
41623 else
41624 begin
41625 if fIsControl then
41626 Style := fStyle and not WS_CAPTION or WS_DLGFRAME
41627 else
41628 Style := fStyle and not (WS_CAPTION or WS_SYSMENU) or WS_POPUP;
41629 ExStyle := fExStyle or WS_EX_DLGMODALFRAME;
41630 end;
41631 end;
41632 {$ENDIF ASM_VERSION}
41634 {$IFDEF ASM_VERSION}
41635 //[function TControl.GetCanResize]
41636 function TControl.GetCanResize: Boolean;
41638 MOV AL, [EAX].fPreventResize
41639 {$IFDEF PARANOIA}
41640 DB $34,$01
41641 {$ELSE}
41642 XOR AL, 1
41643 {$ENDIF}
41644 end;
41645 {$ELSE ASM_VERSION} //Pascal
41646 function TControl.GetCanResize: Boolean;
41647 begin
41648 //UpdateWndStyles;
41649 //Result := LongBool( fStyle and WS_THICKFRAME);
41650 Result := not fPreventResize;
41651 end;
41652 {$ENDIF ASM_VERSION}
41654 //[function WndProcCanResize]
41655 function WndProcCanResize( Sender: PControl; var M: TMsg; var Rslt: Integer ): Boolean;
41656 var W, H: Integer;
41657 P: PMinMaxInfo;
41658 begin
41659 if not Sender.CanResize then
41660 if M.message = WM_GETMINMAXINFO then
41661 begin
41662 Rslt := Sender.CallDefWndProc( M );
41663 W := Sender.FFixWidth;
41664 H := Sender.FFixHeight;
41665 P := Pointer( M.lParam );
41666 P.ptMinTrackSize.x := W;
41667 P.ptMinTrackSize.y := H;
41668 P.ptMaxTrackSize := P.ptMinTrackSize;
41669 Result := True; // stop further processing (prevent resizing)
41670 Exit;
41672 else
41673 if M.message = WM_NCHITTEST then
41674 begin
41675 Rslt := Sender.CallDefWndProc( M );
41676 if (Rslt >= 10) and (Rslt <= 17) then
41677 begin
41678 Rslt := {-}HTBORDER{+}{++}(*18{HTBORDER}*){--};
41679 Result := True;
41680 exit;
41681 end;
41682 end;
41683 Result := False; // continue message processing
41684 end;
41686 {$IFDEF ASM_VERSION}
41687 //[procedure TControl.SetCanResize]
41688 procedure TControl.SetCanResize( const Value: Boolean );
41690 PUSH EBX
41691 MOV EBX, EAX
41693 CALL GetCanResize
41694 CMP AL, DL
41696 JZ @@exit // Value = CanResize
41697 MOV [EBX].fPreventResize, AL
41698 TEST DL, DL
41700 MOV EDX, [EBX].fStyle
41701 JZ @@set_thick
41703 OR EDX, WS_THICKFRAME
41704 JMP @@set_style
41706 @@set_thick:
41707 AND EDX, not WS_THICKFRAME
41709 @@set_style:
41710 MOV EAX, EBX
41711 CALL SetStyle
41713 MOV EAX, EBX
41714 CALL GetWindowHandle
41716 MOV EAX, EBX
41717 CALL GetWidth
41718 MOV [EBX].FFixWidth, EAX
41720 MOV EAX, EBX
41721 CALL GetHeight
41722 MOV [EBX].FFixHeight, EAX
41724 XCHG EAX, EBX
41725 MOV EDX, offset[WndProcCanResize]
41726 CALL TControl.AttachProc
41727 @@exit:
41728 POP EBX
41729 end;
41730 {$ELSE ASM_VERSION} //Pascal
41731 procedure TControl.SetCanResize( const Value: Boolean );
41732 begin
41733 if Value = CanResize then Exit;
41734 fPreventResize := not Value;
41735 if Value then
41736 Style := Style or WS_THICKFRAME
41737 else
41738 Style := Style and not WS_THICKFRAME;
41739 GetWindowHandle;
41740 FFixWidth := Width;
41741 FFixHeight := Height;
41742 AttachProc( WndProcCanResize );
41743 end;
41744 {$ENDIF ASM_VERSION}
41746 {$IFDEF ASM_VERSION}
41747 //[function TControl.GetStayOnTop]
41748 function TControl.GetStayOnTop: Boolean;
41750 CALL UpdateWndStyles
41751 TEST byte ptr [EAX].fExStyle, WS_EX_TOPMOST
41752 SETNZ AL
41753 end;
41754 {$ELSE ASM_VERSION} //Pascal
41755 function TControl.GetStayOnTop: Boolean;
41756 begin
41757 UpdateWndStyles;
41758 Result := LongBool( fExStyle and WS_EX_TOPMOST);
41759 end;
41760 {$ENDIF ASM_VERSION}
41762 {$IFDEF ASM_VERSION}
41763 //[procedure TControl.SetStayOnTop]
41764 procedure TControl.SetStayOnTop(const Value: Boolean);
41766 PUSH EAX
41767 PUSH EDX
41769 CALL GetStayOnTop
41770 POP ECX
41771 MOVZX ECX, CL
41772 CMP AL, CL
41774 POP EAX
41775 JZ @@exit // Value = StayOnTop
41777 MOV EDX, [EAX].fHandle
41778 TEST EDX, EDX
41779 JZ @@1
41781 PUSH SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE
41782 XOR EAX, EAX
41783 PUSH EAX
41784 PUSH EAX
41785 PUSH EAX
41786 PUSH EAX
41787 DEC ECX
41788 DEC ECX
41789 PUSH ECX
41791 PUSH EDX
41792 CALL SetWindowPos
41795 @@1:
41796 JECXZ @@1and
41798 OR byte ptr [EAX].fExStyle, WS_EX_TOPMOST
41801 @@1and: AND byte ptr [EAX].fExStyle, not WS_EX_TOPMOST
41803 @@exit:
41804 end;
41805 {$ELSE ASM_VERSION} //Pascal
41806 procedure TControl.SetStayOnTop(const Value: Boolean);
41807 begin
41808 if Value = GetStayOnTop then Exit;
41809 if fHandle <> 0 then
41810 if Value then
41811 SetWindowPos( fHandle, HWND_TOPMOST, 0,0,0,0,
41812 SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE )
41813 else
41814 SetWindowPos( fHandle, HWND_NOTOPMOST, 0,0,0,0,
41815 SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE )
41816 else
41817 if Value then fExStyle := fExStyle or WS_EX_TOPMOST
41818 else fExStyle := fExStyle and not WS_EX_TOPMOST;
41819 end;
41820 {$ENDIF ASM_VERSION}
41822 {$IFDEF ASM_VERSION}
41823 //[function TControl.UpdateWndStyles]
41824 function TControl.UpdateWndStyles: PControl;
41826 MOV ECX, [EAX].fHandle
41827 JECXZ @@exit
41829 PUSH EBX
41831 XCHG EBX, EAX
41832 PUSH GCL_STYLE
41833 PUSH ECX
41835 PUSH GWL_EXSTYLE
41836 PUSH ECX
41838 PUSH GWL_STYLE
41839 PUSH ECX
41841 CALL GetWindowLong
41842 MOV [EBX].fStyle, EAX
41844 CALL GetWindowLong
41845 MOV [EBX].fExStyle, EAX
41847 CALL GetClassLong
41848 MOV [EBX].fClsStyle, EAX
41849 XCHG EAX, EBX
41850 POP EBX
41851 @@exit:
41852 end;
41853 {$ELSE ASM_VERSION} //Pascal
41854 function TControl.UpdateWndStyles: PControl;
41855 begin
41856 Result := @Self;
41857 if fHandle = 0 then Exit;
41858 fStyle := GetWindowLong( fHandle, GWL_STYLE );
41859 fExStyle := GetWindowLong( fHandle, GWL_EXSTYLE );
41860 fClsStyle := GetClassLong( fHandle, GCL_STYLE );
41861 end;
41862 {$ENDIF ASM_VERSION}
41864 {$IFDEF ASM_VERSION}
41865 //[function TControl.GetChecked]
41866 function TControl.GetChecked: Boolean;
41868 TEST [EAX].fBitBtnOptions, 8 //1 shl Ord(bboFixed)
41869 JZ @@1
41870 MOV AL, [EAX].fChecked
41872 @@1:
41873 PUSH 0
41874 PUSH 0
41875 PUSH BM_GETCHECK
41876 PUSH EAX
41877 CALL Perform
41878 @@exit:
41879 end;
41880 {$ELSE ASM_VERSION} //Pascal
41881 function TControl.GetChecked: Boolean;
41882 begin
41883 if bboFixed in fBitBtnOptions then
41884 Result := fChecked
41885 else
41886 Result := LongBool( Perform( BM_GETCHECK, 0, 0 ) ) ; //= BST_CHECKED;
41887 end;
41888 {$ENDIF ASM_VERSION}
41890 {$IFDEF ASM_VERSION}
41891 //[procedure TControl.Set_Checked]
41892 procedure TControl.Set_Checked(const Value: Boolean);
41894 TEST [EAX].fBitBtnOptions, 8 //1 shl Ord(bboFixed)
41895 JZ @@1
41896 MOV [EAX].fChecked, DL
41897 JMP Invalidate
41898 @@1:
41899 PUSH 0
41900 MOVZX EDX, DL
41901 PUSH EDX
41902 PUSH BM_SETCHECK
41903 PUSH EAX
41904 Call Perform
41905 end;
41906 {$ELSE ASM_VERSION} //Pascal
41907 procedure TControl.Set_Checked(const Value: Boolean);
41908 begin
41909 if bboFixed in fBitBtnOptions then
41910 begin
41911 fChecked := //not fChecked;
41912 Value;
41913 Invalidate;
41915 else
41916 Perform( BM_SETCHECK, Integer( Value ), 0 );
41917 end;
41918 {$ENDIF ASM_VERSION}
41920 //[function TControl.SetChecked]
41921 function TControl.SetChecked(const Value: Boolean): PControl;
41922 begin
41923 Perform( BM_SETCHECK, Integer( Value ), 0 );
41924 Result := @Self;
41925 end;
41927 {$IFDEF ASM_VERSION}
41928 //[function TControl.SetRadioCheckedOld]
41929 function TControl.SetRadioCheckedOld: PControl;
41931 PUSH EAX
41932 MOV ECX, [EAX].fParent
41933 JECXZ @@exit
41935 PUSH [EAX].fMenu
41936 PUSH [ECX].fRadioLast
41937 PUSH [ECX].fRadio1st
41938 MOV EAX, ECX
41939 CALL GetWindowHandle
41940 PUSH EAX
41941 CALL CheckRadioButton
41942 @@exit:
41943 POP EAX
41944 end;
41945 {$ELSE ASM_VERSION} //Pascal
41946 function TControl.SetRadioCheckedOld: PControl;
41947 begin
41948 Result := @Self;
41949 if fParent = nil then Exit;
41950 CheckRadioButton( fParent.GetWindowHandle,
41951 fParent.fRadio1st,
41952 fParent.fRadioLast,
41953 fMenu );
41954 end;
41955 {$ENDIF ASM_VERSION}
41958 //[function TControl.SetRadioChecked]
41959 function TControl.SetRadioChecked: PControl;
41960 begin
41961 Click;
41962 Result := @Self;
41963 end;
41966 //[procedure TControl.Click]
41967 procedure TControl.Click;
41968 begin
41969 if (fCommandActions.aClick <> 0) or
41970 (fCommandActions.aEnter = BN_SETFOCUS) then
41971 Perform( WM_COMMAND, (fCommandActions.aClick shl 16) or fMenu,
41972 GetWindowHandle )
41973 else
41974 begin
41975 Perform( WM_LBUTTONDOWN, MK_LBUTTON, 0 );
41976 Perform( WM_LBUTTONUP, MK_LBUTTON, 0 );
41977 end;
41978 end;
41980 {$IFDEF ASM_VERSION}
41981 //[function TControl.GetSelStart]
41982 function TControl.GetSelStart: Integer;
41984 MOVZX ECX, [EAX].fCommandActions.aGetSelRange
41985 JECXZ @@1
41987 XOR EDX, EDX
41988 PUSH EDX
41989 PUSH EDX
41990 PUSH ECX
41991 PUSH EAX
41992 CALL Perform
41993 CWDE
41996 @@1:
41997 MOVZX ECX, [EAX].fCommandActions.aExGetSelRange
41998 JECXZ @@exit
41999 XCHG EAX, ECX
42001 PUSH EDX
42002 PUSH EDX
42003 PUSH ESP
42004 PUSH EDX
42005 PUSH EAX
42006 PUSH ECX
42007 CALL Perform
42008 POP ECX
42009 POP EDX
42011 @@exit:
42012 XCHG EAX, ECX
42013 end;
42014 {$ELSE ASM_VERSION} //Pascal
42015 function TControl.GetSelStart: Integer;
42016 var SR: TCharRange;
42017 begin
42018 Result := 0;
42019 if fCommandActions.aGetSelRange <> 0 then
42020 Result := LoWord( Perform( fCommandActions.aGetSelRange, 0, 0 ) )
42021 else
42022 if fCommandActions.aExGetSelRange <> 0 then
42023 begin
42024 Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );
42025 Result := SR.cpMin;
42026 end;
42027 end;
42028 {$ENDIF ASM_VERSION}
42030 //[procedure TControl.SetSelStart]
42031 procedure TControl.SetSelStart(const Value: Integer);
42032 begin
42033 ItemSelected[ Value ] := True;
42034 end;
42036 {$IFDEF ASM_VERSION}
42037 //[function TControl.GetSelLength]
42038 function TControl.GetSelLength: Integer;
42040 XOR EDX, EDX
42041 MOVZX ECX, word ptr[EAX].fCommandActions.aGetSelCount
42042 JECXZ @@check_ex
42044 PUSH ECX
42045 AND CH, $7F
42046 PUSH EDX
42047 PUSH EDX
42048 PUSH ECX
42049 PUSH EAX
42050 CALL Perform
42051 POP ECX
42052 SHL CH, 1
42053 JC @@fin_EAX
42055 CMP EAX, 32768
42056 JL @@2
42058 PUSH EAX
42059 POP DX
42060 POP AX
42061 SUB AX, DX
42062 MOVZX EAX, AX
42063 @@fin_EAX:
42066 @@check_ex:
42067 MOVZX ECX, [EAX].fCommandActions.aExGetSelRange
42068 JECXZ @@ret_0
42069 PUSH EDX
42070 PUSH EDX
42071 PUSH ESP
42072 PUSH EDX
42073 PUSH ECX
42074 PUSH EAX
42075 CALL Perform
42076 POP EDX
42077 POP EAX
42078 SUB EAX, EDX
42081 @@ret_0:
42082 XOR EAX, EAX
42083 //RET
42085 @@2: TEST EAX, EAX
42086 JL @@ret_0
42087 end;
42088 {$ELSE ASM_VERSION} //Pascal
42089 function TControl.GetSelLength: Integer;
42090 var SR: TCharRange;
42091 begin
42092 Result := 0;
42093 if fCommandActions.aGetSelCount <> 0 then
42094 begin
42095 Result := Perform( fCommandActions.aGetSelCount and $7FFF, 0, 0 );
42096 if (fCommandActions.aGetSelCount and $8000) = 0 then
42097 if Result >= 32768 then
42098 Result := HiWord( Result ) - LoWord( Result )
42099 else
42100 if Result < 0 then
42101 Result := 0;
42103 else
42104 if fCommandActions.aExGetSelRange <> 0 then
42105 begin
42106 Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );
42107 Result := SR.cpMax - SR.cpMin;
42108 end;
42109 end;
42110 {$ENDIF ASM_VERSION}
42112 {$IFDEF ASM_VERSION}
42113 //[procedure TControl.SetSelLength]
42114 procedure TControl.SetSelLength(const Value: Integer);
42116 PUSH EBP
42117 MOV EBP, ESP
42118 PUSH EAX
42119 PUSH EDX
42120 CALL GetSelStart
42121 POP ECX
42122 POP EDX
42123 ADD ECX, EAX
42124 PUSH ECX
42125 MOVZX ECX, [EDX].fCommandActions.aSetSelRange
42126 JECXZ @@check_ex
42127 PUSH EAX
42128 JMP @@perform
42130 @@check_ex:
42131 MOVZX ECX, [EDX].fCommandActions.aExSetSelRange
42132 JECXZ @@exit
42133 PUSH EAX
42134 PUSH ESP
42135 PUSH 0
42136 @@perform:
42137 PUSH ECX
42138 PUSH EDX
42139 CALL Perform
42140 @@exit: MOV ESP, EBP
42141 POP EBP
42142 end;
42143 {$ELSE ASM_VERSION} //Pascal
42144 procedure TControl.SetSelLength(const Value: Integer);
42146 SR: TCharRange;
42147 begin
42148 SR.cpMin := GetSelStart;
42149 SR.cpMax := SR.cpMin + Value;
42150 if Value < 0 then
42151 SR.cpMax := -1;
42152 if fCommandActions.aSetSelRange <> 0 then
42153 Perform( fCommandActions.aSetSelRange, SR.cpMin, SR.cpMax )
42154 else
42155 if fCommandActions.aExSetSelRange <> 0 then
42156 Perform( fCommandActions.aExSetSelRange, 0, Integer( @SR ) );
42157 // Preform( EM_SCROLLCARET, 0, 0 );
42158 end;
42159 {$ENDIF ASM_VERSION}
42161 {$IFDEF ASM_VERSION}
42162 //[function TControl.GetItems]
42163 function TControl.GetItems(Idx: Integer): String;
42165 PUSH ESI
42166 PUSH EDI
42167 PUSH EBX
42168 PUSH EBP
42169 MOV EBP, ESP
42171 MOV EBX, EAX // @Self
42172 MOV ESI, EDX // Idx
42173 MOV EDI, ECX // @Result
42175 CALL Item2Pos
42176 PUSH 0 // push 0
42177 PUSH EAX // store Pos
42179 XCHG EDX, EAX
42180 MOV EAX, EBX
42181 CALL Pos2Item // EAX = Idx'
42182 XCHG ESI, EAX // ESI = Idx'
42184 XOR EAX, EAX
42185 MOVZX ECX, [EBX].fCommandActions.aGetItemLength
42186 JECXZ @@ret_empty
42188 PUSH ECX // push aGetItemLength
42190 PUSH EBX
42191 CALL Perform
42193 TEST EAX, EAX
42194 JZ @@ret_empty
42196 PUSH EAX // save L
42197 ADD EAX, 4
42199 CALL System.@GetMem // GetMem( L+4 )
42200 POP EDX // restore L
42201 MOV byte ptr [EAX], 0
42202 MOVZX ECX, [EBX].fCommandActions.aGetItemText
42203 JECXZ @@ret_buf
42205 PUSH EDX // save L
42206 MOV word ptr [EAX], DX
42208 PUSH EAX
42209 PUSH EAX // push Buf
42210 PUSH ESI // push Idx
42212 PUSH ECX // push aGetItemText
42213 PUSH EBX
42214 CALL Perform
42215 POP EAX
42217 POP EDX
42218 @@ret_buf:
42219 MOV byte ptr [EAX + EDX], 0 // Buf[ L ] := #0
42221 @@ret_empty: // EAX = 0
42222 XCHG EDX, EAX
42223 MOV EAX, EDI
42224 PUSH EDX
42225 CALL System.@LStrFromPChar
42226 POP ECX
42227 JECXZ @@exit
42228 XCHG EAX, ECX
42229 CALL System.@FreeMem
42231 @@exit:
42232 MOV ESP, EBP
42233 POP EBP
42234 POP EBX
42235 POP EDI
42236 POP ESI
42237 end;
42238 {$ELSE ASM_VERSION} //Pascal
42239 function TControl.GetItems(Idx: Integer): String;
42240 var L, Pos: Integer;
42241 Buf: PChar;
42242 begin
42243 Result := '';
42244 Pos := Item2Pos( Idx );
42245 Idx := Pos2Item( Pos );
42246 if fCommandActions.aGetItemLength <> 0 then
42247 L := Perform( fCommandActions.aGetItemLength, Pos, 0 )
42248 else
42249 Exit;
42250 if L = 0 then Exit;
42251 GetMem( Buf, L + 4 );
42252 PWORD( Buf )^ := L + 1;
42253 if fCommandActions.aGetItemText <> 0 then
42254 Perform( fCommandActions.aGetItemText, Idx, Integer( Buf ) );
42255 Buf[ L ] := #0;
42256 Result := Buf;
42257 FreeMem( Buf );
42258 end;
42259 {$ENDIF ASM_VERSION}
42261 {$IFDEF ASM_VERSION}
42262 //[procedure TControl.SetItems]
42263 procedure TControl.SetItems(Idx: Integer; const Value: String);
42265 PUSH EDI
42266 PUSH EBX
42267 XCHG EBX, EAX
42268 XCHG EDI, EDX // EDI = Idx
42269 CALL ECX2PChar
42270 PUSH ECX // @Value[1]
42272 MOVZX ECX, [EBX].fCommandActions.aSetItemText
42273 JECXZ @@1
42275 PUSH 0
42276 PUSH ECX
42278 MOV EDX, EDI
42279 MOV EAX, EBX
42280 CALL Item2Pos
42281 PUSH EAX // store Strt
42283 MOV EDX, EDI
42284 INC EDX
42285 MOV EAX, EBX
42286 CALL Item2Pos
42287 POP EDX // EDX = Strt
42289 SUB EAX, EDX
42290 PUSH EAX // store L
42292 MOV EAX, EBX
42293 CALL SetSelStart
42295 POP EDX // EDX = L
42296 PUSH EBX // prepare @Self for Perform
42297 XCHG EAX, EBX
42298 CALL SetSelLength
42300 // @Value[1] already in stack,
42301 // 0 already in stack
42302 // aSetItemText already in stack
42303 // @Self already in stack
42305 CALL Perform
42306 JMP @@exit
42308 @@1: // @Value[1] in stack already
42309 POP EDX
42310 MOVZX ECX, [EBX].fCommandActions.aDeleteItem
42311 JECXZ @@exit
42313 {$IFNDEF NOT_FIX_CURINDEX}
42314 PUSH ESI
42315 PUSH EBP
42317 PUSH EDX
42319 MOV EAX, EBX // +AK
42320 CALL GetCurIndex // +AK
42321 XCHG ESI, EAX // ESI = TmpCurIdx
42323 MOV EAX, EBX
42324 MOV EDX, EDI
42325 CALL GetItemData
42326 XCHG EBP, EAX // EBP = TmpData
42328 MOV EDX, EDI
42329 MOV EAX, EBX
42330 CALL Delete
42332 MOV EAX, EBX // *AK
42333 MOV EDX, EDI
42334 POP ECX
42335 CALL Insert
42337 MOV ECX, EBP // ECX = TmpData
42338 MOV EDX, EDI
42339 MOV EAX, EBX
42340 CALL SetItemData
42342 XCHG EAX, EBX // +AK
42343 MOV EDX, ESI // +AK
42344 CALL SetCurIndex // +AK
42346 POP EBP
42347 POP ESI
42348 {$ELSE NOT_FIX_CURINDEX}
42349 PUSH EDX
42351 MOV EDX, EDI
42352 MOV EAX, EBX
42353 CALL Delete
42355 XCHG EAX, EBX
42356 XCHG EDX, EDI
42358 POP ECX
42359 CALL Insert
42360 {$ENDIF NOT_FIX_CURINDEX}
42362 @@exit:
42363 POP EBX
42364 POP EDI
42365 end;
42366 {$ELSE ASM_VERSION} //Pascal
42367 procedure TControl.SetItems(Idx: Integer; const Value: String);
42368 var Strt, L : Integer;
42369 {$IFNDEF NOT_FIX_CURINDEX}
42370 TmpCurIdx: Integer; // AK - Andrzey Kubasek
42371 TmpData: DWORD;
42372 {$ENDIF NOT_FIX_CURINDEX}
42373 begin
42374 if fCommandActions.aSetItemText <> 0 then
42375 begin
42376 Strt := Item2Pos( Idx );
42377 L := Item2Pos( Idx + 1 ) - Strt;
42378 SelStart := Strt;
42379 SelLength := L;
42380 Perform( fCommandActions.aSetItemText, 0, Integer( PChar( Value ) ) );
42382 else
42383 if fCommandActions.aDeleteItem <> 0 then
42384 begin
42385 {$IFNDEF NOT_FIX_CURINDEX}
42386 TmpCurIdx := CurIndex; // +AK
42387 TmpData := ItemData[ Idx ];
42388 {$ENDIF}
42389 Delete( Idx );
42390 Insert( Idx, Value );
42391 {$IFNDEF NOT_FIX_CURINDEX}
42392 CurIndex := TmpCurIdx; //+AK
42393 ItemData[ Idx ] := TmpData;
42394 {$ENDIF}
42395 end;
42396 end;
42397 {$ENDIF ASM_VERSION}
42399 {$IFDEF ASM_VERSION}
42400 //[function TControl.GetItemsCount]
42401 function TControl.GetItemsCount: Integer;
42403 PUSH 0
42404 MOVZX ECX, [EAX].fCommandActions.aGetCount
42405 JECXZ @@ret_0
42406 PUSH 0
42407 PUSH ECX
42408 PUSH EAX
42409 CALL Perform
42410 PUSH EAX
42412 @@ret_0:
42413 POP EAX
42414 end;
42415 {$ELSE ASM_VERSION} //Pascal
42416 function TControl.GetItemsCount: Integer;
42417 begin
42418 Result := 0;
42419 {$IFDEF DEBUG}
42421 {$ENDIF}
42422 if fCommandActions.aGetCount = 0 then Exit;
42423 Result := Perform( fCommandActions.aGetCount, 0, 0 );
42424 {$IFDEF DEBUG}
42425 except
42427 int 3
42428 end;
42429 end;
42430 {$ENDIF}
42431 end;
42432 {$ENDIF ASM_VERSION}
42435 //[procedure TControl.SetItemsCount]
42436 procedure TControl.SetItemsCount(const Value: Integer);
42437 begin
42438 if fCommandActions.aSetCount = 0 then Exit;
42439 Perform( fCommandActions.aSetCount, Value, 0 );
42440 end;
42442 //[PROCEDURE HelpConvertItem2Pos]
42443 {$IFDEF ASM_VERSION}
42444 procedure HelpConvertItem2Pos;
42446 JECXZ @@exit
42447 PUSH 0
42448 PUSH EDX
42449 PUSH ECX
42450 PUSH EAX
42451 CALL TControl.Perform
42452 XOR EDX, EDX
42453 TEST EAX, EAX
42454 JL @@exit
42456 @@exit:
42457 MOV EAX, EDX
42458 end;
42459 {$ENDIF ASM_VERSION}
42460 //[END HelpConvertItem2Pos]
42462 {$IFDEF ASM_VERSION}
42463 //[function TControl.Item2Pos]
42464 function TControl.Item2Pos(ItemIdx: Integer): Integer;
42466 MOVZX ECX, [EAX].fCommandActions.aItem2Pos
42467 JMP HelpConvertItem2Pos
42468 end;
42469 {$ELSE ASM_VERSION} //Pascal
42470 function TControl.Item2Pos(ItemIdx: Integer): Integer;
42471 begin
42472 Result := ItemIdx;
42473 if fCommandActions.aItem2Pos <> 0 then
42474 begin
42475 Result := Perform( fCommandActions.aItem2Pos, ItemIdx, 0 );
42476 if Result < 0 then Result := 0;
42477 end;
42478 end;
42479 {$ENDIF ASM_VERSION}
42481 {$IFDEF ASM_VERSION}
42482 //[function TControl.Pos2Item]
42483 function TControl.Pos2Item(Pos: Integer): Integer;
42485 MOVZX ECX, [EAX].fCommandActions.aPos2Item
42486 JMP HelpConvertItem2Pos
42487 end;
42488 {$ELSE ASM_VERSION} //Pascal
42489 function TControl.Pos2Item(Pos: Integer): Integer;
42490 begin
42491 Result := Pos;
42492 if fCommandActions.aPos2Item <> 0 then
42493 Result := Perform( fCommandActions.aPos2Item, Pos, 0 );
42494 end;
42495 {$ENDIF ASM_VERSION}
42497 //[function WndProcTabChar]
42498 function WndProcTabChar( Sender: PControl; var M: TMsg; var Rslt: Integer ): Boolean;
42499 begin
42500 if M.message = WM_CHAR then
42501 begin
42502 if M.wParam = 9 then
42503 begin
42504 //M.wParam := 0;
42505 Sender.ReplaceSelection( #9, TRUE );
42506 end;
42507 end;
42508 Result := FALSE;
42509 end;
42511 //[function TControl.EditTabChar]
42512 function TControl.EditTabChar: PControl;
42513 begin
42514 AttachProc( WndProcTabChar );
42515 Result := @Self;
42516 end;
42518 {$IFDEF ASM_VERSION}
42519 //[function TControl.Add]
42520 function TControl.Add(const S: String): Integer;
42522 PUSH EBX
42523 MOV EBX, EAX // EBX = @Self
42525 MOVZX ECX, [EBX].fCommandActions.aAddItem // ECX = aAddItem
42526 JECXZ @@chk_addtext
42528 CALL EDX2PChar
42529 PUSH EDX
42530 PUSH 0
42531 PUSH ECX
42532 PUSH EBX
42533 CALL Perform
42534 PUSH EAX
42536 MOV EAX, EBX
42537 CALL TControl.GetItemsCount
42538 XCHG EAX, ECX
42539 LOOP @@ret_EAX
42541 XCHG EAX, EBX
42542 INC ECX
42543 XOR EDX, EDX
42544 CALL TControl.SetItemSelected
42545 @@ret_EAX:
42546 POP EAX
42547 JMP @@exit
42549 @@chk_addtext:
42550 MOV ECX, [EBX].fCommandActions.aAddText
42551 JECXZ @@add_text_simple
42553 CALL ECX
42554 JMP @@exit_0
42556 @@add_text_simple:
42557 PUSH EDX
42558 PUSH 0
42559 MOV EDX, ESP
42560 CALL GetCaption
42561 POP EAX
42562 POP EDX
42563 PUSH EAX
42564 MOV EAX, ESP
42565 CALL System.@LStrCat
42566 MOV EAX, EBX
42567 POP EDX
42568 PUSH EDX
42569 CALL SetCaption
42570 CALL RemoveStr
42571 @@exit_0:
42572 XOR EAX, EAX
42573 @@exit:
42574 POP EBX
42575 end;
42576 {$ELSE ASM_VERSION} //Pascal
42577 function TControl.Add(const S: String): Integer;
42578 begin
42579 if fCommandActions.aAddItem <> 0 then
42580 begin
42581 Result := Perform( fCommandActions.aAddItem, 0, Integer( PChar( S ) ) );
42582 if Count = 1 then
42583 ItemSelected[ 0 ] := True;
42585 else
42586 begin
42587 if assigned( fCommandActions.aAddText ) then
42588 fCommandActions.aAddText( @Self, S )
42589 else
42590 Text := Text + S;
42591 Result := 0;
42592 end;
42593 end;
42594 {$ENDIF ASM_VERSION}
42596 {$IFDEF ASM_VERSION}
42597 //[procedure TControl.Delete]
42598 procedure TControl.Delete(Idx: Integer);
42600 MOVZX ECX, [EAX].fCommandActions.aDeleteItem
42601 JECXZ @@exit
42603 PUSH 0
42604 PUSH EDX
42605 PUSH ECX
42606 PUSH EAX
42607 CALL Perform
42608 @@exit:
42609 end;
42610 {$ELSE ASM_VERSION} //Pascal
42611 procedure TControl.Delete(Idx: Integer);
42612 begin
42613 if fCommandActions.aDeleteItem <> 0 then
42614 Perform( fCommandActions.aDeleteItem, Idx, 0 );
42615 end;
42616 {$ENDIF ASM_VERSION}
42618 {$IFDEF ASM_VERSION}
42619 //[function TControl.Insert]
42620 function TControl.Insert(Idx: Integer; const S: String): Integer;
42622 CALL ECX2PChar
42623 PUSH ECX
42624 MOVZX ECX, [EAX].fCommandActions.aInsertItem
42625 JECXZ @@exit_1
42627 PUSH EDX
42628 PUSH ECX
42629 PUSH EAX
42630 CALL Perform
42633 @@exit_1:OR EAX, -1
42634 POP ECX
42635 end;
42636 {$ELSE ASM_VERSION} //Pascal
42637 function TControl.Insert(Idx: Integer; const S: String): Integer;
42638 begin
42639 if fCommandActions.aInsertItem <> 0 then
42640 Result := Perform( fCommandActions.aInsertItem, Idx, Integer( PChar( S ) ) )
42641 else
42642 Result := -1;
42643 end;
42644 {$ENDIF ASM_VERSION}
42646 {$IFDEF ASM_VERSION}
42647 //[function TControl.GetItemSelected]
42648 function TControl.GetItemSelected(ItemIdx: Integer): Boolean;
42650 MOVZX ECX, [EAX].fCommandActions.aGetSelected
42651 JECXZ @@check_range
42653 PUSH 0
42654 PUSH EDX
42655 PUSH ECX
42656 PUSH EAX
42657 CALL Perform
42658 TEST EAX, EAX
42659 SETG AL
42662 @@check_range:
42663 MOVZX ECX, [EAX].fCommandActions.aGetSelRange
42664 JECXZ @@check_ex
42666 PUSH EDX
42667 PUSH 0
42668 PUSH 0
42669 PUSH ECX
42670 PUSH EAX
42671 CALL Perform
42672 POP EDX
42673 TEST EAX, EAX
42674 JL @@ret_false
42676 CMP DX, AX
42677 JL @@ret_false
42679 SHR EAX, 16
42680 SUB EDX, EAX
42681 SETL AL
42684 @@check_ex:
42685 MOVZX ECX, [EAX].fCommandActions.aExGetSelRange
42686 JECXZ @@ret_false
42687 PUSH EDX
42688 PUSH EDX
42689 PUSH EDX
42690 PUSH ESP
42691 PUSH 0
42692 PUSH ECX
42693 PUSH EAX
42694 CALL Perform
42695 POP ECX
42696 POP EDX
42697 POP EAX
42699 SUB EAX, EDX
42700 CMP EAX, ECX
42701 SETB AL
42704 @@ret_false:
42705 XOR EAX, EAX
42706 end;
42707 {$ELSE ASM_VERSION} //Pascal
42708 function TControl.GetItemSelected(ItemIdx: Integer): Boolean;
42709 var SR: TCharRange;
42710 begin
42711 Result := False;
42712 if fCommandActions.aGetSelected <> 0 then
42713 Result := 0 < Perform( fCommandActions.aGetSelected, ItemIdx, 0 )
42714 else if fCommandActions.aGetSelRange <> 0 then
42715 begin
42716 Perform( fCommandActions.aGetSelRange, Integer( @SR.cpMin ), Integer( @SR.cpMax ) );
42717 Result := (SR.cpMin <= ItemIdx) and (ItemIdx < SR.cpMax);
42719 else if fCommandActions.aExGetSelRange <> 0 then
42720 begin
42721 Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );
42722 Result := (SR.cpMin <= ItemIdx) and (ItemIdx < SR.cpMax);
42723 end;
42724 end;
42725 {$ENDIF ASM_VERSION}
42727 {$IFDEF ASM_VERSION}
42728 //[procedure TControl.SetItemSelected]
42729 procedure TControl.SetItemSelected(ItemIdx: Integer; const Value: Boolean);
42731 PUSH EDX
42732 PUSH ECX
42733 MOVZX ECX, [EAX].fCommandActions.aSetSelected
42734 JECXZ @@chk_aSetCurrent
42736 @@0:
42737 PUSH ECX
42738 PUSH EAX
42739 CALL Perform
42742 @@chk_aSetCurrent:
42743 POP ECX
42744 MOVZX ECX, [EAX].fCommandActions.aSetCurrent
42745 JECXZ @@chk_aSetSelRange
42747 POP EDX
42748 PUSH 0
42749 JMP @@3
42751 @@chk_aSetSelRange:
42752 MOVZX ECX, [EAX].fCommandActions.aSetSelRange
42753 JECXZ @@chk_aExSetSelRange
42754 @@3:
42755 PUSH EDX
42756 JMP @@0
42758 @@else: MOV [EAX].FCurIndex, EDX
42759 CALL Invalidate
42760 JMP @@exit
42762 @@chk_aExSetSelRange:
42763 MOVZX ECX, [EAX].fCommandActions.aExSetSelRange
42764 JECXZ @@else
42766 PUSH EDX
42767 PUSH ESP
42768 PUSH 0
42769 PUSH ECX
42770 PUSH EAX
42771 CALL Perform
42772 POP ECX
42774 @@exit:
42775 POP ECX
42776 end;
42777 {$ELSE ASM_VERSION} //Pascal
42778 procedure TControl.SetItemSelected(ItemIdx: Integer; const Value: Boolean);
42779 var SR: TCharRange;
42780 begin
42781 if fCommandActions.aSetSelected <> 0 then
42782 Perform( fCommandActions.aSetSelected, Integer( Value ), ItemIdx )
42783 else
42784 if fCommandActions.aSetCurrent <> 0 then
42785 Perform( fCommandActions.aSetCurrent, ItemIdx, 0 )
42786 else
42787 if fCommandActions.aSetSelRange <> 0 then
42788 Perform( fCommandActions.aSetSelRange, ItemIdx, ItemIdx )
42789 else
42790 if fCommandActions.aExSetSelRange <> 0 then
42791 begin
42792 SR.cpMin := ItemIdx;
42793 SR.cpMax := ItemIdx;
42794 Perform( fCommandActions.aExSetSelRange, 0, Integer( @SR ) );
42796 else
42797 begin // for ImageShow: set the index and invalidate the control
42798 FCurIndex := ItemIdx;
42799 Invalidate;
42800 end;
42801 end;
42802 {$ENDIF ASM_VERSION}
42804 {$IFDEF ASM_VERSION}
42805 //[procedure TControl.SetCtl3D]
42806 procedure TControl.SetCtl3D(const Value: Boolean);
42808 MOV [EAX].fCtl3Dchild, DL
42809 CMP [EAX].fCtl3D, DL
42810 JE @@exit
42811 MOV [EAX].fCtl3D, DL
42812 PUSHAD
42813 CALL UpdateWndStyles
42814 POPAD
42815 MOV ECX, [EAX].fExStyle
42816 DEC DL
42817 MOV EDX, [EAX].fStyle
42818 JNZ @@1
42819 AND EDX, not WS_BORDER
42820 OR CH, WS_EX_CLIENTEDGE shr 8
42821 JMP @@2
42822 @@1:
42823 OR EDX, WS_BORDER
42824 AND CH, not(WS_EX_CLIENTEDGE shr 8)
42825 @@2:
42826 PUSH ECX
42827 PUSH EAX
42828 CALL SetStyle
42829 POP EAX
42830 POP EDX
42831 JMP SetExStyle
42832 @@exit:
42833 end;
42834 {$ELSE ASM_VERSION} //Pascal
42835 procedure TControl.SetCtl3D(const Value: Boolean);
42836 begin
42837 fCtl3Dchild := Value;
42838 if fCtl3D = Value then Exit;
42839 fCtl3D := Value;
42840 UpdateWndStyles;
42841 if Value then
42842 begin
42843 ExStyle := fExStyle or WS_EX_CLIENTEDGE;
42844 Style := fStyle and not WS_BORDER;
42846 else
42847 begin
42848 ExStyle := fExStyle and not WS_EX_CLIENTEDGE;
42849 Style := fStyle or WS_BORDER;
42850 end;
42851 end;
42852 {$ENDIF ASM_VERSION}
42854 {$IFDEF ASM_VERSION}
42855 //[function TControl.Shift]
42856 function TControl.Shift(dX, dY: Integer): PControl;
42858 PUSHAD
42859 ADD EDX, [EAX].fBoundsRect.TRect.Left
42860 CALL SetLeft
42861 POPAD
42862 PUSH EAX
42863 MOV EDX, [EAX].fBoundsRect.TRect.Top
42864 ADD EDX, ECX
42865 CALL SetTop
42866 POP EAX
42867 end;
42868 {$ELSE ASM_VERSION} //Pascal
42869 function TControl.Shift(dX, dY: Integer): PControl;
42870 begin
42871 Left := fBoundsRect.Left + dX;
42872 Top := fBoundsRect.Top + dY;
42873 Result := @Self;
42874 end;
42875 {$ENDIF ASM_VERSION}
42877 //[procedure SetKeyEvent]
42878 procedure SetKeyEvent( Self_: PControl );
42879 begin
42880 Self_.fWndProcKeybd := WndProcKeybd;
42881 //Self_.AttachProc( WndProcKeyBd );
42882 end;
42884 //[procedure TControl.SetOnChar]
42885 procedure TControl.SetOnChar(const Value: TOnChar);
42886 begin
42887 fOnChar := Value;
42888 SetKeyEvent( @Self );
42889 end;
42891 //[procedure TControl.SetOnKeyDown]
42892 procedure TControl.SetOnKeyDown(const Value: TOnKey);
42893 begin
42894 fOnKeyDown := Value;
42895 SetKeyEvent( @Self );
42896 end;
42898 //[procedure TControl.SetOnKeyUp]
42899 procedure TControl.SetOnKeyUp(const Value: TOnKey);
42900 begin
42901 fOnKeyUp := Value;
42902 SetKeyEvent( @Self );
42903 end;
42905 //[FUNCTION CollectTabControls]
42906 {$IFDEF ASM_VERSION}
42907 function CollectTabControls( Form: PControl ): PList;
42909 PUSH EDI
42910 PUSH EAX
42911 CALL NewList
42912 XCHG EDI, EAX
42913 POP EAX
42914 CALL @@collecttab
42915 XCHG EAX, EDI
42916 POP EDI
42918 @@collecttab:
42919 { <- EDI = Result:PList
42920 EAX = Form (or Control)
42922 PUSH ESI
42923 PUSH EBX
42924 MOV EDX, [EAX].TControl.fChildren
42925 MOV ECX, [EDX].TList.fCount
42926 MOV ESI, [EDX].TList.fItems
42927 JECXZ @@e_loop
42928 @@loo: PUSH ECX
42929 LODSD
42931 PUSH EAX
42933 TEST byte ptr [EAX].TControl.fStyle+2, WS_TABSTOP shr 16
42934 JZ @@call_recur
42936 MOV DL, [EAX].TControl.fTabStop
42937 AND DL, [EAX].TControl.fEnabled
42938 JZ @@call_recur
42940 CALL TControl.GetToBeVisible
42941 TEST AL, AL
42942 POP EAX
42943 JZ @@next
42944 PUSH EAX
42946 XCHG EDX, EAX
42947 PUSH ESI
42948 MOV ECX, [EDI].TList.fCount
42949 MOV ESI, [EDI].TList.fItems
42950 XOR EBX, EBX
42951 JECXZ @@e_loo2
42952 @@loo2: LODSD
42953 MOV EAX, [EAX].TControl.fTabOrder
42954 CMP EAX, [EDX].TControl.fTabOrder
42955 JLE @@next2
42956 POP ESI
42957 MOV ECX, EDX
42958 MOV EDX, EBX
42959 MOV EAX, EDI
42960 CALL TList.Insert
42961 JMP @@call_recur
42963 @@next2: INC EBX
42964 LOOP @@loo2
42965 @@e_loo2:
42966 POP ESI
42967 MOV EAX, EDI
42968 CALL TList.Add
42970 @@call_recur:
42971 POP EAX
42972 MOVZX ECX, [EAX].TControl.fEnabled
42973 JECXZ @@next
42974 CALL @@collecttab
42976 @@next: POP ECX
42977 LOOP @@loo
42979 @@e_loop:
42980 POP EBX
42981 POP ESI
42982 end;
42983 {$ELSE ASM_VERSION} //Pascal
42984 function CollectTabControls( Form: PControl ): PList;
42985 var R: PList;
42986 procedure CollectTab( P: PControl );
42987 var I, J: Integer;
42988 C, D: PControl;
42989 begin
42990 for I := 0 to P.fChildren.fCount - 1 do
42991 begin
42992 C := P.fChildren.fItems[ I ];
42993 if C.fTabstop and C.fEnabled and C.ToBeVisible and
42994 (C.fStyle and WS_TABSTOP <> 0) then
42995 begin
42996 D := nil;
42997 for J := 0 to R.fCount - 1 do
42998 begin
42999 D := R.fItems[ J ];
43000 if D.fTabOrder > C.fTabOrder then
43001 begin
43002 R.Insert( J, C );
43003 break;
43005 else
43006 D := nil;
43007 end;
43008 if D = nil then
43009 R.Add( C );
43010 end;
43011 if C.fEnabled then
43012 CollectTab( C );
43013 end;
43014 end;
43015 begin
43016 R := NewList;
43017 CollectTab( Form );
43018 Result := R;
43019 end;
43020 {$ENDIF ASM_VERSION}
43021 //[END CollectTabControls]
43023 //[PROCEDURE Tabulate2Next]
43024 {$IFDEF ASM_VERSION}
43025 procedure Tabulate2Next( Form: PControl; Dir: Integer );
43027 PUSHAD
43028 PUSH EAX // save Form
43029 MOV EBX, EAX
43030 MOV EBP, EDX // EBP = Dir (direction <0 or >0)
43031 CALL CollectTabControls
43032 XCHG EDI, EAX // EDI = CL (list of controls)
43034 MOV ECX, [EBX].TControl.fCurrentControl // C := Form.fCurrentControl
43035 XOR EBX, EBX // I = 0
43036 JECXZ @@1
43037 MOV EBX, [ECX].TControl.fTabOrder // I = C.fTabOrder
43038 @@1:
43039 MOV ECX, [EDI].TList.fCount
43040 MOV ESI, [EDI].TList.fItems
43041 XOR EDX, EDX
43042 PUSH EDX // Ctrl1 = nil
43043 PUSH EDX // Ctrl2 = nil
43044 //JECXZ @@e_loop
43045 TEST ECX, ECX
43046 JZ @@e_loop
43048 @@loop: PUSH ECX
43049 LODSD
43050 CMP [EAX].TControl.fTabOrder, EBX
43051 JZ @@next
43053 MOV ECX, [ESP+8] // ECX = Ctrl1
43054 JECXZ @@c1nil
43055 MOV ECX, [ECX].TControl.fTabOrder // ECX = Ctrl1.fTabOrder
43056 TEST EBP, EBP
43057 JGE @@c1ge
43059 CMP [EAX].TControl.fTabOrder, EBX
43060 JGE @@2
43061 CMP [EAX].TControl.fTabOrder, ECX
43062 JLE @@2
43064 @@c1new:
43065 MOV [ESP+8], EAX // Ctrl1 := C
43066 JMP @@2
43068 @@c1ge: CMP [EAX].TControl.fTabOrder, EBX
43069 JLE @@2
43070 CMP [EAX].TControl.fTabOrder, ECX
43071 JL @@c1new
43072 JMP @@2
43074 @@c1nil:
43075 TEST EBP, EBP
43076 JL @@c1nil_dirL
43077 CMP [EAX].TControl.fTabOrder, EBX
43078 JG @@c1new
43079 JMP @@2
43081 @@c1nil_dirL:
43082 CMP [EAX].TControl.fTabOrder, EBX
43083 JL @@c1new
43085 @@2:
43086 MOV ECX, [ESP+4] // ECX = Ctrl2
43087 JECXZ @@c2new
43088 MOV ECX, [ECX].TControl.fTabOrder
43090 TEST EBP, EBP
43091 JL @@c2dirL
43092 CMP [EAX].TControl.fTabOrder, ECX
43093 JGE @@next
43094 JMP @@c2new
43096 @@c2dirL:
43097 CMP [EAX].TControl.fTabOrder, ECX
43098 JLE @@next
43099 @@c2new:
43100 MOV [ESP+4], EAX
43102 @@next: POP ECX
43103 DEC ECX
43104 JNZ @@loop
43105 //LOOP @@loop
43106 @@e_loop:
43108 POP EDX // Ctrl2
43109 POP ECX // Ctrl1
43110 INC ECX
43111 LOOP @@3
43112 MOV ECX, EDX
43113 @@3:
43114 POP EBX // EBX = Form
43115 JECXZ @@exit
43117 XCHG EAX, ECX
43118 MOV ECX, [EAX].TControl.fHandle
43119 JECXZ @@no_handle
43121 INC [EAX].TControl.fClickDisabled
43122 PUSH EAX
43123 PUSH ECX
43124 CALL Windows.SetFocus
43125 POP EAX
43126 DEC [EAX].TControl.fClickDisabled
43128 @@no_handle:
43129 MOV [EBX].TControl.fCurrentControl, EAX
43131 @@exit:
43132 XCHG EAX, EDI
43133 CALL TObj.Free
43134 POPAD
43135 end;
43136 {$ELSE ASM_VERSION} //Pascal
43137 procedure Tabulate2Next( Form: PControl; Dir: Integer );
43138 var CL : PList;
43139 I, J : Integer;
43140 Ctrl1, Ctrl2, C : PControl;
43141 begin
43142 CL := CollectTabControls( Form );
43144 I := 0;
43145 C := Form.fCurrentControl;
43146 if C <> nil then
43147 I := C.fTabOrder;
43148 Ctrl2 := nil;
43149 Ctrl1 := nil;
43150 for J := 0 to CL.fCount - 1 do
43151 begin
43152 C := CL.fItems[ J ];
43153 if C.fTabOrder = I then continue;
43154 if (Ctrl1 = nil)
43155 and ( (Dir >= 0) and (C.fTabOrder > I)
43156 or (Dir < 0) and (C.fTabOrder < I) )
43157 or (Dir >= 0)
43158 and (C.fTabOrder > I) and (C.fTabOrder < Ctrl1.fTabOrder)
43159 or (Dir < 0)
43160 and (C.fTabOrder < I) and (C.fTabOrder > Ctrl1.fTabOrder)
43161 then Ctrl1 := C;
43162 if (Ctrl2 = nil)
43163 or (Dir >= 0) and (C.fTabOrder < Ctrl2.fTabOrder)
43164 or (Dir < 0) and (C.fTabOrder > Ctrl2.fTabOrder)
43165 then Ctrl2 := C;
43166 end;
43167 if Ctrl1 = nil then
43168 Ctrl1 := Ctrl2;
43169 if Ctrl1 <> nil then
43170 begin
43171 if Ctrl1.fHandle <> 0 then
43172 begin
43173 Inc( Ctrl1.fClickDisabled );
43174 SetFocus( Ctrl1.fHandle );
43175 Dec( Ctrl1.fClickDisabled );
43176 end;
43177 Form.fCurrentControl := Ctrl1;
43178 end;
43179 CL.Free;
43180 end;
43181 {$ENDIF ASM_VERSION}
43182 //[END Tabulate2Next]
43184 //[FUNCTION Tabulate2Control]
43185 {$IFDEF ASM_VERSION}
43186 function Tabulate2Control( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
43187 const tk_Tab = 1;
43188 tk_LR = 2;
43189 tk_UD = 4;
43190 tk_PuPd= 8;
43192 PUSH ESI
43193 MOV ESI, offset[@@data]
43194 PUSH EAX
43195 MOV AH, 9
43196 @@loop:
43197 LODSB
43198 CMP DL, AL
43199 JE @@1
43200 LODSB
43201 CMP DL, AL
43202 JE @@2
43203 ADD AH, AH
43204 JNB @@loop
43205 POP EAX
43206 @@exit0:
43207 XOR EAX, EAX
43208 JMP @@exit
43210 @@data:
43211 DB -1, VK_TAB, VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT
43213 @@1:
43214 OR EDX, -1
43215 JMP @@3
43216 @@2:
43217 XOR EDX, EDX
43218 TEST AH, 1
43219 JZ @@3
43221 PUSH ECX
43222 PUSH EAX
43223 PUSH VK_SHIFT
43224 CALL GetAsyncKeyState
43226 POP EAX
43227 POP ECX
43228 @@3:
43229 POP ESI
43230 //////////////////////////////////////////////////
43231 MOV AL, AH
43232 {$IFDEF PARANOIA}
43233 DB $24, 1
43234 {$ELSE}
43235 AND AL, 1
43236 {$ENDIF}
43237 TEST byte ptr [ESI].TControl.fLookTabKeys, AL
43238 //////////////////////////////////////////////////
43239 JZ @@exit0
43241 TEST CL, CL
43242 JNZ @@exit
43244 PUSH EDX
43245 MOV EAX, ESI
43246 CALL TControl.ParentForm
43247 POP EDX
43248 CALL Tabulate2Next
43249 @@exit:
43250 POP ESI
43251 end;
43252 {$ELSE ASM_VERSION} //Pascal
43253 function Tabulate2Control( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
43254 var Form: PControl;
43255 begin
43256 Result := False;
43257 case Key of
43258 VK_TAB: if not (tkTab in Self_.fLookTabKeys) then exit;
43259 VK_LEFT, VK_RIGHT: if not (tkLeftRight in Self_.fLookTabKeys) then exit;
43260 VK_UP, VK_DOWN: if not (tkUpDown in Self_.fLookTabKeys) then exit;
43261 VK_NEXT, VK_PRIOR: if not (tkPageUpPageDn in Self_.fLookTabKeys) then exit;
43262 else Exit;
43263 end;
43265 Result := True;
43266 if checkOnly then Exit;
43268 Form := Self_.ParentForm;
43269 case Key of
43270 VK_TAB:
43271 if GetKeyState( VK_SHIFT ) < 0 then
43272 Tabulate2Next( Form, -1 )
43273 else
43274 Tabulate2Next( Form, 1 );
43275 VK_RIGHT, VK_DOWN, VK_NEXT: Tabulate2Next( Form, 1 );
43276 VK_LEFT, VK_UP, VK_PRIOR: Tabulate2Next( Form, -1 );
43277 end;
43278 end;
43279 {$ENDIF ASM_VERSION}
43280 //[END Tabulate2Control]
43282 //[FUNCTION Tabulate2ControlEx]
43283 {$IFDEF ASM_VERSION}
43284 function Tabulate2ControlEx( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
43286 PUSH EDI
43287 MOVZX EDI, CL
43288 TEST byte ptr [EAX].TControl.fLookTabKeys, 1
43289 JZ @@1
43290 @@0:
43291 MOV ECX, EDX
43292 AND CL, 7Fh
43293 CMP CL, VK_TAB
43294 JNE @@1
43296 PUSH EDX
43297 CALL TControl.ParentForm
43298 POP EDX
43299 MOVSX EDX, DL
43300 TEST EDX, EDX
43301 JS @@tab
43303 PUSH EAX
43305 PUSH VK_SHIFT
43306 CALL GetAsyncKeyState
43307 SAR EAX, 31
43308 {$IFDEF PARANOIA}
43309 DB $0C, $01
43310 {$ELSE}
43311 OR AL, 1
43312 {$ENDIF}
43313 MOV EDX, EAX
43315 POP EAX
43316 @@tab:
43317 TEST EDI, EDI
43318 POP EDI
43319 JNZ @@no_tab
43320 CALL Tabulate2Next
43321 @@no_tab:
43322 MOV AL, 1
43325 @@data: DB VK_LEFT, VK_LEFT
43326 DD offset[@@left]
43327 DB VK_UP, 2
43328 DB VK_RIGHT, VK_RIGHT
43329 DD offset[@@right]
43330 DB VK_DOWN, 2
43331 DB VK_UP, VK_PRIOR
43332 DD offset[@@up]
43333 DB VK_TAB or 80h, $C
43334 DB VK_DOWN, VK_NEXT
43335 DD offset[@@down]
43336 DB VK_TAB, $C
43338 @@1:
43340 EAX <- Self_:PControl
43341 DL <- Key
43343 PUSH ESI
43344 MOV ESI, offset[@@data]-6
43345 MOV DH, 9
43346 PUSH EAX
43347 @@loop:
43348 ADD DH, DH
43349 JNB @@l1
43350 JMP @@abort
43351 @@fault1:
43352 POP EDI
43353 POPAD
43354 PUSH EAX
43355 @@abort:
43356 POP EAX
43357 @@abort1:
43358 POP ESI
43359 POP EDI
43360 XOR EAX, EAX
43363 @@right:
43364 MOV EAX, [ESP].TRect.Left
43365 SUB EAX, [ESP+16].TRect.Left
43366 @@left_right:
43367 JL @@next1
43368 MOV EDX, [ESP].TRect.Bottom
43369 SUB EDX, [ESP+16].TRect.Top
43370 JL @@next1
43371 MOV EDX, [ESP].TRect.Top
43372 SUB EDX, [ESP+16].TRect.Bottom
43373 JGE @@next1
43374 @@chk_dist:
43375 CMP EAX, EDI
43376 JA @@next1
43377 MOV EDI, EAX
43378 MOV EAX, [EBX+ECX*4-4]
43379 MOV [ESP+36], EAX // Found = Ctrl
43380 JMP @@next1
43382 @@l1:
43383 LODSD
43384 LODSW
43385 LODSW
43386 CMP AL, DL
43387 JE @@2
43388 CMP AH, DL
43389 JNE @@loop
43391 @@2:
43392 PUSH ESI
43393 LODSD
43394 LODSW
43395 POP ESI
43396 XCHG EDX, EAX
43397 POP EAX
43398 TEST [EAX].TControl.fLookTabKeys, DH
43399 JZ @@abort1
43401 PUSHAD
43402 PUSH EDI
43403 CALL TControl.ParentForm
43404 MOV ECX, [EAX].TControl.fCurrentControl
43405 JECXZ @@fault1
43406 MOV EBP, ECX // EBP = CurCtrl
43408 PUSH EAX // save Form
43409 MOV EBX, EAX
43410 CALL CollectTabControls
43411 PUSH 0 // save Found = nil
43412 PUSH EAX // save CollectedList
43413 MOV EDI, EAX
43415 MOV EBX, [EDI].TList.fItems
43416 ADD ESP, -16
43417 PUSH ESP
43418 PUSH [EBP].TControl.fHandle
43419 CALL GetWindowRect
43421 MOV ECX, [EDI].TList.fCount
43422 OR EDI, -1 // EDI = minDist
43423 @@loop1:
43424 MOV EAX, [EBX+ECX*4-4]
43425 CMP EAX, EBP
43426 JE @@next
43428 MOV DL, [EAX].TControl.fEnabled
43429 AND DL, [EAX].TControl.fTabstop
43430 JZ @@next
43432 ADD ESP, -16
43433 MOV EDX, ESP
43434 PUSH ECX
43436 //CALL TControl.ControlRect
43437 PUSH EDX
43438 PUSH [EAX].TControl.fHandle
43439 CALL GetWindowRect
43441 POP ECX
43442 JMP dword ptr [ESI]
43444 @@left:
43445 MOV EAX, [ESP+16].TRect.Left
43446 SUB EAX, [ESP].TRect.Left
43447 JMP @@left_right
43449 @@not_found:
43450 POP EDI
43451 POPAD
43452 MOV DL, [ESI+4]
43453 POP ESI
43454 JMP @@0
43456 @@up:
43457 MOV EAX, [ESP+16].TRect.Top
43458 SUB EAX, [ESP].TRect.Top
43459 JMP @@up_down
43460 @@down:
43461 MOV EAX, [ESP].TRect.Top
43462 SUB EAX, [ESP+16].TRect.Top
43463 @@up_down:
43464 JL @@next1
43465 MOV EDX, [ESP].TRect.Right
43466 SUB EDX, [ESP+16].TRect.Left
43467 JL @@next1
43468 MOV EDX, [ESP].TRect.Left
43469 SUB EDX, [ESP+16].TRect.Right
43470 JL @@chk_dist
43472 @@next1:
43473 ADD ESP, 16
43474 @@next:
43475 LOOP @@loop1
43476 ADD ESP, 16
43477 POP EAX // pop CollectedList
43478 CALL TObj.Free
43479 POP ECX // pop Found
43480 POP EAX // pop Form
43481 JECXZ @@not_found
43483 POP EDI
43484 TEST EDI, EDI
43485 JNZ @@no_go
43487 MOV [EAX].TControl.fCurrentControl, ECX
43488 INC [ECX].TControl.fClickDisabled
43489 PUSH ECX
43490 MOV ECX, [ECX].TControl.fHandle
43491 JECXZ @@4
43492 PUSH ECX
43493 CALL Windows.SetFocus
43494 @@4: POP ECX
43495 DEC [ECX].TControl.fClickDisabled
43496 @@no_go:
43497 POPAD
43498 POP ESI
43499 POP EDI
43500 MOV AL, 1 // Result = True
43501 end;
43502 {$ELSE ASM_VERSION} //Pascal
43503 function Tabulate2ControlEx( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
43504 label search_tabcontrol;
43505 var Form: PControl;
43506 CL : PList;
43507 I : Integer;
43508 CurCtrl, Ctrl, Found : PControl;
43509 MinDist, Dist: Integer;
43510 R, R1 : TRect;
43511 begin
43512 Result := False;
43513 case Key of
43514 VK_TAB: if not (tkTab in Self_.fLookTabKeys) then exit;
43515 VK_LEFT, VK_RIGHT: if not (tkLeftRight in Self_.fLookTabKeys) then exit;
43516 VK_UP, VK_DOWN: if not (tkUpDown in Self_.fLookTabKeys) then exit;
43517 VK_NEXT, VK_PRIOR: if not (tkPageUpPageDn in Self_.fLookTabKeys) then exit;
43518 else exit;
43519 end;
43521 Result := True;
43522 if checkOnly then Exit;
43524 Form := Self_.ParentForm;
43525 if Key = VK_TAB then
43526 if GetKeyState( VK_SHIFT ) < 0 then
43527 Tabulate2Next( Form, -1 )
43528 else
43529 Tabulate2Next( Form, 1 )
43530 else
43531 begin
43532 CL := CollectTabControls( Form );
43533 I := CL.IndexOf( Form.fCurrentControl );
43534 Found := nil;
43535 if I >= 0 then
43536 begin
43537 CurCtrl := CL.fItems[ I ];
43538 //R := CurCtrl.ControlRect;
43539 GetWindowRect( CurCtrl.Handle, R );
43540 search_tabcontrol:
43541 MinDist := MaxInt;
43542 for I := CL.fCount - 1 downto 0 do
43543 begin
43544 Ctrl := CL.fItems[ I ];
43545 if Ctrl = CurCtrl then continue;
43546 if not (Ctrl.fEnabled and Ctrl.fTabstop) then continue;
43547 //R1 := Ctrl.ControlRect;
43548 GetWindowRect( Ctrl.Handle, R1 );
43549 Dist := MaxInt;
43550 case Key of
43551 VK_LEFT:
43552 begin
43553 if (R1.Bottom < R.Top)
43554 or (R1.Top >= R.Bottom)
43555 or (R1.Left > R.Left) then continue;
43556 Dist := R.Left - R1.Left;
43557 end;
43558 VK_RIGHT:
43559 begin
43560 if (R1.Bottom < R.Top)
43561 or (R1.Top >= R.Bottom)
43562 or (R1.Left < R.Left) then continue;
43563 Dist := R1.Left - R.Left;
43564 end;
43565 VK_UP, VK_PRIOR:
43566 begin
43567 if (R1.Right < R.Left)
43568 or (R1.Left >= R.Right)
43569 or (R1.Top > R.Top) then continue;
43570 Dist := R.Top - R1.Top;
43571 end;
43572 VK_DOWN, VK_NEXT:
43573 begin
43574 if (R1.Right < R.Left)
43575 or (R1.Left >= R.Right)
43576 or (R1.Top < R.Bottom) then continue;
43577 Dist := R1.Top - R.Top;
43578 end;
43579 end;
43580 if Dist < MinDist then
43581 begin
43582 Found := Ctrl;
43583 MinDist := Dist;
43584 end;
43585 end;
43586 if Found = nil then
43587 begin
43588 case Key of
43589 VK_LEFT:
43590 begin
43591 Key := VK_UP; goto search_tabcontrol;
43592 end;
43593 VK_RIGHT:
43594 begin
43595 Key := VK_DOWN; goto search_tabcontrol;
43596 end;
43597 VK_UP, VK_PRIOR:
43598 Tabulate2Next( Form, -1 );
43599 VK_DOWN, VK_NEXT:
43600 Tabulate2Next( Form, 1 );
43601 end;
43603 else
43604 begin
43605 if Found.fHandle <> 0 then
43606 begin
43607 Inc( Found.fClickDisabled );
43608 SetFocus( Found.fHandle );
43609 Dec( Found.fClickDisabled );
43610 end;
43611 Form.fCurrentControl := Found;
43612 end;
43613 end;
43614 CL.Free;
43615 end;
43616 end;
43617 {$ENDIF ASM_VERSION}
43618 //[END Tabulate2ControlEx]
43620 {$IFDEF ASM_VERSION}
43621 //[function TControl.Tabulate]
43622 function TControl.Tabulate: PControl;
43624 PUSH EAX
43625 CALL ParentForm
43626 TEST EAX, EAX
43627 JZ @@exit
43628 MOV [EAX].fGotoControl, offset[Tabulate2Control]
43629 @@exit: POP EAX
43630 end;
43631 {$ELSE ASM_VERSION} //Pascal
43632 function TControl.Tabulate: PControl;
43633 var F : PControl;
43634 begin
43635 Result := @Self;
43636 F := ParentForm;
43637 if F = nil then Exit;
43638 F.fGotoControl := Tabulate2Control;
43639 end;
43640 {$ENDIF ASM_VERSION}
43642 {$IFDEF ASM_VERSION}
43643 //[function TControl.TabulateEx]
43644 function TControl.TabulateEx: PControl;
43646 PUSH EAX
43647 CALL ParentForm
43648 TEST EAX, EAX
43649 JZ @@exit
43650 MOV [EAX].fGotoControl, offset[Tabulate2ControlEx]
43651 @@exit: POP EAX
43652 end;
43653 {$ELSE ASM_VERSION} //Pascal
43654 function TControl.TabulateEx: PControl;
43655 var F : PControl;
43656 begin
43657 Result := @Self;
43658 F := ParentForm;
43659 if F = nil then Exit;
43660 F.fGotoControl := Tabulate2ControlEx;
43661 end;
43662 {$ENDIF ASM_VERSION}
43665 //[procedure TControl.GotoControl]
43666 procedure TControl.GotoControl(Key: DWORD);
43667 var Form: PControl;
43668 begin
43669 Form := ParentForm;
43670 if Form <> nil then
43671 if assigned( Form.fGotoControl ) then
43672 Form.fGotoControl( Form.fCurrentControl, Key, false );
43673 end;
43675 {$IFDEF ASM_VERSION}
43676 //[function TControl.GetCurIndex]
43677 function TControl.GetCurIndex: Integer;
43679 PUSH EBX
43680 XCHG EBX, EAX
43681 MOV EAX, [EBX].fCurIndex
43682 MOVZX ECX, [EBX].fCommandActions.aGetCurrent
43683 JECXZ @@exit
43684 XOR EAX, EAX
43686 CMP CX, LVM_GETNEXTITEM
43687 JNE @@0
43688 INC EAX
43689 INC EAX
43690 JMP @@1
43691 @@0:
43692 CMP CL, EM_LINEINDEX and $FF
43693 JNZ @@2
43694 @@1:
43695 DEC EDX
43696 @@2:
43697 PUSH EAX
43698 PUSH EDX
43699 PUSH ECX
43700 PUSH EBX
43701 CALL Perform
43703 @@exit: POP EBX
43704 end;
43705 {$ELSE ASM_VERSION} //Pascal
43706 function TControl.GetCurIndex: Integer;
43707 var I, J: Integer;
43708 begin
43709 Result := fCurIndex;
43710 if fCommandActions.aGetCurrent = 0 then
43711 Exit;
43712 I := 0;
43713 if fCommandActions.aGetCurrent = EM_LINEINDEX then
43714 Dec( I );
43715 J := 0;
43716 if fCommandActions.aGetCurrent = LVM_GETNEXTITEM then
43717 begin
43718 J := 2 {LVNI_SELECTED};
43719 Dec( I );
43720 end;
43721 Result := Perform( fCommandActions.aGetCurrent, I, J );
43722 end;
43723 {$ENDIF ASM_VERSION}
43725 {$IFDEF ASM_VERSION}
43726 //[procedure TControl.SetCurIndex]
43727 procedure TControl.SetCurIndex(const Value: Integer);
43729 MOVZX ECX, [EAX].fCommandActions.aSetCurrent
43730 JECXZ @@set_item_sel
43731 PUSHAD
43732 PUSH 0
43733 PUSH EDX
43734 PUSH ECX
43735 PUSH EAX
43736 CALL Perform
43737 POPAD
43738 CMP CX, TCM_SETCURSEL
43739 JNE @@exit
43740 PUSH TCN_SELCHANGE
43741 PUSH EAX // idfrom doesn't matter
43742 PUSH [EAX].fHandle
43743 PUSH ESP
43744 PUSH 0
43745 PUSH WM_NOTIFY
43746 PUSH EAX
43747 CALL Perform
43748 POP ECX
43749 POP ECX
43750 POP ECX
43751 @@exit:
43753 @@set_item_sel:
43754 INC ECX
43755 CALL SetItemSelected
43756 end;
43757 {$ELSE ASM_VERSION} //Pascal
43758 procedure TControl.SetCurIndex(const Value: Integer);
43759 var NMHdr: TNMHdr;
43760 begin
43761 if fCommandActions.aSetCurrent <> 0 then
43762 begin
43763 Perform( fCommandActions.aSetCurrent, Value, 0 );
43764 if fCommandActions.aSetCurrent = TCM_SETCURSEL then
43765 begin
43766 NMHdr.code := TCN_SELCHANGE;
43767 NMHdr.hwndFrom := fHandle;
43768 Perform( WM_NOTIFY, 0, Integer( @NMHdr ) );
43769 end;
43771 else
43772 ItemSelected[ Value ] := True;
43773 end;
43774 {$ENDIF ASM_VERSION}
43776 {$IFDEF ASM_VERSION}
43777 //[function TControl.GetTextAlign]
43778 function TControl.GetTextAlign: TTextAlign;
43780 PUSH EAX
43781 CALL UpdateWndStyles
43782 MOV ECX, [EAX].fStyle
43783 MOV EDX, dword ptr [EAX].fCommandActions.aTextAlignRight
43784 XOR EAX, EAX
43785 AND DX, CX
43786 JNZ @@ret_1
43787 SHR EDX, 16
43788 AND ECX, EDX
43789 JNZ @@ret_2
43790 POP EAX
43791 MOVZX EAX, [EAX].fTextAlign
43794 @@ret_2:INC EAX
43795 @@ret_1:INC EAX
43796 @@ret_0:POP ECX
43797 end;
43798 {$ELSE ASM_VERSION} //Pascal
43799 function TControl.GetTextAlign: TTextAlign;
43800 begin
43801 UpdateWndStyles;
43802 if (fStyle and fCommandActions.aTextAlignRight) = fCommandActions.aTextAlignRight then
43803 Result := taRight
43804 else
43805 if (fStyle and fCommandActions.aTextAlignCenter) = fCommandActions.aTextAlignCenter then
43806 Result := taCenter
43807 else
43808 Result := fTextAlign;
43809 end;
43810 {$ENDIF ASM_VERSION}
43812 {$IFDEF ASM_VERSION}
43813 //[function TControl.GetVerticalAlign]
43814 function TControl.GetVerticalAlign: TVerticalAlign;
43816 PUSH EAX
43817 CALL UpdateWndStyles
43818 MOV EDX, dword ptr [EAX].fCommandActions.aVertAlignCenter
43819 MOV ECX, [EAX].fStyle
43820 XOR EAX, EAX
43821 MOV DH, DL
43822 AND DL, CH
43823 JZ @@1
43824 CMP DL, DH
43825 JE @@ret_0
43826 @@1: SHR EDX, 16
43827 MOV DH, DL
43828 AND DL, CH
43829 JZ @@2
43830 CMP DL, DH
43831 JE @@ret_2
43832 @@2: POP EAX
43833 MOVZX EAX, [EAX].fVerticalAlign
43835 @@ret_2:INC EAX
43836 @@ret_1:INC EAX
43837 @@ret_0:POP ECX
43838 end;
43839 {$ELSE ASM_VERSION} //Pascal
43840 function TControl.GetVerticalAlign: TVerticalAlign;
43841 begin
43842 UpdateWndStyles;
43843 if (fStyle and (fCommandActions.aVertAlignCenter shl 8)) = (fCommandActions.aVertAlignCenter shl 8) then
43844 Result := vaCenter
43845 else
43846 if (fStyle and (fCommandActions.aVertAlignBottom shl 8)) = (fCommandActions.aVertAlignBottom shl 8) then
43847 Result := vaBottom
43848 else
43849 Result := fVerticalAlign;
43850 end;
43851 {$ENDIF ASM_VERSION}
43853 {$IFDEF ASM_VERSION}
43854 //[procedure TControl.SetTextAlign]
43855 procedure TControl.SetTextAlign(const Value: TTextAlign);
43857 MOV [EAX].fTextAlign, DL
43858 XOR ECX, ECX
43859 MOV CX, [EAX].fCommandActions.aTextAlignLeft
43860 OR CX, [EAX].fCommandActions.aTextAlignCenter
43861 OR CX, [EAX].fCommandActions.aTextAlignRight
43862 NOT ECX
43863 AND ECX, [EAX].fStyle
43865 AND EDX, 3
43866 OR CX, [EAX + EDX * 2].fCommandActions.aTextAlignLeft
43868 MOV DL, [EAX].fCommandActions.aTextAlignMask
43869 NOT EDX
43870 AND EDX, ECX
43871 CALL SetStyle
43872 end;
43873 {$ELSE ASM_VERSION} //Pascal
43874 procedure TControl.SetTextAlign(const Value: TTextAlign);
43875 var NewStyle: DWORD;
43876 begin
43877 fTextAlign := Value;
43878 NewStyle := 0;
43879 with fCommandActions do
43880 case Value of
43881 taLeft: NewStyle := fStyle and not DWORD(aTextAlignCenter or aTextAlignRight)
43882 or aTextAlignLeft;
43883 taRight: NewStyle := fStyle and not DWORD(aTextAlignLeft or aTextAlignCenter)
43884 or aTextAlignRight;
43885 taCenter: NewStyle := fStyle and not DWORD(aTextAlignLeft or aTextAlignRight)
43886 or aTextAlignCenter;
43887 end;
43888 NewStyle := NewStyle and not DWORD(fCommandActions.aTextAlignMask);
43889 Style := NewStyle;
43890 end;
43891 {$ENDIF ASM_VERSION}
43893 {$IFDEF ASM_noVERSION}
43894 //[procedure TControl.SetVerticalAlign]
43895 procedure TControl.SetVerticalAlign(const Value: TVerticalAlign);
43897 MOV [EAX].fVerticalAlign, DL
43898 XOR ECX, ECX
43899 MOV CX, word ptr [EAX].fCommandActions.aVertAlignTop
43900 OR CH, CL
43901 MOV CL, 0
43902 NOT ECX
43903 AND ECX, [EAX].fStyle
43904 AND EDX, 3
43905 MOV DH, [EAX + EDX].fCommandActions.aVertAlignCenter
43906 MOV DL, 0
43907 OR EDX, ECX
43908 CALL SetStyle
43909 end;
43910 {$ELSE ASM_VERSION} //Pascal
43911 procedure TControl.SetVerticalAlign(const Value: TVerticalAlign);
43912 var NewStyle: DWORD;
43913 begin
43914 fVerticalAlign := Value;
43915 with fCommandActions do
43916 begin
43917 NewStyle := fStyle and not DWORD((aVertAlignTop or aVertAlignCenter or aVertAlignBottom) shl 8);
43918 case Value of
43919 vaCenter: NewStyle := NewStyle or (aVertAlignCenter shl 8);
43920 vaTop: NewStyle := NewStyle or (aVertAlignTop shl 8);
43921 vaBottom: NewStyle := NewStyle or (aVertAlignBottom shl 8);
43922 end;
43923 end;
43924 Style := NewStyle;
43925 end;
43926 {$ENDIF ASM_VERSION}
43928 {$IFDEF ASM_noVERSION}
43929 //[function TControl.Dc2Canvas]
43930 function TControl.Dc2Canvas( Sender: PCanvas ): HDC;
43932 MOV ECX, [EAX].fPaintDC
43933 JECXZ @@chk_fHandle
43934 PUSH ECX
43935 XCHG EAX, EDX // EAX <= Sender
43936 MOV EDX, ECX // EDX <= fPaintDC
43937 PUSH EAX
43938 CALL TCanvas.SetHandle
43939 POP EAX
43940 MOV [EAX].TCanvas.fIsPaintDC, 1
43941 POP ECX
43942 @@ret_ECX:
43943 XCHG EAX, ECX
43945 @@chk_fHandle:
43946 MOV ECX, [EDX].TCanvas.fHandle
43947 INC ECX
43948 LOOP @@ret_ECX
43949 CALL GetWindowHandle
43950 PUSH EAX
43951 CALL GetDC
43952 end;
43953 {$ELSE ASM_VERSION} //Pascal
43954 function TControl.Dc2Canvas( Sender: PCanvas ): HDC;
43955 begin
43956 if fPaintDC <> 0 then
43957 begin
43958 Result := fPaintDC;
43959 Sender.SetHandle( Result );
43960 Sender.fIsPaintDC := True;
43962 else
43963 begin
43964 if Sender.fHandle <> 0 then
43965 Result := Sender.fHandle
43966 else
43967 Result := GetDC( GetWindowHandle );
43968 end;
43969 end;
43970 {$ENDIF ASM_VERSION}
43972 {$IFDEF ASM_VERSION}
43973 //[function TControl.GetCanvas]
43974 function TControl.GetCanvas: PCanvas;
43976 PUSH EBX
43977 PUSH ESI
43978 XCHG EBX, EAX
43980 MOV ESI, [EBX].fCanvas
43981 TEST ESI, ESI
43982 JNZ @@exit
43984 XOR EAX, EAX
43985 CALL NewCanvas
43986 MOV [EBX].fCanvas, EAX
43987 MOV [EAX].TCanvas.fOwnerControl, EBX
43988 MOV [EAX].TCanvas.fOnGetHandle.TMethod.Code, offset[ DC2Canvas ]
43989 MOV [EAX].TCanvas.fOnGetHandle.TMethod.Data, EBX
43990 XCHG ESI, EAX
43992 MOV ECX, [EBX].fFont
43993 JECXZ @@exit
43995 MOV EAX, [ESI].TCanvas.fFont
43996 MOV EDX, ECX
43997 CALL TGraphicTool.Assign
43998 MOV [ESI].TCanvas.fFont, EAX
44000 MOV ECX, [EBX].fBrush
44001 JECXZ @@exit
44003 MOV EAX, [ESI].TCanvas.fBrush
44004 MOV EDX, ECX
44005 CALL TGraphicTool.Assign
44006 MOV [ESI].TCanvas.fBrush, EAX
44008 @@exit: XCHG EAX, ESI
44009 POP ESI
44010 POP EBX
44011 end;
44012 {$ELSE ASM_VERSION} //Pascal
44013 function TControl.GetCanvas: PCanvas;
44014 begin
44015 if not assigned( fCanvas ) then
44016 begin
44017 fCanvas := NewCanvas( 0 );
44018 fCanvas.OnGetHandle := Dc2Canvas;
44019 fCanvas.fOwnerControl := @Self;
44020 if assigned( fFont ) then
44021 fCanvas.fFont := fCanvas.fFont.Assign( fFont );
44022 if assigned( fBrush ) then
44023 fCanvas.fBrush := fCanvas.fBrush.Assign( fBrush );
44024 end;
44025 Result := fCanvas;
44026 end;
44027 {$ENDIF ASM_VERSION}
44029 //[function TControl.DblBufTopParent]
44030 function TControl.DblBufTopParent: PControl;
44031 var Ctl: PControl;
44032 begin
44033 Result := nil;
44034 Ctl := @ Self;
44035 while Ctl <> nil do
44036 begin
44037 if Ctl.fDoubleBuffered then
44038 Result := Ctl;
44039 Ctl := Ctl.fParent;
44040 end;
44041 end;
44043 //[procedure InvalidateDblBufParent]
44044 procedure InvalidateDblBufParent( Sender: PControl );
44045 var C: PControl;
44046 begin
44047 C := Sender.DblBufTopParent;
44048 if C <> nil then
44049 InvalidateRect( C.fHandle, nil, TRUE );
44050 end;
44052 //[function WndFuncPreventDraw]
44053 function WndFuncPreventDraw( W: HWnd; Msg: Cardinal; wParam, lParam: Integer ): Integer; stdcall;
44054 var C: PControl;
44055 PrntW: HWnd;
44056 //********************************************************** Added By M.Gerasimov
44058 PrevProc:Pointer;
44060 //********************************************************** Added By M.Gerasimov
44061 begin
44062 //if not AppletTerminated then
44063 case Msg of
44064 WM_NCPAINT,
44065 //WM_PAINT,
44066 WM_ERASEBKGND:
44067 begin
44068 C := Pointer( GetProp( W, ID_SELF ) );
44069 if C = nil then
44070 begin
44071 PrntW := GetParent( W );
44072 if PrntW <> 0 then
44073 begin
44074 C := Pointer( GetProp( PrntW, ID_SELF ) );
44075 if (C <> nil) and not C.fCannotDoubleBuf and
44076 (C.DblBufTopParent <> nil) and
44077 (not C.DblBufTopParent.fDblBufPainting) then
44078 begin
44079 case Msg of
44080 WM_NCPAINT: Result := 0;
44081 WM_PAINT: Result := 0;
44082 else Result := 1;
44083 end;
44084 Exit;
44085 end;
44086 end;
44087 end;
44088 end;
44089 end;
44090 //********************************************************** By M.Gerasimov
44092 PrevProc:=Pointer(GetProp( W, ID_PREVPROC ));
44093 if PrevProc <> Nil then
44094 Result := CallWindowProc( PrevProc , W, Msg, wParam, lParam )
44095 else
44096 Result:=0;
44098 //********************************************************** Remarked By M.Gerasimov
44099 //Result := CallWindowProc( Pointer( GetProp( W, 'PREV_PROC' ) ),
44100 // W, Msg, wParam, lParam );
44101 //******************************************************************************
44102 end;
44104 //[procedure DblBufCreateWndProc]
44105 procedure DblBufCreateWndProc( Sender: PControl );
44106 var Chld: HWnd;
44107 PrevProc: DWORD;
44108 begin
44109 Chld := GetWindow( Sender.fHandle, GW_CHILD );
44110 while Chld <> 0 do
44111 begin
44112 //********************************************************** Changed By M.Gerasimov
44113 // if GetProp( Chld, 'PREV_PROC' ) = 0 then
44114 //**********************************************************
44115 if GetProp( Chld, ID_PREVPROC ) = 0 then //
44116 //**********************************************************
44117 begin
44118 PrevProc :=
44119 SetWindowLong( Chld, GWL_WNDPROC, Longint( @WndFuncPreventDraw ) );
44120 //********************************************************** Changed By M.Gerasimov
44121 // SetProp( Chld, 'PREV_PROC', PrevProc );
44122 //**********************************************************
44123 SetProp( Chld, ID_PREVPROC, PrevProc ); //
44124 //**********************************************************
44125 end;
44126 Chld := GetWindow( Chld, GW_HWNDNEXT );
44127 end;
44128 end;
44130 //[procedure TControl.SetDoubleBuffered]
44131 procedure TControl.SetDoubleBuffered(const Value: Boolean);
44132 begin
44133 if CannotDoubleBuf then Exit;
44134 fDoubleBuffered := Value;
44135 Global_OnBufferedDraw := WndProcBufferedDraw;
44136 Global_Invalidate := @ InvalidateDblBufParent;
44137 Global_DblBufCreateWnd := @ DblBufCreateWndProc;
44138 end;
44140 {$IFDEF ASM_VERSION}
44141 //[procedure TControl.SetTransparent]
44142 procedure TControl.SetTransparent(const Value: Boolean);
44144 CMP [EAX].fTransparent, DL
44145 JZ @@exit
44146 MOV [EAX].fTransparent, DL
44147 TEST DL, DL
44148 JZ @@exit
44149 MOV ECX, [EAX].fParent
44150 JECXZ @@exit
44151 XCHG EAX, ECX
44152 CALL SetDoubleBuffered
44153 @@exit:
44154 end;
44155 {$ELSE ASM_VERSION} //Pascal
44156 procedure TControl.SetTransparent(const Value: Boolean);
44157 begin
44158 if fTransparent = Value then Exit;
44159 fTransparent := Value;
44160 //ExStyle := ExStyle or WS_EX_TRANSPARENT;
44161 if fParent = nil then Exit;
44162 if Value then
44163 fParent.DoubleBuffered := True;
44164 end;
44165 {$ENDIF ASM_VERSION}
44167 //[function TControl.SetBorder]
44168 function TControl.SetBorder( Value: Integer ): PControl;
44169 begin
44170 fMargin := Value;
44171 Result := @ Self;
44172 end;
44174 { TTrayIcon }
44176 var FTrayItems: PList;
44178 //[FUNCTION WndProcTray]
44179 {$IFDEF ASM_noVERSION}
44180 function WndProcTray( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44182 PUSH ECX
44183 MOV ECX, [EDX].TMsg.message
44184 CMP CX, CM_TRAYICON
44185 JNE @@1
44187 MOV ECX, [EDX].TMsg.lParam
44188 MOV EDX, [EDX].TMsg.wParam
44189 MOV EAX, [EDX].TTrayIcon.fOnMouse.TMethod.Data
44190 CMP word ptr [EDX].TTrayIcon.fOnMouse.TMethod.Code+2, 0
44191 JE @@no_on
44193 CALL [EDX].TTrayIcon.fOnMouse.TMethod.Code
44194 @@no_on:
44195 POP ECX
44196 XOR EAX, EAX
44197 MOV [ECX], EAX
44198 INC EAX
44201 @@1:
44202 SUB ECX, WM_CLOSE
44203 JNE @@exit_0
44204 @@2:
44206 POP ECX
44207 PUSH EBX
44208 XCHG EBX, EAX
44210 MOV EAX, [EBX].TControl.fHandle
44211 CMP EAX, [EDX].TMsg.hwnd
44212 JNE @@otherwin
44214 MOV EDX, [FTrayItems]
44215 MOV ECX, [EDX].TList.fCount
44216 MOV EDX, [EDX].TList.fItems
44217 @@loop:
44218 MOV EAX, [EDX + ECX*4 - 4]
44219 CMP [EAX].TTray.FNoAutoDeactivate, 0
44220 JNZ @@3
44221 CMP [EAX].TTrayIcon.fControl, EBX
44222 JNE @@3
44223 PUSHAD
44224 XOR EDX, EDX
44225 CALL TTrayIcon.SetActive
44226 POPAD
44227 @@3: LOOP @@loop
44229 @@otherwin:
44230 POP EBX
44231 PUSH ECX
44233 @@exit_0:
44234 XOR EAX, EAX
44235 POP ECX
44236 end;
44237 {$ELSE ASM_VERSION} //Pascal
44238 function WndProcTray( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44239 var Self_: PTrayIcon;
44240 I : Integer;
44241 begin
44242 Result := False;
44243 case Msg.message of
44244 CM_TRAYICON:
44245 begin
44246 Self_ := Pointer( Msg.wParam );
44247 if Assigned( Self_.FOnMouse ) then
44248 Self_.FOnMouse( @Self_, Msg.lParam );
44249 Rslt := 0;
44250 Result := True;
44251 end;
44252 WM_CLOSE:
44253 if Msg.hwnd = Control.fHandle then
44254 begin
44255 if FTrayItems <> nil then // ?????????????????
44256 for I := FTrayItems.Count - 1 downto 0 do
44257 begin
44258 Self_ := FTrayItems.Items[ I ];
44259 if not Self_.FNoAutoDeactivate then
44260 if Self_.FControl = Control then
44261 Self_.Active := False;
44262 end;
44263 end;
44264 end;
44265 end;
44266 {$ENDIF ASM_VERSION}
44267 //[END WndProcTray]
44269 //[FUNCTION _NewTrayIcon]
44270 {$IFDEF ASM_VERSION}
44271 function _NewTrayIcon: PTrayIcon;
44272 begin
44273 New(Result,Create);
44274 end;
44275 {$ENDIF ASM_VERSION}
44276 //[END _NewTrayIcon]
44278 function WndProcTrayIconWnd( Wnd: HWnd; Msg: DWORD; wParam, lParam: Integer ): Integer;
44279 stdcall;
44280 var PrevProc: function ( Wnd: HWnd; Msg: DWORD;
44281 wParam, lParam: Integer ): Integer; stdcall;
44282 var Tr: PTrayIcon;
44283 begin
44284 PrevProc := Pointer( GetProp( Wnd, 'TRAYSAVEPROC' ) );
44285 if Msg = CM_TRAYICON then
44286 begin
44287 Tr := Pointer( wParam );
44288 if Assigned( Tr.FOnMouse ) then
44289 Tr.FOnMouse( Tr, lParam );
44290 Result := 0;
44291 Exit;
44293 else
44294 if Msg = WM_CLOSE then
44295 begin
44296 if Assigned( PrevProc ) then
44297 begin
44298 SetWindowLong( Wnd, GWL_WNDPROC, Integer( @ PrevProc ) );
44299 RemoveProp( Wnd, 'TRAYSAVEPROC' );
44300 PostMessage( Wnd, WM_CLOSE, wParam, lParam );
44301 Result := 0;
44302 Exit;
44303 //Wnd := 0;
44304 end;
44305 end;
44306 if (Wnd <> 0) and IsWindow( Wnd ) and Assigned( PrevProc ) then
44307 Result := PrevProc( Wnd, Msg, wParam, lParam )
44308 else
44309 Result := DefWindowProc( Wnd, Msg, wParam, lParam );
44310 end;
44312 //[PROCEDURE TTrayIcon.AttachProc2Wnd]
44313 procedure TTrayIcon.AttachProc2Wnd;
44314 begin
44315 if FWnd = 0 then Exit;
44316 if GetProp( FWnd, 'TRAYSAVEPROC' ) <> 0 then Exit; // already attached
44317 SetProp( FWnd, 'TRAYSAVEPROC', GetWindowLong( FWnd, GWL_WNDPROC ) );
44318 SetWindowLong( FWnd, GWL_WNDPROC, Integer( @ WndProcTrayIconWnd ) );
44319 end;
44320 // [END TTrayIcon.AttachProc2Wnd]
44322 // [PROCEDURE TTrayIcon.DetachProc2Wnd]
44323 procedure TTrayIcon.DetachProc2Wnd;
44324 var OldProc: function ( Wnd: HWnd; Msg: DWORD;
44325 wParam, lParam: Integer ): Integer; stdcall;
44326 begin
44327 if FWnd = 0 then Exit;
44328 OldProc := Pointer( GetProp( FWnd, 'TRAYSAVEPROC' ) );
44329 if not Assigned( OldProc ) then Exit; // not attached
44330 SetWindowLong( FWnd, GWL_WNDPROC, Integer( @ OldProc ) );
44331 RemoveProp( FWnd, 'TRAYSAVEPROC' );
44332 end;
44333 // [END TTrayIcon.DetachProc2Wnd]
44335 //[FUNCTION NewTrayIcon]
44336 {$IFDEF ASM_VERSION}
44337 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;
44339 PUSH EBX
44340 PUSH EDX // push Icon
44341 PUSH EAX // push Wnd
44342 CALL _NewTrayIcon
44343 XCHG EBX, EAX
44345 MOV EAX, [FTrayItems]
44346 TEST EAX, EAX
44347 JNZ @@1
44348 CALL NewList
44349 MOV [FTrayItems], EAX
44350 @@1:
44351 MOV EDX, EBX
44352 CALL TList.Add
44354 POP EAX //Wnd
44355 MOV [EBX].TTrayIcon.fControl, EAX
44356 POP [EBX].TTrayIcon.fIcon //Icon
44358 MOV EDX, offset[WndProcTray]
44359 TEST EAX, EAX
44360 JZ @@2
44361 CALL TControl.AttachProc
44362 @@2:
44363 MOV DL, 1
44364 MOV EAX, EBX
44365 CALL TTrayIcon.SetActive
44366 XCHG EAX, EBX
44367 POP EBX
44368 end;
44369 {$ELSE ASM_VERSION} //Pascal
44370 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;
44371 begin
44372 if FTrayItems = nil then
44373 FTrayItems := NewList;
44375 New( Result, Create );
44376 {+}{++}(*Result := PTrayIcon.Create;*){--}
44377 FTrayItems.Add( Result );
44378 if Wnd <> nil then
44379 Wnd.AttachProc( WndProcTray );
44380 Result.FControl := Wnd;
44381 Result.FIcon := Icon;
44382 Result.Active := True;
44383 end;
44384 {$ENDIF ASM_VERSION}
44385 //[END NewTrayIcon]
44387 var fRecreateMsg: DWORD;
44389 //[FUNCTION WndProcRecreateTrayIcons]
44390 {$IFDEF ASM_VERSION}
44391 function WndProcRecreateTrayIcons( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
44392 asm //cmd //opd
44393 MOV ECX, [fRecreateMsg]
44394 CMP word ptr [EDX].TMsg.message, CX
44395 JNE @@ret_false
44396 PUSH ESI
44397 MOV ESI, [FTrayItems]
44398 MOV ECX, [ESI].TList.fCount
44399 MOV ESI, [ESI].TList.fItems
44400 //JECXZ @@e_loo
44401 @@loo: PUSH ECX
44402 LODSD
44403 MOV DL, [EAX].TTrayIcon.fAutoRecreate
44404 AND DL, [EAX].TTrayIcon.fActive
44405 JZ @@nx
44406 DEC [EAX].TTrayIcon.fActive
44407 CALL TTrayIcon.SetActive
44408 @@nx: POP ECX
44409 LOOP @@loo
44410 @@e_loo:POP ESI
44411 @@ret_false:
44412 XOR EAX, EAX
44413 end;
44414 {$ELSE ASM_VERSION} //Pascal
44415 function WndProcRecreateTrayIcons( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
44416 var I: Integer;
44417 TI: PTrayIcon;
44418 begin
44419 if Msg.message = fRecreateMsg then
44420 begin
44421 for I := 0 to FTrayItems.fCount - 1 do
44422 begin
44423 TI := FTrayItems.Items[ I ];
44424 if TI.fAutoRecreate then
44425 if TI.fActive then
44426 begin
44427 TI.fActive := False;
44428 TI.Active := True;
44429 end;
44430 end;
44431 end;
44432 Result := False;
44433 end;
44434 {$ENDIF ASM_VERSION}
44435 //[END WndProcRecreateTrayIcons]
44437 const
44438 TaskbarCreatedMsg: array[ 0..14 ] of Char = ('T','a','s','k','b','a','r',
44439 'C','r','e','a','t','e','d',#0);
44440 {$IFDEF ASM_VERSION}
44441 //[procedure TTrayIcon.SetAutoRecreate]
44442 procedure TTrayIcon.SetAutoRecreate(const Value: Boolean);
44443 asm //cmd //opd
44444 MOV [EAX].fAutoRecreate, DL
44445 MOV EAX, [EAX].FControl
44446 CALL TControl.ParentForm
44447 MOV EDX, offset[WndProcRecreateTrayIcons]
44448 CALL TControl.AttachProc
44449 PUSH offset[TaskbarCreatedMsg]
44450 CALL RegisterWindowMessage
44451 MOV [fRecreateMsg], EAX
44452 end;
44453 {$ELSE ASM_VERSION} //Pascal
44454 procedure TTrayIcon.SetAutoRecreate(const Value: Boolean);
44455 begin
44456 fAutoRecreate := Value;
44457 FControl.ParentForm.AttachProc( WndProcRecreateTrayIcons );
44458 fRecreateMsg := RegisterWindowMessage( TaskbarCreatedMsg );
44459 end;
44460 {$ENDIF ASM_VERSION}
44462 {$IFDEF ASM_VERSION}
44463 //[destructor TTrayIcon.Destroy]
44464 destructor TTrayIcon.Destroy;
44466 PUSH EBX
44467 PUSH ESI
44468 MOV EBX, EAX
44469 XOR EDX, EDX
44470 CALL SetActive
44472 MOV ECX, [EBX].fIcon
44473 JECXZ @@icon_destroyed
44474 PUSH ECX
44475 CALL DestroyIcon
44476 @@icon_destroyed:
44478 MOV EDX, EBX
44479 MOV ESI, [FTrayItems]
44480 MOV EAX, ESI
44481 CALL TList.IndexOf
44482 TEST EAX, EAX
44483 JL @@fin
44484 XCHG EDX, EAX
44485 MOV EAX, ESI
44486 CALL TList.Delete
44487 MOV EAX, [ESI].TList.fCount
44488 TEST EAX, EAX
44489 JNZ @@fin
44490 XCHG EAX, [FTrayItems]
44491 CALL TObj.Free
44492 @@fin: LEA EAX, [EBX].FTooltip
44493 CALL System.@LStrClr
44494 XCHG EAX, EBX
44495 CALL TObj.Destroy
44496 POP ESI
44497 POP EBX
44498 end;
44499 {$ELSE ASM_VERSION} //Pascal
44500 destructor TTrayIcon.Destroy;
44501 begin
44502 Active := False;
44504 if fIcon <> 0 then
44505 DestroyIcon( fIcon );
44507 FTrayItems.Remove( @ Self );
44508 if FTrayItems.Count = 0 then
44509 Free_And_Nil( FTrayItems );
44510 FTooltip := '';
44511 inherited;
44512 end;
44513 {$ENDIF ASM_VERSION}
44515 {$IFDEF ASM_VERSION}
44516 //[procedure TTrayIcon.SetActive]
44517 procedure TTrayIcon.SetActive(const Value: Boolean);
44519 CMP [EAX].fActive, DL
44520 JE @@exit
44521 MOV ECX, [EAX].fIcon
44522 JECXZ @@exit
44523 PUSH EDX
44524 PUSH EAX
44525 MOV ECX, [EAX].FWnd
44526 INC ECX
44527 LOOP @@1
44528 MOV ECX, [EAX].fControl
44529 XOR EAX, EAX
44530 JECXZ @@1
44531 XCHG EAX, ECX
44532 CALL TControl.GetWindowHandle
44533 @@1:
44534 POP ECX
44535 POP EDX
44536 XCHG EAX, ECX
44537 JECXZ @@exit
44538 MOV [EAX].fActive, DL
44539 MOVZX EDX, DL
44540 XOR DL, 1
44541 ADD EDX, EDX
44542 CALL SetTrayIcon
44543 @@exit:
44544 end;
44545 {$ELSE ASM_VERSION} //Pascal
44546 procedure TTrayIcon.SetActive(const Value: Boolean);
44547 begin
44548 if FActive = Value then Exit;
44549 if FIcon = 0 then Exit;
44550 if (Wnd = 0) and ((FControl = nil) or (FControl.GetWindowHandle = 0)) then Exit;
44551 FActive := Value;
44552 if Value then
44553 SetTrayIcon( NIM_ADD )
44554 else
44555 SetTrayIcon( NIM_DELETE );
44556 end;
44557 {$ENDIF ASM_VERSION}
44559 {$IFDEF ASM_VERSION}
44560 //[procedure TTrayIcon.SetIcon]
44561 procedure TTrayIcon.SetIcon(const Value: HIcon);
44563 MOV ECX, [EAX].fIcon
44564 CMP ECX, EDX
44565 JE @@exit
44566 MOV [EAX].fIcon, EDX
44567 XOR EDX, EDX
44568 JECXZ @@nim_add
44569 INC EDX // NIM_MODIFY = 1
44570 @@nim_add:
44571 MOVZX ECX, [EAX].fActive
44572 JECXZ @@exit
44573 CALL SetTrayIcon
44574 @@exit:
44575 end;
44576 {$ELSE ASM_VERSION} //Pascal
44577 procedure TTrayIcon.SetIcon(const Value: HIcon);
44578 var Cmd : DWORD;
44579 begin
44580 if FIcon = Value then Exit;
44581 // Previous icon is not destroying. This is normal for
44582 // icons, loaded from resources using LoadIcon. For icons,
44583 // created using CreateIconIndirect, You have to call
44584 // DestroyIcon manually.
44585 Cmd := NIM_MODIFY;
44586 if FIcon = 0 then
44587 Cmd := NIM_ADD;
44588 FIcon := Value;
44589 if FActive then
44590 SetTrayIcon( Cmd );
44591 end;
44592 {$ENDIF ASM_VERSION}
44594 {$IFDEF ASM_VERSION}
44595 //[procedure TTrayIcon.SetTooltip]
44596 procedure TTrayIcon.SetTooltip(const Value: String);
44598 PUSH EBX
44599 XCHG EBX, EAX
44600 MOV EAX, [EBX].fTooltip
44601 PUSH EDX
44602 CALL System.@LStrCmp
44603 POP EDX
44604 JE @@exit
44605 LEA EAX, [EBX].fTooltip
44606 CALL System.@LStrAsg
44607 CMP [EBX].fActive, 0
44608 JE @@exit
44609 XOR EDX, EDX
44610 INC EDX // EDX = NIM_MODIFY
44611 XCHG EAX, EBX
44612 CALL SetTrayIcon
44613 @@exit:
44614 POP EBX
44615 end;
44616 {$ELSE ASM_VERSION} //Pascal
44617 procedure TTrayIcon.SetTooltip(const Value: String);
44618 begin
44619 if FTooltip = Value then Exit;
44620 FTooltip := Value;
44621 if Active then
44622 SetTrayIcon( NIM_MODIFY );
44623 end;
44624 {$ENDIF ASM_VERSION}
44626 {$IFDEF ASM_VERSION}
44627 //[procedure TTrayIcon.SetTrayIcon]
44628 procedure TTrayIcon.SetTrayIcon(const Value: DWORD);
44629 const sz_tid = sizeof( TNotifyIconData );
44631 //MOV ECX, [EAX].fIcon
44632 //JECXZ @@exit
44634 CMP [AppletTerminated], 0
44635 JE @@1
44636 MOV DL, NIM_DELETE
44637 @@1:
44638 PUSH EBX
44639 PUSH ESI
44640 MOV ESI, EAX
44641 MOV EBX, EDX
44643 XOR ECX, ECX
44644 PUSH ECX
44645 ADD ESP, -60
44646 MOV EDX, [ESI].fToolTip
44647 CALL EDX2PChar
44648 MOV EAX, ESP
44649 MOV CL, 63
44650 CALL StrLCopy
44652 PUSH [ESI].fIcon
44653 PUSH CM_TRAYICON
44654 XOR EDX, EDX
44655 CMP BL, NIM_DELETE
44656 JE @@2
44657 MOV DL, NIF_ICON or NIF_MESSAGE or NIF_TIP
44658 @@2: PUSH EDX
44659 PUSH ESI
44660 MOV EAX, [ESI].FWnd
44661 TEST EAX, EAX
44662 JNZ @@3
44663 MOV EAX, [ESI].fControl
44664 MOV EAX, [EAX].TControl.fHandle
44665 @@3:
44666 PUSH EAX
44667 PUSH sz_tid
44669 PUSH ESP
44670 PUSH EBX
44671 CALL Shell_NotifyIcon
44673 ADD ESP, sz_tid
44674 POP ESI
44675 POP EBX
44676 @@exit:
44677 end;
44678 {$ELSE ASM_VERSION} //Pascal
44679 procedure TTrayIcon.SetTrayIcon(const Value: DWORD);
44680 var NID : TNotifyIconData;
44681 L : Integer;
44682 V : DWORD;
44683 begin
44684 //if FIcon = 0 then Exit; - already tested
44685 V := Value;
44686 if AppletTerminated then
44687 V := NIM_DELETE;
44688 if Wnd <> 0 then
44689 NID.Wnd := Wnd
44690 else
44691 NID.Wnd := FControl.fHandle;
44693 NID.cbSize := Sizeof( NID );
44694 NID.uID := DWORD( @Self );
44695 NID.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
44696 if V = NIM_DELETE then
44697 NID.uFlags := 0;
44698 NID.uCallbackMessage := CM_TRAYICON;
44699 NID.hIcon := FIcon;
44700 L := Length( FToolTip );
44701 if L > 63 then L := 63;
44702 Move( FTooltip[1], NID.szTip[0], Min( 63, L ) );
44703 NID.szTip[ L ] := #0;
44705 Shell_NotifyIcon( V, @NID );
44706 end;
44707 {$ENDIF ASM_VERSION}
44709 { -- JustOne -- }
44711 var JustOneMutex: THandle;
44713 //[FUNCTION WndProcJustOne]
44714 {$IFDEF ASM_VERSION}
44715 function WndProcJustOne( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44717 MOV ECX, [EDX].TMsg.message
44718 SUB ECX, WM_CLOSE
44719 JE @@1
44720 SUB ECX, WM_NCDESTROY - WM_CLOSE
44721 JNE @@exit
44722 @@1:
44723 XCHG ECX, [JustOneMutex]
44724 JECXZ @@exit
44725 PUSH ECX
44726 PUSH ECX
44727 CALL ReleaseMutex
44728 CALL CloseHandle
44730 @@exit:
44731 XOR EAX, EAX
44732 end;
44733 {$ELSE ASM_VERSION} //Pascal
44734 function WndProcJustOne( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44735 begin
44736 Result := False;
44737 case Msg.message of
44738 WM_CLOSE, WM_NCDESTROY:
44739 if LongBool( JustOneMutex ) then
44740 begin
44741 ReleaseMutex( JustOneMutex );
44742 CloseHandle( JustOneMutex );
44743 JustOneMutex := 0;
44744 end;
44745 end;
44746 end;
44747 {$ENDIF ASM_VERSION}
44748 //[END WndProcJustOne]
44750 //[FUNCTION JustOne]
44751 {$IFDEF ASM_VERSION}
44752 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;
44753 const JOcs: PChar = 'KOL.Just1.CrtSec';
44755 PUSH EBX
44756 PUSH ESI
44757 XOR ESI, ESI
44758 PUSH EDI
44759 XCHG EBX, EAX
44761 CALL EDX2PChar
44762 PUSH EDX
44764 PUSH [JOcs]
44765 PUSH 1
44766 PUSH ESI
44767 MOV EDI, offset[CreateMutex]
44768 CALL EDI
44770 POP EDX
44771 TEST EAX, EAX
44772 JZ @@exit //
44773 PUSH EAX
44774 PUSH EAX
44776 PUSH EDX
44777 PUSH ESI
44778 PUSH ESI
44779 CALL EDI
44780 MOV [JustOneMutex], EAX
44781 TEST EAX, EAX
44782 JE @@1 //
44784 PUSH ESI
44785 PUSH EAX
44786 CALL WaitForSingleObject
44787 SUB EAX, WAIT_TIMEOUT
44788 JE @@1
44790 INC ESI
44791 @@1:
44792 //MOV [EBX].TControl.fWndProcJustOne, offset[WndProcJustOne]
44793 XCHG EAX, EBX
44794 MOV EDX, offset[WndProcJustOne]
44795 CALL TControl.AttachProc
44797 CALL ReleaseMutex
44798 CALL CloseHandle
44800 @@exit:
44801 XCHG EAX, ESI
44802 POP EDI
44803 POP ESI
44804 POP EBX
44805 end;
44806 {$ELSE ASM_VERSION} //Pascal
44807 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;
44808 var CritSecMutex : THandle;
44809 DW : Longint;
44810 begin
44811 Result := False;
44812 CritSecMutex := CreateMutex( nil, True, PChar( 'KOL.Just1.CrtSec' ) );
44813 if CritSecMutex = 0 then Exit;
44815 JustOneMutex := CreateMutex( nil, False, PChar( Identifier ) );
44816 if JustOneMutex <> 0 then
44817 begin
44818 DW := WaitForSingleObject( JustOneMutex, 0 );
44819 Result := (DW <> WAIT_TIMEOUT);
44820 end;
44822 //Wnd.fWndProcJustOne := WndProcJustOne;
44823 Wnd.AttachProc( WndProcJustOne );
44825 ReleaseMutex( CritSecMutex );
44826 CloseHandle( CritSecMutex );
44827 end;
44828 {$ENDIF ASM_VERSION}
44829 //[END JustOne]
44831 { JustOneNotify }
44834 OnAnotherInstance: TOnAnotherInstance;
44835 JustOneMsg: DWORD;
44837 //[FUNCTION WndProcJustOneNotify]
44838 {$IFDEF ASM_VERSION}
44839 function WndProcJustOneNotify( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44841 PUSH EBP
44842 MOV EBP, ESP
44843 PUSHAD
44844 CALL WndProcJustOne
44845 POPAD
44846 XOR EAX, EAX
44847 PUSH ECX
44848 MOV ECX, [EDX].TMsg.message
44849 SUB ECX, [JustOneMsg]
44850 POP ECX
44851 JNE @@exit
44852 MOV [ECX], EAX
44853 CMP [OnAnotherInstance].TMethod.Code, EAX
44854 JE @@exit_1
44856 //MOV EAX, (MAX_PATH + 3) and 0FFFFCh
44857 MOV AH, 2
44858 SUB ESP, EAX
44860 MOV ECX, ESP
44861 PUSH EAX
44862 PUSH ECX
44863 PUSH [EDX].TMsg.lParam
44864 CALL GetWindowText
44866 MOV EDX, ESP
44867 PUSH 0
44868 MOV EAX, ESP
44869 CALL System.@LStrFromPChar
44871 MOV EDX, [ESP]
44872 MOV EAX, [OnAnotherInstance].TMethod.Data
44873 CALL [OnAnotherInstance].TMethod.Code
44875 MOV EAX, ESP
44876 CALL System.@LStrClr
44877 @@exit_1:
44878 MOV AL, 1
44879 @@exit:
44880 MOV ESP, EBP
44881 POP EBP
44882 end;
44883 {$ELSE ASM_VERSION} //Pascal
44884 function WndProcJustOneNotify( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44885 var Buf : array[0..MAX_PATH] of Char;
44886 begin
44887 WndProcJustOne( Control, Msg, Rslt );
44888 Result := False;
44889 if Msg.message = JustOneMsg then
44890 begin
44891 Result := True;
44892 if assigned( OnAnotherInstance ) then
44893 begin
44894 GetWindowText( Msg.lParam, Buf, MAX_PATH );
44895 OnAnotherInstance( Buf );
44896 end;
44897 Rslt := 0;
44898 end;
44899 end;
44900 {$ENDIF ASM_VERSION}
44901 //[END WndProcJustOneNotify]
44903 // Redefine here incorrectly declared BroadcastSystemMessage API function.
44904 // It should not refer to BroadcastSystemMessageA, which is not present in
44905 // earlier versions of Windows95, but to BroadcastSystemMessage, which is
44906 // present in all Windows95/98/Me and NT/2K/XP.
44907 //[API BroadcastSystemMessage]
44908 function BroadcastSystemMessage(Flags: DWORD; Recipients: PDWORD;
44909 uiMessage: UINT; wParam: WPARAM; lParam: LPARAM): Longint; stdcall;
44910 external user32 name 'BroadcastSystemMessage';
44912 //[FUNCTION JustOneNotify]
44913 {$IFDEF ASM_VERSION}
44914 function JustOneNotify( Wnd: PControl; const Identifier : String;
44915 const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;
44917 PUSHAD
44918 MOV EBP, ESP
44920 XCHG EAX, EDX
44921 PUSH EAX
44922 CALL System.@LStrLen
44923 POP EDX
44924 ADD EAX, EAX
44925 SUB ESP, EAX
44926 MOV EAX, ESP
44927 CALL StrPCopy
44928 PUSH '.ega'
44929 PUSH 'sseM'
44930 PUSH ESP
44931 CALL RegisterWindowMessage
44932 MOV [JustOneMsg], EAX
44933 TEST EAX, EAX
44935 MOV ESP, EBP
44936 POPAD
44937 JE @@exit_f
44939 PUSHAD
44940 CALL JustOne
44941 DEC AL
44942 POPAD
44943 JZ @@exit_t
44945 PUSH EBX
44946 XCHG EBX, EAX
44947 XOR EDX, EDX
44948 XCHG [EBX].TControl.fCaption, EDX
44949 PUSH EDX
44951 CALL GetCommandLine
44952 XCHG EDX, EAX
44953 MOV EAX, EBX
44954 CALL TControl.SetCaption
44955 MOV EAX, EBX
44956 CALL TControl.GetWindowHandle
44957 TEST EAX, EAX
44958 JZ @@rest_cap
44960 PUSH BSM_APPLICATIONS
44961 MOV EDX, ESP
44963 PUSH EAX
44964 PUSH 0
44965 PUSH [JustOneMsg]
44966 PUSH EDX
44967 PUSH BSF_QUERY or BSF_IGNORECURRENTTASK
44968 CALL BroadcastSystemMessage
44970 POP EDX
44971 @@rest_cap:
44972 XOR EDX, EDX
44973 MOV EAX, EBX
44974 CALL TControl.SetCaption
44975 POP EDX
44976 MOV [EBX].TControl.fCaption, EDX
44977 PUSH EDX
44978 PUSH [EBX].TControl.fHandle
44979 CALL SetWindowText
44980 POP EBX
44981 @@exit_f:
44982 XOR EAX, EAX
44983 POP EBP // because compiler inserts PUSH EBP;MOV EBP,ESP at the BEGIN
44986 @@exit_t:
44987 PUSHAD
44988 LEA ESI, [aOnAnotherInstance]
44989 LEA EDI, [OnAnotherInstance]
44990 MOVSD
44991 MOVSD
44992 //MOV [EAX].TControl.fWndProcJustOne, offset[WndProcJustOneNotify]
44993 MOV EDX, offset[WndProcJustOneNotify]
44994 CALL TControl.AttachProc
44996 POPAD
44997 MOV AL, 1
44998 end;
44999 {$ELSE ASM_VERSION} //Pascal
45000 function JustOneNotify( Wnd: PControl; const Identifier : String;
45001 const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;
45002 var Recipients : DWord;
45003 OldCap: String;
45004 begin
45005 Result := False;
45006 JustOneMsg := RegisterWindowMessage( PChar( 'Message.' + Identifier ) );
45007 if JustOneMsg = 0 then Exit;
45009 Result := JustOne( Wnd, Identifier );
45010 if not Result then
45011 begin
45012 // Send a message to the first instance of applet
45014 //Wnd.CreateVisible := False;
45015 OldCap := Wnd.Caption;
45016 Wnd.Caption := GetCommandLine;
45017 if Wnd.GetWindowHandle <> 0 then
45018 begin
45019 Recipients := BSM_APPLICATIONS;
45020 BroadcastSystemMessage( BSF_QUERY or BSF_IGNORECURRENTTASK, @Recipients,
45021 JustOneMsg, 0, Wnd.fHandle );
45022 end;
45023 Wnd.Caption := OldCap;
45025 else
45026 begin
45027 // Store event handler to notify this instance about another
45028 // instance staring:
45029 OnAnotherInstance := aOnAnotherInstance;
45030 //Wnd.fWndProcJustOne := WndProcJustOneNotify;
45031 Wnd.AttachProc( WndProcJustOneNotify );
45034 if JustOneNotifier = nil then
45035 JustOneNotifier := ZJustOneNotifier.Create;
45037 end;
45038 end;
45039 {$ENDIF ASM_VERSION}
45040 //[END JustOneNotify]
45043 ///////////////////////////////////////// STRING LIST OBJECT /////////////////
45045 { TStrList }
45047 //[function NewStrList]
45048 function NewStrList: PStrList;
45049 begin
45051 New( Result, Create );
45053 {++}(*
45054 Result := PStrList.Create;
45055 *){--}
45056 end;
45057 //[END NewStrList]
45059 {$IFDEF ASM_VERSION}
45060 //[destructor TStrList.Destroy]
45061 destructor TStrList.Destroy;
45063 PUSH EAX
45064 CALL Clear
45065 POP EAX
45066 CALL TObj.Destroy
45067 end;
45068 {$ELSE ASM_VERSION} //Pascal
45069 destructor TStrList.Destroy;
45070 begin
45071 Clear;
45072 inherited;
45073 end;
45074 {$ENDIF ASM_VERSION}
45076 //[procedure TStrList.Init]
45077 procedure TStrList.Init;
45078 begin
45079 //inherited;
45080 fNameDelim := DefaultNameDelimiter;
45081 end;
45083 {$IFDEF ASM_VERSION}
45084 //[function TStrList.Add]
45085 function TStrList.Add(const S: string): integer;
45087 MOV ECX, EDX
45088 MOV EDX, [EAX].fCount
45089 PUSH EDX
45090 CALL Insert
45091 POP EAX
45092 end;
45093 {$ELSE ASM_VERSION} //Pascal
45094 function TStrList.Add(const S: string): integer;
45095 begin
45096 Result := fCount;
45097 Insert( Result, S );
45098 end;
45099 {$ENDIF ASM_VERSION}
45101 {$IFDEF ASM_VERSION}
45102 //[procedure TStrList.AddStrings]
45103 procedure TStrList.AddStrings(Strings: PStrList);
45105 PUSH EAX
45106 XCHG EAX, EDX
45107 PUSH 0
45108 MOV EDX, ESP
45109 CALL GetTextStr
45110 POP EDX
45111 POP EAX
45112 MOV CL, 1
45113 PUSH EDX
45114 CALL SetText
45115 CALL RemoveStr
45116 end;
45117 {$ELSE ASM_VERSION} //Pascal
45118 procedure TStrList.AddStrings(Strings: PStrList);
45119 begin
45120 SetText( Strings.Text, True );
45121 end;
45122 {$ENDIF ASM_VERSION}
45124 {$IFDEF ASM_VERSION}
45125 //[function TStrList.AppendToFile]
45126 function TStrList.AppendToFile(const FileName: string): Boolean;
45128 PUSH EBX
45129 MOV EBX, EDX
45130 PUSH 0
45131 MOV EDX, ESP
45132 CALL GetTextStr
45133 XCHG EAX, EBX
45134 MOV EDX, ofOpenWrite or ofOpenAlways
45135 CALL FileCreate
45136 MOV EBX, EAX
45137 INC EAX
45138 JZ @@exit
45139 DEC EAX
45140 XOR EDX, EDX
45141 XOR ECX, ECX
45142 MOV CL, spEnd
45143 CALL FileSeek
45144 POP EAX
45145 PUSH EAX
45146 CALL System.@LStrLen
45147 XCHG ECX, EAX
45148 MOV EAX, EBX
45149 POP EDX
45150 PUSH EDX
45151 CALL FileWrite
45152 XCHG EAX, EBX
45153 CALL FileClose
45154 @@exit:
45155 CALL RemoveStr
45156 POP EBX
45157 end;
45158 {$ELSE ASM_VERSION} //Pascal
45159 function TStrList.AppendToFile(const FileName: string): Boolean;
45160 var F: HFile;
45161 Buf: String;
45162 L: Integer;
45163 begin
45164 F := FileCreate( FileName, ofOpenWrite or ofOpenAlways );
45165 Result := F <> INVALID_HANDLE_VALUE;
45166 if Result then
45167 begin
45168 FileSeek( F, 0, spEnd );
45169 Buf := Text;
45170 L := Length( Buf );
45171 FileWrite( F, Buf[ 1 ], L );
45172 FileClose( F );
45173 end;
45174 end;
45175 {$ENDIF ASM_VERSION}
45177 {$IFDEF ASM_VERSION}
45178 //[procedure TStrList.Assign]
45179 procedure TStrList.Assign(Strings: PStrList);
45181 PUSHAD
45182 CALL Clear
45183 POPAD
45184 JMP AddStrings
45185 end;
45186 {$ELSE ASM_VERSION} //Pascal
45187 procedure TStrList.Assign(Strings: PStrList);
45188 begin
45189 Clear;
45190 AddStrings( Strings );
45191 end;
45192 {$ENDIF ASM_VERSION}
45194 {$IFDEF ASM_VERSION}
45195 //[procedure TStrList.Clear]
45196 procedure TStrList.Clear;
45198 PUSH EBX
45199 XCHG EBX, EAX
45200 MOV EDX, [EBX].fCount
45201 @@loo: DEC EDX
45202 JL @@eloo
45203 PUSH EDX
45204 MOV EAX, EBX
45205 CALL Delete
45206 POP EDX
45207 JMP @@loo
45208 @@eloo:
45209 XOR EAX, EAX
45210 MOV [EBX].fTextSiz, EAX
45211 XCHG EAX, [EBX].fTextBuf
45212 TEST EAX, EAX
45213 JZ @@1
45214 CALL System.@FreeMem
45215 //XOR EAX, EAX // not needed: if OK, EAX = 0
45216 @@1: XCHG EAX, [EBX].fList
45217 CALL TObj.Free
45218 POP EBX
45219 end;
45220 {$ELSE ASM_VERSION} //Pascal
45221 procedure TStrList.Clear;
45222 var I: Integer;
45223 begin
45224 if fCount > 0 then
45225 for I := fList.Count - 1 downto 0 do
45226 Delete( I );
45227 fList.Free;
45228 fList := nil;
45229 fCount := 0;
45230 if fTextBuf <> nil then
45231 begin
45232 FreeMem( fTextBuf );
45233 fTextBuf := nil;
45234 fTextSiz := 0;
45235 end;
45236 end;
45237 {$ENDIF ASM_VERSION}
45239 {$IFDEF ASM_VERSION}
45240 //[procedure TStrList.Delete]
45241 procedure TStrList.Delete(Idx: integer);
45243 DEC [EAX].fCount
45244 PUSH EAX
45245 MOV EAX, [EAX].fList
45246 MOV ECX, [EAX].TList.fItems
45247 PUSH dword ptr [ECX+EDX*4]
45248 CALL TList.Delete
45249 POP EAX
45250 POP EDX
45251 MOV ECX, [EDX].fTextSiz
45252 JECXZ @@fremem
45253 CMP EAX, [EDX].fTextBuf
45254 JB @@fremem
45255 ADD ECX, [EDX].fTextBuf
45256 CMP EAX, ECX
45257 JB @@exit
45258 @@fremem:
45259 CALL System.@FreeMem
45260 @@exit:
45261 end;
45262 {$ELSE ASM_VERSION} //Pascal
45263 procedure TStrList.Delete(Idx: integer);
45264 var P: DWORD;
45265 El:Pointer;
45266 begin
45267 P := DWORD( fList.fItems[ Idx ] );
45268 if (fTextBuf <> nil) and ( P >= DWORD( fTextBuf )) and
45269 ( P < DWORD( fTextBuf ) + fTextSiz ) then
45270 else
45271 begin
45272 El := FList.Items[ Idx ];
45273 FreeMem( El );
45274 end;
45275 fList.Delete( Idx );
45276 Dec( fCount );
45277 end;
45278 {$ENDIF ASM_VERSION}
45280 {$IFDEF ASM_VERSION}
45281 //[function TStrList.Get]
45282 function TStrList.Get(Idx: integer): string;
45284 PUSH ECX
45285 MOV EAX, [EAX].fList
45286 TEST EAX, EAX
45287 JZ @@1
45288 CALL TList.Get
45289 @@1: XCHG EDX, EAX
45290 POP EAX
45291 JMP System.@LStrFromPChar
45292 end;
45293 {$ELSE ASM_VERSION} //Pascal
45294 function TStrList.Get(Idx: integer): string;
45295 begin
45296 if fList <> nil then
45297 Result := PChar( fList.Items[ Idx ] )
45298 else Result := '';
45299 end;
45300 {$ENDIF ASM_VERSION}
45302 {$IFDEF ASM_VERSION}
45303 //[function TStrList.GetPChars]
45304 function TStrList.GetPChars(Idx: Integer): PChar;
45306 MOV EAX, [EAX].fList
45307 MOV EAX, [EAX].TList.fItems
45308 MOV EAX, [EAX+EDX*4]
45309 end;
45310 {$ELSE ASM_VERSION} //Pascal
45311 function TStrList.GetPChars(Idx: Integer): PChar;
45312 begin
45313 Result := PChar( fList.fItems[ Idx ] );
45314 end;
45315 {$ENDIF ASM_VERSION}
45317 {$IFDEF ASM_VERSION}
45318 //[function TStrList.GetTextStr]
45319 function TStrList.GetTextStr: string;
45321 PUSH ESI
45322 PUSH EDI
45323 MOV ECX, [EAX].fCount
45324 MOV EAX, [EAX].fList
45325 PUSH ECX
45326 JECXZ @@1
45327 MOV ESI, [EAX].TList.fItems
45328 @@1: PUSH ESI
45329 XCHG EAX, EDX
45330 XOR EDX, EDX
45331 JECXZ @@10
45332 PUSH EAX
45333 @@loo1:
45334 PUSH ECX
45335 PUSH EDX
45336 LODSD
45337 CALL StrLen
45338 POP EDX
45339 LEA EDX, [EDX+EAX+2]
45340 POP ECX
45341 LOOP @@loo1
45343 POP EAX
45344 POP ESI
45345 XCHG ECX, EDX
45346 PUSH EAX
45347 @@10:
45348 {$IFDEF _D2}
45349 CALL _LStrFromPCharLen
45350 {$ELSE}
45351 CALL System.@LStrFromPCharLen
45352 {$ENDIF}
45354 POP EDI
45355 POP ECX
45356 JECXZ @@exit
45357 MOV EDI, [EDI]
45359 @@loo2: PUSH ECX
45360 LODSD
45361 PUSH EAX
45362 CALL StrLen
45363 XCHG ECX, EAX
45364 POP EAX
45365 XCHG EAX, ESI
45366 REP MOVSB
45367 XCHG ESI, EAX
45368 MOV AX, $0A0D
45369 STOSW
45370 POP ECX
45371 LOOP @@loo2
45373 XCHG EAX, ECX
45374 STOSB
45375 @@exit:
45376 POP EDI
45377 POP ESI
45378 end;
45379 {$ELSE ASM_VERSION} //Pascal
45380 function TStrList.GetTextStr: string;
45382 I, Len, Size: integer;
45383 P: PChar;
45384 begin
45385 Size := 0;
45387 for I := 0 to fCount - 1 do
45388 Inc(Size, StrLen( PChar(fList.fItems[I]) ) + 2);
45390 SetString(Result, nil, Size);
45392 P := Pointer(Result);
45393 for I := 0 to Count - 1 do
45394 begin
45395 Len := StrLen(PChar(fList.fItems[I]));
45396 if (Len > 0) then
45397 begin
45398 System.Move(PChar(fList.fItems[I])^, P^, Len);
45399 Inc(P, Len);
45400 end;
45401 P^ := #13;
45402 Inc(P);
45403 P^ := #10;
45404 Inc(P);
45405 end;
45406 end;
45407 {$ENDIF ASM_VERSION}
45409 {$IFDEF ASM_VERSION}
45410 //[function TStrList.IndexOf]
45411 function TStrList.IndexOf(const S: string): integer;
45413 PUSH EBX
45414 PUSH ESI
45415 OR EBX, -1
45416 MOV ECX, [EAX].fCount
45417 JECXZ @@exit
45418 MOV ESI, [EAX].fList
45419 MOV ESI, [ESI].TList.fItems
45420 @@loo: LODSD
45421 INC EBX
45422 CMP EAX, EDX
45423 JE @@exit
45424 OR EDX, EDX
45425 JZ @@1
45426 PUSH EDX
45427 PUSH ECX
45428 CALL StrComp
45429 POP ECX
45430 POP EDX
45431 JE @@exit
45432 @@1: LOOP @@loo
45433 OR EBX, -1
45434 @@exit: XCHG EAX, EBX
45435 POP ESI
45436 POP EBX
45437 end;
45438 {$ELSE ASM_VERSION} //Pascal
45439 function TStrList.IndexOf(const S: string): integer;
45440 begin
45441 for Result := 0 to fCount - 1 do
45442 if (S = PChar( fList.Items[Result] )) then Exit;
45443 Result := -1;
45444 end;
45445 {$ENDIF ASM_VERSION}
45447 //[function TStrList.IndexOf]
45448 function TStrList.IndexOf_NoCase(const S: string): integer;
45449 begin
45450 for Result := 0 to fCount - 1 do
45451 if StrComp_NoCase( PChar( S ), PChar( fList.Items[Result] ) ) = 0 then Exit;
45452 Result := -1;
45453 end;
45455 function TStrList.IndexOfStrL_NoCase( Str: PChar; L: Integer ): integer;
45456 begin
45457 for Result := 0 to fCount - 1 do
45458 if (StrLen( PChar( fList.fItems[ Result ] ) ) = DWORD( L )) and
45459 (StrLComp_NoCase( Str, PChar( fList.fItems[ Result ] ), L ) = 0) then Exit;
45460 Result := -1;
45461 end;
45463 //[function TStrList.Find]
45464 function TStrList.Find(const S: String; var Index: Integer): Boolean;
45466 L, H, I, C: Integer;
45467 begin
45468 Result := FALSE;
45469 L := 0;
45470 H := FCount - 1;
45471 while L <= H do
45472 begin
45473 I := (L + H) shr 1;
45474 C := AnsiCompareStr( PChar( fList.Items[ I ] ), S );
45475 if C < 0 then L := I + 1 else
45476 begin
45477 H := I - 1;
45478 if C = 0 then
45479 begin
45480 Result := TRUE;
45481 L := I;
45482 //break;
45483 //if Duplicates <> dupAccept then L := I;
45484 end;
45485 end;
45486 end;
45487 Index := L;
45488 end;
45490 {$IFDEF ASM_VERSION}
45491 //[procedure TStrList.Insert]
45492 procedure TStrList.Insert(Idx: integer; const S: string);
45494 PUSH EBX
45495 PUSH EDX
45496 PUSH ECX
45497 XCHG EBX, EAX
45498 MOV EAX, [EBX].fList
45499 TEST EAX, EAX
45500 JNZ @@1
45501 CALL NewList
45502 MOV [EBX].fList, EAX
45503 @@1:
45504 POP EAX
45505 PUSH EAX // push S
45506 CALL System.@LStrLen
45507 INC EAX
45508 PUSH EAX // push L
45509 CALL System.@GetMem
45510 MOV byte ptr[EAX], 0
45511 XCHG EDX, EAX
45512 POP ECX
45513 POP EAX
45514 PUSH EDX // push Mem
45515 TEST EAX, EAX
45516 JE @@2
45517 CALL System.Move
45518 @@2: POP ECX
45519 POP EDX
45520 MOV EAX, [EBX].fList
45521 CALL TList.Insert
45522 INC [EBX].fCount
45523 POP EBX
45524 end;
45525 {$ELSE ASM_VERSION} //Pascal
45526 procedure TStrList.Insert(Idx: integer; const S: string);
45527 var Mem: PChar;
45528 L: Integer;
45529 begin
45530 if fList = nil then
45531 fList := NewList;
45532 L := Length( S ) + 1;
45533 GetMem( Mem, L );
45534 Mem[0] := #0;
45535 if L > 1 then
45536 System.Move( S[1], Mem[0], L );
45537 fList.Insert( Idx, Mem );
45538 Inc( fCount );
45539 end;
45540 {$ENDIF ASM_VERSION}
45542 {$IFDEF ASM_VERSION}
45543 //[function TStrList.LoadFromFile]
45544 function TStrList.LoadFromFile(const FileName: string): Boolean;
45546 PUSH EAX
45547 XCHG EAX, EDX
45548 MOV EDX, ofOpenRead or ofShareDenyWrite or ofOpenExisting
45549 CALL FileCreate
45550 INC EAX
45551 JZ @@exit
45552 DEC EAX
45553 PUSH EBX
45554 XCHG EBX, EAX
45555 PUSH 0
45556 PUSH EBX
45557 CALL GetFileSize
45558 XOR EDX, EDX
45559 PUSH EDX
45560 XCHG ECX, EAX
45561 MOV EAX, ESP
45562 PUSH ECX
45563 {$IFDEF _D2}
45564 CALL _LStrFromPCharLen
45565 {$ELSE}
45566 CALL System.@LStrFromPCharLen
45567 {$ENDIF}
45568 POP ECX
45569 MOV EAX, EBX
45570 POP EDX
45571 PUSH EDX
45572 CALL FileRead
45573 XCHG EAX, EBX
45574 CALL FileClose
45575 POP EDX
45576 POP EBX
45577 POP EAX
45578 PUSH EDX
45579 XOR ECX, ECX
45580 CALL SetText
45581 CALL RemoveStr
45582 PUSH EDX
45583 MOV AL, 1
45584 @@exit: POP EDX
45585 end;
45586 {$ELSE ASM_VERSION} //Pascal
45587 function TStrList.LoadFromFile(const FileName: string): Boolean;
45588 var Buf: String;
45589 F: HFile;
45590 Sz: Integer;
45591 begin
45592 F := FileCreate( FileName, ofOpenRead or ofShareDenyWrite or ofOpenExisting );
45593 Result := F <> INVALID_HANDLE_VALUE;
45594 if Result then
45595 begin
45596 Sz := GetFileSize( F, nil );
45597 SetString( Buf, nil, Sz );
45598 FileRead( F, Buf[1], Sz );
45599 FileClose( F );
45601 SetText( Buf, False );
45602 end;
45603 end;
45604 {$ENDIF ASM_VERSION}
45606 {$IFDEF ASM_VERSION}
45607 //[procedure TStrList.LoadFromStream]
45608 procedure TStrList.LoadFromStream(Stream: PStream; Append2List: boolean);
45610 PUSH EAX
45611 PUSH ECX
45612 PUSH EBX
45613 XCHG EAX, EDX
45614 MOV EBX, EAX
45615 CALL TStream.GetSize
45616 PUSH EAX
45617 MOV EAX, EBX
45618 CALL TStream.GetPosition
45619 POP ECX
45620 SUB ECX, EAX
45621 XOR EDX, EDX
45622 PUSH EDX
45623 MOV EAX, ESP
45624 PUSH ECX
45625 {$IFDEF _D2}
45626 CALL _LStrFromPCharLen
45627 {$ELSE}
45628 CALL System.@LStrFromPCharLen
45629 {$ENDIF}
45630 POP ECX
45631 POP EDX
45632 XCHG EAX, EBX
45633 PUSH EDX
45634 CALL TStream.Read
45635 POP EDX
45636 POP EBX
45637 POP ECX
45638 POP EAX
45639 PUSH EDX
45640 CALL SetText
45641 CALL RemoveStr
45642 end;
45643 {$ELSE ASM_VERSION} //Pascal
45644 procedure TStrList.LoadFromStream(Stream: PStream; Append2List: boolean);
45645 var Buf: String;
45646 Sz: Integer;
45647 begin
45648 Sz := Stream.Size - Stream.Position;
45649 SetString( Buf, nil, Sz );
45650 Stream.Read( Buf[1], Sz );
45651 SetText( Buf, Append2List );
45652 end;
45653 {$ENDIF ASM_VERSION}
45655 {$IFDEF ASM_VERSION}
45656 //[procedure TStrList.MergeFromFile]
45657 procedure TStrList.MergeFromFile(const FileName: string);
45659 PUSH EAX
45660 XCHG EAX, EDX
45661 CALL NewReadFileStream
45662 XCHG EDX, EAX
45663 POP EAX
45664 MOV CL, 1
45665 PUSH EDX
45666 CALL LoadFromStream
45667 POP EAX
45668 JMP TObj.Free
45669 end;
45670 {$ELSE ASM_VERSION} //Pascal
45671 procedure TStrList.MergeFromFile(const FileName: string);
45672 var TmpStream: PStream;
45673 begin
45674 TmpStream := NewReadFileStream( FileName );
45675 LoadFromStream( TmpStream, True );
45676 TmpStream.Free;
45677 end;
45678 {$ENDIF ASM_VERSION}
45680 //[procedure TStrList.Move]
45681 procedure TStrList.Move(CurIndex, NewIndex: integer);
45682 begin
45683 fList.MoveItem( CurIndex, NewIndex );
45684 end;
45686 {$IFDEF ASM_VERSION}
45687 //[procedure TStrList.Put]
45688 procedure TStrList.Put(Idx: integer; const Value: string);
45690 PUSH EAX
45691 PUSH EDX
45692 CALL Insert
45693 POP EDX
45694 POP EAX
45695 INC EDX
45696 JMP Delete
45697 end;
45698 {$ELSE ASM_VERSION} //Pascal
45699 procedure TStrList.Put(Idx: integer; const Value: string);
45700 begin
45701 Delete( Idx );
45702 Insert( Idx, Value );
45703 end;
45704 {$ENDIF ASM_VERSION}
45706 {$IFDEF ASM_VERSION}
45707 //[function TStrList.SaveToFile]
45708 function TStrList.SaveToFile(const FileName: string): Boolean;
45710 PUSH EBX
45711 PUSH EAX
45712 XCHG EAX, EDX
45713 MOV EDX, ofOpenWrite or ofOpenAlways
45714 CALL FileCreate
45715 INC EAX
45716 JZ @@exit
45717 DEC EAX
45718 XCHG EBX, EAX
45719 POP EAX
45720 PUSH 0
45721 MOV EDX, ESP
45722 CALL GetTextStr
45723 POP EAX
45724 PUSH EAX
45725 CALL System.@LStrLen
45726 XCHG ECX, EAX
45727 POP EDX
45728 PUSH EDX
45729 MOV EAX, EBX
45730 CALL FileWrite
45731 PUSH EBX
45732 CALL SetEndOfFile
45733 XCHG EAX, EBX
45734 CALL FileClose
45735 CALL RemoveStr
45736 PUSH EDX
45737 INC EAX
45738 @@exit:
45739 POP EDX
45740 POP EBX
45741 end;
45742 {$ELSE ASM_VERSION} //Pascal
45743 function TStrList.SaveToFile(const FileName: string): Boolean;
45744 var F: HFile;
45745 Buf: String;
45746 begin
45747 F := FileCreate( FileName, ofOpenWrite or ofOpenAlways );
45748 Result := F <> INVALID_HANDLE_VALUE;
45749 if Result then
45750 begin
45751 Buf := Text;
45752 FileWrite( F, Buf[ 1 ], Length( Buf ) );
45753 SetEndOfFile( F ); // necessary! - V.K.
45754 FileClose( F );
45755 end;
45756 end;
45757 {$ENDIF ASM_VERSION}
45759 {$IFDEF ASM_VERSION}
45760 //[procedure TStrList.SaveToStream]
45761 procedure TStrList.SaveToStream(Stream: PStream);
45763 PUSH EDX
45764 PUSH 0
45765 MOV EDX, ESP
45766 CALL GetTextStr
45767 POP EAX
45768 PUSH EAX
45769 CALL System.@LStrLen
45770 XCHG ECX, EAX
45771 POP EDX
45772 POP EAX
45773 PUSH EDX
45774 JECXZ @@1
45775 CALL TStream.Write
45776 @@1:
45777 CALL RemoveStr
45778 end;
45779 {$ELSE ASM_VERSION} //Pascal
45780 procedure TStrList.SaveToStream(Stream: PStream);
45781 var S: string;
45782 L: Integer;
45783 begin
45784 S := GetTextStr;
45785 L := Length( S );
45786 if L <> 0 then
45787 Stream.Write( S[1], L );
45788 end;
45789 {$ENDIF ASM_VERSION}
45791 {$IFDEF ASM_VERSION}
45792 //[procedure TStrList.SetText]
45793 procedure TStrList.SetText(const S: string; Append2List: boolean);
45795 DEC CL
45796 JZ @@1
45797 PUSHAD
45798 CALL Clear
45799 POPAD
45800 @@1: CALL EDX2PChar
45801 JZ @@exit
45803 PUSH EBX
45804 PUSH EDI
45805 MOV EBX, EAX
45806 MOV EDI, [EBX].fTextSiz
45808 MOV EAX, [EDX-4] // EAX = Length(S)
45809 INC EAX
45810 PUSH EAX
45812 // add S to text buffer
45813 //CMP byte ptr [EDX], 0
45814 //JZ @@eatb
45816 PUSH EDX
45817 PUSH [EBX].fTextBuf
45818 ADD EAX, [EBX].fTextSiz
45819 CALL System.@GetMem
45820 MOV [EBX].fTextBuf, EAX
45822 MOV ECX, EDI
45823 XCHG EDX, EAX
45824 POP EAX
45825 JECXZ @@atb_fin
45826 PUSH EAX
45827 CALL System.Move
45829 POP EDX
45830 PUSH EDX
45832 PUSH ESI
45833 MOV ESI, [EBX].fList
45834 MOV ESI, [ESI].TList.fItems
45835 MOV ECX, [EBX].fCount
45837 @@atb_loo:
45838 LODSD
45839 SUB EAX, EDX
45840 CMP EAX, [EBX].fTextSiz
45841 JAE @@atb_nxt
45843 ADD EAX, [EBX].fTextBuf
45844 MOV [ESI-4], EAX
45846 @@atb_nxt: LOOP @@atb_loo
45848 POP ESI
45849 POP EAX
45850 CALL System.@FreeMem
45851 @@atb_fin:
45852 POP EAX
45854 MOV EDX, EDI
45855 ADD EDX, [EBX].fTextBuf
45856 POP ECX
45857 PUSH ECX
45858 ADD [EBX].fTextSiz, ECX
45860 CALL System.Move
45862 @@eatb:
45863 ADD EDI, [EBX].fTextBuf // EDI ~ P
45865 MOV ECX, [EBX].fList
45866 INC ECX
45867 LOOP @@2
45868 CALL NewList
45869 MOV [EBX].fList, EAX
45870 @@2:
45871 POP ECX
45872 MOV EDX, [EBX].fCount
45874 PUSH EDI
45875 PUSH ECX
45876 MOV AL, $0D
45878 @@loo1: CMP byte ptr [EDI], 0
45879 JZ @@eloo1
45881 INC EDX
45882 REPNZ SCASB
45883 JNZ @@eloo1
45885 CMP byte ptr [EDI], $0A
45886 JNZ @@loo1
45887 INC EDI
45888 LOOP @@loo1
45890 @@eloo1:
45891 MOV [EBX].fCount, EDX
45892 MOV EAX, [EBX].fList
45893 PUSH EDX
45894 PUSH EAX
45895 CMP EDX, [EAX].TList.fCapacity
45896 JLE @@3
45897 CALL TList.SetCapacity
45898 @@3: POP EAX
45899 POP ECX
45901 XCHG ECX, [EAX].TList.fCount
45902 MOV EDX, [EAX].TList.fItems
45903 LEA EDX, [EDX+ECX*4]
45905 POP ECX
45906 POP EDI
45908 MOV EAX, $0D
45909 @@loo2: CMP byte ptr [EDI], AH
45910 JZ @@eloo2
45912 MOV [EDX], EDI
45913 ADD EDX, 4
45915 REPNZ SCASB
45916 JNZ @@eloo2
45918 MOV [EDI-1], AH
45920 CMP byte ptr [EDI], $0A
45921 JNZ @@loo2
45922 INC EDI
45923 LOOP @@loo2
45924 @@eloo2:
45926 POP EDI
45927 POP EBX
45928 @@exit:
45929 end;
45930 {$ELSE ASM_VERSION} //Pascal
45931 //[procedure TStrList.SetText]
45932 procedure TStrList.SetText(const S: string; Append2List: boolean);
45934 P, TheLast : PChar;
45935 L, I : Integer;
45937 procedure AddTextBuf(Src: PChar; Len: DWORD);
45938 var OldTextBuf, P: PChar;
45939 I : Integer;
45940 begin
45941 if Src <> nil then
45942 begin
45943 OldTextBuf := fTextBuf;
45944 GetMem( fTextBuf, fTextSiz + Len );
45945 if fTextSiz <> 0 then
45946 begin
45947 System.Move( OldTextBuf^, fTextBuf^, fTextSiz );
45948 for I := 0 to fCount - 1 do
45949 begin
45950 P := fList.fItems[ I ];
45951 if (DWORD( P ) >= DWORD( OldTextBuf )) and
45952 (DWORD( P ) < DWORD( OldTextBuf ) + fTextSiz) then
45953 fList.fItems[ I ] := Pointer( DWORD( P ) - DWORD( OldTextBuf ) + DWORD( fTextBuf ) );
45954 end;
45955 FreeMem( OldTextBuf );
45956 end;
45957 System.Move( Src^, fTextBuf[ fTextSiz ], Len );
45958 Inc( fTextSiz, Len );
45959 end;
45960 end;
45962 begin
45963 if not Append2List then Clear;
45964 if S = '' then Exit;
45966 L := fTextSiz;
45967 AddTextBuf( PChar( S ), Length( S ) + 1 );
45969 P := PChar( DWORD( fTextBuf ) + DWORD( L ) );
45970 if fList = nil then
45971 fList := NewList;
45973 I := 0;
45974 TheLast := P + Length( S );
45975 while P^ <> #0 do
45976 begin
45977 Inc( I );
45978 P := StrScanLen( P, #13, TheLast - P );
45979 if P^ = #10 then
45980 Inc( P );
45981 end;
45983 Inc( fCount, I );
45984 if fList.fCapacity < fCount then
45985 fList.Capacity := fCount;
45987 P := PChar( DWORD( fTextBuf ) + DWORD( L ) );
45988 while P^ <> #0 do
45989 begin
45990 fList.Add( P );
45991 P := StrScanLen( P, #13, TheLast - P );
45992 if PChar( P - 1 )^ = #13 then
45993 PChar( P - 1 )^ := #0;
45994 if P^ = #10 then Inc(P);
45995 end;
45996 end;
45997 {$ENDIF ASM_VERSION}
45999 //[procedure TStrList.SetUnixText]
46000 procedure TStrList.SetUnixText(const S: String; Append2List: Boolean);
46001 var S1: String;
46002 begin
46003 S1 := S;
46004 NormalizeUnixText( S1 );
46005 SetText( S1, Append2List );
46006 end;
46008 //[procedure TStrList.SetTextStr]
46009 procedure TStrList.SetTextStr(const Value: string);
46010 begin
46011 SetText( Value, False );
46012 end;
46014 //[PROCEDURE LowerCaseStrFromPCharEDX]
46015 {$IFDEF ASM_VERSION}
46016 procedure LowerCaseStrFromPCharEDX;
46018 { <- EDX = PChar string
46019 -> [ESP] = LowerCase( PChar( EDX ) ),
46020 EAX, EDX, ECX - ?
46022 POP EAX
46023 PUSH 0
46024 PUSH EAX
46025 LEA EAX, [ESP+4]
46026 PUSH EAX
46027 CALL System.@LStrFromPChar
46028 POP EDX
46029 MOV EAX, [EDX]
46030 JMP LowerCase
46031 end;
46032 {$ENDIF ASM_VERSION}
46033 //[END LowerCaseStrFromPCharEDX]
46035 //[FUNCTION CompareStrListItems]
46036 {$IFDEF ASM_VERSION}
46037 function CompareStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46039 CMP [EAX].TStrList.fCaseSensitiveSort, 0
46040 MOV EAX, [EAX].TStrList.fList
46041 MOV EAX, [EAX].TList.fItems
46042 MOV EDX, [EAX+EDX*4]
46043 MOV EAX, [EAX+ECX*4]
46044 XCHG EAX, EDX
46045 JNZ StrComp
46046 PUSH EBX
46048 XCHG EBX, EAX
46049 CALL LowerCaseStrFromPCharEDX
46051 MOV EDX, EBX
46052 CALL LowerCaseStrFromPCharEDX
46054 POP EAX
46055 POP EDX
46056 PUSH EDX
46057 PUSH EAX
46058 CALL EAX2PChar
46059 CALL EDX2PChar
46060 CALL StrComp
46061 XCHG EBX, EAX
46063 CALL RemoveStr
46064 CALL RemoveStr
46066 XCHG EAX, EBX
46067 POP EBX
46068 end;
46069 {$ELSE ASM_VERSION} //Pascal
46070 function CompareStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46071 var S1, S2 : PChar;
46072 begin
46073 S1 := PStrList( Sender ).fList.Items[ e1 ];
46074 S2 := PStrList( Sender ).fList.Items[ e2 ];
46075 if PStrList( Sender ).fCaseSensitiveSort then
46076 Result := StrComp( S1, S2 )
46077 else
46078 Result := StrComp( PChar( LowerCase( S1 ) ), PChar( LowerCase( S2 ) ) );
46079 end;
46080 {$ENDIF ASM_VERSION}
46081 //[END CompareStrListItems]
46083 //[FUNCTION CompareAnsiStrListItems]
46084 {$IFDEF ASM_VERSION}
46085 function CompareAnsiStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46087 CMP byte ptr [EAX].TStrList.fCaseSensitiveSort, 0
46088 MOV EAX, [EAX].TStrList.fList
46089 MOV EAX, [EAX].TList.fItems
46090 MOV EDX, [EAX+EDX*4]
46091 MOV EAX, [EAX+ECX*4]
46092 XCHG EAX, EDX
46093 JZ _AnsiCompareStrNoCase
46094 JMP _AnsiCompareStr
46095 end;
46096 {$ELSE ASM_VERSION} //Pascal
46097 function CompareAnsiStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46098 var S1, S2 : PChar;
46099 begin
46100 S1 := PStrList( Sender ).fList.Items[ e1 ];
46101 S2 := PStrList( Sender ).fList.Items[ e2 ];
46102 if PStrList( Sender ).fCaseSensitiveSort then
46103 Result := _AnsiCompareStr( S1, S2 )
46104 else
46105 Result := _AnsiCompareStrNoCase( S1, S2 );
46106 end;
46107 {$ENDIF ASM_VERSION}
46108 //[END CompareAnsiStrListItems]
46110 {$IFNDEF ASM_VERSION}
46111 //[procedure SwapStrListItems]
46112 procedure SwapStrListItems( const Sender: Pointer; const e1, e2: DWORD );
46113 begin
46114 PStrList( Sender ).Swap( e1, e2 );
46115 end;
46116 {$ENDIF}
46118 {$IFDEF ASM_VERSION}
46119 //[procedure TStrList.Sort]
46120 procedure TStrList.Sort(CaseSensitive: Boolean);
46122 MOV [EAX].fCaseSensitiveSort, DL
46123 PUSH Offset[TStrList.Swap]
46124 MOV ECX, Offset[CompareStrListItems]
46125 MOV EDX, [EAX].fCount
46126 CALL SortData
46127 end;
46128 {$ELSE ASM_VERSION} //Pascal
46129 procedure TStrList.Sort(CaseSensitive: Boolean);
46130 begin
46131 fCaseSensitiveSort := CaseSensitive;
46132 SortData( @Self, fCount, @CompareStrListItems, @SwapStrListItems );
46133 end;
46134 {$ENDIF ASM_VERSION}
46136 {$IFDEF ASM_VERSION}
46137 //[procedure TStrList.AnsiSort]
46138 procedure TStrList.AnsiSort(CaseSensitive: Boolean);
46140 MOV [EAX].fCaseSensitiveSort, DL
46141 PUSH Offset[TStrList.Swap]
46142 MOV ECX, Offset[CompareAnsiStrListItems]
46143 MOV EDX, [EAX].fCount
46144 CALL SortData
46145 end;
46146 {$ELSE ASM_VERSION} //Pascal
46147 procedure TStrList.AnsiSort(CaseSensitive: Boolean);
46148 begin
46149 fCaseSensitiveSort := CaseSensitive;
46150 SortData( @Self, fCount, @CompareAnsiStrListItems, @SwapStrListItems );
46151 end;
46152 {$ENDIF ASM_VERSION}
46154 //[procedure TStrList.Swap]
46155 procedure TStrList.Swap(Idx1, Idx2: Integer);
46156 begin
46157 fList.Swap( Idx1, Idx2 );
46158 end;
46160 //[function TStrList.Last]
46161 function TStrList.Last: String;
46162 begin
46163 if Count = 0 then
46164 Result := ''
46165 else
46166 Result := Items[ Count - 1 ];
46167 end;
46169 //-- code by Dod:
46170 //[function TStrList.IndexOfName]
46171 function TStrList.IndexOfName(Name: string): Integer;
46173 i: Integer;
46174 L: Integer;
46175 begin
46176 Result:=-1;
46177 // Do not start search if empty string
46178 L := Length( Name );
46179 if L > 0 then
46180 begin
46181 Name := LowerCase( Name ) + fNameDelim;
46182 Inc( L );
46183 for i := 0 to fCount - 1 do
46184 begin
46185 // For optimization, check only list entry that begin with same letter as searched name
46186 if StrLComp( PChar( LowerCase( ItemPtrs[ i ] ) ), PChar( Name ), L ) = 0 then
46187 begin
46188 Result:=i;
46189 exit;
46190 end;
46191 end;
46192 end;
46193 end;
46195 //-- code by Dod:
46196 //[function TStrList.GetValue]
46197 function TStrList.GetValue(const Name: string): string;
46199 i: Integer;
46200 begin
46201 I := IndexOfName(Name);
46202 if I >= 0
46203 then Result := Copy(Items[i], Length(Name) + 2, Length(Items[i])-Length(Name)-1)
46204 else Result := '';
46205 end;
46207 //-- code by Dod:
46208 //[procedure TStrList.SetValue]
46209 procedure TStrList.SetValue(const Name, Value: string);
46211 I: Integer;
46212 begin
46213 I := IndexOfName(Name);
46214 if i=-1
46215 then Add( Name + fNameDelim + Value )
46216 else Items[i] := Name + fNameDelim + Value;
46217 end;
46219 //[function TStrList.GetLineName]
46220 function TStrList.GetLineName(Idx: Integer): string;
46221 begin
46222 Result := Items[ Idx ];
46223 Result := Parse( Result, fNameDelim );
46224 end;
46226 //[procedure TStrList.SetLineName]
46227 procedure TStrList.SetLineName(Idx: Integer; const NV: string);
46228 begin
46229 Items[ Idx ] := NV + fNameDelim + LineValue[ Idx ];
46230 end;
46232 //[function TStrList.GetLineValue]
46233 function TStrList.GetLineValue(Idx: Integer): string;
46234 begin
46235 Result := Items[ Idx ];
46236 Parse( Result, fNameDelim );
46237 end;
46239 //[procedure TStrList.SetLineValue]
46240 procedure TStrList.SetLineValue(Idx: Integer; const Value: string);
46241 begin
46242 Items[ Idx ] := LineName[ Idx ] + fNameDelim + Value;
46243 end;
46245 ////////////////////////////////// EXTENDED STRING LIST OBJECT ////////////////
46247 { TStrListEx }
46249 //[function NewStrListEx]
46250 function NewStrListEx: PStrListEx;
46251 begin
46253 new( Result, Create );
46255 {++}(*
46256 Result := PStrListEx.Create;
46257 *){--}
46258 end;
46259 //[END NewStrListEx]
46261 //[destructor TStrListEx.Destroy]
46262 destructor TStrListEx.Destroy;
46263 var Obj: PList;
46264 begin
46265 Obj := FObjects;
46266 inherited;
46267 Obj.Free;
46268 end;
46270 //[function TStrListEx.GetObjects]
46271 function TStrListEx.GetObjects(Idx: Integer): DWORD;
46272 begin
46273 Result := DWORD( FObjects.Items[ Idx ] );
46274 end;
46276 //[procedure TStrListEx.SetObjects]
46277 procedure TStrListEx.SetObjects(Idx: Integer; const Value: DWORD);
46278 begin
46279 ProvideObjCapacity( Idx + 1 );
46280 FObjects.Items[ Idx ] := Pointer( Value );
46281 end;
46283 //[procedure TStrListEx.Init]
46284 procedure TStrListEx.Init;
46285 begin
46286 FObjects := NewList;
46287 end;
46289 //[procedure SwapStrListExItems]
46290 procedure SwapStrListExItems( const Sender: Pointer; const e1, e2: DWORD );
46291 begin
46292 PStrListEx( Sender ).Swap( e1, e2 );
46293 end;
46295 //[procedure TStrListEx.AnsiSort]
46296 procedure TStrListEx.AnsiSort(CaseSensitive: Boolean);
46297 begin
46298 fCaseSensitiveSort := CaseSensitive;
46299 SortData( @Self, fCount, @CompareAnsiStrListItems, @SwapStrListExItems );
46300 end;
46302 //[procedure TStrListEx.Sort]
46303 procedure TStrListEx.Sort(CaseSensitive: Boolean);
46304 begin
46305 fCaseSensitiveSort := CaseSensitive;
46306 SortData( @Self, fCount, @CompareStrListItems, @SwapStrListExItems );
46307 end;
46309 //[procedure TStrListEx.Move]
46310 procedure TStrListEx.Move(CurIndex, NewIndex: integer);
46311 begin
46312 // move string
46313 fList.MoveItem( CurIndex, NewIndex );
46314 // move object
46315 if FObjects.fCount >= Min( CurIndex, NewIndex ) then
46316 begin
46317 ProvideObjCapacity( max( CurIndex, NewIndex ) + 1 );
46318 FObjects.MoveItem( CurIndex, NewIndex );
46319 end;
46320 end;
46322 //[procedure TStrListEx.Swap]
46323 procedure TStrListEx.Swap(Idx1, Idx2: Integer);
46324 begin
46325 // swap strings
46326 fList.Swap( Idx1, Idx2 );
46327 // swap objects
46328 if FObjects.fCount >= Min( Idx1, Idx2 ) then
46329 begin
46330 ProvideObjCapacity( max( Idx1, Idx2 ) + 1 );
46331 FObjects.Swap( Idx1, Idx2 );
46332 end;
46333 end;
46335 //[procedure TStrListEx.ProvideObjCapacity]
46336 procedure TStrListEx.ProvideObjCapacity(NewCap: Integer);
46337 begin
46338 if FObjects.FCount < NewCap then
46339 begin
46340 FObjects.Capacity := NewCap;
46341 FillChar( FObjects.FItems[ FObjects.FCount ],
46342 (FObjects.Capacity - FObjects.Count) * sizeof( Pointer ), 0 );
46343 FObjects.FCount := NewCap;
46344 end;
46345 end;
46347 //[procedure TStrListEx.AddStrings]
46348 procedure TStrListEx.AddStrings(Strings: PStrListEx);
46349 var I: Integer;
46350 begin
46351 I := Count;
46352 if Strings.FObjects.fCount > 0 then
46353 ProvideObjCapacity( Count );
46354 inherited AddStrings( Strings );
46355 if Strings.FObjects.fCount > 0 then
46356 begin
46357 ProvideObjCapacity( I + Strings.FObjects.fCount );
46358 System.Move( Strings.FObjects.FItems[ 0 ],
46359 FObjects.FItems[ I ],
46360 Sizeof( Pointer ) * Strings.FObjects.fCount );
46361 end;
46362 end;
46364 //[procedure TStrListEx.Assign]
46365 procedure TStrListEx.Assign(Strings: PStrListEx);
46366 begin
46367 inherited Assign( Strings );
46368 FObjects.Assign( Strings.FObjects );
46369 end;
46371 //[procedure TStrListEx.Clear]
46372 procedure TStrListEx.Clear;
46373 begin
46374 inherited;
46375 FObjects.Clear;
46376 end;
46378 //[procedure TStrListEx.Delete]
46379 procedure TStrListEx.Delete(Idx: integer);
46380 begin
46381 inherited;
46382 if FObjects.fCount > Idx then // mdw: '>=' -> '>'
46383 FObjects.Delete( Idx );
46384 end;
46386 //[function TStrListEx.LastObj]
46387 function TStrListEx.LastObj: DWORD;
46388 begin
46389 if Count = 0 then
46390 Result := 0
46391 else
46392 Result := Objects[ Count - 1 ];
46393 end;
46395 //[function TStrListEx.AddObject]
46396 function TStrListEx.AddObject(const S: String; Obj: DWORD): Integer;
46397 begin
46398 Result := Count;
46399 InsertObject( Count, S, Obj );
46400 end;
46402 //[procedure TStrListEx.InsertObject]
46403 procedure TStrListEx.InsertObject(Before: Integer; const S: String; Obj: DWORD);
46404 begin
46405 Insert( Before, S );
46406 FObjects.Insert( Before, Pointer( Obj ) );
46407 end;
46409 //[function TStrListEx.IndexOfObj]
46410 function TStrListEx.IndexOfObj( Obj: Pointer ): Integer;
46411 begin
46412 Result := FObjects.IndexOf( Obj );
46413 end;
46416 //[function WStrLen]
46417 function WStrLen( W: PWideChar ): Integer;
46419 XCHG EDI, EAX
46420 XCHG EDX, EAX
46421 OR ECX, -1
46422 XOR EAX, EAX
46423 CMP EAX, EDI
46424 JE @@exit0
46425 REPNE SCASW
46426 DEC EAX
46427 DEC EAX
46428 SUB EAX, ECX
46429 @@exit0:
46430 MOV EDI, EDX
46431 end;
46433 //[procedure WStrCopy]
46434 procedure WStrCopy( Dest, Src: PWideChar );
46436 PUSH EDI
46437 PUSH ESI
46438 MOV ESI,EAX
46439 MOV EDI,EDX
46440 OR ECX, -1
46441 XOR EAX, EAX
46442 REPNE SCASW
46443 NOT ECX
46444 MOV EDI,ESI
46445 MOV ESI,EDX
46446 REP MOVSW
46447 POP ESI
46448 POP EDI
46449 end;
46451 //[function WStrCmp]
46452 function WStrCmp( W1, W2: PWideChar ): Integer;
46454 PUSH ESI
46455 PUSH EDI
46456 XCHG ESI, EAX
46457 MOV EDI, EDX
46458 XOR EAX, EAX
46459 CWDE
46460 @@loop: LODSW
46461 MOV DX, [EDI]
46462 INC EDI
46463 INC EDI
46464 CMP EAX, EDX
46465 JNE @@exit
46466 TEST EAX, EAX
46467 JNZ @@loop
46468 @@exit: SUB EAX, EDX
46469 POP EDI
46470 POP ESI
46471 end;
46473 {$IFNDEF _D2}
46475 //[function NewWStrList]
46476 function NewWStrList: PWStrList;
46477 begin
46478 new( Result, Create );
46479 end;
46481 { TWStrList }
46483 //[function TWStrList.Add]
46484 function TWStrList.Add(const W: WideString): Integer;
46485 begin
46486 Result := Count;
46487 Insert( Result, W );
46488 end;
46490 //[procedure TWStrList.AddWStrings]
46491 procedure TWStrList.AddWStrings(WL: PWStrList);
46492 begin
46493 Text := Text + WL.Text;
46494 end;
46496 //[function TWStrList.AppendToFile]
46497 function TWStrList.AppendToFile(const Filename: String): Boolean;
46498 var Strm: PStream;
46499 begin
46500 Strm := NewReadWriteFileStream( Filename );
46501 Result := Strm.Handle <> INVALID_HANDLE_VALUE;
46502 if Result then
46503 begin
46504 Strm.Position := Strm.Size;
46505 SaveToStream( Strm );
46506 end;
46507 Strm.Free;
46508 end;
46510 //[procedure TWStrList.Assign]
46511 procedure TWStrList.Assign(WL: PWStrList);
46512 begin
46513 Text := WL.Text;
46514 end;
46516 //[procedure TWStrList.Clear]
46517 procedure TWStrList.Clear;
46518 var I: Integer;
46519 P: Pointer;
46520 begin
46521 for I := 0 to Count-1 do
46522 begin
46523 P := fList.Items[ I ];
46524 if P <> nil then
46525 if not( (P >= fText) and (P <= fText + fTextBufSz) ) then
46526 FreeMem( P );
46527 end;
46528 if fText <> nil then
46529 FreeMem( fText );
46530 fText := nil;
46531 fTextBufSz := 0;
46532 fList.Clear;
46533 end;
46535 //[procedure TWStrList.Delete]
46536 procedure TWStrList.Delete(Idx: Integer);
46537 var P: Pointer;
46538 begin
46539 P := fList.Items[ Idx ];
46540 if P <> nil then
46541 if not( (P >= fText) and (P <= fText + fTextBufSz) ) then
46542 FreeMem( P );
46543 fList.Delete( Idx );
46544 end;
46546 //[destructor TWStrList.Destroy]
46547 destructor TWStrList.Destroy;
46548 begin
46549 Clear;
46550 fList.Free;
46551 inherited;
46552 end;
46554 //[function TWStrList.GetCount]
46555 function TWStrList.GetCount: Integer;
46556 begin
46557 Result := fList.Count;
46558 end;
46560 //[function TWStrList.GetItems]
46561 function TWStrList.GetItems(Idx: Integer): WideString;
46562 begin
46563 Result := PWideChar( fList.Items[ Idx ] );
46564 end;
46566 //[function TWStrList.GetPtrs]
46567 function TWStrList.GetPtrs(Idx: Integer): PWideChar;
46568 begin
46569 Result := fList.Items[ Idx ];
46570 end;
46572 //[function TWStrList.GetText]
46573 function TWStrList.GetText: WideString;
46574 const
46575 EoL: array[ 0..5 ] of Char = ( #13, #0, #10, #0, #0, #0 );
46576 var L, I: Integer;
46577 P, Dest: Pointer;
46578 begin
46579 L := 0;
46580 for I := 0 to Count-1 do
46581 begin
46582 P := fList.Items[ I ];
46583 if P <> nil then
46584 L := L + WStrLen( P ) + 2
46585 else
46586 L := L + 2;
46587 end;
46588 SetLength( Result, L );
46589 Dest := PWideChar( Result );
46590 for I := 0 to Count-1 do
46591 begin
46592 P := fList.Items[ I ];
46593 if P <> nil then
46594 begin
46595 WStrCopy( Dest, P );
46596 Dest := Pointer( Integer( Dest ) + WStrLen( P ) * 2 );
46597 end;
46598 WStrCopy( Dest, Pointer( @ EoL[ 0 ] ) );
46599 Dest := Pointer( Integer( Dest ) + 4 );
46600 end;
46601 end;
46603 //[procedure TWStrList.Init]
46604 procedure TWStrList.Init;
46605 begin
46606 fList := NewList;
46607 end;
46609 //[procedure TWStrList.Insert]
46610 procedure TWStrList.Insert(Idx: Integer; const W: WideString);
46611 var P: Pointer;
46612 begin
46613 while Idx < Count-2 do
46614 fList.Add( nil );
46615 GetMem( P, (Length( W ) + 1) * 2 );
46616 fList.Insert( Idx, P );
46617 WStrCopy( P, PWideChar( W ) );
46618 end;
46620 //[function TWStrList.LoadFromFile]
46621 function TWStrList.LoadFromFile(const Filename: String): Boolean;
46622 begin
46623 Clear;
46624 Result := MergeFromFile( Filename );
46625 end;
46627 //[procedure TWStrList.LoadFromStream]
46628 procedure TWStrList.LoadFromStream(Strm: PStream);
46629 begin
46630 Clear;
46631 MergeFromStream( Strm );
46632 end;
46634 //[function TWStrList.MergeFromFile]
46635 function TWStrList.MergeFromFile(const Filename: String): Boolean;
46636 var Strm: PStream;
46637 begin
46638 Strm := NewReadFileStream( Filename );
46639 Result := Strm.Handle <> INVALID_HANDLE_VALUE;
46640 if Result then
46641 MergeFromStream( Strm );
46642 Strm.Free;
46643 end;
46645 //[procedure TWStrList.MergeFromStream]
46646 procedure TWStrList.MergeFromStream(Strm: PStream);
46647 var Buf: WideString;
46648 L: Integer;
46649 begin
46650 L := Strm.Size - Strm.Position;
46651 Assert( L mod 1 = 0, 'Wide strings streams must be of even length in bytes.' );
46652 if L = 0 then Exit;
46653 SetLength( Buf, L div 2 );
46654 Strm.Read( Buf[ 1 ], L );
46655 Text := Text + Buf;
46656 end;
46658 //[procedure TWStrList.Move]
46659 procedure TWStrList.Move(IdxOld, IdxNew: Integer);
46660 begin
46661 fList.MoveItem( IdxOld, IdxNew );
46662 end;
46664 //[function TWStrList.SaveToFile]
46665 function TWStrList.SaveToFile(const Filename: String): Boolean;
46666 var Strm: PStream;
46667 begin
46668 Strm := NewWriteFileStream( Filename );
46669 Result := Strm.Handle <> INVALID_HANDLE_VALUE;
46670 if Result then
46671 SaveToStream( Strm );
46672 Strm.Free;
46673 end;
46675 //[procedure TWStrList.SaveToStream]
46676 procedure TWStrList.SaveToStream(Strm: PStream);
46677 var Buf, Dest: PWideChar;
46678 I, L, Sz: Integer;
46679 P: Pointer;
46680 begin
46681 Sz := 0;
46682 for I := 0 to Count-1 do
46683 begin
46684 P := fList.Items[ I ];
46685 if P <> nil then
46686 Sz := Sz + WStrLen( P ) * 2 + 4
46687 else
46688 Sz := Sz + 4;
46689 end;
46690 GetMem( Buf, Sz );
46691 Dest := Buf;
46692 for I := 0 to Count-1 do
46693 begin
46694 P := fList.Items[ I ];
46695 if P <> nil then
46696 begin
46697 L := WStrLen( P );
46698 System.Move( P^, Dest^, L * 2 );
46699 Inc( Dest, L );
46700 end;
46701 Dest^ := #13;
46702 Inc( Dest );
46703 Dest^ := #10;
46704 Inc( Dest );
46705 end;
46706 Strm.Write( Buf^, Sz );
46707 FreeMem( Buf );
46708 end;
46710 //[procedure TWStrList.SetItems]
46711 procedure TWStrList.SetItems(Idx: Integer; const Value: WideString);
46712 var P: Pointer;
46713 begin
46714 while Idx > Count-1 do
46715 fList.Add( nil );
46716 if WStrLen( ItemPtrs[ Idx ] ) <= Length( Value ) then
46717 WStrCopy( ItemPtrs[ Idx ], PWideChar( Value ) )
46718 else
46719 begin
46720 P := fList.Items[ Idx ];
46721 if P <> nil then
46722 if not ((P >= fText) and (P <= fText + fTextBufSz)) then
46723 FreeMem( P );
46724 GetMem( P, (Length( Value ) + 1) * 2 );
46725 fList.Items[ Idx ] := P;
46726 WStrCopy( P, PWideChar( Value ) );
46727 end;
46728 end;
46730 //[procedure TWStrList.SetText]
46731 procedure TWStrList.SetText(const Value: WideString);
46732 var L, N: Integer;
46733 P: PWideChar;
46734 begin
46735 Clear;
46736 if Value = '' then Exit;
46737 L := (Length( Value ) + 1) * 2;
46738 GetMem( fText, L );
46739 System.Move( Value[ 1 ], fText^, L );
46740 fTextBufSz := Length( Value );
46741 N := 0;
46742 P := fText;
46743 while Word( P^ ) <> 0 do
46744 begin
46745 if (Word( P^ ) = 13) then
46746 begin
46747 Inc( N );
46748 PWord( P )^ := 0;
46749 if Word( P[ 1 ] ) = 10 then
46750 Inc( P );
46752 else
46753 if (Word( P^ ) = 10) and ((P = fText) or (Word( P[ -1 ] ) <> 0)) then
46754 begin
46755 Inc( N );
46756 PWord( P )^ := 0;
46757 end;
46758 Inc( P );
46759 end;
46760 fList.Capacity := N;
46761 P := fText;
46762 while P < fText + fTextBufSz do
46763 begin
46764 fList.Add( P );
46765 while Word( P^ ) <> 0 do Inc( P );
46766 Inc( P );
46767 if Word( P^ ) = 10 then Inc( P );
46768 end;
46769 end;
46771 //[function CompareWStrListItems]
46772 function CompareWStrListItems( const Sender: Pointer; const Idx1, Idx2: DWORD ): Integer;
46773 var WL: PWStrList;
46774 begin
46775 WL := Sender;
46776 Result := WStrCmp( WL.fList.Items[ Idx1 ], WL.fList.Items[ Idx2 ] );
46777 end;
46779 //[function CompareWStrListItems_UpperCase]
46780 function CompareWStrListItems_UpperCase( const Sender: Pointer; const Idx1, Idx2: DWORD ): Integer;
46781 var WL: PWStrList;
46782 L1, L2: Integer;
46783 begin
46784 WL := Sender;
46785 L1 := WStrLen( WL.fList.Items[ Idx1 ] );
46786 L2 := WStrLen( WL.fList.Items[ Idx2 ] );
46787 if Length( WL.fTmp1 ) < L1 then
46788 SetLength( WL.fTmp1, L1 + 1 );
46789 if Length( WL.fTmp2 ) < L2 then
46790 SetLength( WL.fTmp2, L2 + 1 );
46791 if L1 > 0 then
46792 Move( WL.fList.Items[ Idx1 ]^, WL.fTmp1[ 1 ], (L1 + 1) * 2 )
46793 else
46794 WL.fTmp1[ 1 ] := #0;
46795 if L2 > 0 then
46796 Move( WL.fList.Items[ Idx2 ]^, WL.fTmp2[ 1 ], (L2 + 1) * 2 )
46797 else
46798 WL.fTmp2[ 1 ] := #0;
46799 CharUpperBuffW( PWideChar( WL.fTmp1 ), L1 );
46800 CharUpperBuffW( PWideChar( WL.fTmp2 ), L2 );
46801 Result := WStrCmp( PWideChar( WL.fTmp1 ), PWideChar( WL.fTmp2 ) );
46802 end;
46804 //[procedure SwapWStrListItems]
46805 procedure SwapWStrListItems( const Sender: Pointer; const Idx1, Idx2: DWORD );
46806 var WL: PWStrList;
46807 begin
46808 WL := Sender;
46809 WL.Swap( Idx1, Idx2 );
46810 end;
46812 //[procedure TWStrList.Sort]
46813 procedure TWStrList.Sort( CaseSensitive: Boolean );
46814 begin
46815 if CaseSensitive then
46816 SortData( @ Self, Count, @CompareWStrListItems, @SwapWStrListItems )
46817 else
46818 begin
46819 SortData( @ Self, Count, @CompareWStrListItems_UpperCase, @SwapWStrListItems );
46820 fTmp1 := '';
46821 fTmp2 := '';
46822 end;
46823 end;
46825 //[procedure TWStrList.Swap]
46826 procedure TWStrList.Swap(Idx1, Idx2: Integer);
46827 begin
46828 fList.Swap( Idx1, Idx2 );
46829 end;
46831 //[function NewWStrListEx]
46832 function NewWStrListEx: PWStrListEx;
46833 begin
46834 new( Result, Create );
46835 end;
46837 { TWStrListEx }
46839 //[function TWStrListEx.AddObject]
46840 function TWStrListEx.AddObject(const S: WideString; Obj: DWORD): Integer;
46841 begin
46842 Result := Count;
46843 InsertObject( Count, S, Obj );
46844 end;
46846 //[procedure TWStrListEx.AddWStrings]
46847 procedure TWStrListEx.AddWStrings(WL: PWStrListEx);
46848 var I: Integer;
46849 begin
46850 I := Count;
46851 if WL.FObjects.Count > 0 then
46852 ProvideObjectsCapacity( Count );
46853 inherited AddWStrings( WL );
46854 if WL.FObjects.Count > 0 then
46855 begin
46856 ProvideObjectsCapacity( I + WL.FObjects.Count );
46857 System.Move( WL.FObjects.FItems[ 0 ],
46858 FObjects.FItems[ I ],
46859 Sizeof( Pointer ) * WL.FObjects.Count );
46860 end;
46861 end;
46863 //[procedure TWStrListEx.Assign]
46864 procedure TWStrListEx.Assign(WL: PWStrListEx);
46865 begin
46866 inherited Assign( WL );
46867 FObjects.Assign( WL.FObjects );
46868 end;
46870 //[procedure TWStrListEx.Clear]
46871 procedure TWStrListEx.Clear;
46872 begin
46873 inherited Clear;
46874 FObjects.Clear;
46875 end;
46877 //[procedure TWStrListEx.Delete]
46878 procedure TWStrListEx.Delete(Idx: Integer);
46879 begin
46880 inherited Delete( Idx );
46881 if FObjects.FCount >= Idx then
46882 FObjects.Delete( Idx );
46883 end;
46885 //[destructor TWStrListEx.Destroy]
46886 destructor TWStrListEx.Destroy;
46887 begin
46888 fObjects.Free;
46889 inherited;
46890 end;
46892 //[function TWStrListEx.GetObjects]
46893 function TWStrListEx.GetObjects(Idx: Integer): DWORD;
46894 begin
46895 Result := DWORD( fObjects.Items[ Idx ] );
46896 end;
46898 //[function TWStrListEx.IndexOfObj]
46899 function TWStrListEx.IndexOfObj(Obj: Pointer): Integer;
46900 begin
46901 Result := FObjects.IndexOf( Obj );
46902 end;
46904 //[procedure TWStrListEx.Init]
46905 procedure TWStrListEx.Init;
46906 begin
46907 inherited;
46908 fObjects := NewList;
46909 end;
46911 //[procedure TWStrListEx.InsertObject]
46912 procedure TWStrListEx.InsertObject(Before: Integer; const S: WideString;
46913 Obj: DWORD);
46914 begin
46915 Insert( Before, S );
46916 FObjects.Insert( Before, Pointer( Obj ) );
46917 end;
46919 //[procedure TWStrListEx.Move]
46920 procedure TWStrListEx.Move(IdxOld, IdxNew: Integer);
46921 begin
46922 fList.MoveItem( IdxOld, IdxNew );
46923 if FObjects.FCount >= Min( IdxOld, IdxNew ) then
46924 begin
46925 ProvideObjectsCapacity( Max( IdxOld, IdxNew ) + 1 );
46926 FObjects.MoveItem( IdxOld, IdxNew );
46927 end;
46928 end;
46930 //[procedure TWStrListEx.ProvideObjectsCapacity]
46931 procedure TWStrListEx.ProvideObjectsCapacity(NewCap: Integer);
46932 begin
46933 if fObjects.Capacity >= NewCap then Exit;
46934 fObjects.Capacity := NewCap;
46935 FillChar( FObjects.FItems[ FObjects.FCount ],
46936 (FObjects.Capacity - FObjects.Count) * Sizeof( Pointer ), 0 );
46937 FObjects.FCount := NewCap;
46938 end;
46940 //[procedure TWStrListEx.SetObjects]
46941 procedure TWStrListEx.SetObjects(Idx: Integer; const Value: DWORD);
46942 begin
46943 ProvideObjectsCapacity( Idx + 1 );
46944 fObjects.Items[ Idx ] := Pointer( Value );
46945 end;
46947 {$ENDIF}
46951 //////////////////////////////////////////////////////////////////////////
46954 // S O R T I N G
46957 //////////////////////////////////////////////////////////////////////////
46959 { -- qsort -- }
46961 //[PROCEDURE SortData]
46962 {$IFDEF ASM_VERSION} // translated to BASM by Kladov Vladimir
46963 procedure SortData( const Data: Pointer; const uNElem: Dword;
46964 const CompareFun: TCompareEvent;
46965 const SwapProc: TSwapEvent );
46967 CMP EDX, 2
46968 JL @@exit
46970 PUSH EAX // [EBP-4] = Data
46971 PUSH ECX // [EBP-8] = CompareFun
46972 PUSH EBX // EBX = pivotP
46973 XOR EBX, EBX
46974 INC EBX // EBX = 1 to pass to qSortHelp as PivotP
46975 MOV EAX, EDX // EAX = nElem
46976 CALL @@qSortHelp
46977 POP EBX
46978 POP ECX
46979 POP ECX
46980 @@exit:
46981 POP EBP
46982 RET 4
46984 @@qSortHelp:
46985 PUSH EBX // EBX (in) = PivotP
46986 PUSH ESI // ESI = leftP
46987 PUSH EDI // EDI = rightP
46989 @@TailRecursion:
46990 CMP EAX, 2
46991 JG @@2
46992 JNE @@exit_qSortHelp
46993 LEA ECX, [EBX+1]
46994 MOV EDX, EBX
46995 CALL @@Compare
46996 JLE @@exit_qSortHelp
46997 @@swp_exit:
46998 CALL @@Swap
46999 @@exit_qSortHelp:
47000 POP EDI
47001 POP ESI
47002 POP EBX
47005 // ESI = leftP
47006 // EDI = rightP
47007 @@2: LEA EDI, [EAX+EBX-1]
47008 MOV ESI, EAX
47009 SHR ESI, 1
47010 ADD ESI, EBX
47011 MOV ECX, ESI
47012 MOV EDX, EDI
47013 CALL @@CompareLeSwap
47014 MOV EDX, EBX
47015 CALL @@Compare
47017 JG @@4
47018 CALL @@Swap
47019 JMP @@5
47020 @@4: MOV ECX, EBX
47021 MOV EDX, EDI
47022 CALL @@CompareLeSwap
47023 @@5:
47024 CMP EAX, 3
47025 JNE @@6
47026 MOV EDX, EBX
47027 MOV ECX, ESI
47028 JMP @@swp_exit
47029 @@6: // classic Horae algorithm
47031 PUSH EAX // EAX = pivotEnd
47032 LEA EAX, [EBX+1]
47033 MOV ESI, EAX
47034 @@repeat:
47035 MOV EDX, ESI
47036 MOV ECX, EBX
47037 CALL @@Compare
47038 JG @@while2
47039 @@while1:
47040 JNE @@7
47041 MOV EDX, ESI
47042 MOV ECX, EAX
47043 CALL @@Swap
47044 INC EAX
47045 @@7:
47046 CMP ESI, EDI
47047 JGE @@qBreak
47048 INC ESI
47049 JMP @@repeat
47050 @@while2:
47051 CMP ESI, EDI
47052 JGE @@until
47053 MOV EDX, EBX
47054 MOV ECX, EDI
47055 CALL @@Compare
47056 JGE @@8
47057 DEC EDI
47058 JMP @@while2
47059 @@8:
47060 MOV EDX, ESI
47061 MOV ECX, EDI
47062 PUSHFD
47063 CALL @@Swap
47064 POPFD
47065 JE @@until
47066 INC ESI
47067 DEC EDI
47068 @@until:
47069 CMP ESI, EDI
47070 JL @@repeat
47071 @@qBreak:
47072 MOV EDX, ESI
47073 MOV ECX, EBX
47074 CALL @@Compare
47075 JG @@9
47076 INC ESI
47077 @@9:
47078 PUSH EBX // EBX = PivotTemp
47079 PUSH ESI // ESI = leftTemp
47080 DEC ESI
47081 @@while3:
47082 CMP EBX, EAX
47083 JGE @@while3_break
47084 CMP ESI, EAX
47085 JL @@while3_break
47086 MOV EDX, EBX
47087 MOV ECX, ESI
47088 CALL @@Swap
47089 INC EBX
47090 DEC ESI
47091 JMP @@while3
47092 @@while3_break:
47093 POP ESI
47094 POP EBX
47096 MOV EDX, EAX
47097 POP EAX // EAX = nElem
47098 PUSH EDI // EDI = lNum
47099 MOV EDI, ESI
47100 SUB EDI, EDX
47101 ADD EAX, EBX
47102 SUB EAX, ESI
47104 PUSH EBX
47105 PUSH EAX
47106 CMP EAX, EDI
47107 JGE @@10
47109 MOV EBX, ESI
47110 CALL @@qSortHelp
47111 POP EAX
47112 MOV EAX, EDI
47113 POP EBX
47114 JMP @@11
47116 @@10: MOV EAX, EDI
47117 CALL @@qSortHelp
47118 POP EAX
47119 POP EBX
47120 MOV EBX, ESI
47121 @@11:
47122 POP EDI
47123 JMP @@TailRecursion
47125 @@Compare:
47126 PUSH EAX
47127 PUSH EDX
47128 PUSH ECX
47129 MOV EAX, [EBP-4]
47130 DEC EDX
47131 DEC ECX
47132 CALL dword ptr [EBP-8]
47133 POP ECX
47134 POP EDX
47135 TEST EAX, EAX
47136 POP EAX
47139 @@CompareLeSwap:
47140 CALL @@Compare
47141 JG @@ret
47143 @@Swap: PUSH EAX
47144 PUSH EDX
47145 PUSH ECX
47146 MOV EAX, [EBP-4]
47147 DEC EDX
47148 DEC ECX
47149 CALL dword ptr [SwapProc]
47150 POP ECX
47151 POP EDX
47152 TEST EAX, EAX
47153 POP EAX
47154 @@ret:
47157 end;
47158 {$ELSE ASM_VERSION} //Pascal
47159 procedure SortData( const Data: Pointer; const uNElem: Dword;
47160 const CompareFun: TCompareEvent;
47161 const SwapProc: TSwapEvent );
47162 { uNElem - number of elements to sort }
47164 function Compare( const e1, e2 : DWord ) : Integer;
47165 begin
47166 Result := CompareFun( Data, e1 - 1, e2 - 1 );
47167 end;
47169 procedure Swap( const e1, e2 : DWord );
47170 begin
47171 SwapProc( Data, e1 - 1, e2 - 1 );
47172 end;
47174 procedure qSortHelp(pivotP: Dword; nElem: Dword);
47175 label
47176 TailRecursion,
47177 qBreak;
47179 leftP, rightP, pivotEnd, pivotTemp, leftTemp: Dword;
47180 lNum: Dword;
47181 retval: integer;
47182 begin
47183 TailRecursion:
47184 if (nElem <= 2) then
47185 begin
47186 if (nElem = 2) then
47187 begin
47188 rightP := pivotP +1;
47189 retval := Compare(pivotP,rightP);
47190 if (retval > 0) then Swap(pivotP,rightP);
47191 end;
47192 exit;
47193 end;
47194 rightP := (nElem -1) + pivotP;
47195 leftP := (nElem shr 1) + pivotP;
47196 { sort pivot, left, and right elements for "median of 3" }
47197 retval := Compare(leftP,rightP);
47198 if (retval > 0) then Swap(leftP, rightP);
47199 retval := Compare(leftP,pivotP);
47201 if (retval > 0) then
47202 Swap(leftP, pivotP)
47203 else
47204 begin
47205 retval := Compare(pivotP,rightP);
47206 if retval > 0 then Swap(pivotP, rightP);
47207 end;
47208 if (nElem = 3) then
47209 begin
47210 Swap(pivotP, leftP);
47211 exit;
47212 end;
47213 { now for the classic Horae algorithm }
47214 pivotEnd := pivotP + 1;
47215 leftP := pivotEnd;
47216 repeat
47218 retval := Compare(leftP, pivotP);
47219 while (retval <= 0) do
47220 begin
47222 if (retval = 0) then
47223 begin
47224 Swap(leftP, pivotEnd);
47225 Inc(pivotEnd);
47226 end;
47227 if (leftP < rightP) then
47228 Inc(leftP)
47229 else
47230 goto qBreak;
47231 retval := Compare(leftP, pivotP);
47232 end; {while}
47233 while (leftP < rightP) do
47234 begin
47235 retval := Compare(pivotP, rightP);
47236 if (retval < 0) then
47237 Dec(rightP)
47239 else
47240 begin
47241 Swap(leftP, rightP);
47242 if (retval <> 0) then
47243 begin
47244 Inc(leftP);
47245 Dec(rightP);
47246 end;
47247 break;
47248 end;
47249 end; {while}
47251 until (leftP >= rightP);
47252 qBreak:
47253 retval := Compare(leftP,pivotP);
47254 if (retval <= 0) then Inc(leftP);
47256 leftTemp := leftP -1;
47257 pivotTemp := pivotP;
47258 while ((pivotTemp < pivotEnd) and (leftTemp >= pivotEnd)) do
47259 begin
47260 Swap(pivotTemp, leftTemp);
47261 Inc(pivotTemp);
47262 Dec(leftTemp);
47263 end; {while}
47264 lNum := (leftP - pivotEnd);
47265 nElem := ((nElem + pivotP) -leftP);
47267 if (nElem < lNum) then
47268 begin
47269 qSortHelp(leftP, nElem);
47270 nElem := lNum;
47272 else
47273 begin
47274 qSortHelp(pivotP, lNum);
47275 pivotP := leftP;
47276 end;
47277 goto TailRecursion;
47278 end; {qSortHelp }
47280 begin
47281 if (uNElem < 2) then exit; { nothing to sort }
47282 qSortHelp(1, uNElem);
47283 end;
47284 {$ENDIF ASM_VERSION}
47285 //[END SortData]
47287 //[FUNCTION CompareIntegers]
47288 {$IFDEF ASM_VERSION}
47289 function CompareIntegers( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
47291 MOV EDX, [EAX+EDX*4]
47292 SUB EDX, [EAX+ECX*4]
47293 XCHG EAX, EDX
47294 end;
47295 {$ELSE ASM_VERSION} //Pascal
47296 function CompareIntegers( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
47297 var I1, I2 : Integer;
47298 begin
47299 I1 := PInteger( DWORD( Sender ) + e1 * Sizeof( Integer ) )^;
47300 I2 := PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;
47301 Result := 0;
47302 if I1 < I2 then Result := -1
47303 else
47304 if I1 > I2 then Result := 1;
47305 end;
47306 {$ENDIF ASM_VERSION}
47307 //[END CompareIntegers]
47309 //[FUNCTION CompareDwords]
47310 {$IFDEF ASM_VERSION}
47311 function CompareDwords( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
47313 MOV EDX, [EAX+EDX*4]
47314 SUB EDX, [EAX+ECX*4]
47315 XCHG EAX, EDX
47316 JNB @@1
47317 SBB EAX, EAX
47318 @@1:
47319 end;
47320 {$ELSE ASM_VERSION} //Pascal
47321 function CompareDwords( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
47322 var I1, I2 : DWord;
47323 begin
47324 I1 := PDWORD( DWORD( Sender ) + e1 * Sizeof( Integer ) )^;
47325 I2 := PDWORD( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;
47326 Result := 0;
47327 if I1 < I2 then Result := -1
47328 else
47329 if I1 > I2 then Result := 1;
47330 end;
47331 {$ENDIF ASM_VERSION}
47332 //[END CompareDwords]
47334 //[PROCEDURE SwapIntegers]
47335 {$IFDEF ASM_VERSION}
47336 procedure SwapIntegers( const Sender : Pointer; const e1, e2 : DWORD );
47338 LEA EDX, [EAX+EDX*4]
47339 LEA ECX, [EAX+ECX*4]
47340 MOV EAX, [EDX]
47341 XCHG EAX, [ECX]
47342 MOV [EDX], EAX
47343 end;
47344 {$ELSE ASM_VERSION} //Pascal
47345 procedure SwapIntegers( const Sender : Pointer; const e1, e2 : DWORD );
47346 var Tmp : Integer;
47347 begin
47348 Tmp := PInteger( DWORD( Sender ) + e1 * SizeOf( Integer ) )^;
47349 PInteger( DWORD( Sender ) + e1 * Sizeof( Integer ) )^ :=
47350 PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;
47351 PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^ := Tmp;
47352 end;
47353 {$ENDIF ASM_VERSION}
47354 //[END SwapIntegers]
47356 //[procedure SortIntegerArray]
47357 procedure SortIntegerArray( var A : array of Integer );
47358 begin
47359 SortData( @A[ 0 ], High( A ) - Low( A ) + 1, @CompareIntegers, @SwapIntegers );
47360 end;
47362 //[procedure SortDwordArray]
47363 procedure SortDwordArray( var A : array of DWORD );
47364 begin
47365 SortData( @A[ 0 ], High( A ) - Low( A ) + 1, @CompareDwords, @SwapIntegers );
47366 end;
47369 { -- status bar implementation -- }
47371 //[FUNCTION _NewStatusbar]
47372 {$IFDEF ASM_VERSION}
47373 function _NewStatusbar( AParent: PControl ): PControl;
47374 const STAT_CLS_NAM: PChar = STATUSCLASSNAME;
47376 PUSH 0
47377 PUSH 0
47378 //PUSH EAX
47379 //CALL TControl.GetCanResize
47380 CMP [EAX].TControl.fSizeGrip, 0
47381 MOV ECX, WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or 3 or WS_VISIBLE
47382 //MOV CH, AL // SBARS_SIZEGRIP = $0100
47383 JZ @@1
47384 //SETNZ CH
47385 INC CH
47386 AND CL, not 3
47387 @@1:
47388 //POP EAX
47389 MOV EDX, [STAT_CLS_NAM]
47390 CALL _NewCommonControl
47391 PUSH EBX
47392 XCHG EBX, EAX
47393 PUSH EDI
47394 LEA EDI, [EBX].TControl.fBoundsRect
47395 XOR EAX, EAX
47396 STOSD
47397 STOSD
47398 STOSD
47399 STOSD
47400 MOV [EBX].TControl.fAlign, caBottom
47401 INC [EBX].TControl.fNotUseAlign
47402 POP EDI
47403 MOV EAX, EBX
47404 CALL InitCommonControlSizeNotify
47405 XCHG EAX, EBX
47406 POP EBX
47407 end;
47408 {$ELSE ASM_VERSION} //Pascal
47409 function _NewStatusbar( AParent: PControl ): PControl;
47410 var Style: DWORD;
47411 //R: TRect;
47412 begin
47413 Style := WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or 3 or WS_VISIBLE;
47414 {if AParent.CanResize then
47415 Style := Style or SBARS_SIZEGRIP;}
47416 if AParent.fSizeGrip then
47417 Style := (Style or SBARS_SIZEGRIP) and not 3;
47418 Result := _NewCommonControl( AParent, STATUSCLASSNAME,
47419 Style, FALSE, nil );
47421 with Result.fBoundsRect do
47422 begin
47423 Left := 0;
47424 Right := 0;
47425 Top := 0;
47426 Bottom := 0;
47427 end;
47428 Result.fAlign := caBottom;
47429 Result.fNotUseAlign := True;
47430 {$IFDEF TEST_VERSION}
47431 Result.fTag := DWORD( PChar( 'Status bar' ) );
47432 {$ENDIF}
47433 InitCommonControlSizeNotify( Result );
47434 //R := AParent.ClientRect;
47435 //AParent.Perform( WM_SIZING, WMSZ_TOPLEFT, Integer( @ R ) );
47436 //Result.AttachProc( WndProcEraseBkgnd );
47437 end;
47438 {$ENDIF ASM_VERSION}
47439 //[END _NewStatusbar]
47441 {$IFDEF ASM_VERSION}
47442 //[procedure TControl.SetStatusText]
47443 procedure TControl.SetStatusText(Index: Integer; Value: PChar);
47445 PUSHAD
47446 MOV EBX, EDX // EBX = Index
47447 MOV ESI, EAX // ESI = @Self
47449 PUSH Value // prepare value for call at the end of procedure
47450 PUSH EBX // prepare Index for call at the end of procedure
47452 MOV ECX, [ESI].fStatusCtl
47453 INC ECX
47454 LOOP @@status_created
47456 CALL GetClientHeight
47457 PUSH EAX // ch = old client height
47459 MOV EAX, ESI
47460 CALL _NewStatusBar
47461 MOV [ESI].fStatusCtl, EAX
47462 PUSH EAX //-----------v
47464 CALL TControl.GetWindowHandle
47465 MOV [ESI].fStatusWnd, EAX
47466 XCHG EDI, EAX
47467 POP EAX //-----------^
47469 XOR EDX, EDX
47470 PUSH EDX
47471 INC DH
47472 DEC EDX
47473 CMP EBX, EDX
47474 SETZ DL
47475 NEG EDX
47477 @@1: PUSH EDX
47478 PUSH SB_SIMPLE
47480 PUSH EAX
47481 CALL TControl.Perform
47483 ADD ESP, -16
47484 PUSH ESP
47485 PUSH [ESI].fStatusWnd
47486 CALL GetWindowRect
47487 POP EAX
47488 POP EDX
47489 POP EAX
47490 POP EAX
47491 SUB EAX, EDX
47492 MOV [ESI].fClientBottom, EAX
47494 POP EDX // ch
47496 PUSH 0
47497 PUSH 0
47498 PUSH WM_SIZE
47499 PUSH EDI
47501 MOV EAX, ESI
47502 CALL TControl.SetClientHeight
47504 CALL SendMessage
47506 @@status_created:
47507 CMP EBX, 255
47508 JGE @@not_simple
47510 PUSH 0
47511 PUSH 0
47512 PUSH SB_GETPARTS
47513 PUSH [ESI].fStatusWnd
47514 CALL SendMessage
47516 CMP EAX, EBX
47517 JG @@reset_simple
47519 MOV EAX, ESI
47520 CALL GetWidth
47522 MOV ECX, EBX
47523 INC ECX
47524 IDIV ECX
47525 MOV EDX, EAX
47527 ADD ESP, -1024
47528 MOV ECX, EBX
47529 MOV EDI, ESP
47530 JECXZ @@2
47532 @@store_loo:
47533 STOSD
47534 ADD EAX, EDX
47535 LOOP @@store_loo
47536 @@2:
47537 OR dword ptr [ESP+EBX*4], -1
47538 PUSH ESP
47539 INC EBX
47540 PUSH EBX
47541 PUSH SB_SETPARTS
47542 PUSH [ESI].fStatusWnd
47543 CALL SendMessage
47544 ADD ESP, 1024
47546 @@reset_simple:
47547 PUSH 0
47548 PUSH 0
47549 PUSH SB_SIMPLE
47550 PUSH [ESI].fStatusWnd
47551 CALL SendMessage
47553 @@not_simple:
47554 PUSH SB_SETTEXT
47555 PUSH [ESI].fStatusWnd
47556 CALL SendMessage
47557 POPAD
47558 end;
47559 {$ELSE ASM_VERSION} //Pascal
47560 procedure TControl.SetStatusText(Index: Integer; Value: PChar);
47561 var ch: Integer;
47562 R : TRect;
47563 N, I, L, W : Integer;
47564 WidthsBuf: array[ 0..254 ] of Integer;
47565 begin
47566 if fStatusCtl = nil then
47567 begin
47568 ch := GetClientHeight;
47569 fStatusCtl := _NewStatusBar( @Self );
47570 fStatusWnd := fStatusCtl.GetWindowHandle;
47571 fStatusCtl.Perform( SB_SIMPLE, Integer( LongBool( Index = 255 ) ), 0 );
47572 GetWindowRect( fStatusWnd, R );
47573 fClientBottom := R.Bottom - R.Top;
47574 SetClientHeight( ch );
47575 SendMessage( fStatusWnd, WM_SIZE, 0, 0 );
47576 end;
47577 if Index < 255 then
47578 begin
47579 N := SendMessage( fStatusWnd, SB_GETPARTS, 0, 0 );
47580 if N <= Index then
47581 begin
47582 W := Width;
47583 L := W div (Index + 1);
47584 W := L;
47585 for I := 0 to Index - 1 do
47586 begin
47587 WidthsBuf[ I ] := W;
47588 Inc( W, L );
47589 end;
47590 WidthsBuf[ Index ] := -1;
47591 SendMessage( fStatusWnd, SB_SETPARTS, Index + 1, Integer( @WidthsBuf[ 0 ] ) );
47592 end;
47593 SendMessage( fStatusWnd, SB_SIMPLE, 0, 0 );
47594 end;
47595 SendMessage( fStatusWnd, SB_SETTEXT, Index, Integer( Value ) );
47596 end;
47597 {$ENDIF ASM_VERSION}
47599 {$IFDEF ASM_VERSION}
47600 //[function TControl.GetStatusText]
47601 function TControl.GetStatusText( Index: Integer ): PChar;
47603 MOV ECX, [EAX].fStatusWnd
47604 JECXZ @@exit
47606 PUSH EBX
47607 PUSH ESI
47608 XCHG ESI, EAX // ESI = @Self
47609 MOV EBX, EDX // EBX = Index
47611 XOR EAX, EAX
47612 XCHG EAX, [ESI].fStatusTxt
47613 TEST EAX, EAX
47614 JZ @@1
47615 CALL System.@FreeMem
47616 @@1:
47617 XOR EAX, EAX
47619 MOV DL, WM_GETTEXTLENGTH
47620 PUSH WM_GETTEXT
47621 CMP EBX, 255
47622 JZ @@2
47623 POP EAX
47624 MOV EAX, EBX
47625 MOV DX, SB_GETTEXTLENGTH
47626 PUSH SB_GETTEXT
47627 @@2:
47628 MOV EBX, EAX
47630 PUSH 0
47631 PUSH EAX
47632 PUSH EDX
47633 PUSH [ESI].fStatusWnd
47634 CALL SendMessage
47635 TEST AX, AX
47636 JZ @@get_rslt
47638 PUSH EAX
47639 INC EAX
47640 CALL System.@GetMem
47641 POP EDX
47642 MOV [ESI].fStatusTxt, EAX
47643 MOV byte ptr [EAX+EDX], 0
47645 POP EDX // Msg
47646 PUSH EAX
47647 PUSH EBX
47648 PUSH EDX
47649 PUSH [ESI].fStatusWnd
47650 CALL SendMessage
47651 PUSH EDX
47652 @@get_rslt:
47653 POP EDX
47654 MOV ECX, [ESI].fStatusTxt
47655 POP ESI
47656 POP EBX
47658 @@exit: XCHG EAX, ECX
47659 end;
47660 {$ELSE ASM_VERSION} //Pascal
47661 function TControl.GetStatusText( Index: Integer ): PChar;
47662 var L, I: Integer;
47663 Msg: DWORD;
47664 begin
47665 Result := nil;
47666 if fStatusWnd = 0 then Exit;
47667 if fStatusTxt <> nil then
47668 FreeMem( fStatusTxt );
47669 fStatusTxt := nil;
47670 Msg := SB_GETTEXTLENGTH;
47671 I := Index;
47672 if Index = 255 then
47673 begin
47674 Msg := WM_GETTEXTLENGTH;
47675 I := 0;
47676 end;
47677 L := SendMessage( fStatusWnd, Msg, I, 0 ) and $FFFF;
47678 if L > 0 then
47679 begin
47680 GetMem( fStatusTxt, L + 1 );
47681 fStatusTxt[ L ] := #0;
47682 Msg := SB_GETTEXT;
47683 if Index = 255 then
47684 Msg := WM_GETTEXT;
47685 SendMessage( fStatusWnd, Msg, I, Integer( fStatusTxt ) );
47686 end;
47687 Result := fStatusTxt;
47688 end;
47689 {$ENDIF ASM_VERSION}
47691 {$IFDEF ASM_VERSION}
47692 //[procedure TControl.RemoveStatus]
47693 procedure TControl.RemoveStatus;
47695 MOV ECX, [EAX].fStatusCtl
47696 JECXZ @@exit
47697 PUSH EBX
47698 MOV EBX, EAX
47699 CALL GetClientHeight
47700 PUSH EAX
47702 MOV [EBX].fStatusWnd, EDX
47703 XCHG EAX, EDX
47704 XCHG [EBX].fStatusCtl, EAX
47705 CALL TControl.Free
47706 POP EAX
47708 MOV [EBX].fClientBottom, EDX
47709 XCHG EDX, EAX
47710 XCHG EAX, EBX
47711 POP EBX
47712 CALL SetClientHeight
47713 @@exit:
47714 end;
47715 {$ELSE ASM_VERSION} //Pascal
47716 procedure TControl.RemoveStatus;
47717 var ch: Integer;
47718 begin
47719 if fStatusCtl = nil then Exit;
47720 ch := ClientHeight;
47721 fStatusWnd := 0;
47722 fStatusCtl.Free;
47723 fStatusCtl := nil;
47724 fClientBottom := 0;
47725 ClientHeight := ch;
47726 end;
47727 {$ENDIF ASM_VERSION}
47729 {$IFDEF ASM_VERSION}
47730 //[function TControl.StatusPanelCount]
47731 function TControl.StatusPanelCount: Integer;
47733 MOV EAX, [EAX].fStatusWnd
47734 TEST EAX, EAX
47735 JZ @@exit
47736 PUSH 0
47737 PUSH 0
47738 PUSH SB_GETPARTS
47739 PUSH EAX
47740 CALL SendMessage
47741 @@exit:
47742 end;
47743 {$ELSE ASM_VERSION} //Pascal
47744 function TControl.StatusPanelCount: Integer;
47745 begin
47746 Result := 0;
47747 if fStatusWnd = 0 then Exit;
47748 Result := SendMessage( fStatusWnd, SB_GETPARTS, 0, 0 );
47749 end;
47750 {$ENDIF ASM_VERSION}
47752 {$IFDEF ASM_VERSION}
47753 //[function TControl.GetStatusPanelX]
47754 function TControl.GetStatusPanelX(Idx: Integer): Integer;
47756 MOV ECX, [EAX].fStatusWnd
47757 JECXZ @@exit
47758 PUSH EBX
47759 MOV EBX, EDX
47760 ADD ESP, -1024
47761 PUSH ESP
47762 XOR EDX, EDX
47763 DEC DL
47764 PUSH EDX
47765 MOV DX, SB_GETPARTS
47766 PUSH EDX
47767 PUSH ECX
47768 CALL SendMessage
47769 CMP EAX, EBX
47770 MOV ECX, [ESP+EBX*4]
47771 JG @@1
47772 XOR ECX, ECX
47773 @@1: ADD ESP, 1024
47774 POP EBX
47775 @@exit:
47776 XCHG EAX, ECX
47777 end;
47778 {$ELSE ASM_VERSION} //Pascal
47779 function TControl.GetStatusPanelX(Idx: Integer): Integer;
47780 var Buf: array[0..254] of Integer;
47781 N : Integer;
47782 begin
47783 Result := 0;
47784 if fStatusWnd = 0 then Exit;
47785 N := SendMessage( fStatusWnd, SB_GETPARTS, 255, Integer( @Buf[ 0 ] ) );
47786 if N <= Idx then Exit;
47787 Result := Buf[ Idx ];
47788 end;
47789 {$ENDIF ASM_VERSION}
47791 {$IFDEF ASM_VERSION}
47792 //[procedure TControl.SetStatusPanelX]
47793 procedure TControl.SetStatusPanelX(Idx: Integer; const Value: Integer);
47795 ADD ESP, -1024
47796 MOV EAX, [EAX].fStatusWnd
47797 TEST EAX, EAX
47798 JZ @@exit
47800 PUSH ESP
47801 PUSH EDX
47802 PUSH SB_SETPARTS
47803 PUSH EAX
47805 PUSH EDX
47806 PUSH ECX
47808 LEA EDX, [ESP+24]
47809 PUSH EDX
47810 PUSH 255
47811 PUSH SB_GETPARTS
47812 PUSH EAX
47813 CALL SendMessage
47815 POP ECX
47816 POP EDX
47817 CMP EAX, EDX
47818 JG @@1
47819 ADD ESP, 16
47820 JMP @@exit
47822 @@1: MOV [ESP+8], EAX
47823 MOV [ESP+16+EDX*4], ECX
47824 CALL SendMessage
47826 @@exit: ADD ESP, 1024
47827 end;
47828 {$ELSE ASM_VERSION} //Pascal
47829 procedure TControl.SetStatusPanelX(Idx: Integer; const Value: Integer);
47830 var Buf: array[0..254] of Integer;
47831 N : Integer;
47832 begin
47833 if fStatusWnd = 0 then Exit;
47834 N := SendMessage( fStatusWnd, SB_GETPARTS, 255, Integer( @Buf[ 0 ] ) );
47835 if N <= Idx then Exit;
47836 Buf[ Idx ] := Value;
47837 SendMessage( fStatusWnd, SB_SETPARTS, N, Integer( @Buf[ 0 ] ) );
47838 end;
47839 {$ENDIF ASM_VERSION}
47841 //[procedure TControl.SetColor1]
47842 procedure TControl.SetColor1(const Value: TColor);
47843 begin
47844 fColor1 := Value;
47845 Invalidate;
47846 end;
47848 //[procedure TControl.SetColor2]
47849 procedure TControl.SetColor2(const Value: TColor);
47850 begin
47851 fColor2 := Value;
47852 Invalidate;
47853 end;
47855 //[procedure TControl.SetGradientLayout]
47856 procedure TControl.SetGradientLayout(const Value: TGradientLayout);
47857 begin
47858 FGradientLayout := Value;
47859 Invalidate;
47860 end;
47862 //[procedure TControl.SetGradientStyle]
47863 procedure TControl.SetGradientStyle(const Value: TGradientStyle);
47864 begin
47865 FGradientStyle := Value;
47866 Invalidate;
47867 end;
47880 { -- Image List -- }
47883 {$IFDEF USE_CONSTRUCTORS}
47884 //[function NewImageList]
47885 function NewImageList( AOwner: PControl ): PImageList;
47886 begin
47887 new( Result, CreateImageList( AOwner ) );
47888 end;
47889 //[END NewImageList]
47890 {$ELSE not_USE_CONSTRUCTORS}
47891 //[function NewImageList]
47892 function NewImageList( AOwner: PControl ): PImageList;
47893 begin
47894 {*************} DoInitCommonControls( ICC_WIN95_CLASSES );
47896 New( Result, Create );
47898 {++}(*Result := TImageList.Create;*){--}
47899 Result.FAllocBy := 1;
47900 Result.FMasked := True;
47901 if AOwner = nil then exit;
47903 Result.FControl := AOwner;
47904 Result.fNext := PImageList( AOwner.fImageList );
47905 if AOwner.fImageList <> nil then
47906 PImageList( AOwner.fImageList ).fPrev := Result;
47907 Result.fBkColor := clNone;
47908 //ImageList_SetBkColor( Result.FHandle, CLR_NONE );
47909 AOwner.fImageList := Result;
47910 Result.FImgWidth := 32;
47911 Result.FImgHeight := 32;
47912 Result.FColors := ilcDefault;
47913 end;
47914 {$ENDIF}
47916 //[API ImageList_XXX]
47917 function ImageList_Create; stdcall; external cctrl name 'ImageList_Create';
47918 function ImageList_Destroy; external cctrl name 'ImageList_Destroy';
47919 function ImageList_GetImageCount; external cctrl name 'ImageList_GetImageCount';
47920 function ImageList_SetImageCount; external cctrl name 'ImageList_SetImageCount';
47921 function ImageList_Add; external cctrl name 'ImageList_Add';
47922 function ImageList_ReplaceIcon; external cctrl name 'ImageList_ReplaceIcon';
47923 function ImageList_SetBkColor; external cctrl name 'ImageList_SetBkColor';
47924 function ImageList_GetBkColor; external cctrl name 'ImageList_GetBkColor';
47925 function ImageList_SetOverlayImage; external cctrl name 'ImageList_SetOverlayImage';
47926 function ImageList_Draw; external cctrl name 'ImageList_Draw';
47927 function ImageList_Replace; external cctrl name 'ImageList_Replace';
47928 function ImageList_AddMasked; external cctrl name 'ImageList_AddMasked';
47929 function ImageList_DrawEx; external cctrl name 'ImageList_DrawEx';
47930 function ImageList_Remove; external cctrl name 'ImageList_Remove';
47931 function ImageList_GetIcon; external cctrl name 'ImageList_GetIcon';
47932 function ImageList_LoadImageA; external cctrl name 'ImageList_LoadImageA';
47933 function ImageList_LoadImageW; external cctrl name 'ImageList_LoadImageW';
47934 function ImageList_LoadImage; external cctrl name 'ImageList_LoadImageA';
47935 function ImageList_BeginDrag; external cctrl name 'ImageList_BeginDrag';
47936 function ImageList_EndDrag; external cctrl name 'ImageList_EndDrag';
47937 function ImageList_DragEnter; external cctrl name 'ImageList_DragEnter';
47938 function ImageList_DragLeave; external cctrl name 'ImageList_DragLeave';
47939 function ImageList_DragMove; external cctrl name 'ImageList_DragMove';
47940 function ImageList_SetDragCursorImage; external cctrl name 'ImageList_SetDragCursorImage';
47941 function ImageList_DragShowNolock; external cctrl name 'ImageList_DragShowNolock';
47942 function ImageList_GetDragImage; external cctrl name 'ImageList_GetDragImage';
47943 //function ImageList_Read; external cctrl name 'ImageList_Read';
47944 //function ImageList_Write; external cctrl name 'ImageList_Write';
47945 function ImageList_GetIconSize; external cctrl name 'ImageList_GetIconSize';
47946 function ImageList_SetIconSize; external cctrl name 'ImageList_SetIconSize';
47947 function ImageList_GetImageInfo; external cctrl name 'ImageList_GetImageInfo';
47948 function ImageList_Merge; external cctrl name 'ImageList_Merge';
47950 //[function ImageList_AddIcon]
47951 function ImageList_AddIcon(ImageList: HImageList; Icon: HIcon): Integer;
47952 begin
47953 Result := ImageList_ReplaceIcon(ImageList, -1, Icon);
47954 end;
47956 //[function Index2OverlayMask]
47957 function Index2OverlayMask(Index: Integer): Integer;
47958 begin
47959 Result := Index shl 8;
47960 end;
47962 { macros }
47963 //[procedure ImageList_RemoveAll]
47964 procedure ImageList_RemoveAll(ImageList: HImageList); stdcall;
47965 begin
47966 ImageList_Remove(ImageList, -1);
47967 end;
47969 //[function ImageList_ExtractIcon]
47970 function ImageList_ExtractIcon(Instance: THandle; ImageList: HImageList;
47971 Image: Integer): HIcon; stdcall;
47972 begin
47973 Result := ImageList_GetIcon(ImageList, Image, 0);
47974 end;
47976 //[function ImageList_LoadBitmap]
47977 function ImageList_LoadBitmap(Instance: THandle; Bmp: PChar;
47978 CX, Grow: Integer; Mask: TColorRef): HImageList; stdcall;
47979 begin
47980 Result := ImageList_LoadImage(Instance, Bmp, CX, Grow, Mask,
47981 IMAGE_BITMAP, 0);
47982 end;
47984 //[procedure FreeBmp]
47985 procedure FreeBmp( Bmp: HBitmap );
47986 begin
47987 DeleteObject( Bmp );
47988 end;
47990 //[function LoadBmp]
47991 function LoadBmp( Instance: Integer; Rsrc: PChar; MasterObj: PObj ): HBitmap;
47992 begin
47993 Result := LoadBitmap( Instance, Rsrc );
47994 MasterObj.Add2AutoFreeEx( TObjectMethod( MakeMethod( Pointer( Result ), @ FreeBmp ) ) );
47995 end;
47997 { TImageList }
48000 //[function TImageList.Add]
48001 function TImageList.Add(Bmp, Msk: HBitmap): Integer;
48002 begin
48003 Result := -1;
48004 if not HandleNeeded then Exit;
48005 Result := ImageList_Add( FHandle, Bmp, Msk );
48006 end;
48009 //[function TImageList.AddIcon]
48010 function TImageList.AddIcon(Ico: HIcon): Integer;
48011 {var Bmp : HBitmap;
48012 DC : HDC;}
48013 begin
48014 Result := -1;
48015 if ImgWidth = 0 then
48016 ImgWidth := 32;
48017 if ImgHeight = 0 then
48018 ImgHeight := 32;
48019 if not HandleNeeded then Exit;
48021 {DC := GetDC( 0 );
48022 Bmp := CreateCompatibleBitmap( DC, ImgWidth, ImgHeight );
48023 Result := AddMasked( Bmp, 0 );
48024 DeleteObject( Bmp );
48025 ReleaseDC( 0, DC );
48026 if Result >= 0 then
48027 ReplaceIcon( Result, Ico );}
48028 Result := ImageList_AddIcon( fHandle, Ico );
48029 end;
48032 //[function TImageList.AddMasked]
48033 function TImageList.AddMasked(Bmp: HBitmap; Color: TColor): Integer;
48034 begin
48035 Result := -1;
48036 if not HandleNeeded then Exit;
48037 Result := ImageList_AddMasked( FHandle, Bmp, Color2RGB( Color ) );
48038 end;
48041 //[procedure TImageList.Clear]
48042 procedure TImageList.Clear;
48043 begin
48044 Handle := 0;
48045 end;
48048 //[procedure TImageList.Delete]
48049 procedure TImageList.Delete(Idx: Integer);
48050 begin
48051 if FHandle = 0 then Exit;
48052 ImageList_Remove( FHandle, Idx );
48053 end;
48055 {$IFDEF ASM_VERSION}
48056 //[destructor TImageList.Destroy]
48057 destructor TImageList.Destroy;
48059 PUSH EAX
48060 XOR EDX, EDX
48061 CALL SetHandle
48062 POP EAX
48063 MOV EDX, [EAX].fNext
48064 MOV ECX, [EAX].fPrev
48065 TEST EDX, EDX
48066 JZ @@nonext
48067 MOV [EDX].fPrev, ECX
48068 @@nonext:
48069 JECXZ @@noprev
48070 MOV [ECX].fNext, EDX
48071 @@noprev:
48072 MOV ECX, [EAX].fControl
48073 JECXZ @@fin
48074 CMP [ECX].TControl.fImageList, EAX
48075 JNZ @@fin
48076 MOV [ECX].TControl.fImageList, EDX
48077 @@fin: CALL TObj.Destroy
48078 end;
48079 {$ELSE ASM_VERSION} //Pascal
48080 destructor TImageList.Destroy;
48081 begin
48082 Clear;
48083 if fNext <> nil then
48084 fNext.fPrev := fPrev;
48085 if fPrev <> nil then
48086 fPrev.fNext := fNext;
48087 if fControl <> nil then
48088 if PControl( fControl ).fImageList = @Self then
48089 PControl( fControl ).fImageList := fNext;
48090 inherited;
48091 end;
48092 {$ENDIF ASM_VERSION}
48095 //[procedure TImageList.Draw]
48096 procedure TImageList.Draw(Idx: Integer; DC: HDC; X, Y: Integer);
48097 begin
48098 if FHandle = 0 then Exit;
48099 ImageList_Draw( FHandle, Idx, DC, X, Y, GetDrawStyle );
48100 end;
48102 //[function TImageList.ExtractIcon]
48103 function TImageList.ExtractIcon(Idx: Integer): HIcon;
48104 begin
48105 Result := ImageList_ExtractIcon( 0, FHandle, Idx );
48106 end;
48108 //[function TImageList.ExtractIconEx]
48109 function TImageList.ExtractIconEx(Idx: Integer): HIcon;
48110 begin
48111 Result := ImageList_GetIcon( FHandle, Idx, GetDrawStyle );
48112 end;
48115 //[function TImageList.GetBitmap]
48116 function TImageList.GetBitmap: HBitmap;
48117 var II : TImageInfo;
48118 begin
48119 Result := 0;
48120 if FHandle = 0 then Exit;
48121 if ImageList_GetImageInfo( FHandle, 0, II ) then
48122 Result := II.hbmImage;
48123 end;
48126 //[function TImageList.GetBkColor]
48127 function TImageList.GetBkColor: TColor;
48128 begin
48129 Result := fBkColor;
48130 if FHandle = 0 then Exit;
48131 Result := ImageList_GetBkColor( FHandle );
48132 end;
48135 //[function TImageList.GetCount]
48136 function TImageList.GetCount: Integer;
48137 begin
48138 Result := 0;
48139 if FHandle <> 0 then
48140 Result := ImageList_GetImageCount( FHandle );
48141 end;
48144 //[function TImageList.GetDrawStyle]
48145 function TImageList.GetDrawStyle: DWord;
48146 begin
48147 Result := 0;
48148 if dsBlend25 in DrawingStyle then
48149 Result := Result or ILD_BLEND25;
48150 if dsBlend50 in DrawingStyle then
48151 Result := Result or ILD_BLEND50;
48152 if dsTransparent in DrawingStyle then
48153 Result := Result or ILD_TRANSPARENT
48154 else
48155 if dsMask in DrawingStyle then
48156 Result := Result or ILD_MASK
48157 {else
48158 Result := Result or ILD_NORMAL}; // ILD_NORMAL = 0
48159 end;
48161 {$IFDEF ASM_VERSION}
48162 //[function TImageList.GetHandle]
48163 function TImageList.GetHandle: THandle;
48165 PUSH EAX
48166 CALL HandleNeeded
48167 POP EAX
48168 MOV EAX, [EAX].FHandle
48169 end;
48170 {$ELSE ASM_VERSION} //Pascal
48171 function TImageList.GetHandle: THandle;
48172 begin
48173 HandleNeeded;
48174 Result := FHandle;
48175 end;
48176 {$ENDIF ASM_VERSION}
48179 //[function TImageList.GetMask]
48180 function TImageList.GetMask: HBitmap;
48181 var II : TImageInfo;
48182 begin
48183 Result := 0;
48184 if FHandle = 0 then Exit;
48185 if ImageList_GetImageInfo( FHandle, 0, II ) then
48186 Result := II.hbmMask;
48187 end;
48189 {$IFDEF ASM_noVERSION}
48190 //[function TImageList.HandleNeeded]
48191 function TImageList.HandleNeeded: Boolean;
48192 const ColorFlags : array[ TImageListColors ] of Byte = ( ILC_COLOR,
48193 ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24,
48194 ILC_COLOR32, ILC_COLORDDB );
48196 MOV ECX, [EAX].FHandle
48197 JECXZ @@make_handle
48198 MOV AL, 1
48200 @@make_handle:
48201 MOV ECX, [EAX].fImgWidth
48202 JECXZ @@ret_ECX
48203 MOV EDX, ECX
48204 MOV ECX, [EAX].fImgHeight
48205 JECXZ @@ret_ECX
48206 PUSH EBX
48207 XCHG EBX, EAX
48209 PUSH [EBX].FAllocBy
48210 PUSH 0
48211 MOVZX EAX, [EBX].FColors
48212 MOVZX EAX, byte ptr [ColorFlags+EAX]
48213 CMP [EBX].FMasked, 0
48214 JZ @@flags_ready
48215 {$IFDEF PARANOIA}
48216 DB $0C, $01
48217 {$ELSE}
48218 OR AL, 1
48219 {$ENDIF}
48220 @@flags_ready:
48221 PUSH EAX
48222 PUSH ECX
48223 PUSH EDX
48224 CALL ImageList_Create
48225 MOV [EBX].FHandle, EAX
48226 XCHG ECX, EAX
48227 POP EBX
48228 @@ret_ECX:
48229 TEST ECX, ECX
48230 SETNZ AL
48231 end;
48232 {$ELSE ASM_VERSION} //Pascal
48233 function TImageList.HandleNeeded: Boolean;
48234 const ColorFlags : array[ TImageListColors ] of Byte = ( ILC_COLOR,
48235 ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24,
48236 ILC_COLOR32, ILC_COLORDDB, 0 );
48237 var Flags : DWord;
48238 begin
48239 Result := True;
48240 if FHandle <> 0 then Exit;
48241 Result := False;
48242 if ImgWidth = 0 then Exit;
48243 if ImgHeight = 0 then Exit;
48244 Flags := ColorFlags[ FColors ];
48245 if Masked then
48246 Flags := Flags or ILC_MASK;
48247 FHandle := ImageList_Create( ImgWidth, ImgHeight, Flags, 0, FAllocBy );
48248 if fBkColor <> clNone then
48249 SetBkColor( fBkColor );
48250 Result := FHandle <> 0;
48251 end;
48252 {$ENDIF ASM_VERSION}
48255 //[function TImageList.ImgRect]
48256 function TImageList.ImgRect(Idx: Integer): TRect;
48257 var II : TImageInfo;
48258 begin
48259 Result := MakeRect( 0, 0, 0, 0 );
48260 if FHandle = 0 then Exit;
48261 if ImageList_GetImageInfo( FHandle, Idx, II ) then
48262 Result := II.rcImage;
48263 end;
48265 {$IFDEF ASM_noVERSION}
48266 //[function TImageList.LoadBitmap]
48267 function TImageList.LoadBitmap(ResourceName: PChar;
48268 TranspColor: TColor): Boolean;
48270 PUSH EBX
48271 XCHG EBX, EAX
48272 XCHG EAX, ECX //TranspColor
48273 PUSH EDX
48274 CMP EAX, clNone
48275 JNE @@2rgb
48276 OR EAX, -1
48277 JMP @@tranColorReady
48278 @@2rgb:
48279 CALL Color2RGB
48280 @@tranColorReady:
48281 POP EDX
48282 PUSH EAX
48283 PUSH [EBX].fAllocBy
48284 PUSH [EBX].fImgWidth
48285 PUSH EDX
48286 PUSH [hInstance]
48287 CALL ImageList_LoadBitmap
48288 TEST EAX, EAX
48289 JZ @@exit
48290 XCHG EDX, EAX
48291 XCHG EAX, EBX
48292 CALL SetHandle
48293 MOV AL, 1
48294 @@exit: POP EBX
48295 end;
48296 {$ELSE ASM_VERSION} //Pascal
48297 function TImageList.LoadBitmap(ResourceName: PChar;
48298 TranspColor: TColor): Boolean;
48299 var NewHandle : THandle;
48300 TranColr: TColor;
48301 begin
48302 TranColr := TranspColor;
48303 if TranColr = clNone then TranColr := TColor( CLR_NONE )
48304 else TranColr := Color2RGB( TranColr );
48305 NewHandle := ImageList_LoadBitmap( hInstance, ResourceName,
48306 ImgWidth, AllocBy, TranColr );
48307 //ImageList_GetIconSize( NewHandle, fImgWidth, fImgHeight );
48308 Result := NewHandle <> 0;
48309 if Result then
48310 Handle := NewHandle;
48311 ImageList_GetIconSize( fHandle, FImgWidth, FImgHeight );
48312 end;
48313 {$ENDIF ASM_VERSION}
48316 //[function TImageList.LoadFromFile]
48317 function TImageList.LoadFromFile(FileName: PChar; TranspColor: TColor;
48318 ImgType: TImageType): Boolean;
48319 const ImgTypes:array[ TImageType ] of DWord = ( IMAGE_BITMAP, IMAGE_ICON, IMAGE_CURSOR );
48320 var NewHandle : THandle;
48321 TranspFlag : DWord;
48322 begin
48323 TranspFlag := 0;
48324 if TranspColor <> clNone then
48325 TranspFlag := LR_LOADTRANSPARENT;
48326 NewHandle := ImageList_LoadImage( hInstance, FileName, ImgWidth, AllocBy, Color2RGB( TranspColor ),
48327 ImgTypes[ ImgType ], LR_LOADFROMFILE or TranspFlag );
48328 Result := NewHandle <> 0;
48329 if Result then
48330 Handle := NewHandle;
48331 end;
48334 //[function TImageList.LoadSystemIcons]
48335 function TImageList.LoadSystemIcons(SmallIcons: Boolean): Boolean;
48336 var NewHandle : THandle;
48337 FileInfo : TSHFileInfo;
48338 Flags : DWord;
48339 begin
48340 OleInit;
48341 Flags := SHGFI_SYSICONINDEX;
48342 if SmallIcons then
48343 Flags := Flags or SHGFI_SMALLICON;
48344 NewHandle := SHGetFileInfo( '', 0, FileInfo, Sizeof( FileInfo ), Flags );
48345 Result := NewHandle <> 0;
48346 if Result then
48347 begin
48348 Handle := NewHandle;
48349 FShareImages := True;
48350 end;
48351 end;
48354 //[function TImageList.Merge]
48355 function TImageList.Merge(Idx: Integer; ImgList2: PImageList; Idx2, X,
48356 Y: Integer): PImageList;
48357 var L : THandle;
48358 begin
48359 Result := nil;
48360 //if FHandle = 0 then Exit;
48361 L := ImageList_Merge( FHandle, Idx, ImgList2.Handle, Idx2, X, Y );
48362 if L <> 0 then
48363 begin
48364 Result := NewImageList( fControl );
48365 Result.Handle := L;
48366 end;
48367 end;
48370 //[function TImageList.Replace]
48371 function TImageList.Replace(Idx: Integer; Bmp, Msk: HBitmap): Boolean;
48372 begin
48373 Result := False;
48374 if FHandle = 0 then Exit;
48375 Result := ImageList_Replace( FHandle, Idx, Bmp, Msk );
48376 end;
48379 //[function TImageList.ReplaceIcon]
48380 function TImageList.ReplaceIcon(Idx: Integer; Ico: HIcon): Boolean;
48381 begin
48382 Result := False;
48383 if FHandle = 0 then Exit;
48384 Result := ImageList_ReplaceIcon( FHandle, Idx, Ico ) >= 0;
48385 end;
48388 //[procedure TImageList.SetAllocBy]
48389 procedure TImageList.SetAllocBy(const Value: Integer);
48390 begin
48391 if FHandle <> 0 then Exit;
48392 // AllocBy can be changed only before adding images
48393 // and creating image list handle
48394 FAllocBy := Value;
48395 end;
48398 //[procedure TImageList.SetBkColor]
48399 procedure TImageList.SetBkColor(const Value: TColor);
48400 begin
48401 fBkColor := Value;
48402 if fHandle <> 0 then
48403 ImageList_SetBkColor( FHandle, Color2RGB( Value ) );
48404 end;
48407 //[procedure TImageList.SetColors]
48408 procedure TImageList.SetColors(const Value: TImageListColors);
48409 begin
48410 if FHandle <> 0 then Exit;
48411 FColors := Value;
48412 end;
48414 {$IFDEF ASM_VERSION}
48415 //[procedure TImageList.SetHandle]
48416 procedure TImageList.SetHandle(const Value: THandle);
48418 PUSH EBX
48419 XCHG EBX, EAX
48420 MOV ECX, [EBX].FHandle
48421 CMP ECX, EDX
48422 JZ @@exit
48423 JECXZ @@set_handle
48424 CMP [EBX].fShareImages, 0
48425 JNZ @@set_handle
48426 PUSH EDX
48427 PUSH ECX
48428 CALL ImageList_Destroy
48429 POP EDX
48431 @@set_handle:
48432 MOV [EBX].FHandle, EDX
48433 TEST EDX, EDX
48434 JZ @@set_sz0
48435 LEA EAX, [EBX].FImgHeight
48436 PUSH EAX
48437 LEA EAX, [EBX].FImgWidth
48438 PUSH EAX
48439 PUSH EDX
48440 CALL ImageList_GetIconSize
48441 JMP @@exit
48443 @@set_sz0:
48444 MOV [EBX].fImgWidth, EDX
48445 MOV [EBX].fImgHeight, EDX
48447 @@exit:
48448 POP EBX
48449 end;
48450 {$ELSE ASM_VERSION} //Pascal
48451 procedure TImageList.SetHandle(const Value: THandle);
48452 begin
48453 if FHandle = Value then Exit;
48454 if (FHandle <> 0) and not FShareImages then
48455 ImageList_Destroy( FHandle );
48456 FHandle := Value;
48457 if FHandle <> 0 then
48458 ImageList_GetIconSize( FHandle, FImgWidth, FImgHeight )
48459 else
48460 begin
48461 FImgWidth := 0;
48462 FImgHeight := 0;
48463 end;
48464 //FBkColor := ImageList_GetBkColor( FHandle );
48465 end;
48466 {$ENDIF ASM_VERSION}
48468 //[procedure TImageList.SetImgHeight]
48469 procedure TImageList.SetImgHeight(const Value: Integer);
48470 begin
48471 if FHandle <> 0 then Exit;
48472 FImgHeight := Value;
48473 end;
48475 //[procedure TImageList.SetImgWidth]
48476 procedure TImageList.SetImgWidth(const Value: Integer);
48477 begin
48478 if FHandle <> 0 then Exit;
48479 FImgWidth := Value;
48480 end;
48482 //[procedure TImageList.SetMasked]
48483 procedure TImageList.SetMasked(const Value: Boolean);
48484 begin
48485 if FHandle <> 0 then Exit;
48486 FMasked := Value;
48487 end;
48490 //[function TImageList.GetOverlay]
48491 function TImageList.GetOverlay(Idx: TImgLOVrlayIdx): Integer;
48492 begin
48493 Result := fOverlay[ Idx ];
48494 end;
48496 //[procedure TImageList.SetOverlay]
48497 procedure TImageList.SetOverlay(Idx: TImgLOVrlayIdx; const Value: Integer);
48498 begin
48499 if ImageList_SetOverlayImage( fHandle, Value, Idx shl 8 ) then
48500 fOverlay[ Idx ] := Value;
48501 end;
48503 //[procedure TImageList.StretchDraw]
48504 procedure TImageList.StretchDraw(Idx: Integer; DC: HDC; const Rect: TRect);
48505 begin
48506 if FHandle = 0 then Exit;
48507 ImageList_DrawEx( FHandle, Idx, DC, Rect.Left, Rect.Top,
48508 Rect.Right- Rect.Left, Rect.Bottom-Rect.Top,
48509 BkColor, BlendColor, GetDrawStyle );
48510 end;
48513 //[function GetImgListSize]
48514 function GetImgListSize( Sender: PControl; Size: Integer ): PImageList;
48515 begin
48516 if Size > 16 then
48517 Result := Sender.fCtlImageListNormal
48518 else
48519 Result := Sender.fCtlImageListSml;
48520 if Result <> nil then
48521 begin
48522 if Result.fImgWidth = 0 then
48523 Result.ImgWidth := Size;
48524 if Result.fImgHeight = 0 then
48525 Result.ImgHeight := Size;
48526 //if (Result.FImgWidth <> Size) or (Result.FImgHeight <> Size) then
48527 // Result := nil;
48528 end;
48529 if Result = nil then
48530 begin
48531 Result := Sender.fImageList;
48532 while Result <> nil do
48533 begin
48534 if (Result.FImgWidth = Size) and (Result.FImgHeight = Size) then
48535 break;
48536 Result := Result.fNext;
48537 end;
48538 end;
48539 end;
48542 //[function TControl.GetImgListIdx]
48543 function TControl.GetImgListIdx(const Index: Integer): PImageList;
48544 begin
48545 if Index <> 0 then
48546 Result := GetImgListSize( @Self, Index )
48547 else
48548 begin
48549 Result := fCtlImgListState;
48550 if Result = nil then
48551 begin
48552 Result := fImageList;
48553 while Result <> nil do
48554 begin
48555 if (Result <> GetImgListIdx( 16 )) and (Result <> GetImgListIdx( 32 )) then
48556 break;
48557 Result := Result.fNext;
48558 end;
48559 end;
48560 end;
48561 end;
48564 //[procedure TControl.SetImgListIdx]
48565 procedure TControl.SetImgListIdx(const Index: Integer;
48566 const Value: PImageList);
48567 begin
48569 if Value <> nil then
48570 begin
48571 if Index <> 0 then
48572 if (Value.ImgWidth = 0) or (Value.ImgHeight = 0) then
48573 begin
48574 Value.ImgWidth := Index;
48575 Value.ImgHeight := Index;
48576 end;
48577 end;
48579 case Index of
48580 32: fCtlImageListNormal := Value;
48581 16: fCtlImageListSml := Value;
48582 else fCtlImgListState := Value;
48583 end;
48584 ApplyImageLists2Control( @Self );
48585 end;
48587 { -- list view -- }
48589 //[function WndProcEndLabelEdit]
48590 function WndProcEndLabelEdit( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
48591 var NMhdr: PNMHdr;
48592 LVDisp: PLVDispInfo;
48593 {$IFNDEF _FPC}
48594 {$IFNDEF _D2}
48595 {$IFDEF UNICODE_CTRLS}
48596 LVDispW: PLVDispInfoW;
48597 {$ENDIF UNICODE_CTRLS}
48598 {$ENDIF _D2}
48599 {$ENDIF _FPC}
48600 Flag: Boolean;
48601 begin
48602 Result := False;
48603 if Msg.message = WM_NOTIFY then
48604 begin
48605 NMHdr := Pointer( Msg.lParam );
48606 case NMHdr.code of
48607 LVN_ENDLABELEDIT {$IFDEF UNICODE_CTRLS}, LVN_ENDLABELEDITW {$ENDIF UNICODE_CTRLS}:
48608 begin
48609 LVDisp := Pointer( Msg.lParam );
48610 Result := True;
48611 if LVDisp.item.pszText = nil then Exit;
48612 Rslt := 1;
48613 if assigned( Self_.fOnEditLVItem ) then
48614 begin
48615 {$IFNDEF _FPC}
48616 {$IFNDEF _D2}
48617 {$IFDEF UNICODE_CTRLS}
48618 if NMHdr.code = LVN_ENDLABELEDITW then
48619 begin
48620 LVDispW := Pointer( LVDisp );
48621 Flag := Self_.fOnEditLVItem( Self_, LVDispW.item.iItem,
48622 LVDispW.item.iSubItem, PChar( LVDispW.item.pszText ) );
48623 end else
48624 {$ENDIF UNICODE_CTRLS}
48625 {$ENDIF _D2}
48626 {$ENDIF _FPC}
48627 Flag := Self_.fOnEditLVItem( Self_, LVDisp.item.iItem,
48628 LVDisp.item.iSubItem, LVDisp.item.pszText );
48629 if Flag then Rslt := 1
48630 else Rslt := 0;
48631 end;
48632 end;
48633 end;
48634 end;
48635 end;
48637 //[procedure TControl.SetOnEditLVItem]
48638 procedure TControl.SetOnEditLVItem(const Value: TOnEditLVItem);
48639 begin
48640 fOnEditLVITem := Value;
48641 AttachProc( WndProcEndLabelEdit );
48642 end;
48645 //[procedure TControl.LVColAdd]
48646 procedure TControl.LVColAdd(const aText: String; aalign: TTextAlign;
48647 aWidth: Integer);
48648 begin
48649 ////////////////////////////////////////////////////
48650 //LVColInsert( fLVColCount + 1, aText, aalign, aWidth );
48651 //////////////////////////////////////////////////////
48652 LVColInsert( fLVColCount, aText, aalign, aWidth );// 21.10.2001
48653 ////////////////////////////////////////////////////
48654 end;
48656 {$IFNDEF _FPC}
48657 {$IFNDEF _D2}
48658 //[procedure TControl.LVColAddW]
48659 procedure TControl.LVColAddW(const aText: WideString; aalign: TTextAlign;
48660 aWidth: Integer);
48661 begin
48662 LVColInsertW( fLVColCount, aText, aalign, aWidth );
48663 end;
48664 {$ENDIF _D2}
48665 {$ENDIF _FPC}
48667 //****************** changed by Mike Gerasimov
48668 //[procedure TControl.LVColInsert]
48669 procedure TControl.LVColInsert(ColIdx: Integer; const aText: String;
48670 aAlign: TTextAlign; aWidth: Integer);
48671 var LVColData: TLVColumn;
48672 begin
48673 LVColData.mask := LVCF_FMT or LVCF_TEXT;
48674 if ImageListSmall <> nil then
48675 LVColData.mask := LVColData.mask; // or LVCF_IMAGE ;
48676 LVColData.iImage := -1;
48677 LVColData.fmt := Ord( aAlign );
48678 if aWidth < 0 then
48679 begin
48680 aWidth := -aWidth;
48681 LVColData.fmt := LVColData.fmt or LVCFMT_BITMAP_ON_RIGHT;
48682 end;
48683 LVColData.cx := aWidth;
48684 if aWidth > 0 then
48685 LVColData.mask := LVColData.mask or LVCF_WIDTH;
48686 LVColData.pszText := PChar( aText );
48687 if Perform( LVM_INSERTCOLUMN, ColIdx, Integer( @LVColData ) ) >= 0 then
48688 Inc( fLVColCount );
48689 end;
48691 {$IFNDEF _FPC}
48692 {$IFNDEF _D2}
48693 //[procedure TControl.LVColInsertW]
48694 procedure TControl.LVColInsertW(ColIdx: Integer; const aText: WideString;
48695 aAlign: TTextAlign; aWidth: Integer);
48696 var LVColData: TLVColumnW;
48697 begin
48698 LVColData.mask := LVCF_FMT or LVCF_TEXT;
48699 if ImageListSmall <> nil then
48700 LVColData.mask := LVColData.mask; // or LVCF_IMAGE ;
48701 LVColData.iImage := -1;
48702 LVColData.fmt := Ord( aAlign );
48703 if aWidth < 0 then
48704 begin
48705 aWidth := -aWidth;
48706 LVColData.fmt := LVColData.fmt or LVCFMT_BITMAP_ON_RIGHT;
48707 end;
48708 LVColData.cx := aWidth;
48709 if aWidth > 0 then
48710 LVColData.mask := LVColData.mask or LVCF_WIDTH;
48711 LVColData.pszText := PWideChar( aText );
48712 if Perform( LVM_INSERTCOLUMNW, ColIdx, Integer( @LVColData ) ) >= 0 then
48713 Inc( fLVColCount );
48714 end;
48715 {$ENDIF _D2}
48716 {$ENDIF _FPC}
48718 //[function TControl.GetLVColText]
48719 function TControl.GetLVColText(Idx: Integer): String;
48720 var Buf: array[ 0..4095 ] of Char;
48721 LC: TLVColumn;
48722 begin
48723 LC.mask := LVCF_TEXT;
48724 LC.pszText := @ Buf[ 0 ];
48725 LC.cchTextMax := Sizeof( Buf );
48726 Buf[ 0 ] := #0;
48727 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
48728 Result := Buf;
48729 end;
48731 //[procedure TControl.SetLVColText]
48732 procedure TControl.SetLVColText(Idx: Integer; const Value: String);
48733 var LC: TLVColumn;
48734 begin
48735 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
48736 LC.mask := LVCF_TEXT;
48737 LC.pszText := '';
48738 if Value <> '' then
48739 LC.pszText := @ Value[ 1 ];
48740 Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );
48741 end;
48743 {$IFNDEF _FPC}
48744 {$IFNDEF _D2}
48745 //[function TControl.GetLVColTextW]
48746 function TControl.GetLVColTextW(Idx: Integer): WideString;
48747 var Buf: array[ 0..4095 ] of WideChar;
48748 LC: TLVColumnW;
48749 begin
48750 LC.mask := LVCF_TEXT;
48751 LC.pszText := @ Buf[ 0 ];
48752 LC.cchTextMax := High( Buf ) + 1;
48753 Buf[ 0 ] := #0;
48754 Perform( LVM_GETCOLUMNW, Idx, Integer( @ LC ) );
48755 Result := Buf;
48756 end;
48758 //[procedure TControl.SetLVColTextW]
48759 procedure TControl.SetLVColTextW(Idx: Integer; const Value: WideString);
48760 var LC: TLVColumnW;
48761 begin
48762 FillChar( LC, Sizeof( LC ), 0 );
48763 LC.mask := LVCF_TEXT;
48764 LC.pszText := '';
48765 if Value <> '' then
48766 LC.pszText := @ Value[ 1 ];
48767 Perform( LVM_SETCOLUMNW, Idx, Integer( @ LC ) );
48768 end;
48769 {$ENDIF _D2}
48770 {$ENDIF _FPC}
48772 //[function TControl.GetLVColalign]
48773 function TControl.GetLVColalign(Idx: Integer): TTextAlign;
48774 const Formats: array[ 0..2 ] of TTextAlign = ( taLeft, taRight, taCenter );
48775 var LC: TLVColumn;
48776 begin
48777 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
48778 LC.mask := LVCF_FMT;
48779 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
48780 Result := Formats[ LC.fmt and LVCFMT_JUSTIFYMASK ];
48781 end;
48783 //[procedure TControl.SetLVColalign]
48784 procedure TControl.SetLVColalign(Idx: Integer; const Value: TTextAlign);
48785 const FormatFlags: array[ TTextAlign ] of BYTE = ( LVCFMT_LEFT, LVCFMT_RIGHT,
48786 LVCFMT_CENTER );
48787 var LC: TLVColumn;
48788 begin
48789 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
48790 LC.mask := LVCF_FMT;
48791 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
48792 LC.fmt := LC.fmt and not LVCFMT_JUSTIFYMASK or FormatFlags[ Value ];
48793 Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );
48794 end;
48796 //[function TControl.GetLVColEx]
48797 function TControl.GetLVColEx(Idx: Integer; const Index: Integer): Integer;
48798 var LC: TLVColumn;
48799 begin
48800 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
48801 LC.mask := LoWord( Index );
48802 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
48803 Result := PDWORD( Integer( @ LC ) + HiWord( Index ) )^;
48804 end;
48806 //********************** changed by Mike Gerasimov
48807 //[procedure TControl.SetLVColEx]
48808 procedure TControl.SetLVColEx(Idx: Integer; const Index: Integer;
48809 const Value: Integer);
48810 var LC: TLVColumn;
48811 begin
48812 FillChar(LC,SizeOf(LC),0); // Added Line
48813 LC.mask := LoWord( Index );
48814 if HiWord( Index ) = 24 then // Added Line
48815 begin // Added Line
48816 LC.mask := LC.mask or LVCF_FMT; // Added Line
48817 if Value <>-1 Then // Added Line
48818 LC.fmt := LC.fmt or LVCFMT_IMAGE or LVCFMT_COL_HAS_IMAGES; // Added Line
48819 end;
48820 PDWORD( Integer( @ LC ) + HiWord( Index ) )^ := Value;
48821 Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );
48822 end;
48825 //[function TControl.LVAdd]
48826 function TControl.LVAdd(const aText: String; ImgIdx: Integer;
48827 State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer;
48828 Data: DWORD): Integer;
48829 begin
48830 Result := LVInsert( MaxInt {Count}, aText, ImgIdx, State, StateImgIdx, OverlayImgIdx, Data );
48831 end;
48834 //[function TControl.LVInsert]
48835 function TControl.LVInsert(Idx: Integer; const aText: String;
48836 ImgIdx: Integer; State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer;
48837 Data: DWORD): Integer;
48838 const
48839 LVM_REDRAWITEMS = LVM_FIRST + 21;
48840 var LVI: TLVItem;
48841 begin
48842 LVI.mask := LVIF_TEXT or LVIF_IMAGE or LVIF_PARAM or LVIF_STATE
48843 or LVIF_DI_SETITEM;
48844 LVI.iItem := Idx;
48845 LVI.iSubItem := 0;
48846 LVI.state := 0;
48847 if lvisBlend in State then
48848 LVI.state := LVIS_CUT;
48849 if lvisHighlight in State then
48850 LVI.state := LVI.state or LVIS_DROPHILITED;
48851 if lvisFocus in State then
48852 LVI.state := LVI.state or LVIS_FOCUSED;
48853 if lvisSelect in State then
48854 LVI.state := LVI.state or LVIS_SELECTED;
48855 LVI.stateMask := $FFFF;
48856 if StateImgIdx <> 0 then
48857 LVI.state := LVI.state or ((StateImgIdx and $F) shl 12);
48858 if OverlayImgIdx <> 0 then
48859 LVI.state := LVI.state or ((OverlayImgIdx and $F) shl 8);
48860 LVI.pszText := PChar( aText );
48861 LVI.iImage := ImgIdx;
48862 LVI.lParam := Data;
48863 Result := Perform( LVM_INSERTITEM, 0, Integer( @LVI ) );
48864 //Perform( LVM_REDRAWITEMS, Idx, Idx );
48865 end;
48868 //[procedure TControl.LVSetItem]
48869 procedure TControl.LVSetItem(Idx, Col: Integer; const aText: String;
48870 ImgIdx: Integer; State: TListViewItemState; StateImgIdx,
48871 OverlayImgIdx: Integer; Data: DWORD);
48872 var LVI: TLVItem;
48873 I: Integer;
48874 begin
48875 LVI.mask := LVIF_TEXT or {LVIF_STATE or} LVIF_DI_SETITEM;
48876 if Col = 0 then
48877 begin
48878 LVI.mask := LVIF_TEXT or LVIF_STATE or LVIF_PARAM
48879 or LVIF_DI_SETITEM;
48880 if ImgIdx <> I_SKIP then
48881 LVI.mask := LVI.mask or LVIF_IMAGE;
48882 end;
48883 if ImgIdx < I_SKIP then
48884 LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;
48885 LVI.iItem := Idx;
48886 LVI.iSubItem := Col;
48887 LVI.state := 0;
48888 if lvisBlend in State then
48889 LVI.state := LVIS_CUT;
48890 if lvisHighlight in State then
48891 LVI.state := LVI.state or LVIS_DROPHILITED;
48892 if lvisFocus in State then
48893 LVI.state := LVI.state or LVIS_FOCUSED;
48894 if lvisSelect in State then
48895 LVI.state := LVI.state or LVIS_SELECTED;
48896 LVI.stateMask := $FFFF;
48897 if StateImgIdx <> 0 then
48898 LVI.state := LVI.state or ((StateImgIdx and $F) shl 12);
48899 if StateImgIdx < 0 {= I_SKIP} then
48900 LVI.stateMask := $F0FF;
48901 if OverlayImgIdx <> 0 then
48902 LVI.state := LVI.state or ((OverlayImgIdx and $F) shl 8);
48903 if OverlayImgIdx < 0 {=I_SKIP} then
48904 LVI.stateMask := LVI.stateMask and $FFF;
48905 LVI.pszText := PChar( aText );
48906 LVI.iImage := ImgIdx;
48907 LVI.lParam := Data;
48908 I := Perform( LVM_SETITEM, 0, Integer( @LVI ) );
48909 if (I = 0) and (Col = 0) then
48910 Assert( False, 'Can not set item ' );
48911 end;
48914 //[procedure LVGetItem]
48915 procedure LVGetItem( Sender: PControl; Idx, Col: Integer; var LVI: TLVItem;
48916 TextBuf: PChar; TextBufSize: Integer );
48917 begin
48918 LVI.mask := LVIF_STATE or LVIF_PARAM or LVIF_IMAGE;
48919 if Col > 0 then
48920 if not (lvoSubItemImages in Sender.fLVOptions) then
48921 LVI.mask := LVIF_STATE or LVIF_PARAM;
48922 LVI.iItem := Idx;
48923 LVI.iSubItem := Col;
48924 LVI.pszText := TextBuf;
48925 LVI.cchTextMax := TextBufSize;
48926 if TextBufSize <> 0 then
48927 LVI.mask := LVI.mask or LVIF_TEXT;
48928 Sender.Perform( LVM_GETITEM, 0, Integer( @LVI ) );
48929 end;
48931 {$IFNDEF _FPC}
48932 {$IFNDEF _D2}
48933 //[procedure LVGetItemW]
48934 procedure LVGetItemW( Sender: PControl; Idx, Col: Integer; var LVI: TLVItemW;
48935 TextBuf: PWideChar; TextBufSize: Integer );
48936 begin
48937 LVI.mask := LVIF_STATE or LVIF_PARAM or LVIF_IMAGE;
48938 if Col > 0 then
48939 if not (lvoSubItemImages in Sender.fLVOptions) then
48940 LVI.mask := LVIF_STATE or LVIF_PARAM;
48941 LVI.iItem := Idx;
48942 LVI.iSubItem := Col;
48943 LVI.pszText := TextBuf;
48944 LVI.cchTextMax := TextBufSize;
48945 if TextBufSize <> 0 then
48946 LVI.mask := LVI.mask or LVIF_TEXT;
48947 Sender.Perform( LVM_GETITEMW, 0, Integer( @LVI ) );
48948 end;
48949 {$ENDIF _D2}
48950 {$ENDIF _FPC}
48953 //[function TControl.LVGetItemImgIdx]
48954 function TControl.LVGetItemImgIdx(Idx: Integer): Integer;
48955 var LVI: TLVItem;
48956 begin
48957 LVI.iImage := -1;//= Result if image is not assigned {Andrzej Kubaszek}
48958 LVGetItem( @Self, Idx, 0, LVI, nil, 0 );
48959 Result := LVI.iImage;
48960 end;
48963 //[procedure TControl.LVSetItemImgIdx]
48964 procedure TControl.LVSetItemImgIdx(Idx: Integer; const Value: Integer);
48965 var LVI: TLVItem;
48966 begin
48967 LVGetItem( @Self, Idx, 0, LVI, nil, 0 );
48968 LVI.iImage := Value;
48969 Perform( LVM_SETITEM, 0, Integer( @LVI ) );
48970 end;
48973 //[function TControl.LVGetItemText]
48974 function TControl.LVGetItemText(Idx, Col: Integer): String;
48975 var LVI: TLVItem;
48976 TextBuf: PChar;
48977 BufSize: DWORD;
48978 begin
48979 BufSize := 0;
48980 TextBuf := nil;
48981 repeat
48982 if TextBuf <> nil then
48983 FreeMem( TextBuf );
48984 BufSize := BufSize * 2 + 100; // to vary in asm version
48985 GetMem( TextBuf, BufSize );
48986 TextBuf[ 0 ] := #0;
48987 LVGetItem( @Self, Idx, Col, LVI, TextBuf, BufSize );
48988 until StrLen( TextBuf ) < BufSize - 1;
48989 Result := TextBuf;
48990 FreeMem( TextBuf );
48991 end;
48994 //[procedure TControl.LVSetItemText]
48995 procedure TControl.LVSetItemText(Idx, Col: Integer; const Value: String);
48996 var LVI: TLVItem;
48997 begin
48998 LVI.iSubItem := Col;
48999 LVI.pszText := PChar( Value );
49000 Perform( LVM_SETITEMTEXT, Idx, Integer( @LVI ) );
49001 end;
49003 {$IFNDEF _FPC}
49004 {$IFNDEF _D2}
49005 //[function TControl.LVGetItemTextW]
49006 function TControl.LVGetItemTextW(Idx, Col: Integer): WideString;
49007 var LVI: TLVItemW;
49008 TextBuf: PWideChar;
49009 BufSize: DWORD;
49010 begin
49011 BufSize := 0;
49012 TextBuf := nil;
49013 repeat
49014 if TextBuf <> nil then
49015 FreeMem( TextBuf );
49016 BufSize := BufSize * 2 + 100; // to vary in asm version
49017 GetMem( TextBuf, BufSize * 2 );
49018 TextBuf[ 0 ] := #0;
49019 LVGetItemW( @Self, Idx, Col, LVI, TextBuf, BufSize );
49020 until DWORD( WStrLen( TextBuf ) ) < BufSize - 1;
49021 Result := TextBuf;
49022 FreeMem( TextBuf );
49023 end;
49025 //[procedure TControl.LVSetItemTextW]
49026 procedure TControl.LVSetItemTextW(Idx, Col: Integer;
49027 const Value: WideString);
49028 var LVI: TLVItemW;
49029 begin
49030 LVI.iSubItem := Col;
49031 LVI.pszText := PWideChar( Value );
49032 Perform( LVM_SETITEMTEXTW, Idx, Integer( @LVI ) );
49033 end;
49034 {$ENDIF _D2}
49035 {$ENDIF _FPC}
49038 //[procedure TControl.LVColDelete]
49039 procedure TControl.LVColDelete(ColIdx: Integer);
49040 begin
49041 Perform( LVM_DELETECOLUMN, ColIdx, 0 );
49042 if fLVColCount > 0 then
49043 Dec( fLVColCount );
49044 end;
49047 //[procedure TControl.SetLVOptions]
49048 procedure TControl.SetLVOptions(const Value: TListViewOptions);
49049 begin
49050 if fLVOptions = Value then Exit;
49051 fLVOptions := Value;
49052 ApplyImageLists2ListView( @Self );
49053 PostMessage( fHandle, WM_SIZE, 0, 0 ); // to restore scrollers (otherwise its are lost)
49054 end;
49057 //[procedure TControl.SetLVStyle]
49058 procedure TControl.SetLVStyle(const Value: TListViewStyle);
49059 begin
49060 if fLVStyle = Value then Exit;
49061 fLVStyle := Value;
49062 ApplyImageLists2ListView( @Self );
49063 end;
49065 {$IFDEF ASM_VERSION}
49066 //[function TControl.Perform]
49067 function TControl.Perform(msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;
49069 PUSH [lParam]
49070 PUSH [wParam]
49071 PUSH [msgcode]
49072 MOV EAX, [EBP+8]
49073 CALL TControl.GetWindowHandle
49074 PUSH EAX
49075 CALL Windows.SendMessage
49076 end;
49077 {$ELSE ASM_VERSION} //Pascal
49078 function TControl.Perform(msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;
49079 begin
49080 Result := SendMessage( GetWindowHandle, msgcode, wParam, lParam );
49081 end;
49082 {$ENDIF ASM_VERSION}
49084 {$IFDEF ASM_VERSION}
49085 //[function TControl.GetChildCount]
49086 function TControl.GetChildCount: Integer;
49088 MOV EAX, [EAX].fChildren
49089 MOV EAX, [EAX].TList.fCount
49090 end;
49091 {$ELSE ASM_VERSION} //Pascal
49092 function TControl.GetChildCount: Integer;
49093 begin
49094 Result := fChildren.fCount;
49095 end;
49096 {$ENDIF ASM_VERSION}
49098 //[procedure TControl.LVDelete]
49099 procedure TControl.LVDelete(Idx: Integer);
49100 begin
49101 Perform( LVM_DELETEITEM, Idx, 0 );
49102 end;
49104 //[procedure TControl.LVEditItemLabel]
49105 procedure TControl.LVEditItemLabel(Idx: Integer);
49106 begin
49107 Perform( LVM_EDITLABEL, Idx, 0 );
49108 end;
49111 //[function TControl.LVItemRect]
49112 function TControl.LVItemRect(Idx: Integer; Part: TGetLVItemPart): TRect;
49113 const Parts: array[ TGetLVItemPart ] of Byte = (
49114 LVIR_BOUNDS, LVIR_ICON, LVIR_LABEL, LVIR_SELECTBOUNDS );
49115 begin
49116 Result := MakeRect( Parts[ Part ], 0, 0, 0 );
49117 if Perform( LVM_GETITEMRECT, Idx, Integer( @Result ) ) = 0 then
49118 Result := MakeRect( 0, 0, 0, 0 );
49119 end;
49121 //[function TControl.LVSubItemRect]
49122 function TControl.LVSubItemRect(Idx, ColIdx: Integer): TRect;
49123 var Hdr: HWnd;
49124 R, R1: TRect;
49125 ClassNameBuf: array[ 0..31 ] of Char;
49126 HdItem: THDItem;
49127 begin
49128 Result.Top := ColIdx; // + 1; error in MSDN ?
49129 Result.Left := LVIR_BOUNDS;
49130 if Perform( LVM_GETSUBITEMRECT, Idx, Integer( @Result ) ) <> 0 then
49131 Exit;
49132 Result := MakeRect( 0, 0, 0, 0 );
49133 if ColIdx > 0 then R := LVSubItemRect( Idx, ColIdx - 1 )
49134 else R := LVItemRect( Idx, lvipBounds );
49135 if (R.Left = 0) and (R.Right = 0) and
49136 (R.Top = 0) and (R.Bottom = 0) then Exit;
49137 Hdr := GetWindow( GetWindowHandle, GW_CHILD );
49138 if Hdr <> 0 then
49139 begin
49140 if GetClassName( Hdr, ClassNameBuf, 32 ) > 0 then
49141 if ClassNameBuf = 'SysHeader32' then
49142 begin
49143 if ColIdx > 0 then R.Left := R.Right
49144 else R.Left := 0;
49145 R1.Top := 0; R1.Left := 0;
49146 Windows.ClientToScreen( Hdr,{$IFDEF FPC} PPoint( @ R1.Left )^ {$ELSE} R1.TopLeft {$ENDIF} );
49147 Windows.ScreenToClient( fHandle, {$IFDEF FPC} PPoint( @ R1.Left )^ {$ELSE} R1.TopLeft {$ENDIF} );
49148 R1 := R;
49149 HdItem.Mask := HDI_WIDTH;
49150 if SendMessage( Hdr, HDM_GETITEM, ColIdx, Integer( @HdItem ) ) = 0 then Exit;
49151 R1.Right := R1.Left + HdItem.cxy;
49152 Result := R1;
49153 end;
49154 end;
49155 end;
49158 //[function TControl.LVGetItemPos]
49159 function TControl.LVGetItemPos(Idx: Integer): TPoint;
49160 begin
49161 Perform( LVM_GETITEMPOSITION, Idx, Integer( @Result ) );
49162 end;
49165 //[procedure TControl.LVSetItemPos]
49166 procedure TControl.LVSetItemPos(Idx: Integer; const Value: TPoint);
49167 begin
49168 Perform( LVM_SETITEMPOSITION32, Idx, Integer( @Value ) );
49169 end;
49172 //[function TControl.LVItemAtPos]
49173 function TControl.LVItemAtPos(X, Y: Integer): Integer;
49174 var Dummy: TWherePosLVItem;
49175 begin
49176 Result := LVItemAtPosEx( X, Y, Dummy );
49177 end;
49180 //[function TControl.LVItemAtPosEx]
49181 function TControl.LVItemAtPosEx(X, Y: Integer;
49182 var Where: TWherePosLVItem): Integer;
49183 var HTI: TLVHitTestInfo;
49184 begin
49185 HTI.pt.x := X;
49186 HTI.pt.y := Y;
49187 Perform( LVM_HITTEST, 0, Integer( @HTI ) );
49188 Result := HTI.iItem;
49189 Where := lvwpOnColumn;
49190 if HTI.flags = LVHT_ONITEMICON then
49191 Where := lvwpOnIcon
49192 else
49193 if HTI.flags = LVHT_ONITEMLABEL then
49194 Where := lvwpOnLabel
49195 else
49196 if HTI.flags = LVHT_ONITEMSTATEICON then
49197 Where := lvwpOnStateIcon
49198 else
49199 if HTI.flags = LVHT_ONITEM then
49200 Where := lvwpOnItem;
49201 end;
49203 //[procedure TControl.LVMakeVisible]
49204 procedure TControl.LVMakeVisible(Item: Integer; PartiallyOK: Boolean);
49205 begin
49206 if Item < 0 then Exit;
49207 Perform( LVM_ENSUREVISIBLE, Item, Integer( PartiallyOK ) );
49208 end;
49211 //[procedure TControl.LVSetColorByIdx]
49212 procedure TControl.LVSetColorByIdx(const Index: Integer;
49213 const Value: TColor);
49214 var MsgCode: Integer;
49215 ColorValue: TColor;
49216 begin
49217 MsgCode := Index + 1;
49218 case MsgCode of
49219 LVM_SETTEXTCOLOR: fTextColor := Value;
49220 LVM_SETTEXTBKCOLOR: fLVTextBkColor := Value;
49221 LVM_SETBKCOLOR: fColor := Value;
49222 end;
49223 ColorValue := Color2RGB( Value );
49224 Perform( MsgCode, 0, ColorValue );
49225 end;
49227 {$IFDEF F_P}
49228 //[function TControl.LVGetColorByIdx]
49229 function TControl.LVGetColorByIdx(const Index: Integer): TColor;
49230 begin
49231 CASE Index OF
49232 LVM_SETTEXTCOLOR: Result := fTextColor;
49233 LVM_SETTEXTBKCOLOR: Result := fLVTextBkColor;
49234 LVM_SETBKCOLOR: Result := fColor;
49235 END;
49236 end;
49237 {$ENDIF F_P}
49240 //[function TControl.GetIntVal]
49241 function TControl.GetIntVal(const Index: Integer): Integer;
49242 begin
49243 Result := GetItemVal( 0, Index );
49244 end;
49247 //[procedure TControl.SetIntVal]
49248 procedure TControl.SetIntVal(const Index, Value: Integer);
49249 begin
49250 SetItemVal( Value, Index, 0 );
49251 end;
49254 //[function TControl.GetItemVal]
49255 function TControl.GetItemVal(Item: Integer; const Index: Integer): Integer;
49256 begin
49257 Result := Perform( LoWord(Index), Item, 0 );
49258 end;
49260 {$IFDEF ASM_VERSION}
49261 //[procedure TControl.SetItemVal]
49262 procedure TControl.SetItemVal(Item: Integer; const Index: Integer; const Value: Integer);
49264 PUSH EAX
49265 PUSH [Value]
49266 PUSH EDX
49267 MOV EDX, ECX
49268 SHR EDX, 16
49269 JNZ @@1
49270 MOV EDX, ECX
49271 INC EDX
49272 @@1:
49273 MOV EBP, EDX
49274 AND EDX, 7FFFh
49275 PUSH EDX
49276 PUSH EAX
49277 CALL Perform
49278 MOV EAX, EBP
49279 ADD AX, AX
49280 POP EAX
49281 JNB @@2
49282 CALL Invalidate
49283 @@2:
49284 end;
49285 {$ELSE ASM_VERSION} //Pascal
49286 procedure TControl.SetItemVal(Item: Integer; const Index: Integer; const Value: Integer);
49287 var MsgCode: Integer;
49288 begin
49289 MsgCode := HiWord( Index );
49290 if MsgCode = 0 then
49291 MsgCode := Index + 1;
49292 Perform( MsgCode and $7FFF, Item, Value );
49293 if (MsgCode and $8000) <> 0 then
49294 Invalidate;
49295 end;
49296 {$ENDIF ASM_VERSION}
49298 //[procedure TControl.GetSBMinMax]
49299 function TControl.GetSBMinMax: TPoint;
49300 {$IFDEF _D2}
49301 var X, Y: Integer;
49302 {$ENDIF}
49303 begin
49304 if (Handle <> 0) then begin
49305 {$IFDEF _D2}
49306 GetScrollRange(Handle, SB_CTL, X, Y);
49307 Result.X := X;
49308 Result.Y := Y;
49309 {$ELSE}
49310 GetScrollRange(Handle, SB_CTL, Result.X, Result.Y);
49311 {$ENDIF}
49312 Dec(Result.Y, SBPageSize - 1);
49314 else
49315 Result := fSBMinMax;
49316 end;
49318 //[procedure TControl.GetSBPageSize]
49319 function TControl.GetSBPageSize: Integer;
49321 SI: TScrollInfo;
49322 begin
49323 FillChar(SI, SizeOf(SI), 0);
49324 SI.cbSize := SizeOf(SI);
49325 SI.fMask := SIF_PAGE;
49326 SBGetScrollInfo(SI);
49327 Result := SI.nPage;
49328 end;
49330 //[procedure TControl.GetSBPosition]
49331 function TControl.GetSBPosition: Integer;
49332 begin
49333 Result := GetScrollPos(Handle, SB_CTL);
49334 end;
49336 //[procedure TControl.SetSBMax]
49337 procedure TControl.SetSBMax(Value: Longint);
49339 P: TPoint;
49340 begin
49341 fSBMinMax.Y := Value;
49342 if (Handle <> 0) then begin
49343 P := SBMinMax;
49344 P.Y := Value;
49345 SBMinMax := P;
49346 end;
49347 end;
49349 //[procedure TControl.SetSBMin]
49350 procedure TControl.SetSBMin(Value: Longint);
49352 P: TPoint;
49353 begin
49354 fSBMinMax.X := Value;
49355 if (Handle <> 0) then begin
49356 P := SBMinMax;
49357 P.X := Value;
49358 SBMinMax := P;
49359 end;
49360 end;
49362 //[procedure TControl.SetSBPageSize]
49363 procedure TControl.SetSBPageSize(Value: Integer);
49365 SI: TScrollInfo;
49366 begin
49367 fSBPageSize := Value;
49368 if (Handle <> 0) then begin
49369 FillChar(SI, SizeOf(SI), 0);
49370 SI.cbSize := SizeOf(SI);
49371 SI.fMask := SIF_PAGE or SIF_RANGE;
49372 SBGetScrollInfo(SI);
49373 if (SI.nMax = 0) and (SI.nMin = 0) then
49374 SI.nMax := 1;
49375 SI.nMax := SI.nMax - Integer(SI.nPage) + Value;
49376 SI.nPage := Value;
49377 SBSetScrollInfo(SI);
49378 end;
49379 end;
49381 //[procedure TControl.SetSBPosition]
49382 procedure TControl.SetSBPosition(Value: Integer);
49383 begin
49384 fSBPosition := Value;
49385 if (Handle <> 0) then
49386 SetScrollPos(Handle, SB_CTL, Value, True);
49387 end;
49389 //[procedure TControl.SetSBMinMax]
49390 procedure TControl.SetSBMinMax(const Value: TPoint);
49391 begin
49392 GetSBMinMax;
49393 if (Handle <> 0) then
49394 SetScrollRange(Handle, SB_CTL, Value.X, Value.Y + SBPageSize - 1, True)
49395 else
49396 fSBMinMax := Value;
49397 end;
49399 //[procedure TControl.SBSetScrollInfo]
49400 function TControl.SBSetScrollInfo(const SI: TScrollInfo): Integer;
49401 begin
49402 Result := SetScrollInfo(Handle, SB_CTL, SI, True)
49403 end;
49405 //[procedure TControl.SBGetScrollInfo]
49406 function TControl.SBGetScrollInfo(var SI: TScrollInfo): Boolean;
49407 begin
49408 Result := Cardinal(GetScrollInfo(Handle, SB_CTL, SI)) <> 0;
49409 end;
49412 { -- OpenSaveDialog -- }
49415 //[function NewOpenSaveDialog]
49416 function NewOpenSaveDialog( const Title, StrtDir: String;
49417 Options: TOpenSaveOptions ): POpenSaveDialog;
49418 begin
49420 New( Result, Create );
49421 {+}{++}(*Result := POpenSaveDialog.Create;*){--}
49422 Result.FOptions := Options;
49423 if Options = [] then
49424 Result.FOptions := DefOpenSaveDlgOptions;
49425 Result.fOpenDialog := True;
49426 Result.FTitle := Title;
49427 Result.FInitialDir := StrtDir;
49428 end;
49429 //[END NewOpenSaveDialog]
49431 { TOpenSaveDialog }
49433 {$IFDEF ASM_VERSION}
49434 //[destructor TOpenSaveDialog.Destroy]
49435 destructor TOpenSaveDialog.Destroy;
49436 asm //cmd //opd
49437 PUSH EAX
49438 PUSH 0
49439 LEA EDX, [EAX].FFilter
49440 PUSH EDX
49441 LEA EDX, [EAX].FInitialDir
49442 PUSH EDX
49443 LEA EDX, [EAX].FDefExtension
49444 PUSH EDX
49445 LEA EDX, [EAX].FFileName
49446 PUSH EDX
49447 LEA EAX, [EAX].FTitle
49448 @@loo:
49449 CALL System.@LStrClr
49450 POP EAX
49451 TEST EAX, EAX
49452 JNZ @@loo
49453 POP EAX
49454 CALL TObj.Destroy
49455 end;
49456 {$ELSE ASM_VERSION} //Pascal
49457 destructor TOpenSaveDialog.Destroy;
49458 begin
49459 FFilter := '';
49460 FInitialDir := '';
49461 FDefExtension := '';
49462 FFileName := '';
49463 FTitle := '';
49464 {$IFDEF OpenSaveDialog_Extended}
49465 TemplateName := '';
49466 {$ENDIF}
49467 inherited;
49468 end;
49469 {$ENDIF ASM_VERSION}
49471 {$IFDEF ASM_VERSION}
49472 //[function TOpenSaveDialog.Execute]
49473 function TOpenSaveDialog.Execute: Boolean;
49475 PUSH EBX
49476 XCHG EBX, EAX
49478 XOR ECX, ECX
49479 {$IFDEF OpenSaveDialog_Extended}
49480 PUSH [EBX].TemplateName
49481 PUSH [EBX].HookProc
49482 {$ELSE}
49483 PUSH ECX // prepare lpTemplateName = nil
49484 PUSH ECX // prepare lpfnHook = nil
49485 {$ENDIF}
49486 PUSH EBX // prepare lCustData = @Self
49487 MOV EDX, [EBX].FDefExtension
49488 CALL EDX2PChar
49489 PUSH EDX // prepare lpstrDefExt = FDefExtension
49490 PUSH ECX // prepare nFileExtension, nFileOffset: Word = 0, 0
49491 // prepare flags:
49492 LEA EAX, [EBX].FOptions
49493 MOV EDX, Offset[@@OpenSaveFlags]
49494 {$IFDEF OpenSaveDialog_Extended}
49495 MOV CL, 14
49496 {$ELSE}
49497 MOV CL, 12
49498 {$ENDIF}
49499 CALL MakeFlags
49500 XOR ECX, ECX
49501 OR EAX, OFN_EXPLORER or OFN_LONGNAMES or OFN_ENABLESIZING
49502 PUSH EAX // push Flags
49503 PUSH [EBX].FTitle // prepare lpstrTitle
49504 PUSH [EBX].FInitialDir // prepare lpstrInitialDir
49505 PUSH ECX // prepare nMaxFileTitle = 0
49506 PUSH ECX // prepare lpstrFileTitle = nil
49507 TEST AH, 2 // MultiSelect?
49508 MOV EAX, 65520
49509 JNZ @@1
49510 MOV AX, MAX_PATH+2
49511 @@1: PUSH EAX // prepare nMaxFile
49512 CALL System.@GetMem
49513 POP ECX
49514 PUSH ECX
49515 PUSH EAX // prepare lpStrFile
49516 XOR EDX, EDX
49518 @@2: //MOV [EAX], DL // clear it initially {Vadim Petrov: it is necessary}
49519 //INC EAX
49520 //LOOP @@2
49522 MOV EDX, [EBX].fFileName // no, fill it initilly by FileName
49523 CALL EDX2PChar
49524 DEC ECX // added 5 october 2003 to prevent possible error if FileName too big
49525 CALL StrLCopy
49526 XOR EDX, EDX
49528 PUSH [EBX].FFilterIndex // prepare nFilterIndex
49529 PUSH EDX // prepare nMaxCustFilter
49530 PUSH EDX // prepare lpstrCustomFilter
49531 PUSH EDX // prepare lpstrFilter = nil
49532 MOV EAX, ESP
49533 OR EDX, [EBX].FFilter
49534 JZ @@5
49536 MOV ECX, offset[@@0]
49537 CALL System.@LStrCat3 // prepare lpStrFilter = FFilter + #0
49538 POP EAX
49539 PUSH EAX
49540 XOR EDX, EDX
49541 @@3: INC EAX // filter is not starting from ';' or '|'...
49542 CMP [EAX], DL
49543 JZ @@5
49544 CMP byte ptr [EAX], '|'
49545 JNZ @@3
49546 @@4: MOV [EAX], DL
49547 JMP @@3
49548 @@OpenSaveFlags:
49549 DD OFN_CREATEPROMPT, OFN_EXTENSIONDIFFERENT, OFN_FILEMUSTEXIST
49550 DD OFN_HIDEREADONLY, OFN_NOCHANGEDIR, OFN_NODEREFERENCELINKS
49551 DD OFN_ALLOWMULTISELECT, OFN_NONETWORKBUTTON, OFN_NOREADONLYRETURN
49552 DD OFN_OVERWRITEPROMPT, OFN_PATHMUSTEXIST, OFN_READONLY, OFN_NOVALIDATE
49553 {$IFDEF OpenSaveDialog_Extended}
49554 DD OFN_ENABLETEMPLATE, OFN_ENABLEHOOK
49555 {$ENDIF}
49557 DD -1, 1
49558 @@0: DB 0
49561 @@5:
49562 PUSH [hInstance] // prepare hInstance
49564 MOV ECX, [EBX].TControl.fWnd
49565 INC ECX
49566 LOOP @@6
49567 MOV ECX, [Applet]
49568 JECXZ @@6
49569 MOV ECX, [ECX].TControl.fHandle
49570 @@6: PUSH ECX // prepare hWndOwner
49571 PUSH 76 // prepare lStructSize
49573 PUSH ESP
49574 CMP [EBX].FOpenDialog, DL
49575 JZ @@7
49576 CALL GetOpenFileName
49577 JMP @@8
49578 @@7: CALL GetSaveFileName
49579 @@8:
49580 PUSH EAX
49581 XOR EDX, EDX
49582 TEST EAX, EAX
49583 JZ @@10
49585 MOV EAX, [ESP+4].TOpenFileName.nFilterIndex
49586 MOV [EBX].FFilterIndex, EAX
49588 MOV EAX, [ESP+4].TOpenFileName.lpstrFile
49589 MOV EDX, EAX
49590 XOR ECX, ECX
49592 TEST [EBX].FOptions, 1 shl OSAllowMultiSelect
49593 JZ @@10
49595 DEC EAX
49596 @@9: INC EAX
49597 CMP byte ptr [EAX], CL
49598 JNZ @@9
49599 CMP byte ptr [EAX+1], CL
49600 JZ @@10
49601 MOV byte ptr [EAX], 13
49602 JMP @@9
49604 @@10:
49605 LEA EAX, [EBX].FFileName
49606 CALL System.@LStrFromPChar
49607 MOV EAX, [ESP+4].TOpenFileName.lpstrFile
49608 CALL System.@FreeMem // v1.86 +AK
49610 LEA EAX, [ESP+4].TOpenFileName.lpstrFilter
49611 CALL System.@LStrClr
49613 POP EAX
49614 ADD ESP, 76
49615 POP EBX
49616 end;
49617 {$ELSE ASM_VERSION} //Pascal
49618 function TOpenSaveDialog.Execute: Boolean;
49619 const OpenSaveFlags: array[ TOpenSaveOption ] of Integer = (
49620 OFN_CREATEPROMPT,
49621 OFN_EXTENSIONDIFFERENT,
49622 OFN_FILEMUSTEXIST,
49623 OFN_HIDEREADONLY,
49624 OFN_NOCHANGEDIR,
49625 OFN_NODEREFERENCELINKS,
49626 OFN_ALLOWMULTISELECT,
49627 OFN_NONETWORKBUTTON,
49628 OFN_NOREADONLYRETURN,
49629 OFN_OVERWRITEPROMPT,
49630 OFN_PATHMUSTEXIST,
49631 OFN_READONLY,
49632 OFN_NOVALIDATE
49633 //{$IFDEF OpenSaveDialog_Extended}
49635 OFN_ENABLETEMPLATE,
49636 OFN_ENABLEHOOK
49637 //{$ENDIF}
49640 Ofn : TOpenFilename;
49641 Fltr : String;
49642 TempFilename : String;
49644 Function MakeFilter(s : string) : String;
49646 format of filter for API call is following:
49647 'text files'#0'*.txt'#0
49648 'bitmap files'#0'*.bmp'#0#0
49650 var Str: PChar;
49651 begin
49652 Result := s;
49653 if Result='' then
49654 exit;
49655 Result:=Result+#0; {Delphi string always end on #0 is this is #0#0}
49656 Str := PChar( Result );
49657 while Str^ <> #0 do
49658 begin
49659 if Str^ = '|' then
49660 Str^ := #0;
49661 Inc( Str );
49662 end;
49663 end;
49665 begin
49666 Fillchar( ofn, sizeof( ofn ), 0 );
49668 ofn.lStructSize:= 76; //to provide correct work in Win9x
49669 //sizeof(ofn); - by suggestion of Michael Morozov, 28-Nov-2001
49670 if fWnd <> 0 then
49671 ofn.hWndOwner := fWnd
49672 else
49673 if assigned(applet) then
49674 ofn.hwndOwner:=applet.Handle;
49676 ofn.hInstance:=HInstance;
49678 Fltr:=MakeFilter(FFilter);
49679 if Fltr <> '' then
49680 ofn.lpstrFilter:=pchar(Fltr);
49682 //ofn.lpstrCustomFilter:=nil;
49683 //ofn.nMaxCustFilter:=0;
49684 ofn.nFilterIndex:=FFilterIndex;
49686 if OSAllowMultiSelect in FOptions then
49687 ofn.nMaxFile:=High(word)-14 // by V.K. (exchanged condition)
49688 else
49689 ofn.nMaxFile:=MAX_PATH+2;
49691 TempFileName:=StringOfChar(#0,ofn.nMaxFile); {Vadim Petrov}
49692 ofn.lpstrFile:=StrLCopy(pchar(TempFileName), pchar(fFileName),
49693 Min(ofn.nMaxFile,Length(fFileName)));
49695 ofn.lpstrInitialDir:=Pointer(FInitialDir);
49696 ofn.lpstrTitle:=Pointer(FTitle);
49697 ofn.Flags := MakeFlags( @FOptions, OpenSaveFlags )
49698 or OFN_EXPLORER or OFN_LONGNAMES or OFN_ENABLESIZING;
49700 ofn.lpstrDefExt:=PChar(FDefExtension);
49701 ofn.lCustData:=integer(@self);
49702 {$IFDEF OpenSaveDialog_Extended}
49703 ofn.lpTemplateName := PChar( TemplateName );
49704 ofn.lpfnHook := HookProc;
49705 {$ELSE}
49706 ofn.lpTemplateName:=nil;
49707 ofn.lpfnHook:=nil;
49708 {$ENDIF}
49709 if fOpenDialog then
49710 result:=GetOpenFileName(ofn)
49711 else
49712 result:=GetSaveFileName(ofn);
49713 if result then begin
49714 fFilterIndex := ofn.nFilterIndex; // by Vadim
49715 if OSAllowMultiSelect in foptions then begin
49716 FFileName:=copy(TempFileName, 1, pos(#0#0, tempfilename)-1);
49717 while pos(#0, ffilename) > 0 do begin
49718 FFilename[pos(#0, ffilename)]:=#13;
49719 end;
49720 end else
49721 FFileName:=copy(tempFileName, 1, pos(#0, TempFilename)
49722 -1 // by X.Y.B.
49724 end else
49725 FFilename:='';
49726 end;
49727 {$ENDIF ASM_VERSION}
49729 { -- OpenDirDialog -- }
49732 //[function NewOpenDirDialog]
49733 function NewOpenDirDialog( const Title: String; Options: TOpenDirOptions ):
49734 POpenDirDialog;
49735 begin
49737 New( Result, Create );
49738 {+}{++}(*Result := POpenDirDialog.Create;*){--}
49739 Result.FOptions := [ odOnlySystemDirs ];
49740 if Options <> [] then
49741 Result.FOptions := Options;
49742 Result.FTitle := Title;
49743 end;
49744 //[END NewOpenDirDialog]
49746 { TOpenDirDialog }
49748 {$IFDEF ASM_VERSION}
49749 //[destructor TOpenDirDialog.Destroy]
49750 destructor TOpenDirDialog.Destroy;
49751 asm //cmd //opd
49752 PUSH EAX
49753 PUSH 0
49754 LEA EDX, [EAX].FTitle
49755 PUSH EDX
49756 LEA EDX, [EAX].FInitialPath
49757 PUSH EDX
49758 LEA EAX, [EAX].FStatusText
49759 @@loo: CALL System.@LStrClr
49760 POP EAX
49761 TEST EAX, EAX
49762 JNZ @@loo
49763 POP EAX
49764 CALL TObj.Destroy
49765 end;
49766 {$ELSE ASM_VERSION} //Pascal
49767 destructor TOpenDirDialog.Destroy;
49768 begin
49769 FTitle := '';
49770 FInitialPath := '';
49771 FStatusText := '';
49772 inherited;
49773 end;
49774 {$ENDIF ASM_VERSION}
49776 type
49777 {$IFNDEF _D2}
49778 (*IMalloc = interface(IUnknown)
49779 ['{00000002-0000-0000-C000-000000000046}']
49780 function Alloc(cb: Longint): Pointer; stdcall;
49781 function Realloc(pv: Pointer; cb: Longint): Pointer; stdcall;
49782 procedure Free(pv: Pointer); stdcall;
49783 function GetSize(pv: Pointer): Longint; stdcall;
49784 function DidAlloc(pv: Pointer): Integer; stdcall;
49785 procedure HeapMinimize; stdcall;
49786 end;*)
49787 {$ENDIF}
49789 PSHItemID = ^TSHItemID;
49790 TSHItemID = packed record
49791 cb: Word; { Size of the ID (including cb itself) }
49792 abID: array[0..0] of Byte; { The item ID (variable length) }
49793 end;
49795 PItemIDList = ^TItemIDList;
49796 TItemIDList = record
49797 mkid: TSHItemID;
49798 end;
49800 PBrowseInfo = ^TBrowseInfo;
49801 TBrowseInfo = record
49802 hwndOwner: HWND;
49803 pidlRoot: PItemIDList;
49804 pszDisplayName: PAnsiChar; { Return display name of item selected. }
49805 lpszTitle: PAnsiChar; { text to go in the banner over the tree. }
49806 ulFlags: UINT; { Flags that control the return stuff }
49807 lpfn: Pointer; //TFNBFFCallBack;
49808 lParam: LPARAM; { extra info that's passed back in callbacks }
49809 iImage: Integer; { output var: where to return the Image index. }
49810 end;
49812 //[API SHXXXXXXXXXX]
49813 function SHBrowseForFolder(var lpbi: TBrowseInfo): PItemIDList; stdcall;
49814 external 'shell32.dll' name 'SHBrowseForFolderA';
49815 function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL; stdcall;
49816 external shell32 name 'SHGetPathFromIDListA';
49818 function CoTaskMemAlloc(cb : DWORD) : pointer; stdcall; external 'ole32.dll'
49819 name 'CoTaskMemAlloc';
49821 procedure CoTaskMemFree(pv: Pointer); stdcall; external 'ole32.dll'
49822 name 'CoTaskMemFree';
49824 const
49825 BIF_RETURNONLYFSDIRS = $0001; { For finding a folder to start document searching }
49826 BIF_DONTGOBELOWDOMAIN = $0002; { For starting the Find Computer }
49827 BIF_STATUSTEXT = $0004;
49828 BIF_RETURNFSANCESTORS = $0008;
49829 BIF_EDITBOX = $0010;
49830 BIF_VALIDATE = $0020; { insist on valid result (or CANCEL) }
49831 BIF_BROWSEFORCOMPUTER = $1000; { Browsing for Computers. }
49832 BIF_BROWSEFORPRINTER = $2000; { Browsing for Printers }
49833 BIF_BROWSEINCLUDEFILES = $4000; { Browsing for Everything }
49835 BFFM_INITIALIZED = 1;
49836 BFFM_SELCHANGED = 2;
49838 BFFM_SETSTATUSTEXT = WM_USER + 100;
49839 BFFM_ENABLEOK = WM_USER + 101;
49840 BFFM_SETSELECTION = WM_USER + 102;
49843 {$IFDEF ASM_VERSION} // WndOwner
49844 //[function TOpenDirDialog.Execute]
49845 function TOpenDirDialog.Execute: Boolean;
49847 PUSH EBX
49848 XCHG EBX, EAX
49850 XOR ECX, ECX
49851 PUSH ECX // prepare iImage = 0
49852 PUSH EBX // prepare lParam = @Self
49853 PUSH [EBX].FCallBack // prepare lpfn = FCallBack
49854 LEA EAX, [EBX].FOptions
49855 MOV EDX, Offset[@@FlagsArray]
49856 MOV CL, 5
49857 CALL MakeFlags
49858 PUSH EAX // prepare ulFlags = Options
49859 PUSH [EBX].FTitle // prepare lpszTitle
49860 LEA EAX, [EBX].FBuf
49861 PUSH EAX // prepare pszDisplayName
49862 PUSH 0 // prepare pidlRoot
49863 MOV ECX, [EBX].fWnd
49864 INC ECX
49865 LOOP @@1
49866 MOV ECX, Applet
49867 JECXZ @@1
49868 MOV ECX, [ECX].TControl.fHandle
49869 @@1: PUSH ECX // prepare hwndOwner
49871 PUSH ESP
49872 CALL SHBrowseForFolder
49873 ADD ESP, 32
49874 TEST EAX, EAX
49875 JZ @@exit
49877 PUSH EAX
49879 LEA EDX, [EBX].FBuf
49880 PUSH EDX
49881 PUSH EAX
49882 CALL SHGetPathFromIDList
49884 CALL CoTaskMemFree
49886 MOV AL, 1
49887 JMP @@fin
49889 @@FlagsArray:
49890 DD BIF_BROWSEFORCOMPUTER, BIF_BROWSEFORPRINTER, BIF_DONTGOBELOWDOMAIN
49891 DD BIF_RETURNFSANCESTORS, BIF_RETURNONLYFSDIRS, BIF_STATUSTEXT, BIF_BROWSEINCLUDEFILES
49893 @@exit: XOR EAX, EAX
49894 @@fin:
49895 POP EBX
49896 end;
49897 {$ELSE ASM_VERSION} //Pascal
49898 function TOpenDirDialog.Execute: Boolean;
49899 const FlagsArray: array[ TOpenDirOption ] of Integer =
49900 ( BIF_BROWSEFORCOMPUTER, BIF_BROWSEFORPRINTER, BIF_DONTGOBELOWDOMAIN,
49901 BIF_RETURNFSANCESTORS, BIF_RETURNONLYFSDIRS, BIF_STATUSTEXT,
49902 BIF_BROWSEINCLUDEFILES );
49903 var BI : TBrowseInfo;
49904 Browse : PItemIdList;
49905 begin
49906 Result := False;
49907 if WndOwner <> 0 then
49908 BI.hwndOwner := WndOwner
49909 else
49910 if assigned( Applet ) then
49911 BI.hwndOwner := Applet.Handle
49912 else
49913 BI.hwndOwner := 0;
49914 BI.pidlRoot := nil;
49915 BI.pszDisplayName := @FBuf[ 0 ];
49916 BI.lpszTitle := PChar( Title );
49917 BI.ulFlags := MakeFlags( @FOptions, FlagsArray );
49918 BI.lpfn := FCallBack;
49919 BI.lParam := Integer( @Self );
49920 Browse := SHBrowseForFolder( BI );
49921 if Browse <> nil then
49922 begin
49923 SHGetPathFromIDList( Browse, @FBuf[ 0 ] );
49924 CoTaskMemFree( Browse );
49925 Result := True;
49926 end;
49927 end;
49928 {$ENDIF ASM_VERSION}
49930 //[function TOpenDirDialog.GetInitialPath]
49931 function TOpenDirDialog.GetInitialPath: String;
49932 begin
49933 Result := IncludeTrailingPathDelimiter( fInitialPath );
49934 end;
49936 //[function TOpenDirDialog.GetPath]
49937 function TOpenDirDialog.GetPath: String;
49938 begin
49939 Result := FBuf;
49940 end;
49942 //[FUNCTION OpenDirSelChangeCallBack]
49943 {$IFDEF ASM_VERSION}
49944 function OpenDirSelChangeCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ):
49945 Integer; stdcall;
49947 MOV EAX, [lpData]
49948 MOV ECX, [EAX].TOpenDirDialog.FOnSelChanged.TMethod.Code
49949 JECXZ @@exit
49951 LEA EDX, [EAX].TOpenDirDialog.FBuf
49952 PUSH EDX
49953 PUSH [lParam]
49954 CALL SHGetPathFromIDList
49956 //EnableOK := 0;
49957 //Self_.FOnSelChanged( Self_, Self_.FBuf, EnableOK, Self_.FStatusText );
49959 MOV EDX, [lpData]
49960 LEA ECX, [EDX].TOpenDirDialog.FBuf
49961 PUSH 0
49962 PUSH ESP
49963 LEA EAX, [EDX].TOpenDirDialog.FStatusText
49964 PUSH EAX
49965 MOV EAX, [EDX].TOpenDirDialog.FOnSelChanged.TMethod.Data
49966 CALL dword ptr [EDX].TOpenDirDialog.FOnSelChanged.TMethod.Code
49967 POP ECX
49968 JECXZ @@1
49970 INC ECX
49971 PUSH ECX
49972 PUSH 0
49973 PUSH BFFM_ENABLEOK
49974 PUSH [Wnd]
49975 CALL SendMessage
49976 @@1:
49977 MOV EDX, [lpData]
49978 MOV ECX, [EDX].TOpenDirDialog.FStatusText
49979 JECXZ @@exit
49981 PUSH ECX
49982 PUSH 0
49983 PUSH BFFM_SETSTATUSTEXT
49984 PUSH [Wnd]
49985 CALL SendMessage
49987 @@exit: XOR EAX, EAX
49988 end;
49989 {$ELSE ASM_VERSION} //Pascal
49990 function OpenDirSelChangeCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ):
49991 Integer; stdcall;
49992 var _Self_: POpenDirDialog;
49993 EnableOK: Integer;
49994 begin
49995 _Self_ := Pointer( lpData );
49996 if assigned( _Self_.FOnSelChanged ) then
49997 begin
49998 SHGetPathFromIDList( PItemIDList( lParam ), @ _Self_.FBuf[ 0 ] );
49999 EnableOK := 0;
50000 _Self_.FOnSelChanged( _Self_, _Self_.FBuf, EnableOK, _Self_.FStatusText );
50001 if EnableOK <> 0 then
50002 SendMessage( Wnd, BFFM_ENABLEOK, 0, EnableOK + 1 );
50003 if _Self_.FStatusText <> '' then
50004 SendMessage( Wnd, BFFM_SETSTATUSTEXT, 0, Integer( PChar( _Self_.FStatusText ) ) );
50005 end;
50006 Result := 0;
50007 end;
50008 {$ENDIF ASM_VERSION}
50009 //[END OpenDirSelChangeCallBack]
50011 //[FUNCTION OpenDirCallBack]
50012 {$IFDEF ASM_VERSION}
50013 function OpenDirCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ): Integer;
50014 stdcall;
50016 MOV EAX, [Wnd]
50017 MOV EDX, [lpData]
50018 MOV ECX, [Msg]
50019 LOOP @@chk_sel_chg
50020 // Msg = 1 -> BFFM_Initialized
50022 MOV ECX, [EDX].TOpenDirDialog.FCenterProc
50023 JECXZ @@1
50024 PUSH EDX
50025 CALL ECX
50026 POP EDX
50027 @@1: MOV ECX, [EDX].TOpenDirDialog.FInitialPath
50028 JECXZ @@exit
50029 PUSH ECX
50030 PUSH 1
50031 PUSH BFFM_SETSELECTION
50032 PUSH [Wnd]
50033 CALL SendMessage
50034 JMP @@exit
50036 @@chk_sel_chg:
50037 LOOP @@exit
50038 // Msg = 2 -> BFFM_SelChanged
50040 MOV ECX, [EDX].TOpenDirDialog.FDoSelChanged
50041 JECXZ @@exit
50042 POP EBP
50043 JMP ECX
50045 @@exit: XOR EAX, EAX
50046 end;
50047 {$ELSE ASM_VERSION} //Pascal
50048 function OpenDirCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ): Integer;
50049 stdcall;
50050 var Self_ : POpenDirDialog;
50051 begin
50052 Self_ := Pointer( lpData );
50053 if Msg = BFFM_INITIALIZED then
50054 begin
50055 if assigned( Self_.FCenterProc ) then
50056 Self_.FCenterProc( Wnd );
50057 if Self_.FInitialPath <> '' then
50058 SendMessage( Wnd, BFFM_SETSELECTION, 1, Integer( PChar( Self_.FInitialPath ) ) );
50060 else
50061 if Msg = BFFM_SELCHANGED then
50062 begin
50063 if assigned( Self_.FDoSelChanged ) then
50064 Self_.FDoSelChanged( Wnd, Msg, lParam, lpData );
50065 end;
50066 Result := 0;
50067 end;
50068 {$ENDIF ASM_VERSION}
50069 //[END OpenDirCallBack]
50071 //[PROCEDURE OpenDirDlgCenter]
50072 {$IFDEF ASM_VERSION}
50073 procedure OpenDirDlgCenter( Wnd: HWnd );
50075 PUSH EBX
50076 MOV EBX, EAX
50078 ADD ESP, -16
50079 PUSH ESP
50080 PUSH EAX
50081 CALL GetWindowRect
50082 POP EDX // EDX = Left
50083 POP ECX // ECX = Top
50084 POP EAX // EAX = Right
50085 SUB EAX, EDX // EAX = W
50086 POP EDX // EDX = Bottom
50087 SUB EDX, ECX // EDX = H
50088 XOR ECX, ECX
50089 INC ECX
50090 PUSH ECX // prepare True
50091 PUSH EDX // prepare H
50092 PUSH EAX // prepare W
50094 INC ECX
50095 @@1:
50096 PUSH ECX
50098 DEC ECX
50099 PUSH ECX
50100 CALL GetSystemMetrics
50102 POP ECX
50103 SUB EAX, [ESP+4]
50104 SAR EAX, 1
50105 PUSH EAX
50107 LOOP @@1
50110 PUSH SM_CYSCREEN
50111 CALL GetSystemMetrics
50112 SUB EAX, [ESP+4]
50113 SAR EAX, 1
50114 PUSH EAX
50116 PUSH SM_CXSCREEN
50117 CALL GetSystemMetrics
50118 SUB EAX, [ESP+4]
50119 SAR EAX, 1
50120 PUSH EAX
50123 PUSH EBX
50124 CALL MoveWindow
50125 POP EBX
50126 end;
50127 {$ELSE ASM_VERSION} //Pascal
50128 procedure OpenDirDlgCenter( Wnd: HWnd );
50129 var R: TRect;
50130 W, H: Integer;
50131 begin
50132 GetWindowRect( Wnd, R );
50133 W := R.Right - R.Left;
50134 H := R.Bottom - R.Top;
50135 R.Left := (GetSystemMetrics( SM_CXSCREEN ) - W) div 2;
50136 R.Top := (GetSystemMetrics( SM_CYSCREEN ) - H) div 2;
50137 MoveWindow( Wnd, R.Left, R.Top, W, H, True );
50138 end;
50139 {$ENDIF ASM_VERSION}
50140 //[END OpenDirDlgCenter]
50142 {$IFDEF ASM_VERSION}
50143 //[procedure TOpenDirDialog.SetCenterOnScreen]
50144 procedure TOpenDirDialog.SetCenterOnScreen(const Value: Boolean);
50146 MOV [EAX].FCenterOnScreen, DL
50147 MOVZX ECX, DL
50148 JECXZ @@1
50149 MOV ECX, Offset[OpenDirDlgCenter]
50150 @@1: MOV [EAX].FCenterProc, ECX
50151 end;
50152 {$ELSE ASM_VERSION} //Pascal
50153 procedure TOpenDirDialog.SetCenterOnScreen(const Value: Boolean);
50154 var P: procedure( Wnd: HWnd );
50155 begin
50156 FCenterOnScreen := Value;
50157 P := nil;
50158 if Value then
50159 P := @OpenDirDlgCenter;
50160 FCenterProc := P;
50161 end;
50162 {$ENDIF ASM_VERSION}
50164 //[procedure TOpenDirDialog.SetInitialPath]
50165 procedure TOpenDirDialog.SetInitialPath(const Value: String);
50166 begin
50167 FCallBack := @OpenDirCallBack;
50168 FInitialPath := ExcludeTrailingPathDelimiter( Value );
50169 end;
50171 //[procedure TOpenDirDialog.SetOnSelChanged]
50172 procedure TOpenDirDialog.SetOnSelChanged(const Value: TOnODSelChange);
50173 begin
50174 FOnSelChanged := Value;
50175 FCallBack := @OpenDirCallBack;
50176 FDoSelChanged := @OpenDirSelChangeCallBack;
50177 end;
50180 type
50181 PByteArray =^TByteArray;
50182 TByteArray = array[Word]of Byte;
50184 //[API CreateMappedBitmap]
50185 function CreateMappedBitmap(Instance: THandle; Bitmap: Integer;
50186 Flags: UINT; ColorMap: PColorMap; NumMaps: Integer): HBitmap; stdcall;
50187 external cctrl name 'CreateMappedBitmap';
50189 //[function CreateMappedBitmapEx]
50190 function CreateMappedBitmapEx(Instance: THandle; BmpRsrcName: PChar; Flags:
50191 Cardinal; ColorMap: PColorMap; NumMaps: Integer): HBitmap;
50192 var bi: TBITMAPINFO;
50193 DC, tmcl: Cardinal;
50194 Bits: PByteArray;
50195 i, j, k, CO, bps: Integer;
50196 tm: array [1..4] of byte absolute tmcl;
50197 bm: Windows.TBITMAP;
50198 CM: PColorMap;
50199 DW: HWnd;
50200 begin
50201 Result := LoadBitmap( Instance, BmpRsrcName );
50202 if Result = 0 then
50203 begin
50204 {$IFDEF DEBUG}
50205 ShowMessage( 'Can not load bitmap ' + BmpRsrcName + ', error ' +
50206 Int2Str( GetLastError ) + ': ' + SysErrorMessage( GetLastError ) );
50207 {$ENDIF}
50208 Exit;
50209 end;
50210 DW := GetDesktopWindow;
50211 DC := GetDC(DW);
50212 FillChar( bm, SizeOf(bm), 0 );
50213 GetObject( Result, SizeOf( bm ), @bm );
50215 FillChar( bi, SizeOf( bi ), 0 );
50216 bi.bmiHeader.biSize := SizeOf( bi.bmiHeader );
50217 bi.bmiHeader.biWidth := bm.bmWidth;
50218 bi.bmiHeader.biHeight := -bm.bmHeight;
50219 bi.bmiHeader.biPlanes := 1;
50220 bi.bmiHeader.biBitCount := 24;
50221 // BitCout - always 24 for easy algorythm
50222 bi.bmiHeader.biCompression:=BI_RGB;
50223 bps := CalcScanLineSize( @bi.bmiHeader );
50225 GetMem( Bits, bps * bm.bmHeight );
50226 GetDIBits( DC, Result, 0, bm.bmHeight, @Bits[0], bi, DIB_RGB_COLORS );
50227 DeleteObject( Result );
50229 for i := 0 to bm.bmHeight - 1 do begin
50230 for j := 0 to bm.bmWidth - 1 do begin
50231 CO := bps * i + 3 * j;
50232 for k := 0 to NumMaps - 1 do begin
50233 CM := Pointer( Integer( ColorMap ) + SizeOf( TColorMap ) * k );
50234 if RGB( Bits[CO+2], Bits[CO+1], Bits[CO] ) = CM.cFrom then
50235 begin
50236 tmcl := CM.cTo;
50237 tm[4]:=tm[1];
50238 tm[1]:=tm[3];
50239 tm[3]:=tm[4];
50240 Move( tmcl, Bits[CO], 3);
50241 end;
50242 end;
50243 end;
50244 end;
50245 Result := CreateDIBitmap( DC, bi.bmiHeader, CBM_INIT, @Bits[0], bi,
50246 DIB_RGB_COLORS );
50247 ReleaseDC( DW, DC );
50248 FreeMem( Bits );
50249 end;
50252 //[function LoadMappedBitmap]
50253 function LoadMappedBitmap( hInst: THandle; BmpResID: Integer; const Map: array of TColor )
50254 : HBitmap;
50255 var Map2Pass: Pointer;
50256 begin
50257 Map2Pass := nil;
50258 if High( Map ) > 0 then
50259 Map2Pass := PColorMap( @Map[ 0 ] );
50260 Result := CreateMappedBitmap( hInst, BmpResID, 0, Map2Pass, (High( Map ) + 1) div 2 );
50261 end;
50263 //[function LoadMappedBitmapEx]
50264 function LoadMappedBitmapEx( MasterObj: PObj; hInst: THandle; BmpResName: PChar; const Map: array of TColor )
50265 : HBitmap;
50266 var Map2Pass: Pointer;
50267 begin
50268 Map2Pass := nil;
50269 if High( Map ) > 0 then
50270 Map2Pass := PColorMap( @Map[ 0 ] );
50271 Result := CreateMappedBitmapEx( hInst, BmpResName, 0, Map2Pass, (High( Map ) + 1) div 2 );
50272 if MasterObj <> nil then
50273 MasterObj.Add2AutoFreeEx( TObjectMethod( MakeMethod( Pointer( Result ), @ FreeBmp ) ) );
50274 end;
50276 { -- Toolbar -- }
50278 {$IFDEF ASM_noVERSION} // width
50279 //[procedure TControl.TBAddBitmap]
50280 procedure TControl.TBAddBitmap(Bitmap: HBitmap);
50281 const szBI = sizeof(TBitmapInfo);
50283 TEST EDX, EDX
50284 JZ @@exit
50285 JGE @@1
50286 CMP EDX, -6
50287 JL @@1
50289 NEG EDX
50290 DEC EDX
50291 PUSH EDX
50292 PUSH -1
50293 XOR EDX, EDX
50294 JMP @@2
50296 @@1: PUSH EDX // AB.hInst = Bitmap
50297 PUSH 0 // AB.nID = 0
50299 PUSH EAX // > @Self
50300 ADD ESP, -szBI
50301 PUSH ESP
50302 PUSH szBI
50303 PUSH EDX
50304 CALL GetObject
50305 TEST EAX, EAX
50306 JG @@11
50308 ADD ESP, szBI
50309 JMP @@exit
50311 @@11: MOV EAX, [ESP].TBitmapInfo.bmiHeader.biWidth
50312 MOV ECX, [ESP].TBitmapInfo.bmiHeader.biHeight
50313 TEST ECX, ECX
50314 JGE @@12
50315 NEG ECX
50316 @@12: ADD ESP, szBI
50317 CDQ // EDX = 0
50318 DIV ECX // EAX = N
50319 XCHG EAX, [ESP] // > N
50320 PUSH EAX // > @Self
50322 MOV EDX, ECX
50323 SHL EDX, 16
50324 OR ECX, EDX
50326 PUSH EDX
50327 PUSH EDX
50328 PUSH TB_AUTOSIZE
50329 PUSH EAX
50331 PUSH ECX
50332 PUSH EDX
50333 PUSH TB_SETBITMAPSIZE
50334 PUSH EAX
50335 CALL Perform
50336 CALL Perform
50337 POP EAX
50338 POP EDX
50340 @@2: PUSH ESP
50341 PUSH EDX
50342 PUSH TB_ADDBITMAP
50343 PUSH EAX
50344 CALL Perform
50345 POP ECX
50346 POP ECX
50347 @@exit:
50348 end;
50349 {$ELSE ASM_VERSION} //Pascal
50350 procedure TControl.TBAddBitmap(Bitmap: HBitmap);
50351 const NstdBitmaps: array[ 0..5 ] of DWORD = ( 15, 15, 0, 0, 13, 13 );
50352 var BI: TBitmapInfo;
50353 AB: TTBAddBitmap;
50354 N, W: Integer;
50355 begin
50356 if Bitmap = 0 then Exit;
50357 if (Integer( Bitmap ) >= -10) and (Integer( Bitmap ) <= -1) then
50358 begin
50359 AB.hInst := THandle(-1);
50360 AB.nID := -Integer(Bitmap) - 1;
50361 N := 0; //NstdBitmaps[ AB.nID ]; // (this value is ignored)
50363 else
50364 if GetObject( Bitmap, sizeof( TBitmapInfo ), @BI ) > 0 then
50365 begin
50366 AB.hInst := 0;
50367 AB.nID := Bitmap;
50368 W := fTBBtnImgWidth;
50369 if W = 0 then
50370 W := Abs( BI.bmiHeader.biHeight );
50371 N := BI.bmiHeader.biWidth div W;
50372 Perform( TB_SETBITMAPSIZE, 0, MAKELONG( W, Abs(BI.bmiHeader.biHeight )) );
50373 Perform( TB_AUTOSIZE, 0, 0 );
50375 else Exit;
50376 Perform( TB_ADDBITMAP, N, Integer( @AB ) );
50377 end;
50378 {$ENDIF ASM_VERSION}
50380 var ToolbarsIDcmd: Integer = 100;
50381 {$IFDEF ASM_VERSION}
50382 //[function TControl.TBAddInsButtons]
50383 function TControl.TBAddInsButtons(Idx: Integer; const Buttons: array of PChar;
50384 const BtnImgIdxArray: array of Integer): Integer; stdcall;
50386 { [EBP+$8] = @Self
50387 [EBP+$C] = Idx
50388 [EBP+$10] = Buttons
50389 [EBP+$14] = High(Butons)
50390 [EBP+$18] = BtnImgIdxArray
50391 [EBP+$1C] = High(BtnImgIdxArray)
50393 PUSH EBX
50394 PUSH ESI
50395 PUSH EDI
50396 OR EBX, -1
50397 MOV EAX, 20
50398 MOV ECX, [EBP+$14]
50399 CMP ECX, EBX
50400 JLE @@fin
50401 INC ECX
50402 MUL ECX
50403 CALL System.@GetMem
50404 PUSH EAX // save AB to FreeMem after
50405 MOV EDX, EBX
50406 DEC EDX // nBmp := -2
50408 MOV ECX, [EBP+$14]
50409 INC ECX
50410 JZ @@exit
50412 MOV ECX, [EBP+$1C]
50413 INC ECX
50414 JZ @@1
50415 MOV ECX, [BtnImgIdxArray]
50416 MOV EDX, [ECX]
50417 DEC EDX // nBmp := BtnImgIdxArray[ 0 ] - 1
50418 @@1: MOV ECX, [EBP+$14]
50419 INC ECX
50420 MOV ESI, [Buttons]
50421 MOV EDI, EAX // EDI = PAB
50422 PUSH 0 // N:=0 in [EBP-$14]
50423 // -- impossible?-- JZ @@break
50424 @@loop:
50425 LODSD
50426 TEST EAX, EAX
50427 JZ @@break
50428 //CMP byte ptr [EAX], 0
50429 //JZ @@break
50430 PUSH ECX
50432 CMP word ptr [EAX], '-'
50433 JNE @@2
50435 OR EAX, -1
50436 STOSD
50437 //INC EAX //=0
50438 MOV EAX, [ToolbarsIDcmd]
50439 TEST EBX, EBX
50440 {$IFDEF USE_CMOV}
50441 CMOVL EBX, EAX
50442 {$ELSE}
50443 JGE @@b0
50444 MOV EBX, EAX
50445 @@b0: {$ENDIF}
50447 //INC [ToolbarsIDcmd]
50448 STOSD
50449 XOR EAX, EAX
50450 INC AH // TBSTYLE_SEP = 1
50451 STOSD
50452 DEC AH
50453 STOSD
50454 DEC EAX
50455 JMP @@3
50457 DD -1, 1
50458 @@0: DB 0
50460 @@2:
50461 INC EDX // Inc( nBmp )
50462 PUSH EAX
50464 MOV EAX, [EBP+$1C]
50465 MOV ECX, [EBP-$14]
50466 CMP EAX, ECX
50467 MOV EAX, EDX
50468 JL @@21
50469 MOV EAX, [BtnImgIdxArray]
50470 MOV EAX, [EAX+ECX*4]
50471 @@21: STOSD
50473 TEST EDX, EDX
50474 JGE @@2a
50475 DEC EDX
50476 @@2a:
50478 MOV EAX, [ToolbarsIDcmd]
50479 //INC [ToolbarsIDcmd]
50480 STOSD
50481 TEST EBX, EBX
50482 {$IFDEF USE_CMOV}
50483 CMOVL EBX, EAX
50484 {$ELSE}
50485 JGE @@210
50486 MOV EBX, EAX
50487 @@210: {$ENDIF}
50489 POP ECX
50490 MOV AX, $1004 // AL=fsState=_ENABLED, AH=fsStyle=_AUTOSIZE
50491 CMP byte ptr [ECX], '^'
50492 JNE @@22
50493 MOV AH, TBSTYLE_DROPDOWN or TBSTYLE_AUTOSIZE
50494 INC ECX
50495 @@22: CMP byte ptr [ECX], '-'
50496 JZ @@23
50497 CMP byte ptr [ECX], '+'
50498 JNZ @@24
50499 MOV AL, TBSTATE_ENABLED or TBSTATE_CHECKED
50500 @@23: INC ECX
50501 OR AH, TBSTYLE_CHECK
50502 CMP byte ptr [ECX], '!'
50503 JNZ @@24
50504 OR AH, TBSTYLE_GROUP
50505 INC ECX
50506 @@24: STOSD
50507 MOV EAX, [EBP+8]
50508 STOSD
50509 OR EAX, -1
50510 CMP word ptr [ECX], ' '
50511 JZ @@3
50512 CMP byte ptr [ECX], 0
50513 JZ @@3
50515 PUSH EDX
50516 PUSH 0
50517 MOV EDX, ECX
50518 MOV EAX, ESP
50519 CALL System.@LStrFromPChar
50520 MOV EAX, ESP
50521 MOV EDX, offset[@@0]
50522 CALL System.@LStrCat
50523 PUSH dword ptr [ESP]
50524 PUSH 0
50525 PUSH TB_ADDSTRING
50526 PUSH dword ptr [EBP+8]
50527 CALL Perform
50528 STOSD
50530 CALL RemoveStr
50531 POP EDX
50532 JMP @@30
50534 @@3: STOSD
50535 @@30: INC dword ptr [EBP-$14]
50536 INC [ToolbarsIDcmd]
50537 POP ECX
50538 DEC ECX
50539 JNZ @@loop
50540 @@break:
50541 POP ECX
50542 JECXZ @@exit
50543 PUSH dword ptr [ESP]
50544 MOV EAX, [Idx]
50545 TEST EAX, EAX
50546 JGE @@31
50548 PUSH ECX
50549 PUSH TB_ADDBUTTONS
50550 JMP @@32
50551 @@31:
50552 PUSH EAX
50553 PUSH TB_INSERTBUTTON
50554 @@32:
50555 PUSH dword ptr [EBP+8]
50556 CALL Perform
50557 @@exit:
50558 POP EAX
50559 //TEST EAX, EAX
50560 //JZ @@fin
50561 CALL System.@FreeMem
50563 @@fin:
50564 POP EDI
50565 POP ESI
50566 XCHG EAX, EBX
50567 POP EBX
50568 end;
50569 {$ELSE ASM_VERSION} //Pascal
50570 function TControl.TBAddInsButtons(Idx: Integer; const Buttons: array of PChar;
50571 const BtnImgIdxArray: array of Integer): Integer; stdcall;
50573 function AddInsButtons: Integer;
50574 type TTBBtnArray = array[ 0..100000 ] of TTBButton;
50575 PTBBtnArray = ^TTBBtnArray;
50576 var AB: PTBBtnArray;
50577 I, N, nBmp: Integer;
50578 PAB: PTBButton;
50579 Str: PChar;
50580 begin
50581 Result := -1;
50582 AB := nil;
50583 if High( Buttons ) >= 0 then
50584 GetMem( AB, Sizeof( TTBButton ) * (High(Buttons) + 1) );
50585 N := 0;
50586 PAB := @AB[ 0 ];
50587 nBmp := -2;
50588 if High(BtnImgIdxArray) >= 0 then
50589 nBmp := BtnImgIdxArray[ 0 ] - 1;
50590 for I:= 0 to High( Buttons ) do
50591 begin
50592 if Buttons[ I ] = nil then break;
50594 {if High( BtnImgIdxArray ) >= 0 then
50595 if I > High( BtnImgIdxArray ) then
50596 nBmp := -3;}
50598 if Buttons[ I ] = {$IFDEF F_P}''+{$ENDIF} '-' then
50599 begin
50600 PAB.iBitmap := -1;
50601 //PAB.idCommand := 0;
50602 PAB.fsState := 0;
50603 PAB.fsStyle := TBSTYLE_SEP;
50604 PAB.iString := -1;
50606 else
50607 begin
50608 Str := Buttons[ I ];
50609 Inc( nBmp );
50610 PAB.iBitmap := nBmp;
50611 if nBmp < 0 then
50612 Dec( nBmp );
50613 if High( BtnImgIdxArray ) >= N then
50614 PAB.iBitmap := BtnImgIdxArray[ N ];
50615 {PAB.idCommand := ToolbarsIDcmd;
50616 if Result < 0 then Result := PAB.idCommand;
50617 Inc( ToolbarsIDcmd );}
50618 PAB.fsState := TBSTATE_ENABLED;
50619 PAB.fsStyle := TBSTYLE_BUTTON or TBSTYLE_AUTOSIZE;
50620 if Str^ = '^' then
50621 begin
50622 PAB.fsStyle := TBSTYLE_DROPDOWN or TBSTYLE_AUTOSIZE;
50623 Inc( Str );
50624 end;
50625 if Str^ in [ '-', '+' ] then
50626 begin
50627 PAB.fsStyle := PAB.fsStyle or TBSTYLE_CHECK;
50628 if Str^ = '+' then
50629 PAB.fsState := PAB.fsState or TBSTATE_CHECKED;
50630 Inc( Str );
50631 if Str^ = '!' then
50632 begin
50633 PAB.fsStyle := PAB.fsStyle or TBSTYLE_GROUP;
50634 Inc( Str );
50635 end;
50636 end;
50637 if (Str = {$IFDEF F_P}''+{$ENDIF} ' ') or (Str^ = #0) then
50638 PAB.iString := -1
50639 //Perform( TB_ADDSTRING, 0, Integer( PChar( '' + #0 ) ) )
50640 // an experiment: is it possible to remove space right to image
50641 // without setting tboTextBottom option (non compatible with FixFlatXP)
50642 // answer: seems not possible.
50643 else
50644 PAB.iString :=
50645 Perform( TB_ADDSTRING, 0, Integer( PChar( '' + Str + #0 ) ) );
50646 end;
50648 PAB.idCommand := ToolbarsIDcmd;
50649 if Result < 0 then Result := PAB.idCommand;
50650 Inc( ToolbarsIDcmd );
50652 PAB.dwData := Integer( @Self );
50653 Inc( N );
50654 Inc( PAB );
50655 end;
50656 if N > 0 then
50657 begin
50658 if Idx < 0 then
50659 Perform( TB_ADDBUTTONS, N, Integer( @AB[ 0 ] ) )
50660 else
50661 Perform( TB_INSERTBUTTON, Idx, Integer( @AB[ 0 ] ) );
50662 end;
50663 if AB <> nil then
50664 FreeMem( AB );
50665 end;
50666 begin
50667 if High( Buttons ) < 0 then
50668 Result := -1
50669 else
50670 Result := AddInsButtons;
50671 end;
50672 {$ENDIF ASM_VERSION}
50674 {$IFDEF ASM_VERSION}
50675 //[function TControl.TBAddButtons]
50676 function TControl.TBAddButtons(const Buttons: array of PChar;
50677 const BtnImgIdxArray: array of Integer): Integer;
50679 PUSH dword ptr [EBP+8]
50680 PUSH dword ptr [EBP+12]
50681 PUSH ECX
50682 PUSH EDX
50683 PUSH -1
50684 PUSH EAX
50685 CALL TBAddInsButtons
50686 end;
50687 {$ELSE ASM_VERSION} //Pascal
50688 function TControl.TBAddButtons(const Buttons: array of PChar;
50689 const BtnImgIdxArray: array of Integer): Integer;
50690 begin
50691 Result := TBAddInsButtons( -1, Buttons, BtnImgIdxArray );
50692 end;
50693 {$ENDIF ASM_VERSION}
50696 //[function TControl.TBInsertButtons]
50697 function TControl.TBInsertButtons(BeforeIdx: Integer;
50698 Buttons: array of PChar; BtnImgIdxArray: array of Integer): Integer;
50699 var I, J, K: Integer;
50700 begin
50701 J := -1;
50702 Result := -1;
50703 for I := 0 to High( Buttons ) do
50704 begin
50705 if I <= High( BtnImgIdxArray ) then
50706 J := BtnImgIdxArray[ I ]
50707 else
50708 if J >= 0 then Inc( J );
50709 K := TBAddInsButtons( BeforeIdx, [ Buttons[ I ], '' ], [ J ] );
50710 if Result < 0 then Result := K;
50711 end;
50712 end;
50714 //[function GetTBBtnGoodID]
50715 function GetTBBtnGoodID( Toolbar: PControl; BtnIDorIdx: Integer ): Integer;
50716 // change by Alexander Pravdin (to fix toolbar with separator first):
50717 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
50718 var Btn1st, i: Integer; btn: TTBButton;
50719 begin
50720 Result := BtnIDorIdx;
50721 Btn1st := 0;
50722 for i := 0 to Toolbar.TBButtonCount - 1 do begin
50723 Toolbar.Perform( TB_GETBUTTON, i, Integer( @btn ) );
50724 if btn.fsStyle <> TBSTYLE_SEP then begin
50725 Btn1st := i;
50726 Break;
50727 end;
50728 end;
50729 if Result < Toolbar.TBIndex2Item( Btn1st ) then
50730 Result := Toolbar.TBIndex2Item( Result );
50731 end;
50733 type
50734 TTBButtonEvent = packed Record
50735 BtnID: DWORD;
50736 Event: TOnToolbarButtonClick;
50737 end;
50738 PTBButtonEvent = ^TTBButtonEvent;
50740 //[procedure TControl.TBFreeTBevents]
50741 procedure TControl.TBFreeTBevents;
50742 begin
50743 fTBevents.Release;
50744 end;
50746 //[function WndProcToolbarButtonsClicks]
50747 function WndProcToolbarButtonsClicks( TB: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
50748 var Notify: PTBNotify;
50749 I: Integer;
50750 Event: PTBButtonEvent;
50751 begin
50752 Result := FALSE;
50753 if Msg.message = WM_NOTIFY then
50754 begin
50755 Notify := Pointer( Msg.lParam );
50756 if Notify.hdr.code = NM_CLICK then
50757 begin
50758 for I := TB.fTBevents.fCount-1 downto 0 do
50759 begin
50760 Event := TB.fTBevents.fItems[ I ];
50761 if Integer( Event.BtnID ) = Notify.iItem then
50762 begin
50763 if Assigned( Event.Event ) then
50764 begin
50765 TB.RefInc;
50766 Rslt := DefWindowProc( Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam );
50767 Event.Event( TB, Event.BtnID );
50768 //Rslt := TB.CallDefWndProc( Msg );
50769 TB.RefDec;
50770 Result := TRUE;
50771 Exit;
50772 end;
50773 break;
50774 end;
50775 end;
50776 end;
50777 end;
50778 end;
50780 //[procedure TControl.TBAssignEvents]
50781 procedure TControl.TBAssignEvents(BtnID: Integer;
50782 Events: array of TOnToolbarButtonClick);
50783 var I: Integer;
50784 EventRec: PTBButtonEvent;
50785 begin
50786 if fTBevents = nil then
50787 begin
50788 fTBevents := NewList;
50789 Add2AutoFreeEx( TBFreeTBevents );
50790 AttachProc( WndProcToolbarButtonsClicks );
50791 end;
50792 BtnID := GetTBBtnGoodID( @Self, BtnID );
50793 for I := 0 to High( Events ) do
50794 begin
50795 GetMem( EventRec, Sizeof( TTBButtonEvent ) );
50796 fTBevents.Add( EventRec );
50797 EventRec.Event := Events[ I ];
50798 EventRec.BtnID := BtnID;
50799 Inc( BtnID );
50800 end;
50801 end;
50803 //[procedure TControl.TBResetImgIdx]
50804 procedure TControl.TBResetImgIdx( BtnID, BtnCount: Integer );
50805 begin
50806 while BtnCount > 0 do
50807 begin
50808 TBButtonImage[ BtnID ] := -2;
50809 Inc( BtnID );
50810 Dec( BtnCount );
50811 end;
50812 end;
50815 //[function TControl.TBGetButtonVisible]
50816 function TControl.TBGetButtonVisible(BtnID: Integer): Boolean;
50817 begin
50818 Result := Perform( TB_ISBUTTONHIDDEN, GetTBBtnGoodID( @ Self, BtnID ), 0 ) = 0;
50819 end;
50822 //[function TControl.TBItem2Index]
50823 function TControl.TBItem2Index(BtnID: Integer): Integer;
50824 begin
50825 Result := Perform( TB_COMMANDTOINDEX, BtnID, 0 );
50826 end;
50829 //[procedure TControl.TBSetButtonVisible]
50830 procedure TControl.TBSetButtonVisible(BtnID: Integer;
50831 const Value: Boolean);
50832 begin
50833 BtnID := GetTBBtnGoodID( @Self, BtnID );
50834 Perform( TB_HIDEBUTTON, BtnID, Integer( not Value ) );
50835 end;
50837 {$IFDEF ASM_VERSION}
50838 //[function TControl.TBGetBtnStt]
50839 function TControl.TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;
50841 PUSH 0
50842 PUSH ECX
50843 PUSH EAX
50844 CALL GetTBBtnGoodID
50845 POP EDX
50846 POP ECX
50847 PUSH EAX
50848 ADD ECX, 8
50849 PUSH ECX
50850 PUSH EDX
50851 CALL Perform
50852 TEST EAX, EAX
50853 SETNZ AL
50854 end;
50855 {$ELSE ASM_VERSION} //Pascal
50856 function TControl.TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;
50857 begin
50858 BtnID := GetTBBtnGoodID( @Self, BtnID );
50859 Result := Perform( Index + 8, BtnID, 0 ) <> 0;
50860 end;
50861 {$ENDIF ASM_VERSION}
50864 //[procedure TControl.TBSetBtnStt]
50865 procedure TControl.TBSetBtnStt(BtnID: Integer; const Index: Integer; const Value: Boolean);
50866 begin
50867 BtnID := GetTBBtnGoodID( @Self, BtnID );
50868 Perform( Index, BtnID, Integer( Value ) );
50869 end;
50871 {$IFDEF ASM_VERSION}
50872 //[function TControl.TBIndex2Item]
50873 function TControl.TBIndex2Item(Idx: Integer): Integer;
50874 //*/////////////////////////////////////////////////////
50875 const //
50876 _sizeof_TTBButton = sizeof( TTBButton ); //
50877 //*/////////////////////////////////////////////////////
50879 //*/////////////////////////////////////////////////////
50880 // ADD ESP, -sizeof(TTBButton)
50881 //*/////////////////////////////////////////////////////
50882 ADD ESP, -_sizeof_TTBButton //
50883 //*/////////////////////////////////////////////////////
50884 PUSH ESP
50885 PUSH EDX
50886 PUSH TB_GETBUTTON
50887 PUSH EAX
50888 CALL Perform
50889 TEST EAX, EAX
50890 MOV EAX, [ESP].TTBButton.idCommand
50891 JNZ @@1
50892 OR EAX, -1
50893 //*/////////////////////////////////////////////////////
50894 //@@1: ADD ESP, sizeof( TTBButton )
50895 //*/////////////////////////////////////////////////////
50896 @@1: ADD ESP, _sizeof_TTBButton //
50897 //*/////////////////////////////////////////////////////
50898 end;
50899 {$ELSE ASM_VERSION} //Pascal
50900 function TControl.TBIndex2Item(Idx: Integer): Integer;
50901 var ButtonInfo: TTBButton;
50902 begin
50903 Result := -1;
50904 if Perform( TB_GETBUTTON, Idx, Integer( @ButtonInfo ) ) <> 0 then
50905 Result := ButtonInfo.idCommand;
50906 end;
50907 {$ENDIF ASM_VERSION}
50909 {$IFDEF ASM_VERSION}
50910 //[function TControl.TBGetButtonText]
50911 function TControl.TBGetButtonText( BtnID: Integer ): String;
50913 PUSH ECX
50914 ADD ESP, -1024
50915 PUSH ESP
50916 PUSH EAX
50917 CALL GetTBBtnGoodID
50918 POP EDX
50919 PUSH EAX
50920 PUSH TB_GETBUTTONTEXT
50921 PUSH EDX
50922 CALL Perform
50923 TEST EAX, EAX
50924 JLE @@2
50925 MOV EDX, ESP
50926 JMP @@1
50927 @@2: XOR EDX, EDX
50928 @@1: MOV EAX, [ESP+1024]
50929 CALL System.@LStrFromPChar
50930 ADD ESP, 1028
50931 end;
50932 {$ELSE ASM_VERSION} //Pascal
50933 function TControl.TBGetButtonText( BtnID: Integer ): String;
50934 var Buffer: array[ 0..1023 ] of Char;
50935 begin
50936 BtnID := GetTBBtnGoodID( @Self, BtnID );
50937 if Perform( TB_GETBUTTONTEXT, BtnID, Integer( @Buffer[ 0 ] ) ) > 0 then
50938 Result := Buffer
50939 else
50940 Result := '';
50941 end;
50942 {$ENDIF ASM_VERSION}
50945 //[function TControl.TBGetButtonRect]
50946 function TControl.TBGetButtonRect(BtnID: Integer): TRect;
50947 begin
50948 BtnID := GetTBBtnGoodID( @Self, BtnID );
50949 Perform( TB_GETITEMRECT, TBItem2Index( BtnID ), Integer( @Result ) );
50950 end;
50953 //[function TControl.TBGetRows]
50954 function TControl.TBGetRows: Integer;
50955 begin
50956 Result := 1;
50957 UpdateWndStyles;
50958 if (TBSTYLE_WRAPABLE and fStyle) <> 0 then
50959 Result := Perform( TB_GETROWS, 0, 0 );
50960 end;
50963 //[procedure TControl.TBSetRows]
50964 procedure TControl.TBSetRows(const Value: Integer);
50965 begin
50966 Perform( TB_SETROWS, Value, 0 );
50967 end;
50969 {$IFDEF ASM_VERSION}
50970 //[procedure TControl.TBSetTooltips]
50971 procedure TControl.TBSetTooltips(BtnID1st: Integer;
50972 Tooltips: array of PChar);
50974 PUSH EBX
50975 PUSH ESI
50976 MOV ESI, ECX
50977 MOV EBX, EAX
50978 PUSHAD
50979 MOV ECX, [EBX].fTBttCmd
50980 INC ECX
50981 LOOP @@1
50982 CALL NewList
50983 MOV [EBX].fTBttCmd, EAX
50984 CALL NewStrList
50985 MOV [EBX].fTBttTxt, EAX
50986 @@1: POPAD
50987 MOV ECX, [EBP+8]
50988 INC ECX
50989 JZ @@exit
50990 @@loop:
50991 PUSH ECX
50992 PUSH EDX
50993 PUSH 0
50994 LODSD
50995 MOV EDX, EAX
50996 MOV EAX, ESP
50997 CALL System.@LStrFromPChar
50999 MOV EDX, [ESP+4]
51000 MOV EAX, [EBX].fTBttCmd
51001 CALL TList.IndexOf
51002 TEST EAX, EAX
51003 JGE @@2
51005 MOV EDX, [ESP+4]
51006 MOV EAX, [EBX].fTBttCmd
51007 CALL TList.Add
51008 POP EDX
51009 PUSH EDX
51010 MOV EAX, [EBX].fTBttTxt
51011 CALL TStrList.Add
51012 JMP @@3
51014 @@2:
51015 MOV EDX, EAX
51016 POP ECX
51017 PUSH ECX
51018 MOV EAX, [EBX].fTBttTxt
51019 CALL TStrList.Put
51020 @@3:
51021 CALL RemoveStr
51023 POP EDX
51024 POP ECX
51025 INC EDX
51026 LOOP @@loop
51027 @@exit:
51028 POP ESI
51029 POP EBX
51030 end;
51031 {$ELSE ASM_VERSION} //Pascal
51032 procedure TControl.TBSetTooltips(BtnID1st: Integer;
51033 Tooltips: array of PChar);
51034 var I, J: Integer;
51035 begin
51036 if not assigned( fTBttCmd ) then
51037 begin
51038 fTBttCmd := NewList;
51039 fTBttTxt := NewStrList;
51040 end;
51041 for I:= 0 to High( Tooltips ) do
51042 begin
51043 J := fTBttCmd.IndexOf( Pointer( BtnID1st ) );
51044 if J < 0 then
51045 begin
51046 fTBttCmd.Add( Pointer( BtnID1st ) );
51047 fTBttTxt.Add( Tooltips[ I ] );
51049 else
51050 fTBttTxt.Items[ J ] := Tooltips[ I ];
51051 Inc( BtnID1st );
51052 end;
51053 end;
51054 {$ENDIF ASM_VERSION}
51056 {$IFDEF ASM_VERSION}
51057 //[function TControl.TBButtonAtPos]
51058 function TControl.TBButtonAtPos(X, Y: Integer): Integer;
51060 PUSH EAX
51061 CALL TBBtnIdxAtPos
51062 TEST EAX, EAX
51063 MOV EDX, EAX
51064 POP EAX
51065 JGE TBIndex2Item
51066 MOV EAX, EDX
51067 end;
51068 {$ELSE ASM_VERSION} //Pascal
51069 function TControl.TBButtonAtPos(X, Y: Integer): Integer;
51070 var I: Integer;
51071 begin
51072 I := TBBtnIdxAtPos( X, Y );
51073 if I >= 0 then
51074 I := TBIndex2Item( I );
51075 Result := I;
51076 end;
51077 {$ENDIF ASM_VERSION}
51079 {$IFDEF ASM_VERSION}
51080 //[function TControl.TBBtnIdxAtPos]
51081 function TControl.TBBtnIdxAtPos(X, Y: Integer): Integer;
51083 PUSH EBX
51084 PUSH ECX
51085 PUSH EDX
51086 MOV EBX, EAX
51087 CALL GetItemsCount
51088 MOV ECX, EAX
51089 JECXZ @@fin
51090 @@1: PUSH ECX
51091 ADD ESP, -16
51092 PUSH ESP
51093 DEC ECX
51094 PUSH ECX
51095 PUSH TB_GETITEMRECT
51096 PUSH EBX
51097 CALL Perform
51098 MOV EDX, ESP
51099 LEA EAX, [ESP+20]
51100 CALL PointInRect
51101 ADD ESP, 16
51102 POP ECX
51103 TEST AL, AL
51104 {$IFDEF USE_CMOV}
51105 CMOVNZ EAX, ECX
51106 {$ELSE}
51107 JZ @@2
51108 MOV EAX, ECX
51109 JMP @@fin
51110 @@2: {$ENDIF}
51111 JNZ @@fin
51113 LOOP @@1
51114 @@fin: DEC EAX
51115 POP EDX
51116 POP EDX
51117 POP EBX
51118 end;
51119 {$ELSE ASM_VERSION} //Pascal
51120 function TControl.TBBtnIdxAtPos(X, Y: Integer): Integer;
51121 var I: Integer;
51122 R: TRect;
51123 P: TPoint;
51124 begin
51125 P := MakePoint( X, Y );
51126 for I := TBButtonCount - 1 downto 0 do
51127 begin
51128 Perform( TB_GETITEMRECT, I, Integer( @R ) );
51129 if PointInRect( P, R ) then
51130 begin
51131 Result := I;
51132 Exit;
51133 end;
51134 end;
51135 Result := -1;
51136 end;
51137 {$ENDIF ASM_VERSION}
51140 //[procedure TControl.TBDeleteButton]
51141 procedure TControl.TBDeleteButton(BtnID: Integer);
51142 begin
51143 BtnID := GetTBBtnGoodID( @Self, BtnID );
51144 Perform( TB_DELETEBUTTON, TBItem2Index( BtnID ), 0 );
51145 end;
51148 //[procedure TControl.TBDeleteBtnByIdx]
51149 procedure TControl.TBDeleteBtnByIdx(Idx: Integer);
51150 begin
51151 Perform( TB_DELETEBUTTON, Idx, 0 );
51152 end;
51155 //[procedure TControl.Clear]
51156 procedure TControl.Clear;
51157 begin
51158 fCommandActions.aClear( @Self );
51159 end;
51161 {$IFDEF ASM_noVERSION}
51162 //[function TControl.TBGetBtnImgIdx]
51163 function TControl.TBGetBtnImgIdx(BtnID: Integer): Integer;
51164 const szTBButton = sizeof( TTBButton );
51166 ADD ESP, -szTBButton
51167 PUSH ESP
51168 PUSH EAX
51169 CALL TBItem2Index
51170 POP EDX
51171 PUSH EAX
51172 PUSH TB_GETBUTTON
51173 PUSH EDX
51174 CALL Perform
51175 POP EAX
51176 ADD ESP, szTBButton-4
51177 end;
51178 {$ELSE ASM_VERSION} //Pascal
51179 function TControl.TBGetBtnImgIdx(BtnID: Integer): Integer;
51180 var B: TTBButton;
51181 begin
51182 Perform( TB_GETBUTTON, TBItem2Index( GetTBBtnGoodID( @Self, BtnID ) ), Integer( @B ) );
51183 Result := B.iBitmap;
51184 end;
51185 {$ENDIF ASM_VERSION}
51188 //[procedure TControl.TBSetBtnImgIdx]
51189 procedure TControl.TBSetBtnImgIdx(BtnID: Integer; const Value: Integer);
51190 begin
51191 Perform( TB_CHANGEBITMAP, GetTBBtnGoodID( @Self, BtnID ), Value );
51192 end;
51194 {$IFDEF ASM_VERSION}
51195 //[procedure TControl.TBSetButtonText]
51196 procedure TControl.TBSetButtonText(BtnID: Integer; const Value: String);
51198 PUSH 0
51199 PUSH ECX
51200 PUSH EAX
51201 CALL GetTBBtnGoodID
51202 POP EDX
51204 ADD ESP, -16
51205 PUSH TBIF_TEXT
51206 PUSH 32 //Sizeof( TTBButtonInfo )
51207 PUSH ESP
51208 PUSH EAX
51209 PUSH TB_SETBUTTONINFO
51210 PUSH EDX
51211 CALL Perform
51212 ADD ESP, 32 //sizeof( TTBButtonInfo )
51213 end;
51214 {$ELSE ASM_VERSION} //Pascal
51215 procedure TControl.TBSetButtonText(BtnID: Integer; const Value: String);
51216 var BI: TTBButtonInfo;
51217 begin
51218 BtnID := GetTBBtnGoodID( @Self, BtnID );
51219 BI.cbSize := Sizeof( BI );
51220 BI.dwMask := TBIF_TEXT;
51221 BI.pszText := PChar( Value );
51222 Perform( TB_SETBUTTONINFO, BtnID, Integer( @BI ) );
51223 end;
51224 {$ENDIF ASM_VERSION}
51226 {$IFDEF ASM_VERSION}
51227 //[function TControl.TBGetBtnWidth]
51228 function TControl.TBGetBtnWidth(BtnID: Integer): Integer;
51230 ADD ESP, -16
51231 MOV ECX, ESP
51232 CALL TBGetButtonRect
51233 POP EDX
51234 POP ECX
51235 POP EAX
51236 SUB EAX, EDX
51237 POP EDX
51238 end;
51239 {$ELSE ASM_VERSION} //Pascal
51240 function TControl.TBGetBtnWidth(BtnID: Integer): Integer;
51241 var R: TRect;
51242 begin
51243 R := TBButtonRect[ BtnID ];
51244 Result := R.Right - R.Left;
51245 end;
51246 {$ENDIF ASM_VERSION}
51248 {$IFDEF ASM_VERSION}
51249 //[procedure TControl.TBSetBtnWidth]
51250 procedure TControl.TBSetBtnWidth(BtnID: Integer; const Value: Integer);
51252 PUSH EBX
51253 MOV EBX, ECX
51255 PUSH EAX
51256 CALL GetTBBtnGoodID
51257 POP EDX
51259 ADD ESP, -24
51260 PUSH TBIF_SIZE or TBIF_STYLE
51261 PUSH 32
51262 MOV ECX, ESP
51264 PUSH ECX
51265 PUSH EAX
51266 PUSH TB_SETBUTTONINFO
51267 PUSH EDX
51269 PUSH ECX
51270 PUSH EAX
51271 PUSH TB_GETBUTTONINFO
51272 PUSH EDX
51273 CALL Perform
51275 MOV [ESP+16+18], BX
51276 AND byte ptr [ESP+16].TTBButtonInfo.fsStyle, not TBSTYLE_AUTOSIZE
51277 CALL Perform
51278 ADD ESP, 32
51279 POP EBX
51280 end;
51281 {$ELSE ASM_VERSION} //Pascal
51282 procedure TControl.TBSetBtnWidth(BtnID: Integer; const Value: Integer);
51283 var BI: TTBButtonInfo;
51284 begin
51285 BI.cbSize := Sizeof( BI );
51286 BI.dwMask := TBIF_SIZE or TBIF_STYLE;
51287 BtnID := GetTBBtnGoodID( @Self, BtnID );
51288 Perform( TB_GETBUTTONINFO, BtnID, Integer( @BI ) );
51289 BI.cx := Value;
51290 BI.fsStyle := BI.fsStyle and not TBSTYLE_AUTOSIZE;
51291 Perform( TB_SETBUTTONINFO, BtnID, Integer( @BI ) );
51292 end;
51293 {$ENDIF ASM_VERSION}
51295 //[procedure TControl.TBSetBtMinMaxWidth]
51296 procedure TControl.TBSetBtMinMaxWidth(const Idx: Integer; const Value: Integer);
51297 begin
51298 case Idx of
51299 0: FTBBtMinWidth := Value;
51300 1: FTBBtMaxWidth := Value;
51301 end;
51302 Perform( TB_SETBUTTONWIDTH, 0, FTBBtMaxWidth or (FTBBtMinWidth shl 16) );
51303 end;
51305 {$IFDEF F_P}
51306 //[function TControl.TBGetBtMinMaxWidth]
51307 function TControl.TBGetBtMinMaxWidth(const Idx: Integer): Integer;
51308 begin
51309 CASE Idx OF
51310 0: Result := FTBBtMinWidth;
51311 1: Result := FTBBtMaxWidth;
51312 END;
51313 end;
51314 {$ENDIF F_P}
51316 //[procedure TControl.SetDroppedDown]
51317 procedure TControl.SetDroppedDown(const Value: Boolean);
51318 begin
51319 //fDropped := Value;
51320 Perform( CB_SHOWDROPDOWN, Integer( Value ), 0 );
51321 end;
51323 {$IFDEF ASM_VERSION}
51324 //[procedure TControl.AddDirList]
51325 procedure TControl.AddDirList(const Filemask: String; Attrs: DWORD);
51327 CALL EDX2PChar
51328 PUSH EDX
51329 PUSH ECX
51330 MOVZX ECX, [EAX].fCommandActions.aDir
51331 JECXZ @@exit
51332 PUSH ECX
51333 PUSH EAX
51334 CALL Perform
51336 @@exit:
51337 POP ECX
51338 POP ECX
51339 end;
51340 {$ELSE ASM_VERSION} //Pascal
51341 procedure TControl.AddDirList(const Filemask: String; Attrs: DWORD);
51342 begin
51343 if fCommandActions.aDir <> 0 then
51344 Perform( fCommandActions.aDir, Attrs, Integer( PChar( Filemask ) ) );
51345 end;
51346 {$ENDIF ASM_VERSION}
51348 //[FUNCTION WndProcShowModal]
51349 {$IFDEF ASM_VERSION}
51350 function WndProcShowModal( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
51352 CMP word ptr [EDX].TMsg.message, WM_CLOSE
51353 JNZ @@ret_false
51354 {//++++++ AP
51355 PUSH EBX
51356 MOV EBX, 1
51357 CMP [EAX].TControl.fOnClose.TMethod.Code, 0
51358 JZ @@AP1
51359 PUSH EAX
51360 PUSH EDX
51361 PUSH ECX
51362 XCHG EDX, EAX
51363 PUSH EBX
51364 MOV ECX, ESP
51365 MOV EAX, [EDX].TControl.fOnClose.TMethod.Data
51366 CALL dword ptr [EDX].TControl.fOnClose.TMethod.Code
51367 POP EBX
51368 POP ECX
51369 POP EDX
51370 POP EAX
51371 @@AP1:
51372 //------ AP}
51374 XCHG EDX, EAX
51375 XOR EAX, EAX
51376 CMP [EDX].TControl.fModalResult, EAX
51377 JNZ @@1
51378 OR [EDX].TControl.fModalResult, -1
51379 @@1:
51380 {//++++++ AP
51381 TEST BL, BL
51382 JNZ @@AP2
51383 MOV [EDX].TControl.fModalResult, 0
51384 @@AP2:
51385 POP EBX
51386 //------ AP}
51388 MOV [ECX], EAX
51389 INC EAX
51391 @@ret_false:
51392 XOR EAX, EAX
51394 end;
51395 {$ELSE ASM_VERSION} //Pascal
51396 function WndProcShowModal( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
51397 //var Accept: Boolean; // {Alexander Pravdin, AP}
51398 begin
51399 if Msg.message = WM_CLOSE then
51400 begin
51401 //++++++++ {AP} +++++++++++++++++++++++++++++++++++++++++++++++++++++++//
51402 {Accept := True; //
51403 if Assigned( Self_.fOnClose ) then Self_.fOnClose( Self_, Accept ); //
51404 }//-------- {AP} ----------------------------------------------------//
51405 if Self_.ModalResult = 0 then { (Sergey Shishmintzev) }
51406 Self_.ModalResult := -1;
51407 //++++++++ {AP} +++++++++++++++++++++++++++++++++++++++++++++++++++++++//
51408 {if not Accept then //
51409 Self_.ModalResult := 0; //íå çàêðûâàåì ôîðìó, îñòàâëÿÿ å¸ íà ýêðàíå//
51410 }//-------- {AP} ----------------------------------------------------//
51411 Rslt := 0;
51412 Result := True; // Do not process !
51414 else
51415 Result := False;
51416 end;
51417 {$ENDIF ASM_VERSION}
51418 //[END WndProcShowModal]
51420 {$IFDEF ASM_noVERSION}
51421 //[function TControl.ShowModal]
51422 function TControl.ShowModal: Integer;
51424 MOV ECX, [EAX].fParent
51425 JECXZ @@show
51426 MOVZX ECX, [EAX].fIsControl
51427 JECXZ @@show_modal
51428 @@show:
51429 CALL Show
51430 XOR EAX, EAX
51432 @@show_modal:
51433 PUSHAD
51435 MOV EBX, EAX
51436 MOV EDI, [Applet]
51438 XOR EBP, EBP // CurCtl = nil
51440 MOV EAX, [EDI].fCurrentControl
51441 CMP [EDI].TControl.FIsApplet, 0
51442 {$IFDEF USE_CMOV}
51443 CMOVZ EAX, EDI
51444 {$ELSE}
51445 JNZ @@curctrl_save
51446 MOV EAX, EDI
51447 @@curctrl_save:
51448 {$ENDIF}
51450 PUSH EAX
51452 MOV EDX, offset[WndProcShowModal]
51453 PUSH EDX
51455 MOV EAX, EBX
51456 CALL TControl.AttachProc
51457 XOR EDX, EDX
51458 MOV [EBX].fModalResult, EDX
51460 CALL NewList
51461 XCHG EAX, EBP
51463 XOR ECX, ECX
51464 INC ECX
51465 MOV ESI, EDI
51467 CMP [EDI].TControl.FIsApplet, 0
51468 JZ @@isapplet
51470 MOV EBP, [EDI].fCurrentControl // CurCtl = Applet.fCurrentControl
51472 MOV ESI, [EDI].fChildren
51473 MOV ECX, [ESI].TList.fCount
51474 MOV ESI, [ESI].TList.fItems
51476 @@1loo: LODSD
51478 @@isapplet:
51480 PUSH ECX
51481 CMP EAX, EBX
51482 JE @@1nx
51483 PUSH EAX
51484 CALL GetEnabled
51485 TEST AL, AL
51486 POP EAX
51487 JZ @@1nx
51488 PUSH EAX
51489 MOV DL, 0
51490 CALL SetEnabled
51491 POP EDX
51492 MOV EAX, EBP
51493 CALL TList.Add
51494 @@1nx: POP ECX
51495 LOOP @@1loo
51497 INC [EBX].fModal
51498 MOV EAX, [Applet]
51499 MOV [EAX].fModalForm, EBX
51501 MOV EAX, EBX
51502 CALL Show
51504 @@msgloo:
51505 MOVZX ECX, [AppletTerminated]
51506 OR ECX, [EBX].fModalResult
51507 JNZ @@e_msgloo
51508 CALL WaitMessage
51509 MOV EAX, EDI
51510 CALL ProcessMessages
51511 {$IFNDEF NOT_USE_OnIdle}
51512 MOV EAX, EBX
51513 CALL [ProcessIdle]
51514 {$ENDIF}
51515 JMP @@msgloo
51517 @@e_msgloo:
51518 POP EDX
51519 MOV EAX, EBX
51520 CALL TControl.DetachProc
51522 DEC [EBX].fModal
51523 MOV EAX, [Applet]
51524 XOR ECX, ECX
51525 MOV [EAX].fModalForm, ECX
51527 MOV ECX, [EBP].TList.fCount
51528 JECXZ @@2end
51529 MOV ESI, [EBP].TList.fItems
51531 @@2loo: LODSD
51532 PUSH ECX
51533 MOV DL, 1
51534 CALL TControl.SetEnabled
51535 POP ECX
51536 LOOP @@2loo
51538 @@2end:
51539 MOV EAX, EBP
51540 CALL TObj.Free
51542 POP ECX
51543 JECXZ @@exit
51544 PUSH 0
51545 PUSH WA_ACTIVE
51546 PUSH WM_ACTIVATE
51547 PUSH [ECX].fHandle
51548 CALL PostMessage
51550 TEST EBP, EBP // CurCtl = nil ?
51551 JZ @@exit
51552 MOV EAX, EBP
51553 MOV DL, 1
51554 CALL TControl.SetFocused
51556 @@exit:
51557 POPAD
51558 MOV EAX, [EAX].fModalResult
51559 end;
51560 {$ELSE ASM_VERSION} //Pascal
51561 {$IFDEF USE_SHOWMODALPARENTED_ALWAYS}
51562 function TControl.ShowModal: Integer;
51563 begin
51564 Result := ShowModalParented(Applet);
51565 end;
51566 {$ELSE not USE_SHOWMODALPARENTED_ALWAYS}
51567 function TControl.ShowModal: Integer;
51568 var FL: PList;
51569 var CurForm: PControl;
51570 I: Integer;
51571 F: PControl;
51572 CurCtl: PControl; // { Alexander Pravdin }
51573 begin
51574 Result := 0;
51575 if (fIsControl) or (fParent = nil) then
51576 begin
51577 Show;
51578 Exit;
51579 end;
51580 AttachProc( WndProcShowModal );
51581 CurForm := Applet.fCurrentControl;
51582 FL := NewList;
51583 CurCtl := nil; // { Alexander Pravdin }
51585 if Applet.IsApplet then
51586 for I := 0 to Applet.ChildCount - 1 do
51587 begin
51588 F := Applet.fChildren.Items[ I ];
51589 if F <> @Self then
51590 if F.Enabled then
51591 begin
51592 FL.Add( F );
51593 F.Enabled := FALSE;
51594 end;
51596 else
51597 begin
51598 CurForm := Applet;
51599 if Applet.Enabled then
51600 begin
51601 FL.Add( Applet );
51602 CurCtl := Applet.fCurrentControl; { Alexander Pravdin }
51603 Applet.Enabled := FALSE;
51604 end;
51605 end;
51607 Inc( fModal );
51608 Applet.fModalForm := @ Self;
51609 Enabled := TRUE;
51611 Show;
51612 ModalResult := 0;
51613 while not AppletTerminated and (ModalResult = 0) do
51614 begin
51615 WaitMessage;
51616 Applet.ProcessMessages;
51617 {$IFNDEF NOT_USE_OnIdle}
51618 ProcessIdle( @Self );
51619 {$ENDIF}
51620 end;
51622 Dec( fModal );
51623 Applet.fModalForm := nil;
51625 DetachProc( WndProcShowModal );
51626 for I := 0 to FL.Count - 1 do
51627 begin
51628 F := FL.Items[ I ];
51629 F.Enabled := TRUE;
51630 //EnableWindow( F.Handle, TRUE );
51631 //F.Perform( WM_ENABLE, 1, 0 );
51632 end;
51633 FL.Free;
51635 if CurForm <> nil then
51636 PostMessage( CurForm.Handle, WM_ACTIVATE, WA_ACTIVE, 0 );
51637 if CurCtl <> nil then CurCtl.SetFocused( TRUE ); { Alexander Pravdin }
51639 Result := ModalResult;
51640 end;
51641 {$ENDIF USE_SHOWMODALPARENTED_ALWAYS}
51642 {$ENDIF ASM_VERSION}
51644 //[function TControl.ShowModalParented]
51645 {$IFNDEF NEW_MODAL}
51646 function TControl.ShowModalParented( const AParent: PControl ): Integer;
51647 begin
51648 Result := 0;
51649 end;
51650 {$ELSE NEW_MODAL defined}
51651 function TControl.ShowModalParented( const AParent: PControl ): Integer;
51653 FL: PList;
51654 OldMF, F: PControl;
51655 I: Integer;
51656 begin
51657 Result := 0;
51658 if ( AParent = nil ) then Exit;
51660 Inc( fModal );
51661 FL := NewList;
51662 OldMF := AParent.fModalForm;
51663 AParent.fModalForm := @Self;
51665 if AParent.fIsApplet or ( AParent.IsMainWindow and AParent.fIsForm ) then
51666 begin
51667 for I := 0 to AParent.ChildCount - 1 do
51668 begin
51669 F := AParent.fChildren.Items[ I ];
51670 if ( F <> @Self ) and F.fIsForm and F.fEnabled and F.fVisible then
51671 begin
51672 FL.Add( F );
51673 F.Enabled := FALSE;
51674 end;
51675 end;
51676 end;
51678 if AParent.fIsForm and AParent.Enabled then
51679 begin
51680 FL.Add( AParent );
51681 AParent.Enabled := FALSE;
51682 end;
51684 ModalResult := 0;
51685 Show;
51686 while not AppletTerminated and ( ModalResult = 0 ) do
51687 begin
51688 WaitMessage;
51689 AParent.ProcessMessages;
51690 {$IFNDEF NOT_USE_OnIdle}
51691 ProcessIdle( @Self );
51692 {$ENDIF}
51693 end;
51695 AParent.fModalForm := OldMF;
51696 Dec( fModal );
51697 for I := 0 to FL.Count - 1 do
51698 PControl( FL.Items[ I ] ).Enabled := True;
51699 FL.Free;
51700 Hide;
51701 Result := ModalResult;
51702 end;
51703 {$ENDIF NEW_MODAL}
51705 //[function DisableWindows]
51706 function DisableWindows( W: hwnd; LPARAM: Integer ): Bool; stdcall;
51707 var FL: PList;
51708 Buf: array[ 0..127 ] of Char;
51709 begin
51710 FL := Pointer( LPARAM );
51711 if IsWindowEnabled( W ) and (W <> FL.Tag) then
51712 begin
51713 GetClassName( W, @ Buf[ 0 ], Sizeof( Buf ) );
51714 if Buf <> 'ComboLBox' then
51715 begin
51716 FL.Add( Pointer( W ) );
51717 EnableWindow( W, FALSE );
51718 end;
51719 end;
51720 Result := TRUE;
51721 end;
51723 //[function TControl.ShowModalEx]
51724 function TControl.ShowModalEx: Integer;
51725 var FL: PList;
51726 var CurForm: PControl;
51727 I: Integer;
51728 W: HWnd;
51729 CurCtl: PControl; { Alexander Pravdin }
51730 begin
51731 Result := 0;
51732 if (fIsControl) or (fParent = nil) then
51733 begin
51734 Show;
51735 Exit;
51736 end;
51737 AttachProc( WndProcShowModal );
51738 CurForm := Applet.fCurrentControl;
51739 FL := NewList;
51740 FL.Tag := fHandle;
51742 // ++++ { Alexander Pravdin }
51743 if not Applet.fIsApplet then CurCtl := Applet.fCurrentControl
51744 else CurCtl := nil;
51745 // ----
51746 CreateWindow;
51748 EnumThreadWindows( GetCurrentThreadID, @ DisableWindows, Integer( FL ) );
51749 Enabled := TRUE;
51751 Inc( fModal );
51752 Applet.fModalForm := @ Self;
51753 Show;
51754 ModalResult := 0;
51755 while not AppletTerminated and (ModalResult = 0) do
51756 begin
51757 WaitMessage;
51758 Applet.ProcessMessages;
51759 {$IFNDEF NOT_USE_OnIdle}
51760 ProcessIdle( @Self );
51761 {$ENDIF}
51762 end;
51764 Dec( fModal );
51765 Applet.fModalForm := @ Self;
51767 DetachProc( WndProcShowModal );
51769 for I := 0 to FL.Count - 1 do
51770 begin
51771 W := THandle( FL.Items[ I ] );
51772 EnableWindow( W, TRUE );
51773 end;
51774 FL.Free;
51776 if CurForm <> nil then
51777 PostMessage( CurForm.Handle, WM_ACTIVATE, WA_ACTIVE, 0 );
51778 if CurCtl <> nil then CurCtl.SetFocused( True ); { Alexander Pravdin }
51779 Result := ModalResult;
51780 end;
51782 //[function TControl.GetModal]
51783 function TControl.GetModal: Boolean;
51784 begin
51785 Result := fModal > 0;
51786 end;
51788 {$IFDEF USE_SETMODALRESULT}
51789 //[procedure TControl.SetModalResult]
51790 procedure TControl.SetModalResult( const Value: Integer );
51791 begin
51792 //if fModal <= 0 then Exit;
51793 fModalResult := Value;
51794 if Value <> 0 then
51795 PostMessage( GetWindowHandle, 0, 0, 0 );
51796 end;
51797 {$ENDIF}
51800 //////////////////////////////////////////////////////////////////
51802 // T I M E R
51804 //////////////////////////////////////////////////////////////////
51806 var TimerOwnerWnd: PControl;
51807 TimerCount: Integer = 0;
51809 { -- Constructor of timer -- }
51811 //[function NewTimer]
51812 function NewTimer( Interval: Integer ): PTimer;
51813 begin
51815 New( Result, Create );
51816 {+}{++}(*Result := PTimer.Create;*){--}
51817 if Interval <= 0 then Interval := 1000;
51818 Result.fInterval := Interval;
51819 Inc( TimerCount );
51820 end;
51821 //[END NewTimer]
51823 { -- Timer procedure -- }
51825 //[FUNCTION TimerProc]
51826 {$IFDEF ASM_VERSION}
51827 function TimerProc( Wnd : HWnd; Msg : Integer; T : PTimer; CurrentTime : DWord ): Integer;
51828 stdcall;
51829 asm //cmd //opd
51830 MOV EDX, T
51831 MOV ECX, [EDX].TTimer.fOnTimer.TMethod.Code
51832 JECXZ @@exit
51833 MOV EAX, [EDX].TTimer.fOnTimer.TMethod.Data
51834 CALL ECX
51835 @@exit: XOR EAX, EAX
51836 end;
51837 {$ELSE ASM_VERSION} //Pascal
51838 function TimerProc( Wnd : HWnd; Msg : Integer; T : PTimer; CurrentTime : DWord ): Integer;
51839 stdcall;
51840 begin
51841 if Assigned( T.fOnTimer ) then
51842 T.fOnTimer( T );
51843 Result := 0;
51844 end;
51845 {$ENDIF ASM_VERSION}
51846 //[END TimerProc]
51848 { TTimer }
51850 {$IFDEF ASM_VERSION}
51851 //[destructor TTimer.Destroy]
51852 destructor TTimer.Destroy;
51854 PUSH EAX
51855 XOR EDX, EDX
51856 CALL TTimer.SetEnabled
51857 POP EAX
51858 CALL TObj.Destroy
51859 DEC [TimerCount]
51860 JNZ @@exit
51861 XOR EAX, EAX
51862 XCHG EAX, [TimerOwnerWnd]
51863 CALL TObj.Free
51864 @@exit:
51865 end;
51866 {$ELSE ASM_VERSION} //Pascal
51867 destructor TTimer.Destroy;
51868 begin
51869 Enabled := False;
51870 inherited;
51871 Dec( TimerCount );
51872 if TimerCount = 0 then
51873 begin
51874 TimerOwnerWnd.Free;
51875 TimerOwnerWnd := nil;
51876 end;
51877 end;
51878 {$ENDIF ASM_VERSION}
51880 {$IFDEF ASM_VERSION}
51881 //[procedure TTimer.SetEnabled]
51882 procedure TTimer.SetEnabled(const Value: Boolean);
51884 PUSH EBX
51885 XCHG EBX, EAX
51887 CMP [EBX].fEnabled, DL
51888 JZ @@exit
51890 MOV [EBX].fEnabled, DL
51892 TEST DL, DL
51893 JZ @@disable
51895 MOV ECX, [TimerOwnerWnd]
51896 INC ECX
51897 LOOP @@owner_ready
51899 INC ECX
51900 MOV EDX, offset[EmptyString]
51901 XOR EAX, EAX
51902 CALL _NewWindowed
51903 MOV [TimerOwnerWnd], EAX
51904 MOV [EAX].TControl.fStyle, 0
51905 INC [EAX].TControl.fIsControl
51906 XCHG ECX, EAX
51908 @@owner_ready:
51910 PUSH offset[TimerProc]
51911 PUSH [EBX].fInterval
51912 PUSH EBX
51913 XCHG EAX, ECX
51914 CALL TControl.GetWindowHandle
51915 PUSH EAX
51916 CALL SetTimer
51917 MOV [EBX].fHandle, EAX
51919 JMP @@exit
51921 @@disable:
51922 XOR ECX, ECX
51923 XCHG ECX, [EBX].TTimer.fHandle
51924 JECXZ @@exit
51926 PUSH ECX
51927 MOV EAX, [TimerOwnerWnd]
51928 PUSH [EAX].TControl.fHandle
51929 CALL KillTimer
51931 @@exit:
51932 POP EBX
51933 end;
51934 {$ELSE ASM_VERSION} //Pascal
51935 procedure TTimer.SetEnabled(const Value: Boolean);
51936 begin
51937 if FEnabled = Value then Exit;
51938 fEnabled := Value;
51939 if Value then
51940 begin
51941 if TimerOwnerWnd = nil then
51942 begin
51943 TimerOwnerWnd := _NewWindowed( nil, '', TRUE );
51944 TimerOwnerWnd.fStyle := 0;
51945 TimerOwnerWnd.fIsControl := TRUE;
51946 end;
51947 fHandle := SetTimer( TimerOwnerWnd.GetWindowHandle, Integer( @Self ),
51948 fInterval, @TimerProc );
51950 else
51951 begin
51952 if fHandle <> 0 then
51953 begin
51954 KillTimer( TimerOwnerWnd.fHandle, fHandle );
51955 fHandle := 0;
51956 end;
51957 end;
51958 end;
51959 {$ENDIF ASM_VERSION}
51961 {$IFDEF ASM_VERSION}
51962 //[procedure TTimer.SetInterval]
51963 procedure TTimer.SetInterval(const Value: Integer);
51965 CMP EDX, [EAX].fInterval
51966 JE @@exit
51967 MOV [EAX].fInterval, EDX
51968 PUSH dword ptr [EAX].fEnabled
51969 PUSH EAX
51970 XOR EDX, EDX
51971 CALL SetEnabled
51972 POP EAX
51973 POP EDX
51974 CALL SetEnabled
51975 @@exit:
51976 end;
51977 {$ELSE ASM_VERSION} //Pascal
51978 procedure TTimer.SetInterval(const Value: Integer);
51979 var WasEnabled : Boolean;
51980 begin
51981 if fInterval = Value then Exit;
51982 fInterval := Value;
51983 WasEnabled := Enabled;
51984 Enabled := False;
51985 Enabled := WasEnabled;
51986 end;
51987 {$ENDIF ASM_VERSION}
51990 { TMMTimer }
51992 { ------------ declarations moved here from MMSystem -------------------- }
51993 const
51994 TIME_ONESHOT = 0; { program timer for single event }
51995 TIME_PERIODIC = 1; { program for continuous periodic event }
51996 TIME_CALLBACK_FUNCTION = $0000; { callback is function }
51997 TIME_CALLBACK_EVENT_SET = $0010; { callback is event - use SetEvent }
51998 TIME_CALLBACK_EVENT_PULSE = $0020; { callback is event - use PulseEvent }
52000 type
52001 TFNTimeCallBack = procedure(uTimerID, uMessage: UINT;
52002 dwUser, dw1, dw2: DWORD) stdcall;
52003 //[API timeSetEvent]
52004 function timeSetEvent(uDelay, uResolution: UINT;
52005 lpFunction: TFNTimeCallBack; dwUser: DWORD; uFlags: UINT): THandle; stdcall;
52006 external 'winmm.dll' name 'timeSetEvent';
52007 function timeKillEvent(uTimerID: UINT): Integer; stdcall;
52008 external 'winmm.dll' name 'timeKillEvent';
52009 { ----------------------------------------------------------------------- }
52011 //[procedure MMTimerCallback]
52012 procedure MMTimerCallback(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD);
52013 stdcall;
52014 var MMTimer: PMMTimer;
52015 begin
52016 MMTimer := Pointer( dwUser );
52017 if Assigned( MMTimer.FOnTimer ) then
52018 MMTimer.fOnTimer( MMTimer );
52019 end;
52021 //[function NewMMTimer]
52022 function NewMMTimer( Interval: Integer ): PMMTimer;
52023 begin
52025 New( Result, Create );
52026 {+} {++}(* Result := PMMTimer.Create; *){--}
52027 Result.fInterval := Interval;
52028 Result.FPeriodic := TRUE;
52029 end;
52030 //[END NewMMTimer]
52032 //[destructor TMMTimer.Destroy]
52033 destructor TMMTimer.Destroy;
52034 begin
52035 Enabled := FALSE;
52036 Inc( TimerCount );
52037 inherited;
52038 end;
52040 //[procedure TMMTimer.SetEnabled]
52041 procedure TMMTimer.SetEnabled(const Value: Boolean);
52042 begin
52043 if Value xor (fHandle <> 0) then
52044 begin
52045 if fHandle = 0 then
52046 fHandle := timeSetEvent( Interval, Resolution, MMTimerCallback, DWORD( @ Self ),
52047 Integer( Periodic ) or TIME_CALLBACK_FUNCTION )
52048 else
52049 begin
52050 timeKillEvent( fHandle );
52051 fHandle := 0;
52052 end;
52053 end;
52054 fEnabled := Value;
52055 end;
52067 ////////////////////////////////////////////////////////////////////////
52070 // t B I T M A P
52073 ///////////////////////////////////////////////////////////////////////
52075 { -- bitmap -- }
52077 //[FUNCTION PrepareBitmapHeader]
52078 {$IFDEF ASM_VERSION}
52079 function PrepareBitmapHeader( W, H, BitsPerPixel: Integer ): PBitmapInfo;
52080 const szIH = sizeof(TBitmapInfoHeader);
52081 szHd = szIH + 256 * Sizeof(TRGBQuad);
52083 PUSH EDI
52085 PUSH ECX // BitsPerPixel
52086 PUSH EDX // H
52087 PUSH EAX // W
52089 MOV EAX, szHd
52090 CALL AllocMem
52092 MOV EDI, EAX
52093 XCHG ECX, EAX
52095 XOR EAX, EAX
52096 MOV AL, szIH
52097 STOSD // biSize = Sizeof( TBitmapInfoHeader )
52098 POP EAX // ^ W
52099 STOSD // -> biWidth
52100 POP EAX // ^ H
52101 STOSD // -> biHeight
52102 XOR EAX, EAX
52103 INC EAX
52104 STOSW // 1 -> biPlanes
52105 POP EAX // ^ BitsPerPixel
52106 STOSW // -> biBitCount
52108 XCHG EAX, ECX // EAX = Result
52109 POP EDI
52110 end;
52111 {$ELSE ASM_VERSION} //Pascal
52112 function PrepareBitmapHeader( W, H, BitsPerPixel: Integer ): PBitmapInfo;
52113 begin
52114 Assert( W > 0, 'Width must be >0' );
52115 Assert( H > 0, 'Height must be >0' );
52117 Result := AllocMem( 256*Sizeof(TRGBQuad)+Sizeof(TBitmapInfoHeader) );
52118 Assert( Result <> nil, 'No memory' );
52120 Result.bmiHeader.biSize := Sizeof( TBitmapInfoHeader );
52121 Result.bmiHeader.biWidth := W;
52122 Result.bmiHeader.biHeight := H; // may be, -H ?
52123 Result.bmiHeader.biPlanes := 1;
52124 Result.bmiHeader.biBitCount := BitsPerPixel;
52125 //Result.bmiHeader.biCompression := BI_RGB; // BI_RGB = 0
52126 end;
52127 {$ENDIF ASM_VERSION}
52128 //[END PrepareBitmapHeader]
52130 const
52131 BitsPerPixel_By_PixelFormat: array[ TPixelFormat ] of Byte =
52132 ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );
52134 //[FUNCTION Bits2PixelFormat]
52135 {$IFDEF ASM_VERSION}
52136 function Bits2PixelFormat( BitsPerPixel: Integer ): TPixelFormat;
52138 PUSH ESI
52139 MOV ESI, offset[ BitsPerPixel_By_PixelFormat + 1 ]
52140 XOR ECX, ECX
52141 XCHG EDX, EAX
52142 @@loo: INC ECX
52143 LODSB
52144 CMP AL, DL
52145 JZ @@exit
52146 TEST AL, AL
52147 JNZ @@loo
52148 @@exit: XCHG EAX, ECX
52149 POP ESI
52150 end;
52151 {$ELSE ASM_VERSION} //Pascal
52152 function Bits2PixelFormat( BitsPerPixel: Integer ): TPixelFormat;
52153 var I: TPixelFormat;
52154 begin
52155 for I := High(I) downto Low(I) do
52156 if BitsPerPixel = BitsPerPixel_By_PixelFormat[ I ] then
52157 begin
52158 Result := I;
52159 Exit;
52160 end;
52161 Result := pfDevice;
52162 end;
52163 {$ENDIF ASM_VERSION}
52164 //[END Bits2PixelFormat]
52166 //[procedure DummyDetachCanvas]
52167 procedure DummyDetachCanvas( Sender: PBitmap );
52168 begin
52169 end;
52171 //[FUNCTION _NewBitmap]
52172 {$IFDEF ASM_VERSION}
52173 function _NewBitmap( W, H: Integer ): PBitmap;
52174 begin
52175 New( Result, Create );
52176 Result.fDetachCanvas := DummyDetachCanvas;
52177 Result.fWidth := W;
52178 Result.fHeight := H;
52179 end;
52180 {$ENDIF ASM_VERSION}
52181 //[END _NewBitmap]
52183 //[FUNCTION NewBitmap]
52184 {$IFDEF ASM_VERSION}
52185 function NewBitmap( W, H: Integer ): PBitmap;
52187 PUSH EAX
52188 PUSH EDX
52189 CALL _NewBitmap
52190 POP EDX
52191 POP ECX
52192 PUSH EAX
52193 INC [EAX].TBitmap.fHandleType
52194 JECXZ @@exit
52195 TEST EDX, EDX
52196 JZ @@exit
52197 PUSH EBX
52198 PUSH EAX
52199 PUSH EDX
52200 PUSH ECX
52201 PUSH 0
52202 CALL GetDC
52203 PUSH EAX
52204 XCHG EBX, EAX
52205 CALL CreateCompatibleBitmap
52206 POP EDX
52207 MOV [EDX].TBitmap.fHandle, EAX
52208 PUSH EBX
52209 PUSH 0
52210 CALL ReleaseDC
52211 POP EBX
52212 @@exit: POP EAX
52213 end;
52214 {$ELSE ASM_VERSION} //Pascal
52215 function NewBitmap( W, H: Integer ): PBitmap;
52216 var DC: HDC;
52217 begin
52219 New( Result, Create );
52220 {+}{++}(*Result := PBitmap.Create;*){--}
52221 Result.fHandleType := bmDDB;
52222 Result.fDetachCanvas := DummyDetachCanvas;
52223 Result.fWidth := W;
52224 Result.fHeight := H;
52225 if (W <> 0) and (H <> 0) then
52226 begin
52227 //DC := CreateCompatibleDC( 0 );
52228 DC := GetDC( 0 );
52229 Result.fHandle := CreateCompatibleBitmap( DC, W, H );
52230 Assert( Result.fHandle <> 0, 'Can not create bitmap handle' );
52231 //DeleteDC( DC );
52232 ReleaseDC( 0, DC );
52233 end;
52234 end;
52235 {$ENDIF ASM_VERSION}
52236 //[END NewBitmap]
52238 const InitColors: array[ 0..17 ] of DWORD = ( $F800, $7E0, $1F, 0, $800000, $8000,
52239 $808000, $80, $800080, $8080, $808080, $C0C0C0, $FF0000, $FF00, $FFFF00, $FF,
52240 $FF00FF, $FFFF );
52241 //[PROCEDURE PreparePF16bit]
52242 {$IFDEF ASM_VERSION}
52243 procedure PreparePF16bit( DIBHeader: PBitmapInfo );
52244 const szBIH = sizeof(TBitmapInfoHeader);
52246 MOV byte ptr [EAX].TBitmapInfoHeader.biCompression, BI_BITFIELDS
52247 ADD EAX, szBIH
52248 XCHG EDX, EAX
52249 MOV EAX, offset[InitColors]
52250 XOR ECX, ECX
52251 MOV CL, 19*4
52252 CALL System.Move
52253 end;
52254 {$ELSE ASM_VERSION} //Pascal
52255 procedure PreparePF16bit( DIBHeader: PBitmapInfo );
52256 begin
52257 DIBHeader.bmiHeader.biCompression := BI_BITFIELDS;
52258 Move( InitColors[ 0 ], DIBHeader.bmiColors[ 0 ], 19*Sizeof(TRGBQUAD) );
52259 end;
52260 {$ENDIF ASM_VERSION}
52261 //[END PreparePF16bit]
52263 //[FUNCTION NewDIBBitmap]
52264 {$IFDEF ASM_VERSION}
52265 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;
52267 PUSH EBX
52269 PUSH ECX
52270 PUSH EDX
52271 PUSH EAX
52272 CALL _NewBitmap
52273 XCHG EBX, EAX
52274 POP EAX //W
52275 POP EDX //H
52276 POP ECX //PixelFormat
52278 TEST EAX, EAX
52279 JZ @@exit
52280 TEST EDX, EDX
52281 JZ @@exit
52283 PUSH EAX
52284 MOVZX EAX, CL
52285 JMP @@loadBitsPixel
52286 @@loadDefault:
52287 MOVZX EAX, [DefaultPixelFormat]
52288 @@loadBitsPixel:
52289 MOVZX ECX, byte ptr [ BitsPerPixel_By_PixelFormat + EAX ]
52290 JECXZ @@loadDefault
52291 MOV [EBX].TBitmap.fNewPixelFormat, AL
52292 {$IFDEF PARANOIA}
52293 DB $3C, pf16bit
52294 {$ELSE}
52295 CMP AL, pf16bit
52296 {$ENDIF}
52297 POP EAX
52299 PUSHFD
52300 CALL PrepareBitmapHeader
52301 MOV [EBX].TBitmap.fDIBHeader, EAX
52302 POPFD
52303 JNZ @@2
52305 CALL PreparePF16bit
52307 @@2:
52308 MOV EAX, EBX
52309 CALL TBitmap.GetScanLineSize
52310 MOV EDX, [EBX].TBitmap.fHeight
52311 MUL EDX
52312 MOV [EBX].TBitmap.fDIBSize, EAX
52313 CALL AllocMem
52314 MOV [EBX].TBitmap.fDIBBits, EAX
52315 @@exit:
52316 XCHG EAX, EBX
52317 POP EBX
52318 end;
52319 {$ELSE ASM_VERSION} //Pascal
52320 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;
52321 const BitsPerPixel: array[ TPixelFormat ] of Byte = ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );
52322 var BitsPixel: Integer;
52323 //AField: PDWORD;
52324 //DC0 : HDC;
52325 begin
52327 New( Result, Create );
52328 {+}{++}(*Result := PBitmap.Create;*){--}
52329 Result.fDetachCanvas := DummyDetachCanvas;
52330 Result.fWidth := W;
52331 Result.fHeight := H;
52332 if (W <> 0) and (H <> 0) then
52333 begin
52334 BitsPixel := BitsPerPixel[ PixelFormat ];
52335 if BitsPixel = 0 then
52336 begin
52337 Result.fNewPixelFormat := DefaultPixelFormat;
52338 BitsPixel := BitsPerPixel[DefaultPixelFormat];
52340 else
52341 Result.fNewPixelFormat := PixelFormat;
52342 ASSERT( Result.fNewPixelFormat in [ pf1bit..pf32bit ], 'Strange pixel format' );
52343 Result.fDIBHeader := PrepareBitmapHeader( W, H, BitsPixel );
52344 if PixelFormat = pf16bit then
52345 begin
52346 PreparePF16bit( Result.fDIBHeader );
52348 Result.fDIBHeader.bmiHeader.biCompression := BI_BITFIELDS;
52349 AField := @Result.fDIBHeader.bmiColors[ 0 ];
52350 AField^ := $F800; Inc( AField );
52351 AField^ := $07E0; Inc( AField );
52352 AField^ := $001F; Inc( AField );
52353 DC0 := CreateCompatibleDC( 0 );
52354 GetSystemPaletteEntries( DC0, 0, 16, AField^ );
52355 DeleteDC( DC0 );
52357 end;
52359 Result.fDIBSize := Result.ScanLineSize * H;
52360 Result.fDIBBits := AllocMem( Result.fDIBSize );
52361 ASSERT( Result.fDIBBits <> nil, 'No memory' );
52362 end;
52363 end;
52364 {$ENDIF ASM_VERSION}
52365 //[END NewDIBBitmap]
52367 { TBitmap }
52369 {$IFDEF ASM_VERSION}
52370 //[procedure TBitmap.ClearData]
52371 procedure TBitmap.ClearData;
52373 PUSH EBX
52374 MOV EBX, EAX
52375 CALL [EBX].fDetachCanvas
52376 XOR ECX, ECX
52377 XCHG ECX, [EBX].fHandle
52378 JECXZ @@1
52379 PUSH ECX
52380 CALL DeleteObject
52381 XOR ECX, ECX
52382 MOV [EBX].fDIBBits, ECX
52383 @@1: XCHG ECX, [EBX].fDIBBits
52384 JECXZ @@2
52385 XCHG EAX, ECX
52386 CALL System.@FreeMem
52387 @@2: XOR ECX, ECX
52388 XCHG ECX, [EBX].fDIBHeader
52389 JECXZ @@3
52390 XCHG EAX, ECX
52391 CALL System.@FreeMem
52392 @@3: XOR EAX, EAX
52393 MOV [EBX].fScanLineSize, EAX
52394 MOV [EBX].fGetDIBPixels, EAX
52395 MOV [EBX].fSetDIBPixels, EAX
52396 XCHG EAX, EBX
52397 POP EBX
52398 CALL ClearTransImage
52399 end;
52400 {$ELSE ASM_VERSION} //Pascal
52401 procedure TBitmap.ClearData;
52402 begin
52403 fDetachCanvas( @Self );
52404 if fHandle <> 0 then
52405 begin
52406 DeleteObject( fHandle );
52407 fHandle := 0;
52408 fDIBBits := nil;
52409 //fDIBHeader := nil;
52410 end;
52411 if fDIBBits <> nil then
52412 begin
52413 FreeMem( fDIBBits );
52414 fDIBBits := nil;
52415 end;
52416 if fDIBHeader <> nil then
52417 begin
52418 FreeMem( fDIBHeader );
52419 fDIBHeader := nil;
52420 end;
52421 fScanLineSize := 0;
52422 fGetDIBPixels := nil;
52423 fSetDIBPixels := nil;
52424 ClearTransImage;
52425 end;
52426 {$ENDIF ASM_VERSION}
52428 {$IFDEF ASM_VERSION}
52429 //[procedure TBitmap.Clear]
52430 procedure TBitmap.Clear;
52432 PUSH EAX
52433 CALL RemoveCanvas
52434 POP EAX
52435 PUSH EAX
52436 CALL ClearData
52437 POP EAX
52438 XOR EDX, EDX
52439 MOV [EAX].fWidth, EDX
52440 MOV [EAX].fHeight, EDX
52441 MOV [EAX].fDIBAutoFree, DL
52442 end;
52443 {$ELSE ASM_VERSION} //Pascal
52444 procedure TBitmap.Clear;
52445 begin
52446 RemoveCanvas;
52447 ClearData;
52448 fWidth := 0;
52449 fHeight := 0;
52450 fDIBAutoFree := FALSE;
52451 end;
52452 {$ENDIF ASM_VERSION}
52454 //[function TBitmap.GetBoundsRect]
52455 function TBitmap.GetBoundsRect: TRect;
52456 begin
52457 Result := MakeRect( 0, 0, Width, Height );
52458 end;
52460 {$IFDEF ASM_VERSION}
52461 //[destructor TBitmap.Destroy]
52462 destructor TBitmap.Destroy;
52464 PUSH EAX
52465 CALL Clear
52466 POP EAX
52467 CALL TObj.Destroy
52468 end;
52469 {$ELSE ASM_VERSION} //Pascal
52470 destructor TBitmap.Destroy;
52471 begin
52472 Clear;
52473 inherited;
52474 end;
52475 {$ENDIF ASM_VERSION}
52477 //[function TBitmap.BitsPerPixel]
52478 function TBitmap.BitsPerPixel: Integer;
52479 var B: tagBitmap;
52480 begin
52481 CASE PixelFormat OF
52482 pf1bit: Result := 1;
52483 pf4bit: Result := 4;
52484 pf8bit: Result := 8;
52485 pf15bit: Result := 15;
52486 pf16bit: Result := 16;
52487 pf24bit: Result := 24;
52488 pf32bit: Result := 32;
52489 else begin
52490 Result := 0;
52491 if fHandle <> 0 then
52492 if GetObject( fHandle, Sizeof( B ), @B ) > 0 then
52493 Result := B.bmBitsPixel * B.bmPlanes;
52494 end;
52495 END;
52496 end;
52498 {$IFDEF ASM_VERSION}
52499 //[procedure TBitmap.Draw]
52500 procedure TBitmap.Draw(DC: HDC; X, Y: Integer);
52501 const szBitmap = sizeof( tagBitmap );
52502 asm // [EBP+8] = Y
52503 PUSH EDX // [EBP-4] = DC
52504 PUSH ECX // [EBP-8] = X
52505 PUSH EBX
52506 PUSH ESI
52507 @@try_again:
52508 MOV EBX, EAX
52509 CALL GetEmpty // GetEmpty must be assembler version !
52510 JZ @@exit
52512 MOV ECX, [EBX].fHandle
52513 JECXZ @@2
52515 //MOV EAX, EBX
52516 //CALL [EBX].fDetachCanvas // detached in StartDC
52518 ADD ESP, -szBitmap
52519 PUSH ESP
52520 PUSH szBitmap
52521 PUSH [EBX].fHandle
52522 CALL GetObject
52523 TEST EAX, EAX
52524 MOV ESI, [ESP].tagBitmap.bmHeight
52525 {$IFDEF USE_CMOV}
52526 CMOVZ ESI, [EBX].fHeight
52527 {$ELSE}
52528 JNZ @@1
52529 MOV ESI, [EBX].fHeight
52530 @@1: {$ENDIF}
52532 ADD ESP, szBitmap
52533 CALL StartDC
52535 PUSH SRCCOPY
52536 PUSH 0
52537 PUSH 0
52538 PUSH EAX
52539 CALL @@prepare
52540 CALL BitBlt
52541 CALL FinishDC
52542 JMP @@exit
52544 @@prepare:
52545 XCHG ESI, [ESP]
52546 PUSH [EBX].fWidth
52547 PUSH Y
52548 PUSH dword ptr [EBP-8]
52549 PUSH dword ptr [EBP-4]
52550 JMP ESI
52552 @@2:
52553 MOV ECX, [EBX].fDIBHeader
52554 JECXZ @@exit
52556 MOV ESI, [ECX].TBitmapInfoHeader.biHeight
52557 TEST ESI, ESI
52558 JGE @@20
52559 NEG ESI
52560 @@20:
52561 PUSH SRCCOPY
52562 PUSH DIB_RGB_COLORS
52563 PUSH ECX
52564 PUSH [EBX].fDIBBits
52565 PUSH ESI
52566 PUSH [EBX].fWidth
52567 PUSH 0
52568 PUSH 0
52569 CALL @@prepare
52570 CALL StretchDIBits
52571 TEST EAX, EAX
52572 JNZ @@exit
52573 MOV EAX, EBX
52574 CALL GetHandle
52575 TEST EAX, EAX
52576 XCHG EAX, EBX
52577 JNZ @@try_again
52578 @@exit:
52579 POP ESI
52580 POP EBX
52581 MOV ESP, EBP
52582 end;
52583 {$ELSE ASM_VERSION} //Pascal
52584 procedure TBitmap.Draw(DC: HDC; X, Y: Integer);
52586 DCfrom, DC0: HDC;
52587 oldBmp: HBitmap;
52588 oldHeight: Integer;
52589 B: tagBitmap;
52590 label
52591 TRYAgain;
52592 begin
52593 TRYAgain:
52594 if Empty then Exit;
52595 if fHandle <> 0 then
52596 begin
52597 fDetachCanvas( @Self );
52598 oldHeight := fHeight;
52599 if GetObject( fHandle, sizeof( B ), @B ) <> 0 then
52600 oldHeight := B.bmHeight;
52601 ASSERT( oldHeight > 0, 'oldHeight must be > 0' );
52603 DC0 := GetDC( 0 );
52604 DCfrom := CreateCompatibleDC( DC0 );
52605 ReleaseDC( 0, DC0 );
52607 oldBmp := SelectObject( DCfrom, fHandle );
52608 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
52610 BitBlt( DC, X, Y, fWidth, oldHeight, DCfrom, 0, 0, SRCCOPY );
52611 {$IFDEF CHK_BITBLT} Chk_BitBlt; {$ENDIF}
52613 SelectObject( DCfrom, oldBmp );
52614 DeleteDC( DCfrom );
52616 else
52617 if fDIBBits <> nil then
52618 begin
52619 oldHeight := Abs(fDIBHeader.bmiHeader.biHeight);
52620 ASSERT( oldHeight > 0, 'oldHeight must be > 0' );
52621 ASSERT( fWidth > 0, 'Width must be > 0' );
52622 if StretchDIBits( DC, X, Y, fWidth, oldHeight, 0, 0, fWidth, oldHeight,
52623 fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY ) = 0 then
52624 begin
52625 if GetHandle <> 0 then
52626 goto TRYAgain;
52627 end;
52628 end;
52629 end;
52630 {$ENDIF ASM_VERSION}
52632 {$IFDEF ASM_VERSION}
52633 //[procedure TBitmap.StretchDraw]
52634 procedure TBitmap.StretchDraw(DC: HDC; const Rect: TRect);
52636 PUSH EBX
52637 PUSH EDI
52638 PUSH EBP
52639 MOV EBP, ESP
52640 PUSH EDX
52641 PUSH ECX
52642 MOV EBX, EAX
52643 CALL GetEmpty
52644 JZ @@exit
52646 MOV ECX, [EBX].fHandle
52647 JECXZ @@2
52649 @@0:
52650 CALL StartDC
52651 PUSH SRCCOPY
52652 PUSH [EBX].fHeight
52653 PUSH [EBX].fWidth
52654 PUSH 0
52655 PUSH 0
52656 PUSH EAX
52658 CALL @@prepare
52659 CALL StretchBlt
52660 CALL FinishDC
52661 JMP @@exit
52663 @@prepare:
52664 POP EDI
52665 MOV EAX, [EBP-8]
52666 MOV EDX, [EAX].TRect.Bottom
52667 MOV ECX, [EAX].TRect.Top
52668 SUB EDX, ECX
52669 PUSH EDX
52670 MOV EDX, [EAX].TRect.Right
52671 MOV EAX, [EAX].TRect.Left
52672 SUB EDX, EAX
52673 PUSH EDX
52674 PUSH ECX
52675 PUSH EAX
52676 PUSH dword ptr [EBP-4]
52677 JMP EDI
52680 @@2: MOV ECX, [EBX].fDIBHeader
52681 JECXZ @@exit
52683 PUSH SRCCOPY
52684 PUSH DIB_RGB_COLORS
52685 PUSH ECX
52686 PUSH [EBX].fDIBBits
52687 PUSH [EBX].fHeight
52688 PUSH [EBX].fWidth
52689 PUSH 0
52690 PUSH 0
52691 CALL @@prepare
52692 CALL StretchDIBits
52693 TEST EAX, EAX
52694 JG @@exit
52696 MOV EAX, EBX
52697 CALL GetHandle
52698 MOV ECX, [EBX].fHandle
52699 JECXZ @@exit
52700 JMP @@0
52702 @@exit: MOV ESP, EBP
52703 POP EBP
52704 POP EDI
52705 POP EBX
52706 end;
52707 {$ELSE ASM_VERSION} //Pascal
52708 procedure TBitmap.StretchDraw(DC: HDC; const Rect: TRect);
52709 var DCfrom: HDC;
52710 oldBmp: HBitmap;
52711 label DrawHandle;
52712 begin
52713 if Empty then Exit;
52714 DrawHandle:
52715 if fHandle <> 0 then
52716 begin
52717 fDetachCanvas( @Self );
52718 DCfrom := CreateCompatibleDC( 0 );
52719 oldBmp := SelectObject( DCfrom, fHandle );
52720 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
52721 StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left,
52722 Rect.Bottom - Rect.Top, DCfrom, 0, 0, fWidth, fHeight,
52723 SRCCOPY );
52724 SelectObject( DCfrom, oldBmp );
52725 DeleteDC( DCfrom );
52727 else
52728 if fDIBBits <> nil then
52729 begin
52730 if StretchDIBits( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left,
52731 Rect.Bottom - Rect.Top, 0, 0, fWidth, fHeight,
52732 fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY )<=0 then
52733 begin
52734 if GetHandle <> 0 then
52735 goto DrawHandle;
52736 end;
52737 end;
52738 end;
52739 {$ENDIF ASM_VERSION}
52741 //[procedure TBitmap.DrawMasked]
52742 procedure TBitmap.DrawMasked(DC: HDC; X, Y: Integer; Mask: HBitmap);
52743 begin
52744 StretchDrawMasked( DC, MakeRect( X, Y, X + fWidth, Y + fHeight ), Mask );
52745 end;
52747 {$IFDEF ASM_VERSION}
52748 //[procedure TBitmap.DrawTransparent]
52749 procedure TBitmap.DrawTransparent(DC: HDC; X, Y: Integer; TranspColor: TColor);
52751 PUSH ECX
52752 MOV ECX, TranspColor
52753 INC ECX
52754 MOV ECX, [Y]
52755 JNZ @@2
52756 XCHG ECX, [ESP]
52757 CALL Draw
52758 JMP @@exit
52759 @@2:
52760 ADD ECX, [EAX].fHeight
52761 PUSH ECX
52762 MOV ECX, [EBP-4]
52763 ADD ECX, [EAX].fWidth
52764 PUSH ECX
52765 PUSH [Y]
52766 PUSH dword ptr [EBP-4]
52767 MOV ECX, ESP
52768 PUSH [TranspColor]
52769 CALL StretchDrawTransparent
52770 @@exit:
52771 MOV ESP, EBP
52772 end;
52773 {$ELSE ASM_VERSION} //Pascal
52774 procedure TBitmap.DrawTransparent(DC: HDC; X, Y: Integer; TranspColor: TColor);
52775 begin
52776 if TranspColor = clNone then
52777 Draw( DC, X, Y )
52778 else
52779 StretchDrawTransparent( DC, MakeRect( X, Y, X + fWidth, Y + fHeight ),
52780 TranspColor );
52781 end;
52782 {$ENDIF ASM_VERSION}
52784 {$IFDEF ASM_VERSION}
52785 //[procedure TBitmap.StretchDrawTransparent]
52786 procedure TBitmap.StretchDrawTransparent(DC: HDC; const Rect: TRect; TranspColor: TColor);
52788 PUSH EBX
52789 XCHG EBX, EAX
52790 MOV EAX, [TranspColor]
52791 INC EAX
52792 MOV EAX, EBX
52793 JNZ @@2
52794 CALL StretchDraw
52795 JMP @@exit
52796 @@2:
52797 PUSH EDX
52798 PUSH ECX
52799 CALL GetHandle
52800 TEST EAX, EAX
52801 JZ @@exit2
52803 MOV EAX, [TranspColor]
52804 CALL Color2RGB
52805 MOV ECX, [EBX].fTransMaskBmp
52806 JECXZ @@makemask0
52807 CMP EAX, [EBX].fTransColor
52808 JE @@3
52809 @@makemask0:
52810 MOV [EBX].fTransColor, EAX
52811 INC ECX
52812 LOOP @@20
52813 //MOV EAX, [EBX].fWidth
52814 //MOV EDX, [EBX].fHeight
52815 XOR EAX, EAX // pass height = 0
52816 // absolutely no matter what to pass as width
52817 CALL NewBitmap
52818 MOV [EBX].fTransMaskBmp, EAX
52819 @@20:
52820 MOV EAX, [EBX].fTransMaskBmp
52821 PUSH EAX
52822 MOV EDX, EBX
52823 CALL Assign
52824 POP EAX
52825 MOV EDX, [EBX].fTransColor
52826 CALL Convert2Mask
52827 @@3:
52828 MOV EAX, [EBX].fTransMaskBmp
52829 CALL GetHandle
52830 POP ECX
52831 POP EDX
52832 PUSH EAX
52833 XCHG EAX, EBX
52834 CALL StretchDrawMasked
52835 JMP @@exit
52836 @@exit2:
52837 POP ECX
52838 POP EDX
52839 @@exit:
52840 POP EBX
52841 end;
52842 {$ELSE ASM_VERSION} //Pascal
52843 procedure TBitmap.StretchDrawTransparent(DC: HDC; const Rect: TRect; TranspColor: TColor);
52844 begin
52845 if TranspColor = clNone then
52846 StretchDraw( DC, Rect )
52847 else
52848 begin
52849 if GetHandle = 0 then Exit;
52850 TranspColor := Color2RGB( TranspColor );
52851 if (fTransMaskBmp = nil) or (fTransColor <> TranspColor) then
52852 begin
52853 if fTransMaskBmp = nil then
52854 fTransMaskBmp := NewBitmap( 0, 0 {fWidth, fHeight} );
52855 fTransColor := TranspColor;
52856 // Create here mask bitmap:
52857 fTransMaskBmp.Assign( @Self );
52858 fTransMaskBmp.Convert2Mask( TranspColor );
52859 end;
52860 StretchDrawMasked( DC, Rect, fTransMaskBmp.Handle );
52861 end;
52862 end;
52863 {$ENDIF ASM_VERSION}
52865 const
52866 ROP_DstCopy = $00AA0029;
52867 {$IFDEF ASM_VERSION}
52868 //[procedure TBitmap.StretchDrawMasked]
52869 procedure TBitmap.StretchDrawMasked(DC: HDC; const Rect: TRect; Mask: HBitmap);
52871 PUSH EDX // [EBP-4] = DC
52872 PUSH ECX // [EBP-8] = Rect
52873 PUSH EBX // save EBX
52874 MOV EBX, EAX
52875 PUSH ESI // save ESI
52876 CALL GetHandle
52877 TEST EAX, EAX
52878 JZ @@to_exit
52880 PUSH 0
52881 CALL CreateCompatibleDC
52882 PUSH EAX // [EBP-20] = MaskDC
52884 PUSH [Mask]
52885 PUSH EAX
52886 CALL SelectObject
52887 PUSH EAX // [EBP-24] = Save4Mask
52889 CALL StartDC // [EBP-28] = DCfrom; [EBP-32] = Save4From
52891 PUSH [EBX].fHeight
52892 PUSH [EBX].fWidth
52893 PUSH EAX
52894 CALL CreateCompatibleBitmap
52895 PUSH EAX // [EBP-36] = MemBmp
52897 PUSH 0
52898 CALL CreateCompatibleDC
52899 PUSH EAX // [EBP-40] = MemDC
52901 PUSH dword ptr [EBP-36] //MemBmp
52902 PUSH EAX
52903 CALL SelectObject
52904 PUSH EAX // [EBP-44] = Save4Mem
52906 PUSH SRCCOPY
52907 MOV EAX, [EBP-20] //MaskDC
52908 CALL @@stretch1
52910 PUSH SRCERASE
52911 MOV EAX, [EBP-28] //DCfrom
52912 CALL @@stretch1
52914 PUSH 0
52915 PUSH dword ptr [EBP-4] //DC
52916 CALL SetTextColor
52917 PUSH EAX // [EBP-48] = crText
52919 PUSH $FFFFFF
52920 PUSH dword ptr [EBP-4] //DC
52921 CALL Windows.SetBkColor
52922 PUSH EAX // [EBP-52] = crBack
52924 PUSH SRCAND
52925 MOV EAX, [EBP-20] //MaskDC
52926 CALL @@stretch2
52928 PUSH SRCINVERT
52929 MOV EAX, [EBP-40] //MemDC
52930 CALL @@stretch2
52932 PUSH dword ptr [EBP-4] //DC
52933 CALL Windows.SetBkColor
52935 PUSH dword ptr [EBP-4] //DC
52936 CALL SetTextColor
52938 MOV ESI, offset[FinishDC]
52939 CALL ESI
52940 CALL DeleteObject // DeleteObject( MemBmp )
52942 CALL ESI
52944 CALL ESI
52945 @@to_exit:
52947 JC @@exit
52949 @@stretch1:
52950 POP ESI
52951 PUSH [EBX].fHeight
52952 PUSH [EBX].fWidth
52953 XOR EDX, EDX
52954 PUSH EDX
52955 PUSH EDX
52956 PUSH EAX
52957 PUSH [EBX].fHeight
52958 PUSH [EBX].fWidth
52959 PUSH EDX
52960 PUSH EDX
52961 PUSH dword ptr [EBP-40] //MemDC
52962 JMP @@stretch3
52964 @@stretch2:
52965 POP ESI
52966 PUSH [EBX].fHeight
52967 PUSH [EBX].fWidth
52968 PUSH 0
52969 PUSH 0
52970 PUSH EAX
52971 MOV EAX, [EBP-8] //Rect
52972 MOV EDX, [EAX].TRect.Bottom
52973 MOV ECX, [EAX].TRect.Top
52974 SUB EDX, ECX
52975 PUSH EDX
52976 MOV EDX, [EAX].TRect.Right
52977 MOV EAX, [EAX].TRect.Left
52978 SUB EDX, EAX
52979 PUSH EDX
52980 PUSH ECX
52981 PUSH EAX
52982 PUSH dword ptr [EBP-4] //DC
52983 @@stretch3:
52984 CALL StretchBlt
52985 JMP ESI
52987 @@exit:
52988 POP ESI
52989 POP EBX
52990 MOV ESP, EBP
52991 end;
52992 {$ELSE ASM_VERSION} //Pascal
52993 procedure TBitmap.StretchDrawMasked(DC: HDC; const Rect: TRect; Mask: HBitmap);
52995 DCfrom, MemDC, MaskDC: HDC;
52996 MemBmp: HBITMAP;
52997 Save4From, Save4Mem, Save4Mask: THandle;
52998 crText, crBack: TColorRef;
52999 //SavePal: HPALETTE;
53000 begin
53001 if GetHandle = 0 then Exit;
53002 fDetachCanvas( @Self );
53003 //SavePal := 0;
53005 DCfrom := CreateCompatibleDC( 0 );
53006 Save4From := SelectObject( DCfrom, fHandle );
53007 ASSERT( Save4From <> 0, 'Can not select source bitmap to DC' );
53008 MaskDC := CreateCompatibleDC( 0 );
53009 Save4Mask := SelectObject( MaskDC, Mask );
53010 ASSERT( Save4Mask <> 0, 'Can not select mask bitmap to DC' );
53011 MemDC := CreateCompatibleDC( 0 );
53012 //try
53013 MemBmp := CreateCompatibleBitmap( DCfrom, fWidth, fHeight );
53014 Save4Mem := SelectObject( MemDC, MemBmp );
53015 ASSERT( Save4Mem <> 0, 'Can not select memory bitmap to DC' );
53016 //SavePal := SelectPalette(DCfrom, SystemPalette16, False);
53017 //SelectPalette(DCfrom, SavePal, False);
53018 //if SavePal <> 0 then
53019 // SavePal := SelectPalette(MemDC, SavePal, True)
53020 //else
53021 // SavePal := SelectPalette(MemDC, SystemPalette16, True);
53022 //RealizePalette(MemDC);
53024 StretchBlt( MemDC, 0, 0, fWidth, fHeight, MaskDC, 0, 0, fWidth, fHeight, SrcCopy);
53025 StretchBlt( MemDC, 0, 0, fWidth, fHeight, DCfrom, 0, 0, fWidth, fHeight, SrcErase);
53026 crText := SetTextColor(DC, $0);
53027 crBack := Windows.SetBkColor(DC, $FFFFFF);
53028 StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top,
53029 MaskDC, 0, 0, fWidth, fHeight, SrcAnd);
53030 StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top,
53031 MemDC, 0, 0, fWidth, fHeight, SrcInvert);
53032 Windows.SetBkColor( DC, crBack);
53033 SetTextColor( DC, crText);
53035 if Save4Mem <> 0 then
53036 SelectObject( MemDC, Save4Mem );
53037 DeleteObject(MemBmp);
53038 //finally
53039 //if SavePal <> 0 then SelectPalette(MemDC, SavePal, False);
53040 DeleteDC(MemDC);
53041 SelectObject( DCfrom, Save4From );
53042 DeleteDC( DCfrom );
53043 SelectObject( MaskDC, Save4Mask );
53044 DeleteDC( MaskDC );
53045 //end;
53046 end;
53047 {$ENDIF ASM_VERSION}
53049 //[procedure ApplyBitmapBkColor2Canvas]
53050 procedure ApplyBitmapBkColor2Canvas( Sender: PBitmap );
53051 begin
53052 if Sender.fCanvas = nil then Exit;
53053 Sender.fCanvas.Brush.Color := Sender.BkColor;
53054 end;
53056 //[PROCEDURE DetachBitmapFromCanvas]
53057 {$IFDEF ASM_VERSION}
53058 procedure DetachBitmapFromCanvas( Sender: PBitmap );
53060 XOR ECX, ECX
53061 XCHG ECX, [EAX].TBitmap.fCanvasAttached
53062 JECXZ @@exit
53063 PUSH ECX
53064 MOV EAX, [EAX].TBitmap.fCanvas
53065 PUSH [EAX].TCanvas.fHandle
53066 CALL SelectObject
53067 @@exit:
53068 end;
53069 {$ELSE ASM_VERSION} //Pascal
53070 procedure DetachBitmapFromCanvas( Sender: PBitmap );
53071 begin
53072 if Sender.fCanvasAttached = 0 then Exit;
53073 SelectObject( Sender.fCanvas.fHandle, Sender.fCanvasAttached );
53074 Sender.fCanvasAttached := 0;
53075 end;
53076 {$ENDIF ASM_VERSION}
53077 //[END DetachBitmapFromCanvas]
53079 {$IFDEF ASM_VERSION}
53080 //[function TBitmap.GetCanvas]
53081 function TBitmap.GetCanvas: PCanvas;
53083 PUSH EBX
53084 MOV EBX, EAX
53085 CALL GetEmpty
53086 JZ @@exit
53087 MOV EAX, EBX
53088 CALL GetHandle
53089 TEST EAX, EAX
53090 JZ @@exit
53091 MOV ECX, [EBX].fCanvas
53092 INC ECX
53093 LOOP @@ret_Canvas
53095 MOV [EBX].fApplyBkColor2Canvas, offset[ApplyBitmapBkColor2Canvas]
53096 PUSH 0
53097 CALL CreateCompatibleDC
53098 CALL NewCanvas
53099 MOV [EBX].fCanvas, EAX
53100 MOV [EAX].TCanvas.fOnChange.TMethod.Code, offset[CanvasChanged]
53101 MOV [EAX].TCanvas.fOnChange.TMethod.Data, EBX
53102 CALL TCanvas.GetBrush
53103 XOR EDX, EDX
53104 MOV ECX, [EBX].fBkColor
53105 CALL TGraphicTool.SetInt
53107 @@ret_Canvas:
53108 MOV EAX, [EBX].fCanvas
53109 MOV ECX, [EAX].TCanvas.fHandle
53110 INC ECX
53111 LOOP @@attach_Canvas
53112 PUSH EAX
53113 MOV [EBX].fCanvasAttached, ECX
53114 PUSH ECX
53115 CALL CreateCompatibleDC
53116 XCHG EDX, EAX
53117 POP EAX
53118 CALL TCanvas.SetHandle
53120 @@attach_Canvas:
53121 MOV ECX, [EBX].fCanvasAttached
53122 INC ECX
53123 LOOP @@2
53124 PUSH [EBX].fHandle
53125 MOV EAX, [EBX].fCanvas
53126 CALL TCanvas.GetHandle
53127 PUSH EAX
53128 CALL SelectObject
53129 MOV [EBX].fCanvasAttached, EAX
53131 @@2: MOV [EBX].fDetachCanvas, offset[DetachBitmapFromCanvas]
53132 MOV EAX, [EBX].fCanvas
53133 @@exit: POP EBX
53134 end;
53135 {$ELSE ASM_VERSION} //Pascal
53136 function TBitmap.GetCanvas: PCanvas;
53137 var DC: HDC;
53138 begin
53139 Result := nil;
53140 if Empty then Exit;
53141 if GetHandle = 0 then Exit;
53142 if fCanvas = nil then
53143 begin
53144 fApplyBkColor2Canvas := ApplyBitmapBkColor2Canvas;
53145 DC := CreateCompatibleDC( 0 );
53146 fCanvas := NewCanvas( DC );
53147 fCanvas.fIsPaintDC := FALSE;
53148 fCanvas.OnChange := CanvasChanged;
53149 fCanvas.Brush.Color := fBkColor;
53150 end;
53151 Result := fCanvas;
53153 if fCanvas.fHandle = 0 then
53154 begin
53155 DC := CreateCompatibleDC( 0 );
53156 fCanvas.Handle := DC;
53157 fCanvasAttached := 0;
53158 end;
53160 if fCanvasAttached = 0 then
53161 begin
53162 fCanvasAttached := SelectObject( fCanvas.Handle, fHandle );
53163 ASSERT( fCanvasAttached <> 0, 'Can not select bitmap to DC of Canvas' );
53164 end;
53165 fDetachCanvas := DetachBitmapFromCanvas;
53166 end;
53167 {$ENDIF ASM_VERSION}
53169 {$IFDEF ASM_VERSION}
53170 //[function TBitmap.GetEmpty]
53171 function TBitmap.GetEmpty: Boolean;
53173 PUSH ECX
53174 MOV ECX, [EAX].fWidth
53175 JECXZ @@1
53176 MOV ECX, [EAX].fHeight
53177 @@1: TEST ECX, ECX
53178 POP ECX
53179 SETZ AL
53180 end;
53181 {$ELSE ASM_VERSION} //Pascal
53182 function TBitmap.GetEmpty: Boolean;
53183 begin
53184 Result := (fWidth = 0) or (fHeight = 0);
53185 ASSERT( (fWidth >= 0) and (fHeight >= 0), 'Bitmap dimensions can be negative' );
53186 end;
53187 {$ENDIF ASM_VERSION}
53189 {$IFDEF ASM_noVERSION}
53190 //[function TBitmap.GetHandle]
53191 function TBitmap.GetHandle: HBitmap;
53193 PUSH EBX
53194 MOV EBX, EAX
53195 CALL GetEmpty
53196 JZ @@exit
53197 MOV ECX, [EBX].fHandle
53198 INC ECX
53199 LOOP @@exit
53201 MOV ECX, [EBX].fDIBBits
53202 JECXZ @@exit
53204 PUSH ECX
53205 PUSH 0
53206 CALL GetDC
53207 PUSH EAX
53208 PUSH 0
53209 PUSH 0
53210 LEA EDX, [EBX].fDIBBits
53211 PUSH EDX
53212 PUSH DIB_RGB_COLORS
53213 PUSH [EBX].fDIBHeader
53214 PUSH EAX
53215 CALL CreateDIBSection
53216 MOV [EBX].fHandle, EAX
53217 PUSH 0
53218 CALL ReleaseDC
53219 POP EAX
53220 PUSH EAX
53221 MOV EDX, [EBX].fDIBBits
53222 MOV ECX, [EBX].fDIBSize
53223 CALL System.Move
53224 POP EAX
53225 CMP [EBX].fDIBAutoFree, 0
53226 JNZ @@freed
53227 CALL System.@FreeMem
53228 @@freed:MOV [EBX].fDIBAutoFree, 1
53229 XOR EAX, EAX
53230 MOV [EBX].fGetDIBPixels, EAX
53231 MOV [EBX].fSetDIBPixels, EAX
53233 @@exit: MOV EAX, [EBX].fHandle
53234 POP EBX
53235 end;
53236 {$ELSE ASM_VERSION} //Pascal
53237 function TBitmap.GetHandle: HBitmap;
53238 var OldBits: Pointer;
53239 DC0: HDC;
53240 {$IFDEF DEBUG}
53241 B: tagBitmap;
53242 {$ENDIF}
53243 begin
53244 Result := 0;
53245 if Empty then Exit;
53246 if fHandle = 0 then
53247 begin
53248 if fDIBBits <> nil then
53249 begin
53250 OldBits := fDIBBits;
53251 DC0 := GetDC( 0 );
53253 fDIBBits := nil;
53254 //fDIBHeader.bmiHeader.biCompression := 0;
53255 fHandle := CreateDIBSection( DC0, fDIBHeader^, DIB_RGB_COLORS,
53256 fDIBBits, 0, 0 );
53257 {$IFDEF DEBUG}
53258 if fHandle = 0 then
53259 ShowMessage( 'Can not create DIB section, error: ' + Int2Str( GetLastError ) +
53260 ', ' + SysErrorMessage( GetLastError ) );
53261 GetObject( fHandle, Sizeof( B ), @ B );
53262 {$ELSE}
53263 ASSERT( fHandle <> 0, 'Can not create DIB section, error: ' + Int2Str( GetLastError ) +
53264 ', ' + SysErrorMessage( GetLastError ) );
53265 {$ENDIF}
53266 ReleaseDC( 0, DC0 );
53267 if fHandle <> 0 then
53268 begin
53269 Move( OldBits^, fDIBBits^, fDIBSize );
53270 if not fDIBAutoFree then
53271 FreeMem( OldBits );
53272 fDIBAutoFree := TRUE;
53274 fGetDIBPixels := nil;
53275 fSetDIBPixels := nil;
53277 else
53278 fDIBBits := OldBits;
53279 end;
53280 end;
53281 Result := fHandle;
53282 end;
53283 {$ENDIF ASM_VERSION}
53285 //[function TBitmap.GetHandleAllocated]
53286 function TBitmap.GetHandleAllocated: Boolean;
53287 begin
53288 Result := fHandle <> 0;
53289 end;
53291 {$IFDEF ASM_VERSION}
53292 //[procedure TBitmap.LoadFromFile]
53293 procedure TBitmap.LoadFromFile(const Filename: String);
53295 PUSH EAX
53296 XCHG EAX, EDX
53297 CALL NewReadFileStream
53298 XCHG EDX, EAX
53299 POP EAX
53300 PUSH EDX
53301 CALL LoadFromStream
53302 POP EAX
53303 CALL TObj.Free
53304 end;
53305 {$ELSE ASM_VERSION} //Pascal
53306 procedure TBitmap.LoadFromFile(const Filename: String);
53307 var Strm: PStream;
53308 begin
53309 Strm := NewReadFileStream( Filename );
53310 LoadFromStream( Strm );
53311 Strm.Free;
53312 end;
53313 {$ENDIF ASM_VERSION}
53315 //[procedure TBitmap.LoadFromResourceID]
53316 procedure TBitmap.LoadFromResourceID(Inst: DWORD; ResID: Integer);
53317 begin
53318 LoadFromResourceName( Inst, MAKEINTRESOURCE( ResID ) );
53319 end;
53321 {$IFDEF ASM_VERSION}
53322 //[procedure TBitmap.LoadFromResourceName]
53323 procedure TBitmap.LoadFromResourceName(Inst: DWORD; ResName: PChar);
53325 PUSH EBX
53326 MOV EBX, EAX
53327 PUSHAD
53328 CALL Clear
53329 POPAD
53330 XOR EAX, EAX
53331 PUSH ECX
53332 MOVZX ECX, [EBX].fHandleType
53333 INC ECX
53334 LOOP @@1
53335 MOV AH, LR_CREATEDIBSECTION shr 8 // = $2000
53336 @@1: MOV AL, LR_DEFAULTSIZE // = $40
53337 POP ECX
53338 PUSH EAX
53339 PUSH 0
53340 PUSH 0
53341 PUSH IMAGE_BITMAP
53342 PUSH ECX
53343 PUSH EDX
53344 CALL LoadImage
53345 TEST EAX, EAX
53346 JZ @@exit
53347 XCHG EDX, EAX
53348 XCHG EAX, EBX
53349 CALL SetHandle
53350 @@exit: POP EBX
53351 end;
53352 {$ELSE ASM_VERSION} //Pascal
53353 procedure TBitmap.LoadFromResourceName(Inst: DWORD; ResName: PChar);
53354 var ResHandle: HBitmap;
53355 Flg: DWORD;
53356 begin
53357 Clear;
53358 //ResHandle := LoadBitmap( Inst, ResName );
53359 Flg := 0;
53360 if fHandleType = bmDIB then
53361 Flg := LR_CREATEDIBSECTION;
53362 ResHandle := LoadImage( Inst, ResName, IMAGE_BITMAP, 0, 0,
53363 LR_DEFAULTSIZE or Flg );
53364 if ResHandle = 0 then Exit;
53365 //Handle := CopyImage( ResHandle, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG );
53366 Handle := ResHandle;
53367 end;
53368 {$ENDIF ASM_VERSION}
53370 {$IFDEF F_P}
53371 type
53372 TBITMAPFILEHEADER = packed record
53373 bfType: Word;
53374 bfSize: DWORD;
53375 bfReserved1: Word;
53376 bfReserved2: Word;
53377 bfOffBits: DWORD;
53378 end;
53379 {$ENDIF}
53381 {$IFDEF ASM_noVERSION} // error + 16Colors->swap(Gray,Silver) + Core
53382 //[procedure TBitmap.LoadFromStream]
53383 procedure TBitmap.LoadFromStream(Strm: PStream);
53384 type tBFH = TBitmapFileHeader;
53385 tBIH = TBitmapInfoHeader;
53386 const szBIH = Sizeof( tBIH );
53387 szBFH = Sizeof( tBFH );
53389 PUSH EBX
53390 PUSH ESI
53391 MOV EBX, EAX
53392 PUSH EDX
53393 CALL Clear
53394 POP ESI
53395 MOV EAX, ESI
53396 CALL TStream.GetPosition
53397 PUSH EAX // [EBP+4] = Strm.Pos (starting pos)
53398 PUSH EBP
53399 MOV EBP, ESP
53400 ADD ESP, -(szBIH + szBFH)
53402 // reading bitmap
53403 XOR ECX, ECX
53404 MOV [EBX].fHandleType, CL
53405 MOV CL, szBFH
53406 MOV EDX, ESP
53407 PUSH ECX
53408 MOV EAX, ESI
53409 CALL TStream.Read
53410 POP ECX
53411 SUB ECX, EAX
53412 JNZ @@eread1
53414 CMP [ESP].tBFH.bfType, $4D42
53415 JE @@1
53416 MOV EDX, [EBP+4]
53417 MOV EAX, ESI
53418 CALL TStream.Seek
53419 XOR EAX, EAX
53420 XOR EDX, EDX
53421 JMP @@2
53423 @@1:
53424 MOV EDX, [ESP].tBFH.bfSize
53425 MOV EAX, [ESP].tBFH.bfOffBits
53426 @@2:
53427 PUSH EDX // Push Size
53428 PUSH EAX // Push Off
53429 XOR ECX, ECX
53430 MOV CL, szBIH
53431 LEA EDX, [EBP-szBIH]
53432 MOV EAX, ESI
53433 PUSH ECX
53434 CALL TStream.Read // read BIH
53435 POP ECX
53436 @@eread1:
53437 XOR ECX, EAX
53438 JNZ @@eread
53440 MOVZX EAX, [EBP-szBIH].tBIH.biBitCount
53441 MOVZX EDX, [EBP-szBIH].tBIH.biPlanes
53442 MUL EDX
53443 CALL Bits2PixelFormat
53444 {$IFDEF PARANOIA}
53445 DB $3C, pf15bit
53446 {$ELSE}
53447 CMP AL, pf15bit
53448 {$ENDIF}
53449 JNZ @@no15bit
53450 CMP [EBP-szBIH].tBIH.biCompression, 0
53451 JZ @@no15bit
53452 INC AL // AL = pf16bit
53453 @@no15bit:
53454 MOV [EBX].fNewPixelFormat, AL
53456 MOV EAX, szBIH + 1024
53457 CALL System.@GetMem
53458 MOV [EBX].fDIBHeader, EAX
53459 XCHG EDX, EAX
53460 LEA EAX, [EBP-szBIH]
53461 XOR ECX, ECX
53462 MOV CL, szBIH
53463 CALL System.Move
53465 MOV EAX, [EBP-szBIH].tBIH.biWidth
53466 MOV [EBX].fWidth, EAX
53467 MOV EAX, [EBP-szBIH].tBIH.biHeight
53468 TEST EAX, EAX
53469 JGE @@20
53470 NEG EAX
53471 @@20: MOV [EBX].fHeight, EAX
53473 MOV EAX, EBX
53474 CALL GetScanLineSize
53475 MOV EDX, [EBX].fHeight
53476 MUL EDX
53477 MOV [EBX].fDIBSize, EAX
53478 CALL AllocMem
53479 MOV [EBX].fDIBBits, EAX
53481 MOVZX EAX, [EBP-szBIH].tBIH.biBitCount
53482 {$IFDEF PARANOIA}
53483 DB $3C, 8
53484 {$ELSE}
53485 CMP AL, 8
53486 {$ENDIF}
53487 JA @@3
53488 MOV AL, 4
53489 MOVZX ECX, [EBP-szBIH].tBIH.biBitCount
53490 SAL EAX, CL
53491 XCHG ECX, EAX
53492 @@3:
53493 CMP [EBX].TBitmap.fNewPixelFormat, pf16bit
53494 JNE @@30
53495 XOR ECX, ECX
53496 MOV CL, 12 // ColorCount = 12
53497 @@30:
53498 POP EAX // EAX = off
53499 TEST EAX, EAX
53500 JLE @@4
53501 SUB EAX, szBFH + szBIH
53502 CMP EAX, ECX
53503 JZ @@4
53504 XCHG ECX, EAX
53505 @@4:
53506 JECXZ @@5
53507 PUSH ECX
53508 MOV EDX, [EBX].fDIBHeader
53509 ADD EDX, szBIH
53510 MOV EAX, ESI
53511 CALL TStream.Read
53512 POP ECX
53513 XOR EAX, ECX
53514 JNZ @@eread
53515 @@5:
53516 MOV ECX, [EBX].fDIBSize
53517 @@7:
53518 PUSH ECX
53519 MOV EAX, ESI
53520 CALL TStream.GetPosition
53521 PUSH EAX
53522 MOV EAX, ESI
53523 CALL TStream.GetSize
53524 POP EDX
53525 SUB EAX, EDX
53526 POP ECX // Size = fDIBSize
53527 CMP EAX, ECX // Strm.Size - Strm.Position > Size ?
53528 JL @@8
53529 XCHG ECX, EAX
53530 @@8:
53531 // ++++++++++++++ 26-Oct-2003 VK see comment in Pascal
53532 MOV EAX, [EBX].fDIBSize
53533 CMP ECX, EAX
53534 JGE @@9
53535 SUB EAX, ECX
53536 PUSH EAX
53537 MOV EAX, ESI
53538 PUSH ECX
53539 CALL TStream.GetPosition
53540 POP ECX
53541 POP EDX
53542 CMP EDX, EAX
53543 JG @@9
53545 MOV EAX, ESI
53546 NEG EDX
53547 XOR ECX, ECX
53548 INC ECX
53549 CALL TStream.Seek
53551 MOV ECX, [EBX].fDIBSize
53552 @@9:
53553 // ++++++++++++++
53555 PUSH ECX
53556 MOV EDX, [EBX].fDIBBits
53557 MOV EAX, ESI
53558 CALL TStream.Read
53559 POP ECX
53560 XOR EAX, ECX
53561 POP EAX // Strm.Size - Position
53562 POP ECX // fDIBSize
53563 //JNZ @@eread
53565 // end of reading bitmap
53566 @@eread:
53567 MOV ESP, EBP
53568 POP EBP
53569 POP EDX
53570 JZ @@exit
53571 // not success:
53572 XCHG EAX, ESI
53573 XOR ECX, ECX // ECX = spBegin
53574 CALL TStream.Seek
53575 XCHG EAX, EBX
53576 CALL Clear
53577 @@exit: POP ESI
53578 POP EBX
53579 end;
53580 {$ELSE ASM_VERSION} //Pascal
53581 procedure TBitmap.LoadFromStream(Strm: PStream);
53582 type
53583 TColorsArray = array[ 0..15 ] of TColor;
53584 PColorsArray = ^TColorsArray;
53585 PColor = ^TColor;
53586 var Pos : Integer;
53587 BFH : TBitmapFileHeader;
53589 function ReadBitmap : Boolean;
53590 var Size, Size1: Integer;
53591 BCH: TBitmapCoreHeader;
53592 RGBSize: DWORD;
53593 C: PColor;
53594 Off, HdSz, ColorCount: DWORD;
53595 begin
53596 fHandleType := bmDIB;
53597 Result := False;
53598 if Strm.Read( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;
53599 Off := 0; Size := 0;
53600 if BFH.bfType <> $4D42 then
53601 Strm.Seek( Pos, spBegin )
53602 else
53603 begin
53604 Off := BFH.bfOffBits - Sizeof( BFH );
53605 Size := BFH.bfSize; // don't matter, just <> 0 is good
53606 //Size := Min( BFH.bfSize, Strm.Size - Strm.Position );
53607 end;
53608 RGBSize := 4;
53609 HdSz := Sizeof( TBitmapInfoHeader );
53610 fDIBHeader := AllocMem( 256*sizeof(TRGBQuad) + HdSz );
53611 if Strm.Read( fDIBHeader.bmiHeader.biSize, Sizeof( DWORD ) ) <> Sizeof( DWORD ) then
53612 Exit;
53613 if fDIBHeader.bmiHeader.biSize = HdSz then
53614 begin
53615 if Strm.Read( fDIBHeader.bmiHeader.biWidth, HdSz - Sizeof( DWORD ) ) <>
53616 HdSz - Sizeof( DWORD ) then
53617 Exit;
53619 else
53620 if fDIBHeader.bmiHeader.biSize = Sizeof( TBitmapCoreHeader ) then
53621 begin
53622 RGBSize := 3;
53623 HdSz := Sizeof( TBitmapCoreHeader );
53624 if Strm.Read( BCH.bcWidth, HdSz - Sizeof( DWORD ) ) <>
53625 HdSz - Sizeof( DWORD ) then
53626 Exit;
53627 fDIBHeader.bmiHeader.biSize := Sizeof( TBitmapInfoHeader );
53628 fDIBHeader.bmiHeader.biWidth := BCH.bcWidth;
53629 fDIBHeader.bmiHeader.biHeight := BCH.bcHeight;
53630 fDIBHeader.bmiHeader.biPlanes := BCH.bcPlanes;
53631 fDIBHeader.bmiHeader.biBitCount := BCH.bcBitCount;
53633 else Exit;
53634 fNewPixelFormat := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount
53635 * fDIBHeader.bmiHeader.biPlanes );
53636 if (fNewPixelFormat = pf15bit) and (fDIBHeader.bmiHeader.biCompression <> BI_RGB) then
53637 begin
53638 ASSERT( fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS, 'Unsupported bitmap format' );
53639 //fNewPixelFormat := pf16bit;
53640 end;
53641 fWidth := fDIBHeader.bmiHeader.biWidth;
53642 ASSERT( fWidth > 0, 'Bitmap width must be > 0' );
53643 fHeight := Abs(fDIBHeader.bmiHeader.biHeight);
53644 ASSERT( fHeight > 0, 'Bitmap height must be > 0' );
53646 fDIBSize := ScanLineSize * fHeight;
53647 fDIBBits := AllocMem( fDIBSize );
53648 ASSERT( fDIBBits <> nil, 'No memory' );
53650 ColorCount := 0;
53651 if fDIBHeader.bmiHeader.biBitCount <= 8 then
53652 ColorCount := (1 shl fDIBHeader.bmiHeader.biBitCount) * RGBSize
53653 else if fNewPixelFormat in [pf15bit,pf16bit] then
53654 ColorCount := 12;
53656 if Off > 0 then
53657 begin
53658 Off := Off - HdSz;
53659 if (Off <> ColorCount) then
53660 if not(fNewPixelFormat in [pf15bit,pf16bit])
53661 or (Off = 0) //+++ to fix loading 15- and 16-bit bmps with mask omitted
53662 then
53663 ColorCount := Off;
53664 end;
53665 if ColorCount <> 0 then
53666 begin
53667 if Off >= ColorCount then
53668 Off := Off - ColorCount;
53669 if RGBSize = 4 then
53670 begin
53671 if Strm.Read( fDIBheader.bmiColors[ 0 ], ColorCount )
53672 <> DWORD( ColorCount ) then Exit;
53674 else
53675 begin
53676 C := @ fDIBHeader.bmiColors[ 0 ];
53677 while ColorCount > 0 do
53678 begin
53679 if Strm.Read( C^, RGBSize ) <> RGBSize then Exit;
53680 Dec( ColorCount, RGBSize );
53681 Inc( C );
53682 end;
53683 end;
53684 end;
53685 if Off > 0 then
53686 Strm.Seek( Off, spCurrent );
53688 if Size = 0 then
53689 Size := fDIBSize //ScanLineSize * fHeight
53690 else
53691 Size := Min( {Size - Sizeof( TBitmapFileHeader ) - Sizeof( TBitmapInfoHeader )
53692 - ColorCount} fDIBSize, Strm.Size - Strm.Position );
53694 Size1 := Min( Size, fDIBSize );
53696 // +++++++++++++++++++ 26-Oct-2003 by VK
53697 if (Size1 < fDIBSize)
53698 and (DWORD( fDIBSize - Size1 ) <= Strm.Position) then
53699 begin
53700 Strm.Seek( Size1 - fDIBSize, spCurrent );
53701 Size1 := fDIBSize;
53702 end;
53703 // +++++++++++++++++++ to fix some "incorrect" bitmaps while loading
53705 if Strm.Read( fDIBBits^, Size1 ) <> DWORD( Size1 ) then Exit;
53706 if Size > Size1 then
53707 Strm.Seek( Size - Size1, spCurrent );
53709 Result := True;
53710 end;
53711 {var ColorsArray: PColorsArray;
53712 DC: HDC;
53713 Old: HBitmap;}
53714 begin
53715 Clear;
53716 Pos := Strm.Position;
53717 if not ReadBitmap then
53718 begin
53719 Strm.Seek( Pos, spBegin );
53720 Clear;
53721 end;
53722 {else
53723 begin
53724 if (fDIBBits <> nil) and (fDIBHeader.bmiHeader.biBitCount >= 4) then
53725 begin
53726 ColorsArray := @ fDIBHeader.bmiColors[ 0 ];
53727 if ColorsArray[ 7 ] = $C0C0C0 then
53728 if ColorsArray[ 8 ] = $808080 then
53729 if GetHandle <> 0 then
53730 begin
53731 DC := CreateCompatibleDC( 0 );
53732 Old := SelectObject( DC, fHandle );
53733 SetDIBColorTable( DC, 0, 16, fDIBHeader.bmiColors[ 0 ] );
53734 SelectObject( DC, Old );
53735 DeleteDC( DC );
53736 end;
53737 end;
53738 end;}
53739 end;
53740 {$ENDIF ASM_VERSION}
53742 ////////////////// bitmap RLE-decoding and loading - by Vyacheslav A. Gavrik
53744 //[procedure DecodeRLE4]
53745 procedure DecodeRLE4(Bmp:PBitmap;Data:Pointer); // by Vyacheslav A. Gavrik
53746 procedure OddMove(Src,Dst:PByte;Size:Integer);
53747 begin
53748 if Size=0 then Exit;
53749 repeat
53750 Dst^:=(Dst^ and $F0)or(Src^ shr 4);
53751 Inc(Dst);
53752 Dst^:=(Dst^ and $0F)or(Src^ shl 4);
53753 Inc(Src);
53754 Dec(Size);
53755 until Size=0;
53756 end;
53757 procedure OddFill(Mem:PByte;Size,Value:Integer);
53758 begin
53759 Value:=(Value shr 4)or(Value shl 4);
53760 Mem^:=(Mem^ and $F0)or(Value and $0F);
53761 Inc(Mem);
53762 if Size>1 then FillChar(Mem^,Size,Value);
53763 Mem^:=(Mem^ and $0F)or(Value and $F0);
53764 end;
53766 pb: PByte;
53767 x,y,z,i: Integer;
53768 begin
53769 pb:=Data; x:=0; y:=0;
53770 if Bmp.fScanLineSize = 0 then
53771 Bmp.ScanLineSize;
53772 while y<Bmp.Height do
53773 begin
53774 if pb^=0 then
53775 begin
53776 Inc(pb);
53777 z:=pb^;
53778 case pb^ of
53779 0: begin
53780 Inc(y);
53781 x:=0;
53782 end;
53783 1: Break;
53784 2: begin
53785 Inc(pb); Inc(x,pb^);
53786 Inc(pb); Inc(y,pb^);
53787 end;
53788 else
53789 begin
53790 Inc(pb);
53791 i:=(z+1)shr 1;
53792 if(z and 2)=2 then Inc(i);
53793 if((x and 1)=1)and(x+i<Bmp.Width)then
53794 OddMove(pb,@PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],i)
53795 else
53796 Move(pb^,PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],i);
53797 Inc(pb,i-1);
53798 Inc(x,z);
53799 end;
53800 end;
53801 end else
53802 begin
53803 z:=pb^;
53804 Inc(pb);
53805 if((x and 1)=1)and(x+z<Bmp.Width)then
53806 OddFill(@PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],z shr 1,pb^)
53807 else
53808 FillChar(PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],z shr 1,pb^);
53809 Inc(x,z);
53810 end;
53811 Inc(pb);
53812 end;
53813 end;
53815 //[procedure DecodeRLE8]
53816 procedure DecodeRLE8(Bmp:PBitmap;Data:Pointer); // by Vyacheslav A. Gavrik
53818 pb: PByte;
53819 x,y,z,i: Integer;
53820 begin
53821 pb:=Data; y:=0; x:=0;
53822 if Bmp.fScanLineSize = 0 then
53823 Bmp.ScanLineSize;
53825 while y<Bmp.Height do
53826 begin
53827 if pb^=0 then
53828 begin
53829 Inc(pb);
53830 case pb^ of
53831 0: begin
53832 Inc(y);
53833 x:=0;
53834 end;
53835 1: Break;
53836 2: begin
53837 Inc(pb); Inc(x,pb^);
53838 Inc(pb); Inc(y,pb^);
53839 end;
53840 else
53841 begin
53842 i:=pb^;
53843 z:=(i+1)and(not 1);
53844 Inc(pb);
53845 Move(pb^,PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x],z);
53846 Inc(pb,z-1);
53847 Inc(x,i);
53848 end;
53849 end;
53850 end else
53851 begin
53852 i:=pb^; Inc(pb);
53853 FillChar(PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x],i,pb^);
53854 Inc(x,i);
53855 end;
53856 Inc(pb);
53857 end;
53858 end;
53860 //[function TBitmap.LoadFromFileEx]
53861 function TBitmap.LoadFromFileEx(const Filename: String): Boolean; // by Vyacheslav A. Gavrik
53862 var Strm: PStream;
53863 begin
53864 Strm := NewReadFileStream( Filename );
53865 Result := LoadFromStreamEx(Strm);
53866 Strm.Free;
53867 end;
53869 //[function TBitmap.LoadFromStreamEx]
53870 function TBitmap.LoadFromStreamEx(Strm: PStream): Boolean; // by Vyacheslav A. Gavrik
53871 var Pos : Integer;
53873 function ReadBitmap : Boolean;
53874 var Off, Size, ColorCount: Integer;
53875 BFH : TBitmapFileHeader;
53876 BFHValid: Boolean;
53877 Buffer: Pointer;
53878 begin
53879 fHandleType := bmDIB;
53880 Result := False;
53881 BFHValid := FALSE;
53882 if Strm.Read( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;
53883 Off := 0; Size := 0;
53884 if BFH.bfType <> $4D42 then
53885 Strm.Seek( Pos, spBegin )
53886 else
53887 begin
53888 BFHValid := TRUE;
53889 Off := BFH.bfOffBits;
53890 Size := Strm.GetSize;
53891 end;
53892 GetMem( fDIBHeader, 256*sizeof(TRGBQuad) + sizeof(TBitmapInfoHeader) );
53893 if Strm.Read( fDIBHeader^, Sizeof(TBitmapInfoHeader) ) <> Sizeof(TBitmapInfoHeader) then
53894 Exit;
53895 //if fDIBHeader.bmiHeader.biCompression = BI_RGB then
53896 {if fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS then
53897 //BI_RGB here????
53898 Strm.Read( fDIBHeader.bmiColors[ 0 ], 3 * Sizeof( DWORD ) );}
53900 fNewPixelFormat := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount
53901 * fDIBHeader.bmiHeader.biPlanes );
53903 fWidth := fDIBHeader.bmiHeader.biWidth;
53904 ASSERT( fWidth > 0, 'Bitmap width must be > 0' );
53905 fHeight := Abs(fDIBHeader.bmiHeader.biHeight);
53906 ASSERT( fHeight > 0, 'Bitmap height must be > 0' );
53908 fDIBSize := ScanLineSize * fHeight;
53909 GetMem( fDIBBits, fDIBSize );
53910 ASSERT( fDIBBits <> nil, 'No memory' );
53911 ASSERT( (fDIBHeader.bmiHeader.biCompression and
53912 (BI_RLE8 or BI_RLE4 or BI_RLE8 or BI_BITFIELDS) <> 0) or
53913 (fDIBHeader.bmiHeader.biCompression = BI_RGB),
53914 'Unknown compression algorithm');
53916 ColorCount := 0;
53917 if fDIBHeader.bmiHeader.biBitCount <= 8 then
53918 ColorCount := (1 shl fDIBHeader.bmiHeader.biBitCount) * Sizeof( TRGBQuad )
53919 else if fNewPixelFormat in [ pf16bit ] then
53920 ColorCount := 12;
53922 if Off > 0 then
53923 begin
53924 Off := Off - SizeOf( TBitmapFileHeader ) - Sizeof( TBitmapInfoHeader );
53925 if Off <> ColorCount then
53926 ColorCount := Off;
53927 end;
53928 if fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS then
53929 begin
53930 PDWORD( DWORD( @ fDIBHeader.bmiColors[ 0 ] ) + 8 )^ := ( $00001F );
53931 PDWORD( DWORD( @ fDIBHeader.bmiColors[ 0 ] ) + 4 )^ := ( $0007E0 );
53932 TColor( fDIBHeader.bmiColors[ 0 ] ) := ( $00F800 );
53933 end;
53935 if ColorCount <> 0 then
53936 if Strm.Read( fDIBheader.bmiColors[ 0 ], ColorCount )
53937 <> DWORD( ColorCount ) then Exit;
53939 if not BFHValid then
53940 Size := fDIBSize
53941 else
53942 if(fDIBHeader.bmiHeader.biCompression = BI_RLE8)
53943 or (fDIBHeader.bmiHeader.biCompression=BI_RLE4) then
53944 Size := BFH.bfSize - BFH.bfOffBits
53945 else
53946 begin
53947 if Integer( Strm.Size - BFH.bfOffBits) - Pos > Integer(Size) then
53948 Size := fDIBSize
53949 else
53950 Size := Strm.Size - BFH.bfOffBits - DWORD( Pos );
53951 end;
53953 if (fDIBHeader.bmiHeader.biCompression = BI_RGB) or
53954 (fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS) then
53955 begin
53956 if Strm.Read( fDIBBits^, Size ) <> DWORD( Size ) then
53957 //Exit;
53959 else
53960 begin
53961 GetMem(Buffer,Size);
53962 if Strm.Read(Buffer^,Size) <> DWORD( Size ) then Exit;
53964 if fDIBHeader.bmiHeader.biCompression=BI_RLE8 then
53965 DecodeRLE8(@Self,Buffer)
53966 else
53967 DecodeRLE4(@Self,Buffer);
53969 fDIBHeader.bmiHeader.biCompression := BI_RGB;
53970 FreeMem(Buffer);
53971 end;
53973 Result := True;
53974 end;
53975 begin
53976 Clear;
53977 Pos := Strm.Position;
53978 result := ReadBitmap;
53979 if not result then
53980 begin
53981 Strm.Seek( Pos, spBegin );
53982 Clear;
53983 end;
53984 end;
53986 ///////////////////////////
53988 {$IFDEF ASM_VERSION}
53989 //[function TBitmap.ReleaseHandle]
53990 function TBitmap.ReleaseHandle: HBitmap;
53992 PUSH EBX
53993 MOV EBX, EAX
53994 XOR EDX, EDX
53995 CALL SetHandleType
53996 MOV EAX, EBX
53997 CALL GetHandle
53998 TEST EAX, EAX
53999 JZ @@exit
54001 CMP [EBX].fDIBAutoFree, 0
54002 JZ @@1
54003 MOV EAX, [EBX].fDIBSize
54004 PUSH EAX
54005 CALL System.@GetMem
54006 MOV EDX, EAX
54007 XCHG EAX, [EBX].fDIBBits
54008 POP ECX
54009 CALL System.Move
54010 @@1:
54011 XOR EAX, EAX
54012 MOV [EBX].fDIBAutoFree, AL
54013 XCHG EAX, [EBX].fHandle
54015 @@exit: POP EBX
54016 end;
54017 {$ELSE ASM_VERSION} //Pascal
54018 function TBitmap.ReleaseHandle: HBitmap;
54019 var OldBits: Pointer;
54020 begin
54021 HandleType := bmDIB;
54022 Result := GetHandle;
54023 if Result = 0 then Exit; // only when bitmap is empty
54024 if fDIBAutoFree then
54025 begin
54026 OldBits := fDIBBits;
54027 GetMem( fDIBBits, fDIBSize );
54028 Move( OldBits^, fDIBBits^, fDIBSize );
54029 fDIBAutoFree := FALSE;
54030 end;
54031 fHandle := 0;
54032 end;
54033 {$ENDIF ASM_VERSION}
54035 {$IFDEF ASM_VERSION}
54036 //[procedure TBitmap.SaveToFile]
54037 procedure TBitmap.SaveToFile(const Filename: String);
54039 PUSH EAX
54040 PUSH EDX
54041 CALL GetEmpty
54042 POP EAX
54043 JZ @@exit
54044 CALL NewWriteFileStream
54045 XCHG EDX, EAX
54046 POP EAX
54047 PUSH EDX
54048 CALL SaveToStream
54049 POP EAX
54050 CALL TObj.Free
54051 PUSH EAX
54052 @@exit: POP EAX
54053 end;
54054 {$ELSE ASM_VERSION} //Pascal
54055 procedure TBitmap.SaveToFile(const Filename: String);
54056 var Strm: PStream;
54057 begin
54058 if Empty then Exit;
54059 Strm := NewWritefileStream( Filename );
54060 SaveToStream( Strm );
54061 Strm.Free;
54062 end;
54063 {$ENDIF ASM_VERSION}
54065 {$IFDEF ASM_VERSION}
54066 //[procedure TBitmap.SaveToStream]
54067 procedure TBitmap.SaveToStream(Strm: PStream);
54068 type tBFH = TBitmapFileHeader;
54069 tBIH = TBitmapInfoHeader;
54070 const szBIH = Sizeof( tBIH );
54071 szBFH = Sizeof( tBFH );
54073 PUSH EBX
54074 PUSH ESI
54075 MOV EBX, EAX
54076 MOV ESI, EDX
54077 CALL GetEmpty
54078 JZ @@exit
54079 MOV EAX, ESI
54080 CALL TStream.GetPosition
54081 PUSH EAX
54083 MOV EAX, EBX
54084 XOR EDX, EDX // EDX = bmDIB
54085 CALL SetHandleType
54086 XOR EAX, EAX
54087 MOV EDX, [EBX].fDIBHeader
54088 MOVZX ECX, [EDX].TBitmapInfoHeader.biBitCount
54089 CMP CL, 8
54090 JG @@1
54091 MOV AL, 4
54092 SHL EAX, CL
54093 @@1:
54094 PUSH EAX // ColorsSize
54095 LEA ECX, [EAX + szBFH + szBIH]
54096 CMP [EDX].TBitmapInfoHeader.biCompression, 0
54097 JZ @@10
54098 ADD ECX, 74
54099 @@10:
54100 PUSH ECX // BFH.bfOffBits
54101 PUSH 0
54102 ADD ECX, [EBX].fDIBSize
54103 PUSH ECX
54104 MOV CX, $4D42
54105 PUSH CX
54106 XOR ECX, ECX
54107 MOV EDX, ESP
54108 MOV CL, szBFH
54109 PUSH ECX
54110 MOV EAX, ESI
54111 CALL TStream.Write
54112 POP ECX
54113 ADD ESP, szBFH
54114 XOR EAX, ECX
54115 POP ECX // ColorsSize
54116 JNZ @@ewrite
54118 MOV EDX, [EBX].fDIBHeader
54119 CMP [EDX].TBitmapInfoHeader.biCompression, 0
54120 JZ @@11
54121 ADD ECX, 74
54122 @@11:
54124 ADD ECX, szBIH
54125 PUSH ECX
54126 MOV EAX, ESI
54127 CALL TStream.Write
54128 POP ECX
54129 XOR EAX, ECX
54130 JNZ @@ewrite
54132 MOV ECX, [EBX].fDIBSize
54133 MOV EDX, [EBX].fDIBBits
54134 MOV EAX, ESI
54135 PUSH ECX
54136 CALL TStream.Write
54137 POP ECX
54138 XOR EAX, ECX
54140 @@ewrite:
54141 POP EDX
54142 JZ @@exit
54143 XCHG EAX, ESI
54144 XOR ECX, ECX
54145 CALL TStream.Seek
54146 @@exit:
54147 POP ESI
54148 POP EBX
54149 end;
54150 {$ELSE ASM_VERSION} //Pascal
54151 procedure TBitmap.SaveToStream(Strm: PStream);
54152 var BFH : TBitmapFileHeader;
54153 Pos : Integer;
54154 function WriteBitmap : Boolean;
54155 var ColorsSize, BitsSize, Size : Integer;
54156 begin
54157 Result := False;
54158 if Empty then Exit;
54159 HandleType := bmDIB; // convert to DIB if DDB
54160 FillChar( BFH, Sizeof( BFH ), 0 );
54161 ColorsSize := 0;
54162 with fDIBHeader.bmiHeader do
54163 if biBitCount <= 8 then
54164 ColorsSize := (1 shl biBitCount) * Sizeof( TRGBQuad )
54165 {else
54166 if biCompression <> 0 then
54167 ColorsSize := 12};
54168 BFH.bfOffBits := Sizeof( BFH ) + Sizeof( TBitmapInfoHeader ) + ColorsSize;
54169 BitsSize := fDIBSize; //ScanLineSize * fHeight;
54170 BFH.bfSize := BFH.bfOffBits + DWord( BitsSize );
54171 BFH.bfType := $4D42; // 'BM';
54172 if fDIBHeader.bmiHeader.biCompression <> 0 then
54173 begin
54174 ColorsSize := 12 + 16*sizeof(TRGBQuad);
54175 Inc( BFH.bfOffBits, ColorsSize );
54176 end;
54177 if Strm.Write( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;
54178 Size := Sizeof( TBitmapInfoHeader ) + ColorsSize;
54179 if Strm.Write( fDIBHeader^, Size ) <> DWORD(Size) then Exit;
54180 if Strm.Write( fDIBBits^, BitsSize ) <> DWord( BitsSize ) then Exit;
54181 Result := True;
54182 end;
54183 begin
54184 Pos := Strm.Position;
54185 if not WriteBitmap then
54186 Strm.Seek( Pos, spBegin );
54187 end;
54188 {$ENDIF ASM_VERSION}
54190 {$IFDEF ASM_VERSION}
54191 //[procedure TBitmap.SetHandle]
54192 procedure TBitmap.SetHandle(const Value: HBitmap);
54193 const szB = sizeof( tagBitmap );
54195 PUSH EAX
54196 PUSH EDX
54197 CALL Clear
54198 POP ECX
54199 JECXZ @@exit
54200 PUSH ECX
54201 ADD ESP, -szB
54202 PUSH ESP
54203 PUSH szB
54204 PUSH ECX
54205 CALL GetObject
54206 POP EDX
54207 POP EDX
54208 POP ECX
54209 ADD ESP, 12
54210 TEST EAX, EAX
54211 POP EAX
54212 JZ @@exit
54213 XCHG EAX, [ESP]
54214 MOV [EAX].fWidth, EDX
54215 MOV [EAX].fHeight, ECX
54216 POP EDX
54217 MOV [EAX].fHandle, EDX
54218 MOV [EAX].fHandleType, 1
54219 PUSH EAX
54220 @@exit: POP EAX
54221 end;
54222 {$ELSE ASM_VERSION} //Pascal
54223 procedure TBitmap.SetHandle(const Value: HBitmap);
54224 var B: tagBitmap;
54225 begin
54226 Clear;
54227 if Value = 0 then Exit;
54228 if GetObject( Value, Sizeof( B ), @B ) = 0 then Exit;
54229 fHandle := Value;
54230 fWidth := B.bmWidth;
54231 fHeight := B.bmHeight;
54232 fHandleType := bmDDB;
54233 end;
54234 {$ENDIF ASM_VERSION}
54236 //[procedure TBitmap.SetWidth]
54237 procedure TBitmap.SetWidth(const Value: Integer);
54238 begin
54239 if fWidth = Value then Exit;
54240 fWidth := Value;
54241 FormatChanged;
54242 end;
54244 {$IFDEF ASM_VERSION}
54245 //[procedure TBitmap.SetHeight]
54246 procedure TBitmap.SetHeight(const Value: Integer);
54248 CMP EDX, [EAX].fHeight
54249 JE @@exit
54250 PUSHAD
54251 XOR EDX, EDX
54252 INC EDX
54253 CALL SetHandleType
54254 POPAD
54255 MOV [EAX].fHeight, EDX
54256 CALL FormatChanged
54257 @@exit:
54258 end;
54259 {$ELSE ASM_VERSION} //Pascal
54260 procedure TBitmap.SetHeight(const Value: Integer);
54261 begin
54262 if fHeight = Value then Exit;
54264 HandleType := bmDDB;
54265 // Not too good, but provides correct changing of height
54266 // preserving previous image
54268 fHeight := Value;
54269 FormatChanged;
54270 end;
54271 {$ENDIF ASM_VERSION}
54273 {$IFDEF ASM_VERSION}
54274 //[procedure TBitmap.SetPixelFormat]
54275 procedure TBitmap.SetPixelFormat(Value: TPixelFormat);
54277 PUSH EBX
54278 MOV EBX, EAX
54279 //////////////////////
54280 CALL GetEmpty // if Empty then Exit;
54281 JZ @@exit //
54282 MOV EAX, EBX //
54283 //////////////////////
54284 PUSH EDX
54285 CALL GetPixelFormat
54286 POP EDX
54287 CMP EAX, EDX
54288 JE @@exit
54289 TEST EDX, EDX
54290 MOV EAX, EBX
54291 JNE @@2
54292 // Value = pfDevice (=0)
54293 POP EBX
54294 INC EDX // EDX = bmDDB
54295 JMP SetHandleType
54296 @@2:
54297 MOV [EBX].fNewPixelFormat, DL
54298 CMP DL, pf16bit
54299 JNZ @@3
54300 DEC EDX
54301 @@3: PUSH EDX
54302 XOR EDX, EDX
54303 CALL SetHandleType
54304 MOV EAX, [EBX].fDIBHeader
54305 MOVZX EAX, [EAX].TBitmapInfoHeader.biBitCount
54306 CALL Bits2PixelFormat
54307 POP EDX
54308 CMP AL, DL
54309 XCHG EAX, EBX
54310 @@exit:
54311 POP EBX
54312 JNE FormatChanged
54313 end;
54314 {$ELSE ASM_VERSION} //Pascal
54315 procedure TBitmap.SetPixelFormat(Value: TPixelFormat);
54316 begin
54317 if PixelFormat = Value then Exit;
54318 if Empty then Exit;
54319 if Value = pfDevice then
54320 HandleType := bmDDB
54321 else
54322 begin
54323 fNewPixelFormat := Value;
54324 //if Value = pf16bit then Value := pf15bit;
54325 HandleType := bmDIB;
54326 if Value <> Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount ) then
54327 FormatChanged;
54328 end;
54329 end;
54330 {$ENDIF ASM_VERSION}
54332 //[FUNCTION CalcScanLineSize]
54333 {$IFDEF ASM_VERSION}
54334 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;
54336 MOVZX EDX, [EAX].TBitmapInfoHeader.biBitCount
54337 MOV EAX, [EAX].TBitmapInfoHeader.biWidth
54338 MUL EDX
54339 ADD EAX, 31
54340 SHR EAX, 3
54341 AND EAX, -4
54342 end;
54343 {$ELSE ASM_VERSION} //Pascal
54344 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;
54345 begin
54346 //Result := ((Header.biBitCount * Header.biWidth + 31)
54347 // shr 5) * 4;
54348 Result := ((Header.biBitCount * Header.biWidth + 31) shr 3) and $FFFFFFFC;
54349 end;
54350 {$ENDIF ASM_VERSION}
54351 //[END CalcScanLineSize]
54353 //[PROCEDURE FillBmpWithBkColor]
54354 {$IFDEF ASM_VERSION}
54355 procedure FillBmpWithBkColor( Bmp: PBitmap; DC2: HDC; oldWidth, oldHeight: Integer );
54357 PUSH EBX
54358 PUSH ESI
54359 XCHG EAX, EBX
54360 PUSH EDX // [EBP-12] = DC2
54361 PUSH ECX // [EBP-16] = oldWidth
54362 MOV EAX, [EBX].TBitmap.fBkColor
54363 CALL Color2RGB
54364 TEST EAX, EAX
54365 JZ @@exit
54366 XCHG ESI, EAX // ESI = Color2RGB( Bmp.fBkColor )
54367 MOV EAX, EBX
54368 CALL TBitmap.GetHandle
54369 TEST EAX, EAX
54370 JZ @@exit
54371 PUSH EAX //fHandle
54372 PUSH dword ptr [EBP-12] //DC2
54373 CALL SelectObject
54374 PUSH EAX // [EBP-20] = oldBmp
54375 PUSH ESI
54376 CALL CreateSolidBrush
54377 XCHG ESI, EAX // ESI = Br
54378 PUSH [EBX].TBitmap.fHeight
54379 PUSH [EBX].TBitmap.fWidth
54380 MOV EAX, [oldHeight]
54381 MOV EDX, [EBP-16] //oldWidth
54382 CMP EAX, [EBX].TBitmap.fHeight
54383 JL @@fill
54384 CMP EDX, [EBX].TBitmap.fWidth
54385 JGE @@nofill
54386 @@fill: CMP EAX, [EBX].TBitmap.fHeight
54387 JNE @@1
54388 XOR EAX, EAX
54389 @@1:
54390 CMP EDX, [EBX].TBitmap.fWidth
54391 JNZ @@2
54393 @@2: PUSH EAX
54394 PUSH EDX
54396 MOV EDX, ESP
54397 PUSH ESI
54398 PUSH EDX
54399 PUSH dword ptr [EBP-12] //DC2
54400 CALL Windows.FillRect
54401 POP ECX
54402 POP ECX
54403 @@nofill:
54404 POP ECX
54405 POP ECX
54406 PUSH ESI //Br
54407 CALL DeleteObject
54408 PUSH dword ptr [EBP-12] //DC2
54409 CALL SelectObject
54410 @@exit:
54411 POP ECX
54412 POP EDX
54413 POP ESI
54414 POP EBX
54415 end;
54416 {$ELSE ASM_VERSION} //Pascal
54417 procedure FillBmpWithBkColor( Bmp: PBitmap; DC2: HDC; oldWidth, oldHeight: Integer );
54418 var oldBmp: HBitmap;
54419 R: TRect;
54420 Br: HBrush;
54421 begin
54422 with Bmp{-}^{+} do
54423 if Color2RGB( fBkColor ) <> 0 then
54424 if (oldWidth < fWidth) or (oldHeight < fHeight) then
54425 if GetHandle <> 0 then
54426 begin
54427 oldBmp := SelectObject( DC2, fHandle );
54428 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
54429 Br := CreateSolidBrush( Color2RGB( fBkColor ) );
54430 R := MakeRect( oldWidth, oldHeight, fWidth, fHeight );
54431 if oldWidth = fWidth then
54432 R.Left := 0;
54433 if oldHeight = fHeight then
54434 R.Top := 0;
54435 Windows.FillRect( DC2, R, Br );
54436 DeleteObject( Br );
54437 SelectObject( DC2, oldBmp );
54438 end;
54439 end;
54440 {$ENDIF ASM_VERSION}
54441 //[END FillBmpWithBkColor]
54443 const BitCounts: array[ TPixelFormat ] of Byte = ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );
54444 {$IFDEF ASM_VERSION}
54445 //[procedure TBitmap.FormatChanged]
54446 procedure TBitmap.FormatChanged;
54447 type tBIH = TBitmapInfoHeader;
54448 tBmp = tagBitmap;
54449 const szBIH = Sizeof( tBIH );
54450 szBmp = Sizeof( tBmp );
54452 PUSH EAX
54453 CALL GetEmpty
54454 POP EAX
54455 JZ @@exit
54456 PUSHAD
54457 MOV EBX, EAX
54458 CALL [EBX].fDetachCanvas
54459 XOR EAX, EAX
54460 MOV [EBX].fScanLineSize, EAX
54461 MOV [EBX].fGetDIBPixels, EAX
54462 MOV [EBX].fSetDIBPixels, EAX
54463 MOV ESI, [EBX].fWidth // ESI := oldWidth
54464 MOV EDI, [EBX].fHeight // EDI := oldHeight
54465 MOV ECX, [EBX].fDIBBits
54466 JECXZ @@noDIBBits
54467 MOV EAX, [EBX].fDIBHeader
54468 MOV ESI, [EAX].TBitmapInfo.bmiHeader.biWidth
54469 MOV EDI, [EAX].TBitmapInfo.bmiHeader.biHeight
54470 TEST EDI, EDI
54471 JGE @@1
54472 NEG EDI
54473 @@1: JMP @@createDC2
54474 @@noDIBBits:
54475 MOV ECX, [EBX].fHandle
54476 JECXZ @@createDC2
54477 ADD ESP, -24 // -szBmp
54478 PUSH ESP
54479 PUSH 24 //szBmp
54480 PUSH ECX
54481 CALL GetObject
54482 XCHG ECX, EAX
54483 JECXZ @@2
54484 MOV ESI, [ESP].tBmp.bmWidth
54485 MOV EDI, [ESP].tBmp.bmHeight
54486 @@2: ADD ESP, 24 //szBmp
54487 @@createDC2:
54488 PUSH 0
54489 CALL CreateCompatibleDC
54490 PUSH EAX // > DC2
54491 CMP [EBX].fHandleType, bmDDB
54492 JNE @@DIB_handle_type
54493 PUSH 0
54494 CALL GetDC
54495 PUSH EAX // > DC0
54496 PUSH [EBX].fHeight
54497 PUSH [EBX].fWidth
54498 PUSH EAX
54499 CALL CreateCompatibleBitmap
54500 XCHG EBP, EAX // EBP := NewHandle
54501 PUSH 0
54502 CALL ReleaseDC // <
54503 POP EDX
54504 PUSH EDX // EDX := DC2
54505 PUSH EBP
54506 PUSH EDX
54507 CALL SelectObject
54508 PUSH EAX // > OldBmp
54509 PUSH [EBX].fHeight // prepare Rect(0,0,fWidth,fHeight)
54510 PUSH [EBX].fWidth
54511 PUSH 0
54512 PUSH 0
54513 MOV EAX, [EBX].fBkColor
54514 CALL Color2RGB
54515 PUSH EAX
54516 CALL CreateSolidBrush
54517 MOV EDX, ESP
54518 PUSH EAX // > Br
54519 PUSH EAX
54520 PUSH EDX
54521 PUSH dword ptr [ESP+32] // (DC2)
54522 CALL Windows.FillRect
54523 CALL DeleteObject // <
54524 ADD ESP, 16 // remove Rect
54525 MOV ECX, [EBX].fDIBBits
54526 JECXZ @@draw
54527 PUSH dword ptr [ESP+4] // (DC2)
54528 CALL SelectObject // < (OldBmp)
54529 PUSH DIB_RGB_COLORS // : DIB_RGB_COLORS
54530 PUSH [EBX].fDIBHeader // : fDIBHeader
54531 PUSH [EBX].fDIBBits // : fDIBBits
54532 PUSH [EBX].fHeight // : fHeight
54533 PUSH 0 // : 0
54534 PUSH EBP // : NewHandle
54535 PUSH dword ptr [ESP+24] // (DC2)
54536 CALL SetDIBits
54537 JMP @@clearData
54538 @@draw:
54539 MOV EDX, [ESP+4]
54540 PUSH EDX // prepare DC2 for SelectObject
54541 MOV EAX, EBX
54542 XOR ECX, ECX
54543 PUSH ECX
54544 CALL Draw
54545 CALL SelectObject
54546 @@clearData:
54547 MOV EAX, EBX
54548 CALL ClearData
54549 MOV [EBX].fHandle, EBP
54551 JMP @@fillBkColor
54553 @@DIB_handle_type: // [ESP] = DC2
54554 MOVZX EAX, [EBX].fNewPixelFormat
54555 @@getBitsPixel:
54556 XCHG ECX, EAX
54557 MOV CL, [ECX] + offset BitCounts
54558 MOVZX EAX, [DefaultPixelFormat]
54559 JECXZ @@getBitsPixel
54560 XOR EBP, EBP // NewHandle := 0
54561 MOV EAX, [EBX].fWidth // EAX := fWidth
54562 MOV EDX, [EBX].fHeight // EDX := fHeight
54563 CALL PrepareBitmapHeader
54564 PUSH EAX // > NewHeader
54565 CMP [EBX].fNewPixelFormat, pf16bit
54566 JNE @@newHeaderReady
54567 CALL PreparePF16bit
54568 @@newHeaderReady:
54569 POP EAX
54570 PUSH EAX
54571 CALL CalcScanLineSize
54572 MOV EDX, [EBX].fHeight
54573 MUL EDX
54574 PUSH EAX // > sizeBits
54576 {$IFDEF _FP}
54577 CALL GetMem
54578 {$ELSE}
54579 CALL System.@GetMem
54580 {$ENDIF}
54581 PUSH EAX // > NewBits
54582 PUSH DIB_RGB_COLORS
54583 PUSH dword ptr [ESP+12] // (NewHeader)
54584 PUSH EAX
54585 MOV EAX, [EBX].fHeight
54586 CMP EAX, EDI
54587 {$IFDEF USE_CMOV}
54588 CMOVG EAX, EDI
54589 {$ELSE}
54590 JLE @@3
54591 MOV EAX, EDI
54592 @@3: {$ENDIF}
54594 PUSH EAX
54595 PUSH 0
54596 MOV EAX, EBX
54597 CALL GetHandle
54598 PUSH EAX
54599 PUSH dword ptr [ESP+36] // (DC2)
54600 CALL GetDIBits
54602 MOV EDX, [EBX].fHeight
54603 CMP EDX, EDI
54604 {$IFDEF USE_CMOV}
54605 CMOVG EDX, EDI
54606 {$ELSE}
54607 JLE @@30
54608 MOV EDX, EDI
54609 @@30: {$ENDIF}
54611 CMP EAX, EDX
54612 JE @@2clearData
54614 POP EAX
54615 {$IFDEF _FP}
54616 CALL FreeMem
54617 {$ELSE}
54618 CALL System.@FreeMem
54619 {$ENDIF}
54621 XOR EAX, EAX
54622 PUSH EAX
54624 MOV EDX, ESP // EDX = @NewBits
54625 MOV ECX, [ESP+8] // ECX = @NewHeader
54626 PUSH EAX // -> 0
54627 PUSH EAX // -> 0
54628 PUSH EDX // -> @NewBits
54629 PUSH DIB_RGB_COLORS // -> DIB_RGB_COLORS
54630 PUSH ECX // -> @NewHeader
54631 PUSH dword ptr [ESP+32] // -> DC2
54632 CALL CreateDIBSection
54634 XOR ESI, -1 // use OldWidth to store NewDIBAutoFree flag
54636 XCHG EBP, EAX // EBP := NewHandle
54637 PUSH EBP
54638 PUSH dword ptr [ESP+16] // -> DC2
54639 CALL SelectObject
54640 PUSH EAX // save oldBmp
54641 MOV EDX, [ESP+16] // DC2 -> EDX (DC)
54642 XOR ECX, ECX // 0 -> ECX (X)
54643 PUSH ECX // 0 -> stack (Y)
54644 MOV EAX, EBX
54645 CALL TBitmap.Draw
54646 PUSH dword ptr [ESP+16] // -> DC2
54647 CALL SelectObject
54649 @@2clearData:
54650 MOV EAX, EBX
54651 CALL ClearData
54653 POP [EBX].fDIBBits
54654 POP [EBX].fDIBSize
54655 POP [EBX].fDIBHeader
54656 MOV [EBX].fHandle, EBP
54658 TEST ESI, ESI
54659 MOV [EBX].fDIBAutoFree, 0
54660 JGE @@noDIBautoFree
54661 INC [EBX].fDIBAutoFree
54662 @@noDIBautoFree:
54664 @@fillBkColor:
54665 MOV ECX, [EBX].fFillWithBkColor
54666 JECXZ @@deleteDC2
54667 POP EDX // (DC2)
54668 PUSH EDX
54669 PUSH EDI
54670 XCHG ECX, ESI
54671 XCHG EAX, EBX
54672 CALL ESI
54673 @@deleteDC2:
54674 CALL DeleteDC
54675 POPAD
54676 @@exit:
54677 end;
54678 {$ELSE ASM_VERSION} //Pascal
54679 procedure TBitmap.FormatChanged;
54680 // This method is used whenever Width, Height, PixelFormat or HandleType
54681 // properties are changed.
54682 // Old image will be drawn here to a new one (excluding cases when
54683 // old width or height was 0, and / or new width or height is 0).
54684 // To avoid inserting this code into executable, try not to change
54685 // properties Width / Height of bitmat after it is created using
54686 // NewBitmap( W, H ) function or after it is loaded from file, stream
54687 // or resource.
54689 var B: tagBitmap;
54690 oldBmp, NewHandle: HBitmap;
54691 DC0, DC2: HDC;
54692 NewHeader: PBitmapInfo;
54693 NewBits: Pointer;
54694 oldHeight, oldWidth, sizeBits, bitsPixel: Integer;
54695 Br: HBrush;
54696 N: Integer;
54697 NewDIBAutoFree: Boolean;
54698 Hndl: THandle;
54699 begin
54700 if Empty then Exit;
54701 NewDIBAutoFree := FALSE;
54702 fDetachCanvas( @Self );
54703 fScanLineSize := 0;
54704 fGetDIBPixels := nil;
54705 fSetDIBPixels := nil;
54707 oldWidth := fWidth;
54708 oldHeight := fHeight;
54709 if fDIBBits <> nil then
54710 begin
54711 oldWidth := fDIBHeader.bmiHeader.biWidth;
54712 oldHeight := Abs(fDIBHeader.bmiHeader.biHeight);
54714 else
54715 if fHandle <> 0 then
54716 begin
54717 if GetObject( fHandle, Sizeof( B ), @ B ) <> 0 then
54718 begin
54719 oldWidth := B.bmWidth;
54720 oldHeight := B.bmHeight;
54721 end;
54722 end;
54724 DC2 := CreateCompatibleDC( 0 );
54726 if fHandleType = bmDDB then
54727 begin
54728 // New HandleType is bmDDB: old bitmap can be copied using Draw method
54729 DC0 := GetDC( 0 );
54730 NewHandle := CreateCompatibleBitmap( DC0, fWidth, fHeight );
54731 ASSERT( NewHandle <> 0, 'Can not create DDB' );
54732 ReleaseDC( 0, DC0 );
54734 oldBmp := SelectObject( DC2, NewHandle );
54735 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
54737 Br := CreateSolidBrush( Color2RGB( fBkColor ) );
54738 FillRect( DC2, MakeRect( 0, 0, fWidth, fHeight ), Br );
54739 DeleteObject( Br );
54741 if fDIBBits <> nil then
54742 begin
54743 SelectObject( DC2, oldBmp );
54744 SetDIBits( DC2, NewHandle, 0, fHeight, fDIBBits, fDIBHeader^, DIB_RGB_COLORS );
54746 else
54747 begin
54748 Draw( DC2, 0, 0 );
54749 SelectObject( DC2, oldBmp );
54750 end;
54752 ClearData; // Image is cleared but fWidth and fHeight are preserved
54753 fHandle := NewHandle;
54755 else
54756 begin
54757 // New format is DIB. GetDIBits applied to transform old data to new one.
54758 bitsPixel := BitCounts[ fNewPixelFormat ];
54759 if bitsPixel = 0 then
54760 begin
54761 bitsPixel := BitCounts[DefaultPixelFormat];
54762 end;
54764 NewHandle := 0;
54765 NewHeader := PrepareBitmapHeader( fWidth, fHeight, bitsPixel );
54766 if fNewPixelFormat = pf16bit then
54767 PreparePF16bit( NewHeader );
54769 sizeBits := CalcScanLineSize( @NewHeader.bmiHeader ) * fHeight;
54771 GetMem( NewBits, sizeBits );
54772 ASSERT( NewBits <> nil, 'No memory' );
54774 Hndl := GetHandle;
54775 if Hndl = 0 then Exit;
54776 N :=
54777 GetDIBits( DC2, Hndl, 0, Min( fHeight, oldHeight ),
54778 NewBits, NewHeader^, DIB_RGB_COLORS );
54779 //Assert( N = Min( fHeight, oldHeight ), 'Can not get all DIB bits' );
54780 if N <> Min( fHeight, oldHeight ) then
54781 begin
54782 FreeMem( NewBits );
54783 NewBits := nil;
54784 NewHandle := CreateDIBSection( DC2, NewHeader^, DIB_RGB_COLORS, NewBits, 0, 0 );
54785 NewDIBAutoFree := TRUE;
54786 ASSERT( NewHandle <> 0, 'Can not create DIB secion for pf16bit bitmap' );
54787 oldBmp := SelectObject( DC2, NewHandle );
54788 ASSERT( oldBmp <> 0, 'Can not select pf16bit to DC' );
54789 Draw( DC2, 0, 0 );
54790 SelectObject( DC2, oldBmp );
54791 end;
54793 ClearData;
54794 fDIBSize := sizeBits;
54795 fDIBBits := NewBits;
54796 fDIBHeader := NewHeader;
54797 fHandle := NewHandle;
54798 fDIBAutoFree := NewDIBAutoFree;
54800 end;
54802 if Assigned( fFillWithBkColor ) then
54803 fFillWithBkColor( @Self, DC2, oldWidth, oldHeight );
54805 DeleteDC( DC2 );
54807 end;
54808 {$ENDIF ASM_VERSION}
54810 {$IFDEF ASM_VERSION}
54811 //[function TBitmap.GetScanLine]
54812 function TBitmap.GetScanLine(Y: Integer): Pointer;
54814 MOV ECX, [EAX].fDIBHeader
54815 JECXZ @@exit
54816 MOV ECX, [ECX].TBitmapInfoHeader.biHeight
54817 TEST ECX, ECX
54818 JL @@1
54820 SUB ECX, EDX
54821 DEC ECX
54822 MOV EDX, ECX
54824 @@1: MOV ECX, [EAX].fScanLineSize
54825 INC ECX
54826 PUSH [EAX].fDIBBits
54827 LOOP @@2
54829 PUSH EDX
54830 CALL GetScanLineSize
54831 POP EDX
54832 XCHG ECX, EAX
54834 @@2: XCHG EAX, ECX
54835 MUL EDX
54836 POP ECX
54837 ADD ECX, EAX
54839 @@exit: XCHG EAX, ECX
54840 end;
54841 {$ELSE ASM_VERSION} //Pascal
54842 function TBitmap.GetScanLine(Y: Integer): Pointer;
54843 begin
54844 ASSERT( (Y >= 0) {and (Y < fHeight)}, 'ScanLine index out of bounds' );
54845 ASSERT( fDIBBits <> nil, 'No bits available' );
54846 Result := nil;
54847 if fDIBHeader = nil then Exit;
54849 if fDIBHeader.bmiHeader.biHeight > 0 then
54850 Y := fHeight - 1 - Y;
54851 if fScanLineSize = 0 then
54852 ScanLineSize;
54854 Result := Pointer( Integer( fDIBBits ) + fScanLineSize * Y );
54855 end;
54856 {$ENDIF ASM_VERSION}
54858 {$IFDEF ASM_VERSION}
54859 //[function TBitmap.GetScanLineSize]
54860 function TBitmap.GetScanLineSize: Integer;
54862 MOV ECX, [EAX].fDIBHeader
54863 JECXZ @@exit
54865 PUSH EAX
54866 XCHG EAX, ECX
54867 CALL CalcScanLineSize
54868 XCHG ECX, EAX
54869 POP EAX
54870 MOV [EAX].fScanLineSize, ECX
54872 @@exit: XCHG EAX, ECX
54873 end;
54874 {$ELSE ASM_VERSION} //Pascal
54875 function TBitmap.GetScanLineSize: Integer;
54876 begin
54877 Result := 0;
54878 if fDIBHeader = nil then Exit;
54879 FScanLineSize := CalcScanLineSize( @fDIBHeader.bmiHeader );
54880 Result := FScanLineSize;
54881 end;
54882 {$ENDIF ASM_VERSION}
54884 {$IFDEF ASM_VERSION}
54885 //[procedure TBitmap.CanvasChanged]
54886 procedure TBitmap.CanvasChanged( Sender : PObj );
54888 PUSH EAX
54890 XCHG EAX, EDX
54891 CALL TCanvas.GetBrush
54892 MOV EDX, [EAX].TGraphicTool.fData.Color
54894 POP EAX
54895 MOV [EAX].fBkColor, EAX
54896 CALL ClearTransImage
54897 end;
54898 {$ELSE ASM_VERSION} //Pascal
54899 procedure TBitmap.CanvasChanged( Sender : PObj );
54900 begin
54901 fBkColor := PCanvas( Sender ).Brush.Color;
54902 ClearTransImage;
54903 end;
54904 {$ENDIF ASM_VERSION}
54906 {$IFDEF ASM_VERSION}
54907 //[procedure TBitmap.Dormant]
54908 procedure TBitmap.Dormant;
54910 PUSH EAX
54911 CALL RemoveCanvas
54912 POP EAX
54913 MOV ECX, [EAX].fHandle
54914 JECXZ @@exit
54915 CALL ReleaseHandle
54916 PUSH EAX
54917 CALL DeleteObject
54918 @@exit:
54919 end;
54920 {$ELSE ASM_VERSION} //Pascal
54921 procedure TBitmap.Dormant;
54922 begin
54923 RemoveCanvas;
54924 if fHandle <> 0 then
54925 DeleteObject( ReleaseHandle );
54926 end;
54927 {$ENDIF ASM_VERSION}
54929 {$IFDEF ASM_VERSION}
54930 //[procedure TBitmap.SetBkColor]
54931 procedure TBitmap.SetBkColor(const Value: TColor);
54933 CMP [EAX].fBkColor, EDX
54934 JE @@exit
54935 MOV [EAX].fBkColor, EDX
54936 MOV [EAX].fFillWithBkColor, offset[FillBmpWithBkColor]
54937 MOV ECX, [EAX].fApplyBkColor2Canvas
54938 JECXZ @@exit
54939 CALL ECX
54940 @@exit:
54941 end;
54942 {$ELSE ASM_VERSION} //Pascal
54943 procedure TBitmap.SetBkColor(const Value: TColor);
54944 begin
54945 if fBkColor = Value then Exit;
54946 fBkColor := Value;
54947 fFillWithBkColor := FillBmpWithBkColor;
54948 if Assigned( fApplyBkColor2Canvas ) then
54949 fApplyBkColor2Canvas( @Self );
54950 end;
54951 {$ENDIF ASM_VERSION}
54953 {$IFDEF ASM_VERSION}
54954 //[function TBitmap.Assign]
54955 function TBitmap.Assign(SrcBmp: PBitmap): Boolean;
54956 const szBIH = sizeof(TBitmapInfoHeader);
54958 PUSHAD
54959 XCHG EBX, EAX
54960 @@clear:
54961 MOV ESI, EDX
54962 MOV EAX, EBX
54963 CALL Clear
54964 MOV EAX, ESI
54965 OR EAX, EAX
54966 JZ @@exit
54967 CALL GetEmpty
54968 JZ @@exit
54969 MOV EAX, [ESI].fWidth
54970 MOV [EBX].fWidth, EAX
54971 MOV EAX, [ESI].fHeight
54972 MOV [EBX].fHeight, EAX
54973 MOVZX ECX, [ESI].fHandleType
54974 MOV [EBX].fHandleType, CL
54975 JECXZ @@fmtDIB
54977 DEC ECX // ECX = 0
54978 PUSH ECX
54979 PUSH ECX
54980 PUSH ECX
54981 PUSH ECX //IMAGE_BITMAP=0
54982 PUSH [ESI].fHandle
54983 CALL CopyImage
54984 MOV [EBX].fHandle, EAX
54985 TEST EAX, EAX
54986 XCHG EDX, EAX
54987 JZ @@clear
54988 JMP @@exit
54990 @@fmtDIB:
54991 XCHG EAX, ECX
54992 MOV AX, szBIH+1024
54993 PUSH EAX
54994 CALL System.@GetMem
54995 MOV [EBX].fDIBHeader, EAX
54996 XCHG EDX, EAX
54997 POP ECX
54998 MOV EAX, [ESI].fDIBHeader
54999 CALL System.Move
55000 MOV EAX, [ESI].fDIBSize
55001 MOV [EBX].fDIBSize, EAX
55002 PUSH EAX
55003 CALL System.@GetMem
55004 MOV [EBX].fDIBBits, EAX
55005 XCHG EDX, EAX
55006 POP ECX
55007 MOV EAX, [ESI].fDIBBits
55008 CALL System.Move
55010 INC EBX // reset "ZF"
55012 @@exit:
55013 POPAD
55014 SETNZ AL
55015 end;
55016 {$ELSE ASM_VERSION} //Pascal
55017 function TBitmap.Assign(SrcBmp: PBitmap): Boolean;
55018 begin
55019 Clear;
55020 Result := False;
55021 if SrcBmp = nil then Exit;
55022 if SrcBmp.Empty then Exit;
55023 fWidth := SrcBmp.fWidth;
55024 fHeight := SrcBmp.fHeight;
55025 fHandleType := SrcBmp.fHandleType;
55026 if SrcBmp.fHandleType = bmDDB then
55027 begin
55028 fHandle := CopyImage( SrcBmp.fHandle, IMAGE_BITMAP, 0, 0, 0 {LR_COPYRETURNORG} );
55029 ASSERT( fHandle <> 0, 'Can not copy bitmap image' );
55030 Result := fHandle <> 0;
55031 if not Result then Clear;
55033 else
55034 begin
55035 GetMem( fDIBHeader, Sizeof(TBitmapInfoHeader) + 256*sizeof(TRGBQuad) );
55036 ASSERT( fDIBHeader <> nil, 'No memory' );
55037 Move( SrcBmp.fDIBHeader^, fDIBHeader^, Sizeof(TBitmapInfoHeader) + 256*sizeof(TRGBQuad) );
55038 fDIBSize := SrcBmp.fDIBSize;
55039 GetMem( fDIBBits, fDIBSize );
55040 ASSERT( fDIBBits <> nil, 'No memory' );
55041 Move( SrcBmp.fDIBBits^, fDIBBits^, fDIBSize );
55042 //fDIBAutoFree := TRUE;
55043 Result := True;
55044 end;
55045 end;
55046 {$ENDIF ASM_VERSION}
55048 {$IFDEF ASM_VERSION}
55049 //[procedure TBitmap.RemoveCanvas]
55050 procedure TBitmap.RemoveCanvas;
55052 PUSH EAX
55053 CALL [EAX].fDetachCanvas
55054 POP EDX
55055 XOR EAX, EAX
55056 XCHG EAX, [EDX].fCanvas
55057 CALL TObj.Free
55058 end;
55059 {$ELSE ASM_VERSION} //Pascal
55060 procedure TBitmap.RemoveCanvas;
55061 begin
55062 fDetachCanvas( @Self );
55063 fCanvas.Free;
55064 fCanvas := nil;
55065 end;
55066 {$ENDIF ASM_VERSION}
55068 {$IFDEF ASM_VERSION}
55069 //[function TBitmap.DIBPalNearestEntry]
55070 function TBitmap.DIBPalNearestEntry(Color: TColor): Integer;
55071 const szBIH = sizeof(TBitmapInfoHeader);
55073 PUSH EBX
55074 PUSH ESI
55075 PUSH EDI
55076 XCHG ESI, EAX
55077 XCHG EAX, EDX
55078 CALL Color2RGBQuad
55079 XCHG EDI, EAX
55080 MOV EAX, ESI
55081 CALL GetDIBPalEntryCount
55082 XCHG ECX, EAX
55083 XOR EAX, EAX
55084 JECXZ @@exit
55086 MOV ESI, [ESI].fDIBHeader
55087 ADD ESI, szBIH
55088 XOR EDX, EDX
55089 PUSH EDX
55090 DEC DX
55092 @@loo: LODSD
55093 XOR EAX, EDI
55094 MOV EBX, EAX
55095 SHR EBX, 16
55096 MOV BH, 0
55097 ADD AL, AH
55098 MOV AH, 0
55099 ADC AX, BX
55100 CMP AX, DX
55101 JAE @@1
55102 MOV DX, AX
55103 POP EBX
55104 PUSH EDX // save better index (in high order word)
55105 @@1: ADD EDX, $10000 // increment index
55106 LOOP @@loo
55108 XCHG EAX, ECX
55109 POP AX
55110 POP AX
55111 @@exit:
55112 POP EDI
55113 POP ESI
55114 POP EBX
55115 end;
55116 {$ELSE ASM_VERSION} //Pascal
55117 function TBitmap.DIBPalNearestEntry(Color: TColor): Integer;
55118 var I, Diff, D: Integer;
55119 C : Integer;
55120 begin
55121 Color := TColor( Color2RGBQuad( Color ) );
55122 Result := 0;
55123 Diff := MaxInt;
55124 for I := 0 to DIBPalEntryCount - 1 do
55125 begin
55126 C := Color xor PInteger( Integer( @fDIBHeader.bmiColors[ 0 ] )
55127 + I * Sizeof( TRGBQuad ) )^;
55128 D := TRGBQuad( C ).rgbBlue + TRGBQuad( C ).rgbGreen + TRGBQuad( C ).rgbRed;
55129 if D < Diff then
55130 begin
55131 Diff := D;
55132 Result := I;
55133 end;
55134 end;
55135 end;
55136 {$ENDIF ASM_VERSION}
55138 {$IFDEF ASM_VERSION}
55139 //[function TBitmap.GetDIBPalEntries]
55140 function TBitmap.GetDIBPalEntries(Idx: Integer): TColor;
55141 const szBIH = sizeof(TBitmapInfoHeader);
55143 MOV ECX, [EAX].fDIBHeader
55144 JECXZ @@exit
55146 MOV ECX, [EAX+szBIH+EDX*4]
55147 INC ECX
55149 @@exit: DEC ECX
55150 XCHG EAX, ECX
55151 end;
55152 {$ELSE ASM_VERSION} //Pascal
55153 function TBitmap.GetDIBPalEntries(Idx: Integer): TColor;
55154 begin
55155 Result := TColor(-1);
55156 if fDIBBits = nil then Exit;
55157 ASSERT( PixelFormat in [pf1bit..pf8bit], 'Format has no DIB palette entries available' );
55158 ASSERT( (Idx >= 0) and (Idx < (1 shl fDIBHeader.bmiHeader.biBitCount)),
55159 'DIB palette index out of bounds' );
55160 Result := PDWORD( Integer( @fDIBHeader.bmiColors[ 0 ] )
55161 + Idx * Sizeof( TRGBQuad ) )^;
55162 end;
55163 {$ENDIF ASM_VERSION}
55165 {$IFDEF ASM_VERSION}
55166 //[function TBitmap.GetDIBPalEntryCount]
55167 function TBitmap.GetDIBPalEntryCount: Integer;
55169 PUSH EAX
55170 CALL GetEmpty
55171 POP EAX
55172 JZ @@ret0
55173 CALL GetPixelFormat
55174 MOVZX ECX, AL
55175 MOV EAX, ECX
55176 LOOP @@1
55177 // pf1bit:
55178 INC EAX
55180 @@1:
55181 LOOP @@2
55182 // pf4bit:
55183 MOV AL, 16
55185 @@2:
55186 LOOP @@ret0
55187 // pf8bit:
55188 XOR EAX, EAX
55189 INC AH
55191 @@ret0:
55192 XOR EAX, EAX
55193 end;
55194 {$ELSE ASM_VERSION} //Pascal
55195 function TBitmap.GetDIBPalEntryCount: Integer;
55196 begin
55197 Result := 0;
55198 if Empty then Exit;
55199 case PixelFormat of
55200 pf1bit: Result := 2;
55201 pf4bit: Result := 16;
55202 pf8bit: Result := 256;
55203 else;
55204 end;
55205 end;
55206 {$ENDIF ASM_VERSION}
55208 //[procedure TBitmap.SetDIBPalEntries]
55209 procedure TBitmap.SetDIBPalEntries(Idx: Integer; const Value: TColor);
55210 begin
55211 if fDIBBits = nil then Exit;
55212 Dormant;
55213 PDWORD( Integer( @fDIBHeader.bmiColors[ 0 ] )
55214 + Idx * Sizeof( TRGBQuad ) )^ := Color2RGB( Value );
55215 end;
55217 //[procedure TBitmap.SetHandleType]
55218 procedure TBitmap.SetHandleType(const Value: TBitmapHandleType);
55219 {var B: tagBitmap;
55220 DC0: HDC;}
55221 begin
55222 if fHandleType = Value then Exit;
55223 //++++++++++++++++ ?????????
55224 {if fHandleType = bmDDB then
55225 if PixelFormat = pfDevice then
55226 begin
55227 DC0 := GetDC( 0 );
55228 fNewPixelFormat := Bits2PixelFormat( GetDeviceCaps( DC0, BITSPIXEL ) );
55229 ReleaseDC( 0, DC0 );
55231 else
55232 if FHandle <> 0 then
55233 begin
55234 if GetObject( FHandle, Sizeof( B ), @ B ) > 0 then
55235 fNewPixelFormat := Bits2PixelFormat( B.bmPlanes * B.bmBitsPixel );
55236 end;}
55237 //----------------
55238 fHandleType := Value;
55239 FormatChanged;
55240 end;
55242 //[function TBitmap.GetPixelFormat]
55243 function TBitmap.GetPixelFormat: TPixelFormat;
55244 begin
55245 if (HandleType = bmDDB) or (fDIBBits = nil) then
55246 Result := pfDevice
55247 else
55248 begin
55249 Result := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount );
55250 if (Result = pf15bit) and (fDIBHeader.bmiHeader.biCompression <> 0) then
55251 begin
55252 Assert( fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS, 'Unsupported bitmap format' );
55253 Result := pf16bit;
55254 end;
55255 end;
55256 end;
55258 {$IFDEF ASM_VERSION}
55259 //[procedure TBitmap.ClearTransImage]
55260 procedure TBitmap.ClearTransImage;
55262 OR [EAX].fTransColor, -1
55263 XOR EDX, EDX
55264 XCHG [EAX].fTransMaskBmp, EDX
55265 XCHG EAX, EDX
55266 CALL TObj.Free
55267 end;
55268 {$ELSE ASM_VERSION} //Pascal
55269 procedure TBitmap.ClearTransImage;
55270 begin
55271 fTransColor := clNone;
55272 fTransMaskBmp.Free;
55273 fTransMaskBmp := nil;
55274 end;
55275 {$ENDIF ASM_VERSION}
55277 {$IFDEF ASM_VERSION}
55278 //[procedure TBitmap.Convert2Mask]
55279 procedure TBitmap.Convert2Mask(TranspColor: TColor);
55281 PUSH EBX
55282 PUSH ESI
55283 MOV EBX, EAX
55284 MOV ESI, EDX
55285 CALL GetHandle
55286 TEST EAX, EAX
55287 JZ @@exit
55289 PUSH 0
55290 PUSH 1
55291 PUSH 1
55292 PUSH [EBX].fHeight
55293 PUSH [EBX].fWidth
55294 CALL CreateBitmap
55295 PUSH EAX // MonoHandle
55296 PUSH 0
55297 CALL CreateCompatibleDC
55298 POP EDX
55299 PUSH EDX
55300 PUSH EAX // MonoDC
55302 PUSH EDX
55303 PUSH EAX
55304 CALL SelectObject
55305 PUSH EAX // SaveMono
55307 CALL StartDC // DCfrom, SaveFrom
55308 XCHG EAX, ESI
55309 CALL Color2RGB
55310 PUSH EAX // Color2RGB(TranspColor)
55311 PUSH dword ptr [ESP+8] //DCfrom
55312 CALL Windows.SetBkColor
55313 PUSH EAX // SaveBkColor
55315 PUSH SRCCOPY
55316 PUSH 0
55317 PUSH 0
55318 PUSH dword ptr [ESP+12+4+4] //DCfrom
55319 PUSH [EBX].fHeight
55320 PUSH [EBX].fWidth
55321 PUSH 0
55322 PUSH 0
55323 PUSH dword ptr [ESP+32+16] //MonoDC
55324 CALL BitBlt
55326 PUSH dword ptr [ESP+8] //DCfrom
55327 CALL Windows.SetBkColor // ESP-> SaveFrom
55328 CALL FinishDC // ESP-> SaveMono
55329 CALL FinishDC // ESP-> MonoHandle
55331 MOV EAX, EBX
55332 CALL ClearData
55333 POP [EBX].fHandle
55334 MOV [EBX].fHandleType, bmDDB
55335 @@exit:
55336 POP ESI
55337 POP EBX
55338 end;
55339 {$ELSE ASM_VERSION} //Pascal
55340 procedure TBitmap.Convert2Mask(TranspColor: TColor);
55341 var MonoHandle: HBitmap;
55342 SaveMono, SaveFrom: THandle;
55343 MonoDC, {DC0,} DCfrom: HDC;
55344 SaveBkColor: TColorRef;
55345 begin
55346 if GetHandle = 0 then Exit;
55347 fDetachCanvas( @Self );
55348 ///DC0 := GetDC( 0 );
55349 MonoHandle := CreateBitmap( fWidth, fHeight, 1, 1, nil );
55350 ASSERT( MonoHandle <> 0, 'Can not create monochrome bitmap' );
55351 MonoDC := CreateCompatibleDC( 0 );
55352 SaveMono := SelectObject( MonoDC, MonoHandle );
55353 ASSERT( SaveMono <> 0, 'Can not select bitmap to DC' );
55354 DCfrom := CreateCompatibleDC( 0 );
55355 SaveFrom := SelectObject( DCfrom, fHandle );
55356 ASSERT( SaveFrom <> 0, 'Can not select source bitmap to DC' );
55357 TranspColor := Color2RGB( TranspColor );
55358 SaveBkColor := Windows.SetBkColor( DCfrom, TranspColor );
55359 BitBlt( MonoDC, 0, 0, fWidth, fHeight, DCfrom, 0, 0, SRCCOPY );
55360 {$IFDEF CHK_BITBLT} Chk_BitBlt; {$ENDIF}
55361 Windows.SetBkColor( DCfrom, SaveBkColor );
55362 SelectObject( DCfrom, SaveFrom );
55363 DeleteDC( DCfrom );
55364 SelectObject( MonoDC, SaveMono );
55365 DeleteDC( MonoDC );
55366 ///ReleaseDC( 0, DC0 );
55367 ClearData;
55368 fHandle := MonoHandle;
55369 fHandleType := bmDDB;
55370 end;
55371 {$ENDIF ASM_VERSION}
55373 //[procedure TBitmap.Invert]
55374 procedure TBitmap.Invert;
55375 begin
55376 //BitBlt( Canvas.Handle, 0, 0, Width, Height, Canvas.Handle, 0, 0, DSTINVERT )
55377 InvertRect(Canvas.Handle, BoundsRect);
55378 end;
55380 //[procedure TBitmap.DIBDrawRect]
55381 procedure TBitmap.DIBDrawRect( DC: HDC; X, Y: Integer; const R: TRect );
55382 begin
55383 if fDIBBits = nil then Exit;
55384 StretchDIBits( DC, X, Y, R.Right - R.Left, R.Bottom - R.Top,
55385 R.Left, fHeight - R.Bottom, R.Right - R.Left, R.Bottom - R.Top,
55386 fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY );
55387 end;
55389 //[PROCEDURE _PrepareBmp2Rotate]
55390 {$IFDEF ASM_VERSION}
55391 procedure _PrepareBmp2Rotate;
55392 const szBIH = sizeof(TBitmapInfoHeader);
55394 { <- BL = increment to height }
55395 XCHG EDI, EAX
55396 MOV ESI, EDX // ESI = SrcBmp
55398 XCHG EAX, EDX
55399 CALL TBitmap.GetPixelFormat
55400 MOVZX ECX, AL
55401 PUSH ECX
55403 MOV EDX, [ESI].TBitmap.fWidth
55404 MOVZX EBX, BL
55405 ADD EDX, EBX
55407 MOV EAX, [ESI].TBitmap.fHeight
55408 CALL NewDIBBitmap
55409 STOSD
55410 XCHG EDI, EAX
55412 MOV EAX, [ESI].TBitmap.fDIBHeader
55413 ADD EAX, szBIH
55414 MOV EDX, [EDI].TBitmap.fDIBHeader
55415 ADD EDX, szBIH
55416 XOR ECX, ECX
55417 MOV CH, 4
55418 CALL System.Move
55420 MOV EAX, EDI
55421 XOR EDX, EDX
55422 CALL TBitmap.GetScanLine
55423 MOV EBX, [EDI].TBitmap.fWidth
55424 DEC EBX // EBX = DstBmp.fWidth - 1
55425 XCHG EDI, EAX // EDI = DstBmp.ScanLine[ 0 ]
55427 XOR EDX, EDX
55428 INC EDX
55429 CALL TBitmap.GetScanLine
55430 XCHG EDX, EAX
55431 SUB EDX, EDI // EDX = BytesPerDstLine
55433 MOV EBP, [ESI].TBitmap.fWidth
55434 DEC EBP // EBP = SrcBmp.fWidth - 1
55436 POP ECX // ECX = PixelFormat
55437 end;
55438 {$ENDIF ASM_VERSION}
55439 //[END _PrepareBmp2Rotate]
55441 //[PROCEDURE _RotateBitmapMono]
55442 {$IFDEF ASM_VERSION}
55443 procedure _RotateBitmapMono( var DstBmp: PBitmap; SrcBmp: PBitmap );
55444 const szBIH = sizeof(TBitmapInfoHeader);
55446 PUSHAD
55447 MOV BL, 7
55448 CALL _PrepareBmp2Rotate
55450 SHR EBP, 3
55451 SHL EBP, 8 // EBP = (WBytes-1) * 256
55453 MOV ECX, EBX // ECX and 7 = Shf
55454 SHR EBX, 3
55455 ADD EDI, EBX // EDI = Dst
55457 XOR EBX, EBX // EBX = temp mask
55458 XOR EAX, EAX // Y = 0
55459 @@looY:
55460 PUSH EAX
55461 PUSH EDI // Dst1 = Dst (Dst1 in EDI, Dst saved)
55462 PUSH ESI // SrcBmp
55464 PUSH EDX //BytesPerDstLine
55465 PUSH ECX //Shf
55467 XCHG EDX, EAX
55468 XCHG EAX, ESI
55469 CALL TBitmap.GetScanLine
55470 XCHG ESI, EAX // ESI = Src
55472 POP ECX // CL = Shf
55473 AND ECX, 7 // ECX = Shf
55474 OR ECX, EBP // ECX = (Wbytes-1)*8 + Shf
55475 POP EDX // EDX = BytesPerDstLine
55477 MOV BH, $80
55478 SHR EBX, CL // BH = mask, BL = mask & Tmp
55479 @@looX:
55480 XOR EAX, EAX
55482 LODSB
55484 MOV AH, AL
55485 SHR EAX, CL
55486 OR EAX,$01000000
55488 @@looBits:
55489 MOV BL, AH
55490 AND BL, BH
55491 OR [EDI], BL
55492 ADD EDI, EDX
55493 ADD EAX, EAX
55494 JNC @@looBits
55496 SUB ECX, 256
55497 JGE @@looX
55499 POP ESI // ESI = SrcBmp
55500 POP EDI // EDI = Dst
55501 POP EAX // EAX = Y
55503 ADD ECX, 256-1
55504 JGE @@1
55505 DEC EDI
55506 @@1:
55507 INC EAX
55508 CMP EAX, [ESI].TBitmap.fHeight
55509 JL @@looY
55511 POPAD
55512 end;
55513 {$ELSE ASM_VERSION} //Pascal
55514 procedure _RotateBitmapMono( var DstBmp: PBitmap; SrcBmp: PBitmap );
55515 var X, Y, Z, Shf, Wbytes, BytesPerDstLine: Integer;
55516 Src, Dst, Dst1: PByte;
55517 Tmp: Byte;
55518 begin
55520 DstBmp := NewDIBBitmap( SrcBmp.fHeight, (SrcBmp.fWidth + 7) and not 7, pf1bit );
55521 Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 2 * Sizeof( TRGBQuad ) );
55523 // Calculate ones:
55524 Dst := DstBmp.ScanLine[ 0 ];
55525 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55526 Wbytes := (SrcBmp.fWidth + 7) shr 3;
55528 Inc( Dst, (DstBmp.fWidth - 1) shr 3 );
55529 Shf := (DstBmp.fWidth - 1) and 7;
55531 // Rotating bits:
55532 for Y := 0 to SrcBmp.fHeight - 1 do
55533 begin
55534 Src := SrcBmp.ScanLine[ Y ];
55535 Dst1 := Dst;
55536 for X := Wbytes downto 1 do
55537 begin
55538 Tmp := Src^;
55539 Inc( Src );
55540 for Z := 8 downto 1 do
55541 begin
55542 Dst1^ := Dst1^ or ( (Tmp and $80) shr Shf );
55543 Tmp := Tmp shl 1;
55544 Inc( Dst1, BytesPerDstLine );
55545 end;
55546 end;
55547 Dec( Shf );
55548 if Shf < 0 then
55549 begin
55550 Shf := 7;
55551 Dec( Dst );
55552 end;
55553 end;
55554 end;
55555 {$ENDIF ASM_VERSION}
55556 //[END _RotateBitmapMono]
55558 //[PROCEDURE _RotateBitmap4bit]
55559 {$IFDEF ASM_VERSION}
55560 procedure _RotateBitmap4bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55561 const szBIH = sizeof(TBitmapInfoHeader);
55563 PUSHAD
55564 MOV BL, 1
55565 CALL _PrepareBmp2Rotate
55567 SHR EBP, 1 // EBP = WBytes - 1
55568 SHL EBP, 8 // EBP = (WBytes - 1) * 256
55570 // EBX = DstBmp.fWidth - 1
55571 MOV ECX, EBX
55572 SHL ECX, 2 // ECX and 7 = Shf (0 or 4)
55573 SHR EBX, 1
55574 ADD EDI, EBX // EDI = Dst
55576 XOR EAX, EAX // Y = 0
55577 XOR EBX, EBX
55579 @@looY:
55580 PUSH EAX // save Y
55581 PUSH EDI // Dst1 = Dst (Dst1 in EDI, Dst saved)
55582 PUSH ESI // SrcBmp
55584 PUSH EDX // BytesPerDstLine
55585 PUSH ECX // Shf
55587 XCHG EDX, EAX
55588 XCHG EAX, ESI
55589 CALL TBitmap.GetScanLine
55590 XCHG ESI, EAX // ESI = Src
55592 POP ECX
55593 AND ECX, 7 // CL = Shf
55594 OR ECX, EBP // ECX = (WBytes-1)*256 + Shf
55595 POP EDX // EDX = BytesPerDstLine
55597 MOV BH, $F0
55598 SHR EBX, CL // shift mask right 4 or 0
55600 @@looX:
55601 XOR EAX, EAX
55602 LODSB
55603 MOV AH, AL
55604 SHR EAX, CL
55606 MOV BL, AH
55607 AND BL, BH
55608 OR [EDI], BL
55609 ADD EDI, EDX
55611 SHL EAX, 4
55612 AND AH, BH
55613 OR [EDI], AH
55614 ADD EDI, EDX
55616 SUB ECX, 256
55617 JGE @@looX
55619 POP ESI // ESI = SrcBmp
55620 POP EDI // EDI = Dst
55621 POP EAX // EAX = Y
55623 ADD ECX, 256 - 4
55624 JGE @@1
55626 DEC EDI
55627 @@1:
55628 INC EAX
55629 CMP EAX, [ESI].TBitmap.fHeight
55630 JL @@looY
55632 POPAD
55633 end;
55634 {$ELSE ASM_VERSION} //Pascal
55635 procedure _RotateBitmap4bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55636 var X, Y, Shf, Wbytes, BytesPerDstLine: Integer;
55637 Src, Dst, Dst1: PByte;
55638 Tmp: Byte;
55639 begin
55641 DstBmp := NewDIBBitmap( SrcBmp.fHeight, (SrcBmp.fWidth + 1) and not 1, pf4bit );
55642 Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 16 * Sizeof( TRGBQuad ) );
55644 // Calculate ones:
55645 Dst := DstBmp.ScanLine[ 0 ];
55646 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55647 Wbytes := (SrcBmp.fWidth + 1) shr 1;
55649 Inc( Dst, (DstBmp.fWidth - 1) shr 1 );
55650 Shf := ((DstBmp.fWidth - 1) and 1) shl 2;
55652 // Rotating bits:
55653 for Y := 0 to SrcBmp.fHeight - 1 do
55654 begin
55655 Src := SrcBmp.ScanLine[ Y ];
55656 Dst1 := Dst;
55657 for X := Wbytes downto 1 do
55658 begin
55659 Tmp := Src^;
55660 Inc( Src );
55661 Dst1^ := Dst1^ or ( (Tmp and $F0) shr Shf );
55662 Inc( Dst1, BytesPerDstLine );
55663 Dst1^ := Dst1^ or ( ((Tmp shl 4) and $F0) shr Shf );
55664 Inc( Dst1, BytesPerDstLine );
55665 end;
55666 Dec( Shf, 4 );
55667 if Shf < 0 then
55668 begin
55669 Shf := 4;
55670 Dec( Dst );
55671 end;
55672 end;
55673 end;
55674 {$ENDIF ASM_VERSION}
55675 //[END _RotateBitmap4bit]
55677 //[PROCEDURE _RotateBitmap8bit]
55678 {$IFDEF ASM_VERSION}
55679 procedure _RotateBitmap8bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55680 const szBIH = sizeof(TBitmapInfoHeader);
55682 PUSHAD
55683 XOR EBX, EBX
55684 CALL _PrepareBmp2Rotate
55686 ADD EDI, EBX // EDI = Dst
55688 MOV EBX, EDX // EBX = BytesPerDstLine
55689 DEC EBX
55690 MOV EBP, ESI // EBP = SrcBmp
55692 XOR EDX, EDX // Y = 0
55694 @@looY:
55695 PUSH EDX
55696 PUSH EDI
55698 MOV EAX, EBP
55699 CALL TBitmap.GetScanLine
55700 XCHG ESI, EAX
55701 MOV ECX, [EBP].TBitmap.fWidth
55703 @@looX:
55704 MOVSB
55705 ADD EDI, EBX
55706 LOOP @@looX
55708 POP EDI
55709 POP EDX
55711 DEC EDI
55712 INC EDX
55713 CMP EDX, [EBP].TBitmap.fHeight
55714 JL @@looY
55716 POPAD
55717 end;
55718 {$ELSE ASM_VERSION} //Pascal
55719 procedure _RotateBitmap8bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55720 var X, Y, Wbytes, BytesPerDstLine: Integer;
55721 Src, Dst, Dst1: PByte;
55722 Tmp: Byte;
55723 begin
55725 DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );
55726 Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 256 * Sizeof( TRGBQuad ) );
55728 // Calculate ones:
55729 Wbytes := SrcBmp.fWidth;
55730 Dst := DstBmp.ScanLine[ 0 ];
55731 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55733 Inc( Dst, DstBmp.fWidth - 1 );
55735 // Rotating bits:
55736 for Y := 0 to SrcBmp.fHeight - 1 do
55737 begin
55738 Src := SrcBmp.ScanLine[ Y ];
55739 Dst1 := Dst;
55740 for X := Wbytes downto 1 do
55741 begin
55742 Tmp := Src^;
55743 Inc( Src );
55744 Dst1^ := Tmp;
55745 Inc( Dst1, BytesPerDstLine );
55746 end;
55747 Dec( Dst );
55748 end;
55750 end;
55751 {$ENDIF ASM_VERSION}
55752 //[END _RotateBitmap8bit]
55754 //[PROCEDURE _RotateBitmap16bit]
55755 {$IFDEF ASM_VERSION}
55756 procedure _RotateBitmap16bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55758 PUSHAD
55759 XOR EBX, EBX
55760 CALL _PrepareBmp2Rotate
55762 ADD EBX, EBX
55763 ADD EDI, EBX // EDI = Dst
55764 MOV EBX, EDX // EBX = BytesPerDstLine
55765 DEC EBX
55766 DEC EBX
55767 MOV EBP, ESI // EBP = SrcBmp
55769 XOR EDX, EDX // Y = 0
55771 @@looY:
55772 PUSH EDX
55773 PUSH EDI
55775 MOV EAX, EBP
55776 CALL TBitmap.GetScanLine
55777 XCHG ESI, EAX
55778 MOV ECX, [EBP].TBitmap.fWidth
55780 @@looX:
55781 MOVSW
55782 ADD EDI, EBX
55783 LOOP @@looX
55785 POP EDI
55786 POP EDX
55788 DEC EDI
55789 DEC EDI
55790 INC EDX
55791 CMP EDX, [EBP].TBitmap.fHeight
55792 JL @@looY
55794 POPAD
55795 end;
55796 {$ELSE ASM_VERSION} //Pascal
55797 procedure _RotateBitmap16bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55798 var X, Y, Wwords, BytesPerDstLine: Integer;
55799 Src, Dst, Dst1: PWord;
55800 Tmp: Word;
55801 begin
55803 DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );
55805 // Calculate ones:
55806 Wwords := SrcBmp.fWidth;
55807 Dst := DstBmp.ScanLine[ 0 ];
55808 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55810 Inc( Dst, DstBmp.fWidth - 1 );
55812 // Rotating bits:
55813 for Y := 0 to SrcBmp.fHeight - 1 do
55814 begin
55815 Src := SrcBmp.ScanLine[ Y ];
55816 Dst1 := Dst;
55817 for X := Wwords downto 1 do
55818 begin
55819 Tmp := Src^;
55820 Inc( Src );
55821 Dst1^ := Tmp;
55822 Inc( PByte(Dst1), BytesPerDstLine );
55823 end;
55824 Dec( Dst );
55825 end;
55827 end;
55828 {$ENDIF ASM_VERSION}
55829 //[END _RotateBitmap16bit]
55831 //[PROCEDURE _RotateBitmap2432bit]
55832 {$IFDEF ASM_VERSION}
55833 procedure _RotateBitmap2432bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55835 PUSHAD
55836 XOR EBX, EBX
55837 CALL _PrepareBmp2Rotate
55839 SUB ECX, pf24bit
55840 JNZ @@10
55841 LEA EBX, [EBX+EBX*2]
55842 JMP @@11
55843 @@10:
55844 LEA EBX, [EBX*4]
55845 @@11: ADD EDI, EBX // EDI = Dst
55847 MOV EBX, EDX // EBX = BytesPerDstLine
55848 DEC EBX
55849 DEC EBX
55850 DEC EBX
55852 MOV EBP, ESI // EBP = SrcBmp
55854 XOR EDX, EDX // Y = 0
55856 @@looY:
55857 PUSH EDX
55858 PUSH EDI
55859 PUSH ECX // ECX = 0 if pf24bit (1 if pf32bit)
55861 MOV EAX, EBP
55862 CALL TBitmap.GetScanLine
55863 XCHG ESI, EAX
55864 MOV ECX, [EBP].TBitmap.fWidth
55865 POP EAX
55866 PUSH EAX
55868 @@looX:
55869 MOVSW
55870 MOVSB
55871 ADD ESI, EAX
55872 ADD EDI, EBX
55873 LOOP @@looX
55875 POP ECX
55876 POP EDI
55877 POP EDX
55879 DEC EDI
55880 DEC EDI
55881 DEC EDI
55882 SUB EDI, ECX
55883 INC EDX
55884 CMP EDX, [EBP].TBitmap.fHeight
55885 JL @@looY
55887 POPAD
55888 end;
55889 {$ELSE ASM_VERSION} //Pascal
55890 procedure _RotateBitmap2432bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55891 var X, Y, Wwords, BytesPerDstLine, IncW: Integer;
55892 Src, Dst, Dst1: PDWord;
55893 Tmp: DWord;
55894 begin
55896 DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );
55898 // Calculate ones:
55899 IncW := 4;
55900 if DstBmp.PixelFormat = pf24bit then
55901 IncW := 3;
55902 Wwords := SrcBmp.fWidth;
55903 Dst := DstBmp.ScanLine[ 0 ];
55904 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55906 Inc( PByte(Dst), (DstBmp.fWidth - 1) * IncW );
55908 // Rotating bits:
55909 for Y := 0 to SrcBmp.fHeight - 1 do
55910 begin
55911 Src := SrcBmp.ScanLine[ Y ];
55912 Dst1 := Dst;
55913 for X := Wwords downto 1 do
55914 begin
55915 Tmp := Src^ and $FFFFFF;
55916 Inc( PByte(Src), IncW );
55917 Dst1^ := Dst1^ or Tmp;
55918 Inc( PByte(Dst1), BytesPerDstLine );
55919 end;
55920 Dec( PByte(Dst), IncW );
55921 end;
55923 end;
55924 {$ENDIF ASM_VERSION}
55925 //[END _RotateBitmap2432bit]
55927 type
55928 TRotateBmpRefs = packed record
55929 proc_RotateBitmapMono: procedure( var Dst: PBitmap; Src: PBitmap );
55930 proc_RotateBitmap4bit: procedure( var Dst: PBitmap; Src: PBitmap );
55931 proc_RotateBitmap8bit: procedure( var Dst: PBitmap; Src: PBitmap );
55932 proc_RotateBitmap16bit: procedure( var Dst: PBitmap; Src: PBitmap );
55933 proc_RotateBitmap2432bit: procedure( var Dst: PBitmap; Src: PBitmap );
55934 end;
55937 RotateProcs: TRotateBmpRefs;
55939 //[PROCEDURE _RotateBitmapRight]
55940 {$IFDEF ASM_VERSION}
55941 procedure _RotateBitmapRight( SrcBmp: PBitmap );
55943 PUSH EBX
55944 PUSH EDI
55945 MOV EBX, EAX
55946 CMP [EBX].TBitmap.fHandleType, bmDIB
55947 JNZ @@exit
55949 CALL TBitmap.GetPixelFormat
55950 MOVZX ECX, AL
55951 LOOP @@not1bit
55952 MOV EAX, [RotateProcs.proc_RotateBitmapMono]
55953 @@not1bit:
55954 LOOP @@not4bit
55955 MOV EAX, [RotateProcs.proc_RotateBitmap4bit]
55956 @@not4bit:
55957 LOOP @@not8bit
55958 MOV EAX, [RotateProcs.proc_RotateBitmap8bit]
55959 @@not8bit:
55960 LOOP @@not15bit
55961 INC ECX
55962 @@not15bit:
55963 LOOP @@not16bit
55964 MOV EAX, [RotateProcs.proc_RotateBitmap16bit]
55965 @@not16bit:
55966 LOOP @@not24bit
55967 INC ECX
55968 @@not24bit:
55969 LOOP @@not32bit
55970 MOV EAX, [RotateProcs.proc_RotateBitmap2432bit]
55971 @@not32bit:
55972 TEST EAX, EAX
55973 JZ @@exit
55975 PUSH ECX
55976 XCHG ECX, EAX
55977 MOV EAX, ESP
55978 MOV EDX, EBX
55979 CALL ECX
55981 POP EDI
55982 MOV EAX, [EBX].TBitmap.fWidth
55983 CMP EAX, [EDI].TBitmap.fHeight
55984 JGE @@noCutHeight
55986 MOV EDX, [EDI].TBitmap.fScanLineSize
55987 MUL EDX
55988 MOV [EDI].TBitmap.fDIBSize, EAX
55990 MOV EDX, [EDI].TBitmap.fDIBHeader
55991 MOV EDX, [EDX].TBitmapInfoHeader.biHeight
55992 TEST EDX, EDX
55993 JL @@noCorrectImg
55995 PUSH EAX
55997 MOV EDX, [EDI].TBitmap.fHeight
55998 DEC EDX
55999 MOV EAX, EDI
56000 CALL TBitmap.GetScanLine
56001 PUSH EAX
56003 MOV EDX, [EBX].TBitmap.fWidth
56004 DEC EDX
56005 MOV EAX, EDI
56006 CALL TBitmap.GetScanLine
56007 POP EDX
56009 POP ECX
56010 CALL System.Move
56012 @@noCorrectImg:
56013 MOV EAX, [EBX].TBitmap.fWidth
56014 MOV [EDI].TBitmap.fHeight, EAX
56015 MOV EDX, [EDI].TBitmap.fDIBHeader
56016 MOV [EDX].TBitmapInfoHeader.biHeight, EAX
56018 @@noCutHeight:
56019 MOV EAX, EBX
56020 CALL TBitmap.ClearData
56022 XOR EAX, EAX
56023 XCHG EAX, [EDI].TBitmap.fDIBHeader
56024 XCHG [EBX].TBitmap.fDIBHeader, EAX
56026 XCHG EAX, [EDI].TBitmap.fDIBBits
56027 XCHG [EBX].TBitmap.fDIBBits, EAX
56029 MOV AL, [EDI].TBitmap.fDIBAutoFree
56030 MOV [EBX].TBitmap.fDIBAutoFree, AL
56032 MOV EAX, [EDI].TBitmap.fDIBSize
56033 MOV [EBX].TBitmap.fDIBSize, EAX
56035 MOV EAX, [EDI].TBitmap.fWidth
56036 MOV [EBX].TBitmap.fWidth, EAX
56038 MOV EAX, [EDI].TBitmap.fHeight
56039 MOV [EBX].TBitmap.fHeight, EAX
56041 XCHG EAX, EDI
56042 CALL TObj.Free
56043 @@exit:
56044 POP EDI
56045 POP EBX
56046 end;
56047 {$ELSE ASM_VERSION} //Pascal
56048 procedure _RotateBitmapRight( SrcBmp: PBitmap );
56049 var DstBmp: PBitmap;
56050 RotateProc: procedure( var DstBmp: PBitmap; SrcBmp: PBitmap );
56051 begin
56052 if SrcBmp.fHandleType <> bmDIB then Exit;
56054 case SrcBmp.PixelFormat of
56055 pf1bit: RotateProc := RotateProcs.proc_RotateBitmapMono;
56056 pf4bit: RotateProc := RotateProcs.proc_RotateBitmap4bit;
56057 pf8bit: RotateProc := RotateProcs.proc_RotateBitmap8bit;
56058 pf15bit, pf16bit: RotateProc := RotateProcs.proc_RotateBitmap16bit;
56059 else RotateProc := RotateProcs.proc_RotateBitmap2432bit;
56060 end;
56062 if not Assigned( RotateProc ) then Exit;
56063 RotateProc( DstBmp, SrcBmp );
56065 if DstBmp.fHeight > SrcBmp.fWidth then
56066 begin
56067 DstBmp.fDIBSize := DstBmp.fScanLineSize * SrcBmp.fWidth;
56068 //if DWORD( DstBmp.ScanLine[ 0 ] ) > DWORD( DstBmp.ScanLine[ 1 ] ) then
56069 if DstBmp.fDIBHeader.bmiHeader.biHeight > 0 then
56070 Move( DstBmp.ScanLine[ SrcBmp.fWidth - 1 ]^, DstBmp.ScanLine[ DstBmp.fHeight - 1 ]^,
56071 DstBmp.fDIBSize );
56072 DstBmp.fHeight := SrcBmp.fWidth;
56073 DstBmp.fDIBHeader.bmiHeader.biHeight := DstBmp.fHeight;
56074 end;
56076 SrcBmp.ClearData;
56078 //SrcBmp.fNewPixelFormat := DstBmp.PixelFormat;
56079 SrcBmp.fDIBHeader := DstBmp.fDIBHeader;
56080 DstBmp.fDIBHeader := nil;
56082 SrcBmp.fDIBBits := DstBmp.fDIBBits;
56083 DstBmp.fDIBBits := nil;
56084 SrcBmp.fDIBAutoFree := DstBmp.fDIBAutoFree;
56086 SrcBmp.fDIBSize := DstBmp.fDIBSize;
56088 SrcBmp.fWidth := DstBmp.fWidth;
56089 SrcBmp.fHeight := DstBmp.fHeight;
56090 DstBmp.Free;
56091 end;
56092 {$ENDIF ASM_VERSION}
56093 //[END _RotateBitmapRight]
56095 //[procedure TBitmap.RotateRight]
56096 procedure TBitmap.RotateRight;
56097 const AllRotators: TRotateBmpRefs = (
56098 proc_RotateBitmapMono: _RotateBitmapMono;
56099 proc_RotateBitmap4bit: _RotateBitmap4bit;
56100 proc_RotateBitmap8bit: _RotateBitmap8bit;
56101 proc_RotateBitmap16bit: _RotateBitmap16bit;
56102 proc_RotateBitmap2432bit: _RotateBitmap2432bit );
56103 begin
56104 RotateProcs := AllRotators;
56105 _RotateBitmapRight( @Self );
56106 end;
56108 //[procedure _RotateBitmapLeft]
56109 procedure _RotateBitmapLeft( Src: PBitmap );
56110 begin
56111 _RotateBitmapRight( Src );
56112 _RotateBitmapRight( Src );
56113 _RotateBitmapRight( Src );
56114 end;
56116 //[procedure TBitmap.RotateLeft]
56117 procedure TBitmap.RotateLeft;
56118 begin
56119 RotateRight;
56120 _RotateBitmapRight( @Self );
56121 _RotateBitmapRight( @Self );
56122 end;
56124 //[procedure TBitmap.RotateLeftMono]
56125 procedure TBitmap.RotateLeftMono;
56126 begin
56127 if PixelFormat <> pf1bit then Exit;
56128 RotateProcs.proc_RotateBitmapMono := _RotateBitmapMono;
56129 _RotateBitmapRight( @Self );
56130 end;
56132 //[procedure TBitmap.RotateRightMono]
56133 procedure TBitmap.RotateRightMono;
56134 begin
56135 if PixelFormat <> pf1bit then Exit;
56136 RotateProcs.proc_RotateBitmapMono := _RotateBitmapMono;
56137 _RotateBitmapLeft( @Self );
56138 end;
56140 //[procedure TBitmap.RotateLeft16bit]
56141 procedure TBitmap.RotateLeft16bit;
56142 begin
56143 if PixelFormat <> pf16bit then Exit;
56144 RotateProcs.proc_RotateBitmap16bit := _RotateBitmap16bit;
56145 _RotateBitmapLeft( @Self );
56146 end;
56148 //[procedure TBitmap.RotateLeft4bit]
56149 procedure TBitmap.RotateLeft4bit;
56150 begin
56151 if PixelFormat <> pf4bit then Exit;
56152 RotateProcs.proc_RotateBitmap4bit := _RotateBitmap4bit;
56153 _RotateBitmapLeft( @Self );
56154 end;
56156 //[procedure TBitmap.RotateLeft8bit]
56157 procedure TBitmap.RotateLeft8bit;
56158 begin
56159 if PixelFormat <> pf8bit then Exit;
56160 RotateProcs.proc_RotateBitmap8bit := _RotateBitmap8bit;
56161 _RotateBitmapLeft( @Self );
56162 end;
56164 //[procedure TBitmap.RotateLeftTrueColor]
56165 procedure TBitmap.RotateLeftTrueColor;
56166 begin
56167 if not (PixelFormat in [ pf24bit, pf32bit ]) then Exit;
56168 RotateProcs.proc_RotateBitmap2432bit := _RotateBitmap2432bit;
56169 _RotateBitmapLeft( @Self );
56170 end;
56172 //[procedure TBitmap.RotateRight16bit]
56173 procedure TBitmap.RotateRight16bit;
56174 begin
56175 if PixelFormat <> pf16bit then Exit;
56176 RotateProcs.proc_RotateBitmap16bit := _RotateBitmap16bit;
56177 _RotateBitmapRight( @Self );
56178 end;
56180 //[procedure TBitmap.RotateRight4bit]
56181 procedure TBitmap.RotateRight4bit;
56182 begin
56183 if PixelFormat <> pf4bit then Exit;
56184 RotateProcs.proc_RotateBitmap4bit := _RotateBitmap4bit;
56185 _RotateBitmapRight( @Self );
56186 end;
56188 //[procedure TBitmap.RotateRight8bit]
56189 procedure TBitmap.RotateRight8bit;
56190 begin
56191 if PixelFormat <> pf8bit then Exit;
56192 RotateProcs.proc_RotateBitmap8bit := _RotateBitmap8bit;
56193 _RotateBitmapRight( @Self );
56194 end;
56196 //[procedure TBitmap.RotateRightTrueColor]
56197 procedure TBitmap.RotateRightTrueColor;
56198 begin
56199 if not (PixelFormat in [ pf24bit, pf32bit ]) then Exit;
56200 RotateProcs.proc_RotateBitmap2432bit := _RotateBitmap2432bit;
56201 _RotateBitmapRight( @Self );
56202 end;
56204 {$IFDEF ASM_VERSION}
56205 //[function TBitmap.GetPixels]
56206 function TBitmap.GetPixels(X, Y: Integer): TColor;
56208 PUSH EBX
56209 MOV EBX, EAX
56210 PUSH ECX
56211 PUSH EDX
56212 CALL GetEmpty
56213 PUSHFD
56214 OR EAX, -1
56215 POPFD
56216 JZ @@exit
56218 CALL StartDC
56219 PUSH dword ptr [ESP+12]
56220 PUSH dword ptr [ESP+12]
56221 PUSH EAX
56222 CALL Windows.GetPixel
56223 XCHG EBX, EAX
56224 CALL FinishDC
56225 XCHG EAX, EBX
56226 @@exit:
56227 POP EDX
56228 POP EDX
56229 POP EBX
56230 end;
56231 {$ELSE ASM_VERSION} //Pascal
56232 function TBitmap.GetPixels(X, Y: Integer): TColor;
56233 var DC: HDC;
56234 Save: THandle;
56235 begin
56236 Result := clNone;
56237 //if GetHandle = 0 then Exit;
56238 if Empty then Exit;
56239 fDetachCanvas( @Self );
56240 DC := CreateCompatibleDC( 0 );
56241 Save := SelectObject( DC, GetHandle );
56242 ASSERT( Save <> 0, 'Can not select bitmap to DC' );
56243 Result := Windows.GetPixel( DC, X, Y );
56244 SelectObject( DC, Save );
56245 DeleteDC( DC );
56246 end;
56247 {$ENDIF ASM_VERSION}
56249 {$IFDEF ASM_VERSION}
56250 //[procedure TBitmap.SetPixels]
56251 procedure TBitmap.SetPixels(X, Y: Integer; const Value: TColor);
56253 PUSH EBX
56254 MOV EBX, EAX
56255 PUSH ECX
56256 PUSH EDX
56257 CALL GetEmpty
56258 JZ @@exit
56260 CALL StartDC
56261 MOV EAX, Value
56262 CALL Color2RGB
56263 PUSH EAX
56264 PUSH dword ptr [ESP+16]
56265 PUSH dword ptr [ESP+16]
56266 PUSH dword ptr [ESP+16]
56267 CALL Windows.SetPixel
56268 CALL FinishDC
56269 @@exit:
56270 POP EDX
56271 POP ECX
56272 POP EBX
56273 end;
56274 {$ELSE ASM_VERSION} //Pascal
56275 procedure TBitmap.SetPixels(X, Y: Integer; const Value: TColor);
56276 var DC: HDC;
56277 Save: THandle;
56278 begin
56279 //if GetHandle = 0 then Exit;
56280 if Empty then Exit;
56281 fDetachCanvas( @Self );
56282 DC := CreateCompatibleDC( 0 );
56283 Save := SelectObject( DC, GetHandle );
56284 ASSERT( Save <> 0, 'Can not select bitmap to DC' );
56285 Windows.SetPixel( DC, X, Y, Color2RGB( Value ) );
56286 SelectObject( DC, Save );
56287 DeleteDC( DC );
56288 end;
56289 {$ENDIF ASM_VERSION}
56291 //[FUNCTION _GetDIBPixelsPalIdx]
56292 {$IFDEF ASM_VERSION}
56293 function _GetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer ): TColor;
56294 const szBIH = Sizeof(TBitmapInfoHeader);
56296 PUSH EBX
56297 PUSH EDI
56298 PUSH EDX
56299 XCHG EBX, EAX
56301 XCHG EAX, EDX
56302 MOV EDI, [EBX].TBitmap.fPixelsPerByteMask
56303 INC EDI
56305 DIV EDI
56306 DEC EDI
56307 XCHG ECX, EAX // EAX = Y, ECX = X div (Bmp.fPixeldPerByteMask+1)
56309 MOV EDX, [EBX].TBitmap.fScanLineDelta
56310 IMUL EDX
56312 ADD EAX, [EBX].TBitmap.fScanLine0
56313 MOVZX EAX, byte ptr[EAX+ECX]
56315 POP EDX
56316 MOV ECX, [EBX].TBitmap.fPixelsPerByteMask
56317 AND EDX, ECX
56318 SUB ECX, EDX
56320 PUSH EAX
56321 MOV EDI, [EBX].TBitmap.fDIBHeader
56322 MOVZX EAX, [EDI].TBitmapInfoHeader.biBitCount
56323 MUL ECX
56324 XCHG ECX, EAX
56325 POP EAX
56326 SHR EAX, CL
56327 AND EAX, [EBX].TBitmap.fPixelMask
56329 MOV EAX, [EDI+szBIH+EAX*4]
56330 CALL Color2RGBQuad
56332 POP EDI
56333 POP EBX
56334 end;
56335 {$ELSE ASM_VERSION} //Pascal
56336 function _GetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer ): TColor;
56337 var Pixel: Byte;
56338 begin
56339 Pixel := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta
56340 + (X div (Bmp.fPixelsPerByteMask + 1)) )^;
56341 Pixel := ( Pixel shr ( (Bmp.fPixelsPerByteMask - (X and Bmp.fPixelsPerByteMask))
56342 * Bmp.fDIBHeader.bmiHeader.biBitCount ) )
56343 and Bmp.fPixelMask;
56344 Result := TColor( Color2RGBQuad( TColor( PRGBQuad( DWORD(@Bmp.fDIBHeader.bmiColors[ 0 ])
56345 + Pixel * Sizeof( TRGBQuad ) )^ ) ) );
56346 end;
56347 {$ENDIF ASM_VERSION}
56348 //[END _GetDIBPixelsPalIdx]
56350 //[FUNCTION _GetDIBPixels16bit]
56351 {$IFDEF ASM_VERSION}
56352 function _GetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer ): TColor;
56354 PUSH [EAX].TBitmap.fPixelMask
56355 PUSH EDX // X
56356 PUSH EAX
56357 MOV EAX, [EAX].TBitmap.fScanLineDelta
56358 IMUL ECX
56359 POP EDX
56360 ADD EAX, [EDX].TBitmap.fScanLine0
56361 POP ECX
56362 MOVZX EAX, word ptr [EAX+ECX*2]
56363 POP EDX
56364 CMP DL, 15
56365 JNE @@16bit
56367 MOV EDX, EAX
56368 SHR EDX, 7
56369 SHL EAX, 6
56370 MOV DH, AH
56371 AND DH, $F8
56372 SHL EAX, 13
56373 JMP @@1516bit
56375 @@16bit:
56376 MOV DL, AH
56377 SHL EAX, 5
56378 MOV DH, AH
56379 SHL EAX, 14
56380 @@1516bit:
56381 AND EAX, $F80000
56382 OR EAX, EDX
56383 AND AX, $FCF8
56384 end;
56385 {$ELSE ASM_VERSION} //Pascal
56386 function _GetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer ): TColor;
56387 var Pixel: Word;
56388 begin
56389 Pixel := PWord( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X * 2 )^;
56390 if Bmp.fPixelMask = 15 then
56391 Result := (Pixel shr 7) and $F8 or (Pixel shl 6) and $F800
56392 or (Pixel shl 19) and $F80000
56393 else
56394 Result := (Pixel shr 8) and $F8 or (Pixel shl 5) and $FC00
56395 or (Pixel shl 19) and $F80000;
56396 end;
56397 {$ENDIF ASM_VERSION}
56398 //[END _GetDIBPixels16bit]
56400 //[FUNCTION _GetDIBPixelsTrueColor]
56401 {$IFDEF ASM_VERSION}
56402 function _GetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer ): TColor;
56404 PUSH EBX
56405 XCHG EBX, EAX
56406 PUSH EDX
56407 MOV EAX, [EBX].TBitmap.fScanLineDelta
56408 IMUL ECX
56409 XCHG ECX, EAX
56410 POP EDX
56411 MOV EAX, [EBX].TBitmap.fBytesPerPixel
56412 MUL EDX
56413 ADD EAX, [EBX].TBitmap.fScanLine0
56414 MOV EAX, [EAX+ECX]
56415 AND EAX, $FFFFFF
56416 CALL Color2RGBQuad
56417 POP EBX
56418 end;
56419 {$ELSE ASM_VERSION} //Pascal
56420 function _GetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer ): TColor;
56421 var Pixel: DWORD;
56422 begin
56423 Pixel := PDWORD( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta +
56424 X * Bmp.fBytesPerPixel )^ and $FFFFFF;
56425 Result := TColor( Color2RGBQuad( TColor( Pixel ) ) );
56426 end;
56427 {$ENDIF ASM_VERSION}
56428 //[END _GetDIBPixelsTrueColor]
56430 {$IFDEF ASM_VERSION}
56431 //[function TBitmap.GetDIBPixels]
56432 function TBitmap.GetDIBPixels(X, Y: Integer): TColor;
56434 CMP word ptr [EAX].fGetDIBPixels+2, 0
56435 JNZ @@assigned
56437 // if not assigned, this preparing will be performed for first call:
56438 CMP [EAX].fHandleType, bmDDB
56439 JZ @@GetPixels
56441 PUSHAD
56442 MOV EBX, EAX
56443 XOR EDX, EDX
56444 CALL GetScanLine
56445 MOV [EBX].fScanLine0, EAX
56446 XOR EDX, EDX
56447 INC EDX
56448 MOV EAX, EBX
56449 CALL GetScanLine
56450 SUB EAX, [EBX].fScanLine0
56451 MOV [EBX].fScanLineDelta, EAX
56452 MOV EAX, EBX
56453 CALL GetPixelFormat
56454 MOVZX ECX, AL
56455 MOV DX, $0F00
56456 MOV byte ptr [EBX].fBytesPerPixel, 4
56457 XOR EAX, EAX
56458 LOOP @@if4bit
56459 MOV DX, $0107
56460 JMP @@1bit4bit8bit
56461 @@if4bit:
56462 LOOP @@if8bit
56463 INC EDX // MOV DX, $0F01
56464 JMP @@1bit4bit8bit
56465 @@if8bit:
56466 LOOP @@if15bit
56467 MOV DH, $FF //MOV DX, $FF00
56468 @@1bit4bit8bit:
56469 MOV EAX, offset[_GetDIBPixelsPalIdx]
56470 @@if15bit:
56471 LOOP @@if16bit
56472 //MOV DH, $0F
56473 DEC DH
56474 INC ECX
56475 @@if16bit:
56476 LOOP @@if24bit
56477 INC DH
56478 MOV EAX, offset[_GetDIBPixels16bit]
56479 @@if24bit:
56480 LOOP @@if32bit
56481 DEC [EBX].fBytesPerPixel
56482 INC ECX
56483 DEC EDX
56484 @@if32bit:
56485 LOOP @@iffin
56486 INC EDX
56487 MOV EAX, offset[_GetDIBPixelsTrueColor]
56488 @@iffin:
56489 MOV byte ptr [EBX].fPixelMask, DH
56490 MOV byte ptr [EBX].fPixelsPerByteMask, DL
56491 MOV [EBX].fGetDIBPixels, EAX
56492 TEST EAX, EAX
56493 POPAD
56494 @@GetPixels:
56495 JZ GetPixels
56497 @@assigned:
56498 JMP [EAX].fGetDIBPixels
56499 end;
56500 {$ELSE ASM_VERSION} //Pascal
56501 function TBitmap.GetDIBPixels(X, Y: Integer): TColor;
56502 begin
56503 if not Assigned( fGetDIBPixels ) then
56504 begin
56505 if fHandleType = bmDIB then
56506 begin
56507 fScanLine0 := ScanLine[ 0 ];
56508 fScanLineDelta := Integer(ScanLine[ 1 ]) - Integer(fScanLine0);
56509 case PixelFormat of
56510 pf1bit:
56511 begin
56512 fPixelMask := $01;
56513 fPixelsPerByteMask := 7;
56514 fGetDIBPixels := _GetDIBPixelsPalIdx;
56515 end;
56516 pf4bit:
56517 begin
56518 fPixelMask := $0F;
56519 fPixelsPerByteMask := 1;
56520 fGetDIBPixels := _GetDIBPixelsPalIdx;
56521 end;
56522 pf8bit:
56523 begin
56524 fPixelMask := $FF;
56525 fPixelsPerByteMask := 0;
56526 fGetDIBPixels := _GetDIBPixelsPalIdx;
56527 end;
56528 pf15bit:
56529 begin
56530 fPixelMask := 15;
56531 fGetDIBPixels := _GetDIBPixels16bit;
56532 end;
56533 pf16bit:
56534 begin
56535 fPixelMask := 16;
56536 fGetDIBPixels := _GetDIBPixels16bit;
56537 end;
56538 pf24bit:
56539 begin
56540 fPixelsPerByteMask := 0;
56541 fBytesPerPixel := 3;
56542 fGetDIBPixels := _GetDIBPixelsTrueColor;
56543 end;
56544 pf32bit:
56545 begin
56546 fPixelsPerByteMask := 1;
56547 fBytesPerPixel := 4;
56548 fGetDIBPixels := _GetDIBPixelsTrueColor;
56549 end;
56550 else;
56551 end;
56552 end;
56553 if not Assigned( fGetDIBPixels ) then
56554 begin
56555 Result := Pixels[ X, Y ];
56556 Exit;
56557 end;
56558 end;
56559 Result := fGetDIBPixels( @Self, X, Y );
56560 end;
56561 {$ENDIF ASM_VERSION}
56563 //[PROCEDURE _SetDIBPixels1bit]
56564 {$IFDEF ASM_VERSION}
56565 procedure _SetDIBPixels1bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56567 PUSH EDX
56568 PUSH [EAX].TBitmap.fScanLine0
56569 PUSH ECX
56570 PUSH [EAX].TBitmap.fScanLineDelta
56571 MOV EAX, Value
56572 CALL Color2RGB
56573 MOV EDX, EAX
56574 SHR EAX, 16
56575 ADD AL, DL
56576 ADC AL, DH
56577 CMP EAX, 170
56578 SETGE CL
56579 AND ECX, 1
56580 SHL ECX, 7
56581 POP EAX
56582 POP EDX
56583 IMUL EDX
56584 POP EDX
56585 ADD EAX, EDX
56586 POP EDX
56587 PUSH ECX
56588 MOV ECX, EDX
56589 SHR EDX, 3
56590 ADD EAX, EDX
56591 AND ECX, 7
56592 MOV DX, $FF7F
56593 SHR EDX, CL
56594 AND byte ptr [EAX], DL
56595 POP EDX
56596 SHR EDX, CL
56597 OR byte ptr [EAX], DL
56598 end;
56599 {$ELSE ASM_VERSION} //Pascal
56600 procedure _SetDIBPixels1bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56601 var Pixel: Byte;
56602 Pos: PByte;
56603 Shf: Integer;
56604 begin
56605 Value := Color2RGB( Value );
56606 if ((Value shr 16) and $FF) + ((Value shr 8) and $FF) + (Value and $FF)
56607 < 255 * 3 div 2 then Pixel := 0 else Pixel := $80;
56608 Pos := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X div 8 );
56609 Shf := X and 7;
56610 Pos^ := Pos^ and ($FF7F shr Shf) or (Pixel shr Shf);
56611 end;
56612 {$ENDIF ASM_VERSION}
56613 //[END _SetDIBPixels1bit]
56615 //[PROCEDURE _SetDIBPixelsPalIdx]
56616 {$IFDEF ASM_VERSION}
56617 procedure _SetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56619 XCHG EAX, EBP
56620 PUSH EDX // -> X
56621 PUSH ECX // -> Y
56622 MOV ECX, [EBP].TBitmap.fPixelsPerByteMask
56623 INC ECX
56624 XCHG EAX, EDX
56626 DIV ECX
56627 XCHG ECX, EAX // ECX = X div (fPixelsPerByteMask+1)
56628 POP EAX // <- Y
56629 MOV EDX, [EBP].TBitmap.fScanLineDelta
56630 IMUL EDX
56631 ADD ECX, EAX
56632 ADD ECX, [EBP].TBitmap.fScanLine0 // ECX = Pos
56633 PUSH ECX // -> Pos
56635 MOV EDX, [ESP+16] // Value
56636 MOV EAX, EBP
56637 CALL TBitmap.DIBPalNearestEntry // EAX = Pixel
56639 POP ECX // <- Pos
56640 POP EDX // <- X
56642 PUSH EAX // -> Pixel
56644 MOV EAX, [EBP].TBitmap.fPixelsPerByteMask
56645 AND EDX, EAX
56646 SUB EAX, EDX
56647 MOV EDX, [EBP].TBitmap.fDIBHeader
56648 MOVZX EDX, [EDX].TBitmapInfoHeader.biBitCount
56649 MUL EDX // EAX = Shf
56651 XCHG ECX, EAX // ECX = Shf, EAX = Pos
56652 MOV EDX, [EBP].TBitmap.fPixelMask
56653 SHL EDX, CL
56654 NOT EDX
56655 AND byte ptr [EAX], DL
56657 POP EDX // <- Pixel
56658 SHL EDX, CL
56659 OR byte ptr [EAX], DL
56660 end;
56661 {$ELSE ASM_VERSION} //Pascal
56662 procedure _SetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56663 var Pixel: Byte;
56664 Pos: PByte;
56665 Shf: Integer;
56666 begin
56667 Pixel := Bmp.DIBPalNearestEntry( Value );
56668 Pos := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta
56669 + X div (Bmp.fPixelsPerByteMask + 1) );
56670 Shf := (Bmp.fPixelsPerByteMask - (X and Bmp.fPixelsPerByteMask))
56671 * Bmp.fDIBHeader.bmiHeader.biBitCount;
56672 Pos^ := Pos^ and not (Bmp.fPixelMask shl Shf) or (Pixel shl Shf);
56673 end;
56674 {$ENDIF ASM_VERSION}
56675 //[END _SetDIBPixelsPalIdx]
56677 //[PROCEDURE _SetDIBPixels16bit]
56678 {$IFDEF ASM_VERSION}
56679 procedure _SetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56681 ADD EDX, EDX
56682 ADD EDX, [EAX].TBitmap.fScanLine0
56683 PUSH EDX // -> X*2 + Bmp.fScanLine0
56684 PUSH [EAX].TBitmap.fPixelMask
56685 MOV EAX, [EAX].TBitmap.fScanLineDelta
56686 IMUL ECX
56687 PUSH EAX // -> Y* Bmp.fScanLineDelta
56688 MOV EAX, Value
56689 CALL Color2RGB
56690 POP EBP // <- Y* Bmp.fScanLineDelta
56691 POP EDX
56692 XOR ECX, ECX
56693 SUB DL, 16
56694 JZ @@16bit
56696 MOV CH, AL
56697 SHR CH, 1
56698 SHR EAX, 6
56699 MOV EDX, EAX
56700 AND DX, $3E0
56701 SHR EAX, 13
56702 JMP @@1516
56704 @@16bit:
56705 {$IFDEF PARANOIA}
56706 DB $24, $F8
56707 {$ELSE}
56708 AND AL, $F8
56709 {$ENDIF}
56710 MOV CH, AL
56711 SHR EAX, 5
56712 MOV EDX, EAX
56713 AND DX, $7E0
56714 SHR EAX, 14
56716 @@1516:
56717 MOV AH, CH
56718 AND AX, $FC1F
56719 OR AX, DX
56721 POP EDX
56722 MOV [EBP+EDX], AX
56723 end;
56724 {$ELSE ASM_VERSION} //Pascal
56725 procedure _SetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56726 var RGB16: Word;
56727 Pos: PWord;
56728 begin
56729 Value := Color2RGB( Value );
56730 if Bmp.fPixelMask = 15 then
56731 RGB16 := (Value shr 19) and $001F or (Value shr 6) and $03E0
56732 or (Value shl 7) and $7C00
56733 else
56734 RGB16 := (Value shr 19) and $001F or (Value shr 5) and $07E0
56735 or (Value shl 8) and $F800;
56736 Pos := PWord( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X * 2 );
56737 Pos^ := RGB16;
56738 end;
56739 {$ENDIF ASM_VERSION}
56740 //[END _SetDIBPixels16bit]
56742 //[PROCEDURE _SetDIBPixelsTrueColor]
56743 {$IFDEF ASM_VERSION}
56744 procedure _SetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56746 PUSH [EAX].TBitmap.fScanLineDelta
56747 PUSH [EAX].TBitmap.fScanLine0
56748 MOV EAX, [EAX].TBitmap.fBytesPerPixel
56749 MUL EDX
56750 POP EDX
56751 ADD EDX, EAX
56752 POP EAX
56753 PUSH EDX
56754 IMUL ECX
56755 POP EDX
56756 ADD EDX, EAX
56757 PUSH EDX
56758 MOV EAX, Value
56759 CALL Color2RGBQuad
56760 POP EDX
56761 AND dword ptr [EDX], $FF000000
56762 OR [EDX], EAX
56763 end;
56764 {$ELSE ASM_VERSION} //Pascal
56765 procedure _SetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56766 var RGB: TRGBQuad;
56767 Pos: PDWord;
56768 begin
56769 //Value := Color2RGB( Value );
56770 RGB := Color2RGBQuad( Value );
56771 Pos := PDWORD( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta
56772 + X * Bmp.fBytesPerPixel );
56773 Pos^ := Pos^ and $FF000000 or DWORD(RGB);
56774 end;
56775 {$ENDIF ASM_VERSION}
56776 //[END _SetDIBPixelsTrueColor]
56778 {$IFDEF ASM_VERSION}
56779 //[procedure TBitmap.SetDIBPixels]
56780 procedure TBitmap.SetDIBPixels(X, Y: Integer; const Value: TColor);
56782 CMP word ptr [EAX].fSetDIBPixels+2, 0
56783 JNZ @@assigned
56784 PUSHAD
56785 MOV EBX, EAX
56786 XOR EDX, EDX
56787 CMP [EBX].fHandleType, DL // bmDIB = 0
56788 JNE @@ddb
56789 CALL GetScanLine
56790 MOV [EBX].fScanLine0, EAX
56791 XOR EDX, EDX
56792 INC EDX
56793 MOV EAX, EBX
56794 CALL GetScanLine
56795 SUB EAX, [EBX].fScanLine0
56796 MOV [EBX].fScanLineDelta, EAX
56797 MOV EAX, EBX
56798 CALL GetPixelFormat
56799 MOVZX ECX, AL
56800 MOV DX, $0F01
56801 MOV EAX, offset[_SetDIBPixelsPalIdx]
56802 MOV byte ptr [EBX].fBytesPerPixel, 4
56803 LOOP @@if4bit
56804 MOV EAX, offset[_SetDIBPixels1bit]
56805 @@if4bit:
56806 LOOP @@if8bit
56807 @@if8bit:
56808 LOOP @@if15bit
56809 DEC DL
56810 MOV DH, $FF
56811 @@if15bit:
56812 LOOP @@if16bit
56813 DEC DH
56814 INC ECX
56815 @@if16bit:
56816 LOOP @@if24bit
56817 INC DH
56818 MOV EAX, offset[_SetDIBPixels16bit]
56819 @@if24bit:
56820 LOOP @@if32bit
56821 DEC EDX
56822 DEC [EBX].fBytesPerPixel
56823 INC ECX
56824 @@if32bit:
56825 LOOP @@ifend
56826 INC EDX
56827 MOV EAX, offset[_SetDIBPixelsTrueColor]
56828 @@ifend:
56829 MOV byte ptr [EBX].fPixelMask, DH
56830 MOV byte ptr [EBX].fPixelsPerByteMask, DL
56831 MOV [EBX].fSetDIBPixels, EAX
56832 TEST EAX, EAX
56833 @@ddb:
56834 POPAD
56835 JNZ @@assigned
56836 PUSH Value
56837 CALL SetPixels
56838 JMP @@exit
56839 @@assigned:
56840 PUSH Value
56841 CALL [EAX].fSetDIBPixels
56842 @@exit:
56843 end;
56844 {$ELSE ASM_VERSION} //Pascal
56845 procedure TBitmap.SetDIBPixels(X, Y: Integer; const Value: TColor);
56846 begin
56847 if not Assigned( fSetDIBPixels ) then
56848 begin
56849 if fHandleType = bmDIB then
56850 begin
56851 fScanLine0 := ScanLine[ 0 ];
56852 fScanLineDelta := Integer(ScanLine[ 1 ]) - Integer(fScanLine0);
56853 case PixelFormat of
56854 pf1bit:
56855 begin
56856 //fPixelMask := $01;
56857 //fPixelsPerByteMask := 7;
56858 fSetDIBPixels := _SetDIBPixels1bit;
56859 end;
56860 pf4bit:
56861 begin
56862 fPixelMask := $0F;
56863 fPixelsPerByteMask := 1;
56864 fSetDIBPixels := _SetDIBPixelsPalIdx;
56865 end;
56866 pf8bit:
56867 begin
56868 fPixelMask := $FF;
56869 fPixelsPerByteMask := 0;
56870 fSetDIBPixels := _SetDIBPixelsPalIdx;
56871 end;
56872 pf15bit:
56873 begin
56874 fPixelMask := 15;
56875 fSetDIBPixels := _SetDIBPixels16bit;
56876 end;
56877 pf16bit:
56878 begin
56879 fPixelMask := 16;
56880 fSetDIBPixels := _SetDIBPixels16bit;
56881 end;
56882 pf24bit:
56883 begin
56884 fPixelsPerByteMask := 0;
56885 fBytesPerPixel := 3;
56886 fSetDIBPixels := _SetDIBPixelsTrueColor;
56887 end;
56888 pf32bit:
56889 begin
56890 fPixelsPerByteMask := 1;
56891 fBytesPerPixel := 4;
56892 fSetDIBPixels := _SetDIBPixelsTrueColor;
56893 end;
56894 else;
56895 end;
56896 end;
56897 if not Assigned( fSetDIBPixels ) then
56898 begin
56899 Pixels[ X, Y ] := Value;
56900 Exit;
56901 end;
56902 end;
56903 fSetDIBPixels( @Self, X, Y, Value );
56904 end;
56905 {$ENDIF ASM_VERSION}
56907 {$IFDEF ASM_VERSION}
56908 //[procedure TBitmap.FlipVertical]
56909 procedure TBitmap.FlipVertical;
56911 PUSH EBX
56912 MOV EBX, EAX
56913 MOV ECX, [EBX].fHandle
56914 JECXZ @@noHandle
56916 CALL StartDC
56917 PUSH SrcCopy
56918 MOV EDX, [EBX].fHeight
56919 PUSH EDX
56920 MOV ECX, [EBX].fWidth
56921 PUSH ECX
56922 PUSH 0
56923 PUSH 0
56924 PUSH EAX
56925 NEG EDX
56926 PUSH EDX
56927 PUSH ECX
56928 NEG EDX
56929 DEC EDX
56930 PUSH EDX
56931 PUSH 0
56932 PUSH EAX
56933 CALL StretchBlt
56934 CALL FinishDC
56935 POP EBX
56938 @@noHandle:
56939 MOV ECX, [EBX].fDIBBits
56940 JECXZ @@exit
56942 PUSHAD //----------------------------------------\
56943 XOR EBP, EBP // Y = 0
56944 //+++++++++++++++++++++++++++ provide fScanLineSize
56945 MOV EAX, EBX
56946 MOV EDX, EBP
56947 CALL GetScanLine //
56948 SUB ESP, [EBX].fScanLineSize
56950 @@loo: LEA EAX, [EBP*2]
56951 CMP EAX, [EBX].fHeight
56952 JG @@finloo
56954 MOV EAX, EBX
56955 MOV EDX, EBP
56956 CALL GetScanLine
56957 MOV ESI, EAX // ESI = ScanLine[ Y ]
56958 MOV EDX, ESP
56959 MOV ECX, [EBX].fScanLineSize
56960 PUSH ECX
56961 CALL System.Move
56963 MOV EAX, EBX
56964 MOV EDX, [EBX].fHeight
56965 SUB EDX, EBP
56966 DEC EDX
56967 CALL GetScanLine
56968 MOV EDI, EAX
56969 MOV EDX, ESI
56970 POP ECX
56971 PUSH ECX
56972 CALL System.Move
56974 POP ECX
56975 MOV EAX, ESP
56976 MOV EDX, EDI
56977 CALL System.Move
56979 INC EBP
56980 JMP @@loo
56982 @@finloo:
56983 ADD ESP, [EBX].fScanLineSize
56984 POPAD
56985 @@exit:
56986 POP EBX
56987 end;
56988 {$ELSE ASM_VERSION} //Pascal
56989 procedure TBitmap.FlipVertical;
56990 var DC: HDC;
56991 Save: THandle;
56992 TmpScan: PByte;
56993 Y: Integer;
56994 begin
56995 if fHandle <> 0 then
56996 begin
56997 fDetachCanvas( @Self );
56998 DC := CreateCompatibleDC( 0 );
56999 Save := SelectObject( DC, fHandle );
57000 StretchBlt( DC, 0, fHeight - 1, fWidth, -fHeight, DC, 0, 0, fWidth, fHeight, SRCCOPY );
57001 SelectObject( DC, Save );
57002 DeleteDC( DC );
57004 else
57005 if fDIBBits <> nil then
57006 begin
57007 GetMem( TmpScan, ScanLineSize );
57008 for Y := 0 to fHeight div 2 do
57009 begin
57010 Move( ScanLine[ Y ]^, TmpScan^, fScanLineSize );
57011 Move( ScanLine[ fHeight - Y - 1 ]^, ScanLine[ Y ]^, fScanLineSize );
57012 Move( TmpScan^, ScanLine[ fHeight - Y - 1 ]^, fScanLineSize );
57013 end;
57014 end;
57015 end;
57016 {$ENDIF ASM_VERSION}
57018 {$IFDEF ASM_VERSION}
57019 //[procedure TBitmap.FlipHorizontal]
57020 procedure TBitmap.FlipHorizontal;
57022 PUSH EBX
57023 MOV EBX, EAX
57024 CALL GetHandle
57025 TEST EAX, EAX
57026 JZ @@exit
57028 CALL StartDC
57029 PUSH SrcCopy
57030 MOV EDX, [EBX].fHeight
57031 PUSH EDX
57032 MOV ECX, [EBX].fWidth
57033 PUSH ECX
57034 PUSH 0
57035 PUSH 0
57036 PUSH EAX
57037 PUSH EDX
57038 NEG ECX
57039 PUSH ECX
57040 PUSH 0
57041 NEG ECX
57042 DEC ECX
57043 PUSH ECX
57044 PUSH EAX
57045 CALL StretchBlt
57046 CALL FinishDC
57047 @@exit:
57048 POP EBX
57049 end;
57050 {$ELSE ASM_VERSION} //Pascal
57051 procedure TBitmap.FlipHorizontal;
57052 var DC: HDC;
57053 Save: THandle;
57054 begin
57055 if GetHandle <> 0 then
57056 begin
57057 fDetachCanvas( @Self );
57058 DC := CreateCompatibleDC( 0 );
57059 Save := SelectObject( DC, fHandle );
57060 StretchBlt( DC, fWidth - 1, 0, -fWidth, fHeight, DC, 0, 0, fWidth, fHeight, SRCCOPY );
57061 SelectObject( DC, Save );
57062 DeleteDC( DC );
57063 end;
57064 end;
57065 {$ENDIF ASM_VERSION}
57067 {$IFDEF ASM_VERSION}
57068 //[procedure TBitmap.CopyRect]
57069 procedure TBitmap.CopyRect(const DstRect: TRect; SrcBmp: PBitmap;
57070 const SrcRect: TRect);
57072 PUSHAD
57073 MOV EBX, EAX
57074 MOV ESI, ECX
57075 MOV EDI, EDX
57076 CALL GetHandle
57077 TEST EAX, EAX
57078 JZ @@exit
57079 MOV EAX, ESI
57080 CALL GetHandle
57081 TEST EAX, EAX
57082 JZ @@exit
57083 CALL StartDC
57084 XCHG EBX, ESI
57085 CMP EBX, ESI
57086 JNZ @@diff1
57087 PUSH EAX
57088 PUSH 0
57089 JMP @@nodiff1
57090 @@diff1:
57091 CALL StartDC
57092 @@nodiff1:
57093 PUSH SrcCopy // ->
57094 MOV EBP, [SrcRect]
57095 MOV EAX, [EBP].TRect.Bottom
57096 MOV EDX, [EBP].TRect.Top
57097 SUB EAX, EDX
57098 PUSH EAX // ->
57099 MOV EAX, [EBP].TRect.Right
57100 MOV ECX, [EBP].TRect.Left
57101 SUB EAX, ECX
57102 PUSH EAX // ->
57103 PUSH EDX // ->
57104 PUSH ECX // ->
57105 PUSH dword ptr [ESP+24] // -> DCsrc
57106 MOV EAX, [EDI].TRect.Bottom
57107 MOV EDX, [EDI].TRect.Top
57108 SUB EAX, EDX
57109 PUSH EAX // ->
57110 MOV EAX, [EDI].TRect.Right
57111 MOV ECX, [EDI].TRect.Left
57112 SUB EAX, ECX
57113 PUSH EAX // ->
57114 PUSH EDX // ->
57115 PUSH ECX // ->
57116 PUSH dword ptr [ESP+13*4] // -> DCdst
57117 CALL StretchBlt
57118 CMP EBX, ESI
57119 JNE @@diff2
57120 POP ECX
57121 POP ECX
57122 JMP @@nodiff2
57123 @@diff2:
57124 CALL FinishDC
57125 @@nodiff2:
57126 CALL FinishDC
57127 @@exit:
57128 POPAD
57129 end;
57130 {$ELSE ASM_VERSION} //Pascal
57131 procedure TBitmap.CopyRect(const DstRect: TRect; SrcBmp: PBitmap;
57132 const SrcRect: TRect);
57133 var DCsrc, DCdst: HDC;
57134 SaveSrc, SaveDst: THandle;
57135 begin
57136 if (GetHandle = 0) or (SrcBmp.GetHandle = 0) then Exit;
57137 fDetachCanvas( @Self );
57138 fDetachCanvas( SrcBmp );
57139 DCsrc := CreateCompatibleDC( 0 );
57140 SaveSrc := SelectObject( DCsrc, SrcBmp.fHandle );
57141 DCdst := DCsrc;
57142 SaveDst := 0;
57143 if SrcBmp <> @Self then
57144 begin
57145 DCdst := CreateCompatibleDC( 0 );
57146 SaveDst := SelectObject( DCdst, fHandle );
57147 end;
57148 StretchBlt( DCdst, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left,
57149 DstRect.Bottom - DstRect.Top, DCsrc, SrcRect.Left, SrcRect.Top,
57150 SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top,
57151 SRCCOPY );
57152 if SrcBmp <> @Self then
57153 begin
57154 SelectObject( DCdst, SaveDst );
57155 DeleteDC( DCdst );
57156 end;
57157 SelectObject( DCsrc, SaveSrc );
57158 DeleteDC( DCsrc );
57159 end;
57160 {$ENDIF ASM_VERSION}
57163 //[function TBitmap.CopyToClipboard]
57164 function TBitmap.CopyToClipboard: Boolean;
57165 var DibMem: PChar;
57166 HdrSize: Integer;
57167 Gbl: HGlobal;
57168 begin
57169 Result := FALSE;
57170 if Applet = nil then Exit;
57171 if not OpenClipboard( Applet.GetWindowHandle ) then
57172 Exit;
57173 if EmptyClipboard then
57174 begin
57175 HandleType := bmDIB;
57176 HdrSize := sizeof( TBitmapInfoHeader );
57177 if fDIBHeader.bmiHeader.biBitCount <= 8 then
57178 Inc( HdrSize,
57179 (1 shl fDIBHeader.bmiHeader.biBitCount) * Sizeof( TRGBQuad ) );
57180 Gbl := GlobalAlloc( GMEM_MOVEABLE, HdrSize + fDIBSize );
57181 DibMem := GlobalLock( Gbl );
57182 if DibMem <> nil then
57183 begin
57184 Move( fDIBHeader^, DibMem^, HdrSize );
57185 Move( fDIBBits^, Pointer( Integer( DibMem ) + HdrSize )^, fDIBSize );
57186 if not GlobalUnlock( Gbl ) and (GetLastError = NO_ERROR) then
57187 begin
57188 Result := SetClipboardData( CF_DIB, Gbl ) <> 0;
57189 end;
57190 end;
57191 end;
57192 CloseClipboard;
57193 end;
57195 //[function TBitmap.PasteFromClipboard]
57196 function TBitmap.PasteFromClipboard: Boolean;
57197 var Gbl: HGlobal;
57198 //DIBPtr: PChar;
57199 Size {, HdrSize}: Integer;
57200 Mem: PChar;
57201 Strm: PStream;
57202 begin
57203 Result := FALSE;
57204 if Applet = nil then Exit;
57205 if not OpenClipboard( Applet.GetWindowHandle ) then Exit;
57207 if IsClipboardFormatAvailable( CF_DIB ) then
57208 begin
57209 Gbl := GetClipboardData( CF_DIB );
57210 if Gbl <> 0 then
57211 begin
57212 Size := GlobalSize( Gbl );
57213 Mem := GlobalLock( Gbl );
57215 if (Size > 0) and (Mem <> nil) then
57216 begin
57217 Strm := NewMemoryStream;
57218 Strm.Write( Mem^, Size );
57219 Strm.Position := 0;
57220 LoadFromStreamEx( Strm );
57221 Strm.Free;
57222 Result := not Empty;
57223 end;
57224 FINALLY
57225 GlobalUnlock( Gbl );
57226 END;
57227 end;
57228 end;
57229 FINALLY
57230 CloseClipboard;
57231 END;
57232 end;
57242 ///////////////////////////////////////////////////////////////////////
57245 // I C O N
57248 ///////////////////////////////////////////////////////////////////////
57250 { -- icon -- }
57252 //[function NewIcon]
57253 function NewIcon: PIcon;
57254 begin
57256 New( Result, Create );
57257 {+}{++}(*Result := TIcon.Create;*){--}
57258 Result.FSize := 32;
57259 end;
57261 { TIcon }
57263 //[PROCEDURE asmIconEmpty]
57264 {$IFDEF ASM_VERSION}
57265 procedure asmIconEmpty( Icon: PIcon );
57267 CMP [EAX].TIcon.fHandle, 0
57268 end;
57269 {$ENDIF ASM_VERSION}
57270 //[END asmIconEmpty]
57272 {$IFDEF ASM_VERSION}
57273 //[procedure TIcon.Clear]
57274 procedure TIcon.Clear;
57275 asm //cmd //opd
57276 XOR ECX, ECX
57277 XCHG ECX, [EAX].fHandle
57278 JECXZ @@1
57279 CMP [EAX].fShareIcon, 0
57280 JNZ @@1
57281 PUSH EAX
57282 PUSH ECX
57283 CALL DestroyIcon
57284 POP EAX
57285 @@1: MOV [EAX].fShareIcon, 0
57286 end;
57287 {$ELSE ASM_VERSION} //Pascal
57288 procedure TIcon.Clear;
57289 begin
57290 if fHandle <> 0 then
57291 begin
57292 if not FShareIcon then
57293 //DeleteObject( fHandle );
57294 DestroyIcon( fHandle );
57295 fHandle := 0;
57296 end;
57297 fShareIcon := False;
57298 end;
57299 {$ENDIF ASM_VERSION}
57301 {$IFDEF ASM_VERSION}
57302 //[function TIcon.Convert2Bitmap]
57303 function TIcon.Convert2Bitmap(TranColor: TColor): HBitmap;
57304 asm //cmd //opd
57305 PUSH EBX
57306 PUSH ESI
57307 PUSH EDI
57308 PUSH EBP
57309 MOV EBX, EAX
57310 MOV EBP, EDX
57311 XOR EDX, EDX
57312 CALL asmIconEmpty
57313 JZ @@ret_0
57314 PUSH 0
57315 CALL GetDC
57316 PUSH EAX //> DC0
57317 PUSH EAX
57318 CALL CreateCompatibleDC
57319 XCHG EDI, EAX
57320 MOV EDX, [EBX].fSize
57322 POP EAX
57323 PUSH EAX
57324 PUSH EDX //>Bottom
57325 PUSH EDX //>Right
57326 PUSH 0 //>Top
57327 PUSH 0 //>Left
57329 PUSH EDX
57330 PUSH EDX
57331 PUSH EAX
57332 CALL CreateCompatibleBitmap
57333 XCHG EBP, EAX
57335 CALL Color2RGB
57336 PUSH EAX
57338 PUSH EBP
57339 PUSH EDI
57340 CALL SelectObject
57341 XCHG ESI, EAX
57343 CALL CreateSolidBrush
57345 MOV EDX, ESP
57346 PUSH EAX
57347 PUSH EAX
57348 PUSH EDX
57349 PUSH EDI
57350 CALL Windows.FillRect
57351 CALL DeleteObject
57353 XCHG EAX, EBX
57354 MOV EDX, EDI
57355 XOR ECX, ECX
57356 PUSH ECX
57357 CALL Draw
57359 PUSH EDI
57360 PUSH ESI
57361 CALL FinishDC
57363 ADD ESP, 16
57364 PUSH 0
57365 CALL ReleaseDC
57366 MOV EDX, EBP
57368 @@ret_0:
57369 XCHG EAX, EDX
57370 POP EBP
57371 POP EDI
57372 POP ESI
57373 POP EBX
57374 end;
57375 {$ELSE ASM_VERSION} //Pascal
57376 function TIcon.Convert2Bitmap(TranColor: TColor): HBitmap;
57377 var DC0, DC2: HDC;
57378 Save: THandle;
57379 Br: HBrush;
57380 begin
57381 Result := 0;
57382 if Empty then Exit;
57383 DC0 := GetDC( 0 );
57384 DC2 := CreateCompatibleDC( DC0 );
57385 Result := CreateCompatibleBitmap( DC0, fSize, fSize );
57386 Save := SelectObject( DC2, Result );
57387 Br := CreateSolidBrush( Color2RGB( TranColor ) );
57388 FillRect( DC2, MakeRect( 0, 0, fSize, fSize ), Br );
57389 DeleteObject( Br );
57390 Draw( DC2, 0, 0 );
57391 SelectObject( DC2, Save );
57392 DeleteDC( DC2 );
57393 ReleaseDC( 0, DC0 );
57394 end;
57395 {$ENDIF ASM_VERSION}
57397 {$IFDEF ASM_VERSION}
57398 //[destructor TIcon.Destroy]
57399 destructor TIcon.Destroy;
57400 asm //cmd //opd
57401 PUSH EAX
57402 CALL Clear
57403 POP EAX
57404 CALL TObj.Destroy
57405 end;
57406 {$ELSE ASM_VERSION} //Pascal
57407 destructor TIcon.Destroy;
57408 begin
57409 Clear;
57410 inherited;
57411 end;
57412 {$ENDIF ASM_VERSION}
57414 {$IFDEF ASM_VERSION}
57415 //[procedure TIcon.Draw]
57416 procedure TIcon.Draw(DC: HDC; X, Y: Integer);
57417 asm //cmd //opd
57418 CALL asmIconEmpty
57419 JZ @@exit
57420 PUSH DI_NORMAL
57421 PUSH 0
57422 PUSH 0
57423 PUSH [EAX].fSize
57424 PUSH [EAX].fSize
57425 PUSH [EAX].fHandle
57426 PUSH Y
57427 PUSH ECX
57428 PUSH EDX
57429 CALL DrawIconEx
57430 @@exit:
57431 end;
57432 {$ELSE ASM_VERSION} //Pascal
57433 procedure TIcon.Draw(DC: HDC; X, Y: Integer);
57434 begin
57435 if Empty then Exit;
57436 DrawIconEx( DC, X, Y, fHandle, fSize, fSize, 0, 0, DI_NORMAL );
57437 end;
57438 {$ENDIF ASM_VERSION}
57440 {$IFDEF ASM_VERSION}
57441 //[procedure TIcon.StretchDraw]
57442 procedure TIcon.StretchDraw(DC: HDC; Dest: TRect);
57443 asm //cmd //opd
57444 CALL asmIconEmpty
57445 JZ @@exit
57446 PUSH DI_NORMAL
57447 PUSH 0
57448 PUSH 0
57449 PUSH ECX
57450 PUSH ECX
57451 PUSH [EAX].fHandle
57452 PUSH [ECX].TRect.Top
57453 PUSH [ECX].TRect.Left
57454 PUSH EDX
57455 MOV EAX, [ECX].TRect.Bottom
57456 SUB EAX, [ECX].TRect.Top
57457 MOV [ESP+20], EAX
57458 MOV EAX, [ECX].TRect.Right
57459 SUB EAX, [ECX].TRect.Left
57460 MOV [ESP+16], EAX
57461 CALL DrawIconEx
57462 @@exit:
57463 end;
57464 {$ELSE ASM_VERSION} //Pascal
57465 procedure TIcon.StretchDraw(DC: HDC; Dest: TRect);
57466 begin
57467 if Empty then Exit;
57468 DrawIconEx( DC, Dest.Left, Dest.Top, FHandle, Dest.Right - Dest.Left,
57469 Dest.Bottom - Dest.Top, 0, 0, DI_NORMAL );
57470 end;
57471 {$ENDIF ASM_VERSION}
57473 //[function TIcon.GetEmpty]
57474 function TIcon.GetEmpty: Boolean;
57475 begin
57476 Result := fHandle = 0;
57477 end;
57480 //[function TIcon.GetHotSpot]
57481 function TIcon.GetHotSpot: TPoint;
57482 var II : TIconInfo;
57483 begin
57484 Result := MakePoint( 0, 0 );
57485 if FHandle = 0 then Exit;
57486 GetIconInfo( FHandle, II );
57487 Result.x := II.xHotspot;
57488 Result.y := II.yHotspot;
57489 if II.hbmMask <> 0 then
57490 DeleteObject( II.hbmMask );
57491 if II.hbmColor <> 0 then
57492 DeleteObject( II.hbmColor );
57493 end;
57496 //[procedure TIcon.LoadFromFile]
57497 procedure TIcon.LoadFromFile(const FileName: String);
57498 var Strm : PStream;
57499 begin
57500 Strm := NewReadFileStream( Filename );
57501 LoadFromStream( Strm );
57502 Strm.Free;
57503 end;
57506 //[procedure TIcon.LoadFromStream]
57507 procedure TIcon.LoadFromStream(Strm: PStream);
57508 var DesiredSize : Integer;
57509 Pos : DWord;
57510 Mem : PStream;
57511 ImgBmp, MskBmp : PBitmap;
57512 TmpBmp: PBitmap;
57513 function ReadIcon : Boolean;
57514 var IH : TIconHeader;
57515 IDI, FoundIDI : TIconDirEntry;
57516 I, SumSz, FoundSz, D : Integer;
57517 II : TIconInfo;
57518 BIH : TBitmapInfoheader;
57519 begin
57520 Result := False;
57521 if Strm.Read( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;
57522 if (IH.idReserved <> 0) or ((IH.idType <> 1) and (IH.idType <> 2)) or
57523 (IH.idCount < 1) then Exit;
57524 SumSz := Sizeof( IH );
57525 FoundSz := 1000;
57526 for I := 1 to IH.idCount do
57527 begin
57528 if Strm.Read( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;
57529 if (IDI.bWidth <> IDI.bHeight) and
57530 (IDI.bWidth * 2 <> IDI.bHeight) or
57531 (IDI.bWidth = 0) {or
57532 (IDI.bReserved <> 0) or (IDI.wPlanes <> 0) or (IDI.wBitCount <> 0)} then
57533 Exit;
57534 Inc( SumSz, IDI.dwBytesInRes + Sizeof( IDI ) );
57535 D := IDI.bWidth - DesiredSize;
57536 if D < 0 then D := -D;
57537 if D < FoundSz then
57538 begin
57539 FoundSz := D;
57540 FoundIDI := IDI;
57541 end;
57542 end;
57543 if FoundSz = 1000 then Exit;
57544 Strm.Seek( Integer( Pos ) + FoundIDI.dwImageOffset, spBegin );
57545 fSize := FoundIDI.bWidth;
57547 if Strm.Read( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;
57548 if (BIH.biWidth <> fSize) or
57549 (BIH.biHeight <> fSize * 2) and
57550 (BIH.biHeight <> fSize) then Exit;
57551 BIH.biHeight := fSize;
57553 Mem := NewMemoryStream;
57554 Mem.Write( BIH, Sizeof( BIH ) );
57555 if (FoundIDI.bColorCount >= 2) or (FoundIDI.bReserved = 1) or
57556 (FoundIDI.bColorCount = 0) then
57557 begin
57558 I := 0;
57559 if BIH.biBitCount <= 8 then
57560 I := (1 shl BIH.biBitCount) * Sizeof( TRGBQuad );
57561 if I > 0 then
57562 if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;
57563 I := ((BIH.biBitCount * fSize + 31) div 32) * 4 * fSize;
57564 if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;
57565 ImgBmp := NewBitmap( fSize, fSize );
57566 Mem.Seek( 0, spBegin );
57567 ImgBmp.LoadFromStream( Mem );
57568 if ImgBmp.Empty then Exit;
57569 end;
57571 BIH.biBitCount := 1;
57572 Mem.Seek( 0, spBegin );
57573 Mem.Write( BIH, Sizeof( BIH ) );
57574 I := 0;
57575 Mem.Write( I, Sizeof( I ) );
57576 I := $FFFFFF;
57577 Mem.Write( I, Sizeof( I ) );
57578 I := ((fSize + 31) div 32) * 4 * fSize;
57579 if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;
57581 MskBmp := NewBitmap( fSize, fSize );
57582 Mem.Seek( 0, spBegin );
57583 MskBmp.LoadFromStream( Mem );
57584 if MskBmp.Empty then Exit;
57586 II.fIcon := True;
57587 II.xHotspot := 0;
57588 II.yHotspot := 0;
57589 II.hbmMask := MskBmp.Handle;
57590 II.hbmColor := 0;
57591 if ImgBmp <> nil then
57592 begin
57593 II.hbmColor := ImgBmp.Handle;
57594 {TmpBmp := NewBitmap( ImgBmp.Width, ImgBmp.Height );
57595 TmpBmp.HandleType := bmDIB;
57596 ImgBmp.Draw( TmpBmp.Canvas.Handle, 0, 0 );
57597 II.hbmColor := TmpBmp.Handle;}
57598 end;
57599 fHandle := CreateIconIndirect( II );
57600 //fShareIcon := False;
57601 Strm.Seek( Integer( Pos ) + SumSz, spBegin );
57602 Result := fHandle <> 0;
57603 end;
57604 begin
57605 DesiredSize := fSize;
57606 if DesiredSize = 0 then
57607 DesiredSize := GetSystemMetrics( SM_CXICON );
57608 Clear;
57609 Pos := Strm.Position;
57611 Mem := nil;
57612 ImgBmp := nil;
57613 MskBmp := nil;
57614 TmpBmp := nil;
57616 if not ReadIcon then
57617 begin
57618 Clear;
57619 Strm.Seek( Pos, spBegin );
57620 end;
57622 Mem.Free;
57623 ImgBmp.Free;
57624 MskBmp.Free;
57625 TmpBmp.Free;
57626 end;
57628 {$IFDEF ASM_VERSION}
57629 //[procedure TIcon.SaveToFile]
57630 procedure TIcon.SaveToFile(const FileName: String);
57631 asm //cmd //opd
57632 PUSH EAX
57633 MOV EAX, ESP
57634 MOV ECX, EDX
57635 XOR EDX, EDX
57636 CALL SaveIcons2File
57637 POP EAX
57638 end;
57639 {$ELSE ASM_VERSION} //Pascal
57640 procedure TIcon.SaveToFile(const FileName: String);
57641 begin
57642 SaveIcons2File( [ @Self ], FileName );
57643 end;
57644 {$ENDIF ASM_VERSION}
57646 {$IFDEF ASM_VERSION}
57647 //[procedure TIcon.SaveToStream]
57648 procedure TIcon.SaveToStream(Strm: PStream);
57649 asm //cmd //opd
57650 PUSH EAX
57651 MOV EAX, ESP
57652 MOV ECX, EDX
57653 XOR EDX, EDX
57654 CALL SaveIcons2Stream
57655 POP EAX
57656 end;
57657 {$ELSE ASM_VERSION} //Pascal
57658 procedure TIcon.SaveToStream(Strm: PStream);
57659 begin
57660 SaveIcons2Stream( [ @Self ], Strm );
57661 end;
57662 {$ENDIF ASM_VERSION}
57664 {$IFDEF ASM_noVERSION}
57665 //[procedure TIcon.SetHandle]
57666 procedure TIcon.SetHandle(const Value: HIcon);
57667 const szII = sizeof( TIconInfo );
57668 szBIH = sizeof(TBitmapInfoHeader);
57669 asm //cmd //opd
57670 CMP EDX, [EAX].fHandle
57671 JE @@exit
57672 PUSHAD
57673 PUSH EDX
57674 MOV EBX, EAX
57675 CALL Clear
57676 POP ECX
57677 MOV [EBX].fHandle, ECX
57678 JECXZ @@fin
57679 ADD ESP, -szBIH
57680 PUSH ESP
57681 PUSH ECX
57682 CALL GetIconInfo
57683 MOV ESI, [ESP].TIconInfo.hbmMask
57684 MOV EDI, [ESP].TIconInfo.hbmColor
57685 PUSH ESP
57686 PUSH szBIH
57687 PUSH ESI
57688 CALL GetObject
57689 POP EAX
57690 POP [EBX].fSize
57691 ADD ESP, szBIH-8
57692 TEST ESI, ESI
57693 JZ @@1
57694 PUSH ESI
57695 CALL DeleteObject
57696 @@1: TEST EDI, EDI
57697 JZ @@fin
57698 PUSH EDI
57699 CALL DeleteObject
57700 @@fin: POPAD
57701 @@exit:
57702 end;
57703 {$ELSE ASM_VERSION} //Pascal
57704 procedure TIcon.SetHandle(const Value: HIcon);
57705 var II : TIconInfo;
57706 B: TagBitmap;
57707 begin
57708 if FHandle = Value then Exit;
57709 Clear;
57710 FHandle := Value;
57711 if Value <> 0 then
57712 begin
57713 GetIconInfo( FHandle, II );
57714 GetObject( II.hbmMask, Sizeof( B ), @B );
57715 fSize := B.bmWidth;
57716 if II.hbmMask <> 0 then
57717 DeleteObject( II.hbmMask );
57718 if II.hbmColor <> 0 then
57719 DeleteObject( II.hbmColor );
57720 end;
57721 end;
57722 {$ENDIF ASM_VERSION}
57725 //[procedure TIcon.SetSize]
57726 procedure TIcon.SetSize(const Value: Integer);
57727 begin
57728 if FSize = Value then Exit;
57729 Clear;
57730 FSize := Value;
57731 end;
57733 const PossibleColorBits : array[1..7] of Byte = ( 1, 4, 8, 16, 24, 32, 0 );
57734 //[FUNCTION ColorBits]
57735 {$IFDEF ASM_VERSION}
57736 function ColorBits( ColorsCount : Integer ) : Integer;
57737 asm //cmd //opd
57738 PUSH EBX
57739 MOV EDX, offset[PossibleColorBits]
57740 @@loop: MOVZX ECX, byte ptr [EDX]
57741 JECXZ @@e_loop
57742 INC EDX
57743 XOR EBX, EBX
57744 INC EBX
57745 SHL EBX, CL
57746 CMP EBX, EAX
57747 JL @@loop
57748 @@e_loop:
57749 XCHG EAX, ECX
57750 POP EBX
57751 end;
57752 {$ELSE ASM_VERSION} //Pascal
57753 function ColorBits( ColorsCount : Integer ) : Integer;
57754 var I : Integer;
57755 begin
57756 for I := 1 to 6 do
57757 begin
57758 Result := PossibleColorBits[ I ];
57759 if (1 shl Result) >= ColorsCount then break;
57760 end;
57761 end;
57762 {$ENDIF ASM_VERSION}
57763 //[END ColorBits]
57765 //[function SaveIcons2StreamEx]
57766 function SaveIcons2StreamEx( const BmpHandles: array of HBitmap; Strm: PStream ): Boolean;
57767 var I, Off : Integer;
57768 IDI : TIconDirEntry;
57769 BIH : TBitmapInfoHeader;
57770 B: TagBitmap;
57771 function RGBArraySize : Integer;
57772 begin
57773 Result := 0;
57774 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
57775 Result := (IDI.bColorCount + (IDI.bReserved shl 8)) * Sizeof( TRGBQuad );
57776 end;
57777 function ColorDataSize( W, H: Integer ) : Integer;
57778 var N: Integer;
57779 begin
57780 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
57781 N := (ColorBits( IDI.bColorCount + (IDI.bReserved shl 8) ) )
57782 else
57783 begin
57784 N := IDI.wBitCount;
57785 end;
57786 Result := ((N * W + 31) div 32) * 4
57787 * H;
57788 end;
57789 function MaskDataSize( W, H: Integer ) : Integer;
57790 begin
57791 Result := ((W + 31) div 32) * 4 * H;
57792 end;
57793 var BColor, BMask: HBitmap;
57794 W, H: Integer;
57795 ImgBmp, MskBmp: PBitmap;
57796 IH : TIconHeader;
57797 Colors : PList;
57798 begin
57799 Assert( (High(BmpHandles) >= 0) and (High(BmpHandles) and 1 <> 0),
57800 'Incorrect parameters count in call to SaveIcons2StreamEx' );
57801 Result := False;
57802 IH.idReserved := 0;
57803 IH.idType := 1;
57804 IH.idCount := (High( BmpHandles )+1) div 2;
57805 if Strm.Write( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;
57806 Off := Sizeof( IH ) + IH.idCount * Sizeof( IDI );
57807 Colors := NewList;
57808 ImgBmp := NewBitmap( 0, 0 );
57809 MskBmp := NewBitmap( 0, 0 );
57812 for I := 0 to High( BmpHandles ) div 2 do
57813 begin
57814 BColor := BmpHandles[ I * 2 ];
57815 BMask := BmpHandles[ I * 2 + 1 ];
57816 if (BColor = 0) and (BMask = 0) then break;
57817 Assert( BMask <> 0, 'Mask bitmap not provided for saving icons in SaveIcons2StreamEx' );
57818 GetObject( BMask, Sizeof( B ), @ B );
57819 W := B.bmWidth;
57820 H := B.bmHeight;
57821 if BColor <> 0 then
57822 begin
57823 GetObject( BColor, Sizeof( B ), @B );
57824 Assert( (B.bmWidth = W) and (B.bmHeight = H),
57825 'Mask bitmap size must much color bitmap size in SaveIcons2StreamEx' );
57826 end;
57827 FillChar( IDI, Sizeof( IDI ), 0 );
57829 IDI.bWidth := W;
57830 IDI.bHeight := H;
57831 if BColor = 0 then
57832 IDI.bColorCount := 2
57833 else
57834 begin
57835 ImgBmp.Handle := CopyImage( BColor, IMAGE_BITMAP, W, H,
57836 LR_CREATEDIBSECTION );
57837 FillChar( BIH, Sizeof( BIH ), 0 );
57838 BIH.biSize := Sizeof( BIH );
57839 GetObject( ImgBmp.Handle, Sizeof( B ), @B );
57840 //if ImgBmp.HandleType = bmDDB then
57841 begin
57842 if (B.bmPlanes = 1) and (B.bmBitsPixel >= 15) then
57843 begin
57844 //ImgBmp.PixelFormat := pf24bit;
57845 IDI.bColorCount := 0;
57846 IDI.bReserved := 0;
57847 IDI.wBitCount := B.bmBitsPixel;
57849 else
57850 if B.bmPlanes * (1 shl B.bmBitsPixel) < 16 then
57851 begin
57852 ImgBmp.PixelFormat := pf1bit;
57853 IDI.bColorCount := 2;
57855 else
57856 if B.bmPlanes * (1 shl B.bmBitsPixel) < 256 then
57857 begin
57858 ImgBmp.PixelFormat := pf4bit;
57859 IDI.bColorCount := 16;
57861 else
57862 begin
57863 ImgBmp.PixelFormat := pf8bit;
57864 IDI.bColorCount := 0;
57865 IDI.bReserved := 1;
57866 end;
57867 //GetObject( ImgBmp.Handle, Sizeof( BIH ), @BIH );
57868 end;
57869 //IDI.bColorCount := (1 shl BIH.biBitCount) * BIH.biPlanes;
57870 end;
57871 Colors.Add( Pointer(IDI.bColorCount + (IDI.bReserved shl 8)) );
57872 IDI.dwBytesInRes := Sizeof( BIH ) + RGBArraySize +
57873 ColorDataSize( W, H ) + MaskDataSize( W, H );
57874 IDI.dwImageOffset := Off;
57875 if Strm.Write( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;
57876 Inc( Off, IDI.dwBytesInRes );
57877 end;
57878 for I := 0 to High( BmpHandles ) div 2 do
57879 begin
57880 BColor := BmpHandles[ I * 2 ];
57881 BMask := BmpHandles[ I * 2 + 1 ];
57882 if (BColor = 0) and (BMask = 0) then break;
57883 GetObject( BMask, Sizeof( B ), @ B );
57884 W := B.bmWidth;
57885 H := B.bmHeight;
57887 FillChar( BIH, Sizeof( BIH ), 0 );
57888 BIH.biSize := Sizeof( BIH );
57889 BIH.biWidth := W;
57890 BIH.biHeight := H;
57891 if BColor <> 0 then
57892 BIH.biHeight := W * 2;
57893 BIH.biPlanes := 1;
57894 PWord( @ IDI.bColorCount )^ := DWord( Colors.Items[ I ] );
57895 if IDI.wBitCount = 0 then
57896 IDI.wBitCount := ColorBits( PWord( @ IDI.bColorCount )^ );
57897 BIH.biBitCount := IDI.wBitCount;
57898 BIH.biSizeImage := Sizeof( BIH ) + ColorDataSize( W, H ) + MaskDataSize( W, H );
57899 if Strm.Write( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;
57900 if BColor <> 0 then
57901 begin
57903 ImgBmp.Handle := CopyImage( BColor, IMAGE_BITMAP, W, H, 0 );
57904 case BIH.biBitCount of
57905 1 : ImgBmp.PixelFormat := pf1bit;
57906 4 : ImgBmp.PixelFormat := pf4bit;
57907 8 : ImgBmp.PixelFormat := pf8bit;
57908 16: ImgBmp.PixelFormat := pf16bit;
57909 24: ImgBmp.PixelFormat := pf24bit;
57910 32: ImgBmp.PixelFormat := pf32bit;
57911 end;
57913 else
57914 begin
57915 ImgBmp.Handle := CopyImage( BMask, IMAGE_BITMAP, W, H, 0 );
57916 ImgBmp.PixelFormat := pf1bit;
57917 end;
57918 if ImgBmp.FDIBBits <> nil then
57919 begin
57920 if Strm.Write( Pointer(Integer(ImgBmp.FDIBHeader) + Sizeof(TBitmapInfoHeader))^,
57921 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) ) <>
57922 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) then Exit;
57923 if Strm.Write( ImgBmp.FDIBBits^, ColorDataSize( W, H ) ) <>
57924 DWord( ColorDataSize( W, H ) ) then Exit;
57925 end;
57926 MskBmp.Handle := CopyImage( BMask, IMAGE_BITMAP, W, H, 0 );
57928 MskBmp.PixelFormat := pf1bit;
57929 if Strm.Write( MskBmp.FDIBBits^, MaskDataSize( W, H ) ) <>
57930 DWord( MaskDataSize( W, H ) ) then Exit;
57931 end;
57933 FINALLY
57934 Colors.Free;
57935 ImgBmp.Free;
57936 MskBmp.Free;
57937 END;
57938 Result := True;
57939 end;
57941 {$IFDEF FPC}
57942 {$DEFINE _D3orFPC}
57943 {$ENDIF}
57944 {$IFDEF _D2orD3}
57945 {$DEFINE _D3orFPC}
57946 {$ENDIF}
57947 //[procedure SaveIcons2Stream]
57948 procedure SaveIcons2Stream( const Icons : array of PIcon; Strm : PStream );
57949 var I, J, Pos : Integer;
57950 {$IFDEF _D3orFPC}
57951 Bitmaps: array[ 0..63 ] of HBitmap;
57952 {$ELSE DELPHI}
57953 Bitmaps: array of HBitmap;
57954 {$ENDIF FPC/DELPHI}
57955 II: TIconInfo;
57956 Bmp: HBitmap;
57957 begin
57958 for I := 0 to High( Icons ) do
57959 begin
57960 if Icons[ I ].Handle = 0 then Exit;
57961 for J := I + 1 to High( Icons ) do
57962 if Icons[ I ].Size = Icons[ J ].Size then Exit;
57963 end;
57964 Pos := Strm.Position;
57966 {$IFDEF _D3orFPC}
57967 for I := 0 to High( Bitmaps ) do
57968 Bitmaps[ I ] := 0;
57969 {$ELSE DELPHI}
57970 SetLength( Bitmaps, Length( Icons ) * 2 );
57971 {$ENDIF FPC/DELPHI}
57972 for I := 0 to High( Icons ) do
57973 begin
57974 GetIconInfo( Icons[ I ].Handle, II );
57975 Bitmaps[ I * 2 ] := II.hbmColor;
57976 Bitmaps[ I * 2 + 1 ] := II.hbmMask;
57977 end;
57979 if not SaveIcons2StreamEx( Bitmaps, Strm ) then
57980 Strm.Seek( Pos, spBegin );
57982 for I := 0 to High( Bitmaps ) do
57983 begin
57984 Bmp := Bitmaps[ I ];
57985 if Bmp <> 0 then
57986 DeleteObject( Bmp );
57987 end;
57988 end;
57990 var I, J, Pos : Integer;
57991 IH : TIconHeader;
57992 Colors : PList;
57993 ImgBmp,
57994 MskBmp : PBitmap;
57995 function WriteIcons : Boolean;
57996 var I, Off : Integer;
57997 IDI : TIconDirEntry;
57998 BIH : TBitmapInfoHeader;
57999 II : TIconInfo;
58000 B: TagBitmap;
58001 function RGBArraySize : Integer;
58002 begin
58003 Result := 0;
58004 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
58005 Result := (IDI.bColorCount + (IDI.bReserved shl 8)) * Sizeof( TRGBQuad );
58006 end;
58007 function ColorDataSize : Integer;
58008 var N: Integer;
58009 begin
58010 //Result := 0;
58011 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
58012 N := (ColorBits( IDI.bColorCount + (IDI.bReserved shl 8) ) )
58013 else
58014 N := IDI.wBitCount;
58015 Result := ((N * Icons[ I ].Size + 31) div 32) * 4
58016 * Icons[ I ].Size;
58017 end;
58018 function MaskDataSize : Integer;
58019 begin
58020 Result := ((Icons[ I ].Size + 31) div 32) * 4
58021 * Icons[ I ].Size;
58022 end;
58023 begin
58024 Result := False;
58025 if Strm.Write( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;
58026 Off := Sizeof( IH ) + IH.idCount * Sizeof( IDI );
58027 for I := Low( Icons ) to High( Icons ) do
58028 begin
58029 FillChar( IDI, Sizeof( IDI ), 0 );
58030 IDI.bWidth := Icons[ I ].Size;
58031 IDI.bHeight := Icons[ I ].Size;
58032 GetIconInfo( Icons[ I ].Handle, II );
58033 if II.hbmColor = 0 then
58034 IDI.bColorCount := 2
58035 else
58036 begin
58037 {ImgBmp.Handle := CopyImage( II.hbmColor, IMAGE_BITMAP, Icons[ I ].Size,
58038 Icons[ I ].Size, LR_CREATEDIBSECTION );}
58039 ImgBmp.Handle := II.hbmColor;
58040 II.hbmColor := 0;
58041 FillChar( BIH, Sizeof( BIH ), 0 );
58042 BIH.biSize := Sizeof( BIH );
58043 GetObject( ImgBmp.Handle, Sizeof( B ), @B );
58044 //if ImgBmp.HandleType = bmDDB then
58045 begin
58046 if (B.bmPlanes = 1) and (B.bmBitsPixel >= 15) then
58047 begin
58048 //ImgBmp.PixelFormat := pf24bit;
58049 IDI.bColorCount := 0;
58050 IDI.bReserved := 0;
58051 IDI.wBitCount := B.bmBitsPixel;
58053 else
58054 if B.bmPlanes * (1 shl B.bmBitsPixel) < 16 then
58055 begin
58056 ImgBmp.PixelFormat := pf1bit;
58057 IDI.bColorCount := 2;
58059 else
58060 if B.bmPlanes * (1 shl B.bmBitsPixel) < 256 then
58061 begin
58062 ImgBmp.PixelFormat := pf4bit;
58063 IDI.bColorCount := 16;
58065 else
58066 begin
58067 ImgBmp.PixelFormat := pf8bit;
58068 IDI.bColorCount := 0;
58069 IDI.bReserved := 1;
58070 end;
58071 //GetObject( ImgBmp.Handle, Sizeof( BIH ), @BIH );
58072 end;
58073 //IDI.bColorCount := (1 shl BIH.biBitCount) * BIH.biPlanes;
58074 //--//DeleteObject( II.hbmColor );
58075 end;
58076 if II.hbmMask <> 0 then
58077 DeleteObject( II.hbmMask );
58078 Colors.Add( Pointer(IDI.bColorCount + (IDI.bReserved shl 8)) );
58079 IDI.dwBytesInRes := Sizeof( BIH ) + RGBArraySize +
58080 ColorDataSize + MaskDataSize;
58081 IDI.dwImageOffset := Off;
58082 if Strm.Write( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;
58083 Inc( Off, IDI.dwBytesInRes );
58084 end;
58085 for I := Low( Icons ) to High( Icons ) do
58086 begin
58087 FillChar( BIH, Sizeof( BIH ), 0 );
58088 BIH.biSize := Sizeof( BIH );
58089 BIH.biWidth := Icons[ I ].Size;
58090 BIH.biHeight := Icons[ I ].Size;
58091 //GetObject( Icons[ I ].Handle, Sizeof( II ), @II );
58092 GetIconInfo( Icons[ I ].Handle, II );
58093 if II.hbmColor <> 0 then
58094 BIH.biHeight := Icons[ I ].Size * 2;
58095 BIH.biPlanes := 1;
58096 PWord( @ IDI.bColorCount )^ := DWord( Colors.Items[ I - Low( Icons ) ] );
58097 if IDI.wBitCount = 0 then
58098 IDI.wBitCount := ColorBits( PWord( @ IDI.bColorCount )^ );
58099 BIH.biBitCount := IDI.wBitCount;
58100 BIH.biSizeImage := Sizeof( BIH ) + ColorDataSize + MaskDataSize;
58101 if Strm.Write( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;
58102 if II.hbmColor <> 0 then
58103 begin
58105 ImgBmp.Handle := {CopyImage( II.hbmColor, IMAGE_BITMAP, Icons[ I ].Size,
58106 Icons[ I ].Size, 0 );}
58107 II.hbmColor;
58108 II.hbmColor := 0;
58109 case BIH.biBitCount of
58110 1 : ImgBmp.PixelFormat := pf1bit;
58111 4 : ImgBmp.PixelFormat := pf4bit;
58112 8 : ImgBmp.PixelFormat := pf8bit;
58113 16: ImgBmp.PixelFormat := pf16bit;
58114 24: ImgBmp.PixelFormat := pf24bit;
58115 32: ImgBmp.PixelFormat := pf32bit;
58116 end;
58118 else
58119 begin
58120 ImgBmp.Handle := CopyImage( II.hbmMask, IMAGE_BITMAP, Icons[ I ].Size,
58121 Icons[ I ].Size, 0 );
58122 ImgBmp.PixelFormat := pf1bit;
58123 end;
58124 if ImgBmp.FDIBBits <> nil then
58125 begin
58126 if Strm.Write( Pointer(Integer(ImgBmp.FDIBHeader) + Sizeof(TBitmapInfoHeader))^,
58127 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) ) <>
58128 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) then Exit;
58129 if Strm.Write( ImgBmp.FDIBBits^, ColorDataSize ) <>
58130 DWord( ColorDataSize ) then Exit;
58131 end;
58132 MskBmp.Handle := CopyImage( II.hbmMask, IMAGE_BITMAP, Icons[ I ].Size,
58133 Icons[ I ].Size, 0 {LR_COPYRETURNORG} );
58134 //***
58135 if II.hbmMask <> 0 then
58136 DeleteObject( II.hbmMask );
58137 if II.hbmColor <> 0 then
58138 DeleteObject( II.hbmColor );
58139 //***
58141 MskBmp.PixelFormat := pf1bit;
58142 if Strm.Write( MskBmp.FDIBBits^, MaskDataSize ) <>
58143 DWord( MaskDataSize ) then Exit;
58144 end;
58145 Result := True;
58146 end;
58147 begin
58148 for I := Low( Icons ) to High( Icons ) do
58149 begin
58150 if Icons[ I ].Handle = 0 then Exit;
58151 for J := I + 1 to High( Icons ) do
58152 if Icons[ I ].Size = Icons[ J ].Size then Exit;
58153 end;
58154 IH.idReserved := 0;
58155 IH.idType := 1;
58156 IH.idCount := High( Icons ) - Low( Icons ) + 1;
58157 Pos := Strm.Position;
58158 Colors := NewList;
58159 ImgBmp := NewBitmap( 0, 0 );
58160 MskBmp := NewBitmap( 0, 0 );
58162 if not WriteIcons then
58163 Strm.Seek( Pos, spBegin );
58165 ImgBmp.Free;
58166 MskBmp.Free;
58167 Colors.Free;
58168 end;
58171 //[procedure SaveIcons2File]
58172 procedure SaveIcons2File( const Icons : array of PIcon; const FileName : String );
58173 var Strm: PStream;
58174 begin
58175 Strm := NewWriteFileStream( FileName );
58176 SaveIcons2Stream( Icons, Strm );
58177 Strm.Free;
58178 end;
58180 //[procedure TIcon.LoadFromExecutable]
58181 procedure TIcon.LoadFromExecutable(const FileName: String; IconIdx: Integer);
58182 var I: Integer;
58183 begin
58184 Clear;
58185 I := ExtractIcon( hInstance, PChar( FileName ), IconIdx );
58186 if I > 1 then
58187 Handle := I;
58188 end;
58190 //[function GetFileIconCount]
58191 function GetFileIconCount( const FileName: String ): Integer;
58192 begin
58193 Result := ExtractIcon( hInstance, PChar( FileName ), DWORD(-1) );
58194 end;
58196 //[procedure TIcon.LoadFromResourceID]
58197 procedure TIcon.LoadFromResourceID(Inst, ResID, DesiredSize: Integer);
58198 begin
58199 LoadFromResourceName( Inst, MAKEINTRESOURCE( ResID ), DesiredSize );
58200 end;
58202 //[procedure TIcon.LoadFromResourceName]
58203 procedure TIcon.LoadFromResourceName(Inst: Integer; ResName: PChar; DesiredSize: Integer);
58204 begin
58205 Handle := LoadImage( Inst, ResName, IMAGE_ICON, DesiredSize, DesiredSize,
58206 $8000 {LR_SHARED} );
58207 {if Handle = 0 then
58208 Handle := LoadIcon( Inst, ResName )
58209 else}
58210 if fHandle <> 0 then FShareIcon := True;
58211 end;
58213 //[function LoadImgIcon]
58214 function LoadImgIcon( RsrcName: PChar; Size: Integer ): HIcon;
58215 begin
58216 Result := LoadImage( hInstance, RsrcName, IMAGE_ICON, Size, Size, $8000 {LR_SHARED} );
58217 end;
58220 ////////////////////////////////////////////////////////////////////////
58223 // M E T A F I L E
58226 ////////////////////////////////////////////////////////////////////////
58228 {++}(*
58229 //[API SetEnhMetaFileBits]
58230 function SetEnhMetaFileBits; external gdi32 name 'SetEnhMetaFileBits';
58231 function PlayEnhMetaFile; external gdi32 name 'PlayEnhMetaFile';
58232 *){--}
58234 //[function NewMetafile]
58235 function NewMetafile: PMetafile;
58236 begin
58238 new( Result, Create );
58239 {+}{++}(*Result := PMetafile.Create;*){--}
58240 end;
58241 //[END NewMetafile]
58243 { TMetafile }
58245 //[procedure TMetafile.Clear]
58246 procedure TMetafile.Clear;
58247 begin
58248 if fHandle <> 0 then
58249 DeleteEnhMetaFile( fHandle );
58250 fHandle := 0;
58251 end;
58253 //[destructor TMetafile.Destroy]
58254 destructor TMetafile.Destroy;
58255 begin
58256 if fHeader <> nil then
58257 FreeMem( fHeader );
58258 Clear;
58259 inherited;
58260 end;
58262 //[procedure TMetafile.Draw]
58263 procedure TMetafile.Draw(DC: HDC; X, Y: Integer);
58264 begin
58265 StretchDraw( DC, MakeRect( X, Y, X + Width, Y + Height ) );
58266 end;
58268 //[function TMetafile.Empty]
58269 function TMetafile.Empty: Boolean;
58270 begin
58271 Result := fHandle = 0;
58272 end;
58274 //[function TMetafile.GetHeight]
58275 function TMetafile.GetHeight: Integer;
58276 begin
58277 Result := 0;
58278 if Empty then Exit;
58279 RetrieveHeader;
58280 Result := fHeader.rclBounds.Bottom - fHeader.rclBounds.Top;
58281 end;
58283 //[function TMetafile.GetWidth]
58284 function TMetafile.GetWidth: Integer;
58285 begin
58286 Result := 0;
58287 if Empty then Exit;
58288 RetrieveHeader;
58289 Result := fHeader.rclBounds.Right - fHeader.rclBounds.Left;
58290 end;
58292 //[function TMetafile.LoadFromFile]
58293 function TMetafile.LoadFromFile(const Filename: String): Boolean;
58294 var Strm: PStream;
58295 begin
58296 Strm := NewReadFileStream( FileName );
58297 Result := LoadFromStream( Strm );
58298 Strm.Free;
58299 end;
58301 //[function ComputeAldusChecksum]
58302 function ComputeAldusChecksum(var WMF: TMetafileHeader): Word;
58303 type
58304 PWord = ^Word;
58306 pW: PWord;
58307 pEnd: PWord;
58308 begin
58309 Result := 0;
58310 pW := @WMF;
58311 pEnd := @WMF.CheckSum;
58312 while Longint(pW) < Longint(pEnd) do
58313 begin
58314 Result := Result xor pW^;
58315 Inc(Longint(pW), SizeOf(Word));
58316 end;
58317 end;
58319 //[function TMetafile.LoadFromStream]
58320 function TMetafile.LoadFromStream(Strm: PStream): Boolean;
58321 var WMF: TMetaFileHeader;
58322 WmfHdr: TMetaHeader;
58323 EnhHdr: TEnhMetaHeader;
58324 Pos, Pos1: Integer;
58325 Sz: Integer;
58326 MemStrm: PStream;
58327 MFP: TMetafilePict;
58328 begin
58329 Result := FALSE;
58330 Pos := Strm.Position;
58332 if Strm.Read( WMF, Sizeof( WMF ) ) <> Sizeof( WMF ) then
58333 begin
58334 Strm.Position := Pos;
58335 Exit;
58336 end;
58338 MemStrm := NewMemoryStream;
58340 if WMF.Key = WMFKey then
58341 begin // Windows metafile
58343 if WMF.CheckSum <> ComputeAldusChecksum( WMF ) then
58344 begin
58345 Strm.Position := Pos;
58346 Exit;
58347 end;
58349 Pos1 := Strm.Position;
58350 if Strm.Read( WmfHdr, Sizeof( WmfHdr ) ) <> Sizeof( WmfHdr ) then
58351 begin
58352 Strm.Position := Pos;
58353 Exit;
58354 end;
58356 Strm.Position := Pos1;
58357 Sz := WMFHdr.mtSize * 2;
58358 Stream2Stream( MemStrm, Strm, Sz );
58359 FillChar( MFP, Sizeof( MFP ), 0 );
58360 MFP.mm := MM_ANISOTROPIC;
58361 fHandle := SetWinMetafileBits( Sz, MemStrm.Memory, 0, MFP );
58364 else
58365 begin // may be enchanced?
58367 Strm.Position := Pos;
58368 if Strm.Read( EnhHdr, Sizeof( EnhHdr ) ) < 8 then
58369 begin
58370 Strm.Position := Pos;
58371 Exit;
58372 end;
58373 // yes, enchanced
58374 Strm.Position := Pos;
58375 Sz := EnhHdr.nBytes;
58376 Stream2Stream( MemStrm, Strm, Sz );
58377 fHandle := SetEnhMetaFileBits( Sz, MemStrm.Memory );
58379 end;
58381 MemStrm.Free;
58382 Result := fHandle <> 0;
58383 if not Result then
58384 Strm.Position := Pos;
58386 end;
58388 //[procedure TMetafile.RetrieveHeader]
58389 procedure TMetafile.RetrieveHeader;
58390 var SzHdr: Integer;
58391 begin
58392 if fHeader <> nil then
58393 FreeMem( fHeader );
58394 SzHdr := GetEnhMetaFileHeader( fHandle, 0, nil );
58395 GetMem( fHeader, SzHdr );
58396 GetEnhMetaFileHeader( fHandle, SzHdr, fHeader );
58397 end;
58399 //[procedure TMetafile.SetHandle]
58400 procedure TMetafile.SetHandle(const Value: THandle);
58401 begin
58402 Clear;
58403 fHandle := Value;
58404 end;
58406 //[procedure TMetafile.StretchDraw]
58407 procedure TMetafile.StretchDraw(DC: HDC; const R: TRect);
58408 begin
58409 if Empty then Exit;
58410 PlayEnhMetaFile( DC, fHandle, R );
58411 end;
58425 //[procedure AlignChildrenProc]
58426 procedure AlignChildrenProc( Sender: PObj );
58427 type
58428 TAligns = set of TControlAlign;
58429 var P: PControl;
58430 CR: TRect;
58431 procedure DoAlign( Allowed: TAligns );
58432 var I: Integer;
58433 C: PControl;
58434 R, R1: TRect;
58435 W, H: Integer;
58436 ChgPos, ChgSiz: Boolean;
58437 begin
58438 for I := 0 to P.fChildren.fCount - 1 do
58439 begin
58440 C := P.fChildren.fItems[ I ];
58441 if not C.ToBeVisible then continue;
58442 // important: not fVisible, and even not Visible, but ToBeVisible!
58443 if C.fNotUseAlign then continue;
58444 if C.FAlign in Allowed then
58445 begin
58446 R := C.BoundsRect;
58447 R1 := R;
58448 W := R.Right - R.Left;
58449 H := R.Bottom - R.Top;
58450 case C.FAlign of
58451 caTop:
58452 begin
58453 OffsetRect( R, 0, -R.Top + CR.Top + P.Margin );
58454 Inc( CR.Top, H + P.Margin );
58455 R.Left := CR.Left + P.Margin;
58456 R.Right := CR.Right - P.Margin;
58457 end;
58458 caBottom:
58459 begin
58460 OffsetRect( R, 0, -R.Bottom + CR.Bottom - P.Margin );
58461 Dec( CR.Bottom, H + P.Margin );
58462 R.Left := CR.Left + P.Margin;
58463 R.Right := CR.Right - P.Margin;
58464 end;
58465 caLeft:
58466 begin
58467 OffsetRect( R, -R.Left + CR.Left + P.Margin, 0 );
58468 Inc( CR.Left, W + P.Margin );
58469 R.Top := CR.Top + P.Margin;
58470 R.Bottom := CR.Bottom - P.Margin;
58471 end;
58472 caRight:
58473 begin
58474 OffsetRect( R, -R.Right + CR.Right - P.Margin, 0 );
58475 Dec( CR.Right, W + P.Margin );
58476 R.Top := CR.Top + P.Margin;
58477 R.Bottom := CR.Bottom - P.Margin;
58478 end;
58479 caClient:
58480 begin
58481 R := CR;
58482 InflateRect( R, -P.Margin, -P.Margin );
58483 end;
58484 end;
58485 if R.Right < R.Left then R.Right := R.Left;
58486 if R.Bottom < R.Top then R.Bottom := R.Top;
58487 ChgPos := (R.Left <> R1.Left) or (R.Top <> R1.Top);
58488 ChgSiz := (R.Right - R.Left <> W) or (R.Bottom - R.Top <> H);
58489 if ChgPos or ChgSiz then
58490 begin
58491 C.BoundsRect := R;
58492 if ChgSiz then
58493 AlignChildrenProc( C );
58494 end;
58495 end;
58496 end;
58497 end;
58498 begin
58499 P := Pointer( Sender );
58500 if P = nil then Exit; // Called for form - ignore.
58501 CR := P.ClientRect;
58502 DoAlign( [ caTop, caBottom ] );
58503 DoAlign( [ caLeft, caRight ] );
58504 DoAlign( [ caClient ] );
58505 end;
58508 //[procedure TControl.Set_Align]
58509 procedure TControl.Set_Align(const Value: TControlAlign);
58510 begin
58511 Global_Align := AlignChildrenProc;
58512 if fNotUseAlign then Exit;
58513 if FAlign = Value then Exit;
58514 FAlign := Value;
58515 //Global_Align( Parent );
58516 AlignChildrenProc( Parent );
58517 end;
58520 //[function TControl.SetAlign]
58521 function TControl.SetAlign(AAlign: TControlAlign): PControl;
58522 begin
58523 Set_Align( AAlign );
58524 Result := @Self;
58525 end;
58528 //[function WndProcPreventResizeFlicks]
58529 function WndProcPreventResizeFlicks( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
58530 type TRectsArray = array[0..2] of TRect;
58531 PRectsArray = ^TRectsArray;
58532 TChange = ( ChgL, ChgT, ChgR, ChgB );
58533 TChanges = Set of TChange;
58534 var Rects : PRectsArray;
58535 Changes : Set of TChange;
58536 Resizing : Boolean;
58537 X, Y, DX, DY : Integer;
58538 EntireRect, Src, Dst : TRect;
58540 function GetClientAfter : TRect;
58541 var R : TRect;
58542 begin
58543 R := Rects[ 2 ];
58544 OffsetRect( R, Rects[ 0 ].Left - Rects[ 1 ].Left,
58545 Rects[ 0 ].Top - Rects[ 1 ].Top );
58546 if Rects[ 0 ].Right - Rects[ 0 ].Left <> Rects[ 1 ].Right - Rects[ 1 ].Left then
58547 R.Right := R.Left + (R.Right - R.Left)
58548 + (Rects[ 0 ].Right - Rects[ 0 ].Left)
58549 - (Rects[ 1 ].Right - Rects[ 1 ].Left);
58550 if Rects[ 0 ].Bottom - Rects[ 0 ].Top <> Rects[ 1 ].Bottom - Rects[ 1 ].Top then
58551 R.Bottom := R.Top + (R.Bottom - R.Top)
58552 + (Rects[ 0 ].Bottom - Rects[ 0 ].Top)
58553 - (Rects[ 1 ].Bottom - Rects[ 1 ].Top);
58554 Result := R;
58555 end;
58557 procedure DoResize( F : PControl; Changes : TChanges );
58558 var ClientAfter : TRect;
58560 procedure CollectClipRgn( V : PControl; Changes : TChanges );
58561 var C : PControl;
58562 I : Integer;
58563 begin
58564 for I := 0 to V.FChildren.FCount - 1 do
58565 begin
58566 C := V.FChildren.FItems[ I ];
58567 if not C.Visible then Continue;
58569 if C.fNotUseAlign then
58570 begin
58571 C.Update;
58572 end;
58573 end;
58574 end; // of CollectClipRgn
58577 begin // DoResize
58578 ClientAfter := GetClientAfter;
58579 //ClipRgn := CreateRectRgn( ClientAfter.Left, ClientAfter.Top,
58580 // ClientAfter.Right, ClientAfter.Bottom );
58581 CollectClipRgn( F, Changes );
58582 //ScrollWithoutClipRgn;
58583 //DeleteObject( ClipRgn );
58584 end; // of DoResize
58586 var PR: PRect;
58587 R: TRect;
58588 begin // Procedure WndProcResizeFlicks
58589 Result := False;
58590 case Msg.message of
58591 WM_NCCALCSIZE:
58592 if Msg.wParam <> 0 then
58593 begin
58594 Rects := Pointer( Msg.lParam );
58595 Changes := [];
58596 if Rects[ 0 ].Left <> Rects[ 1 ].Left then
58597 Changes := Changes + [ ChgL ];
58598 if Rects[ 0 ].Top <> Rects[ 1 ].Top then
58599 Changes := Changes + [ ChgT ];
58600 if Rects[ 0 ].Right <> Rects[ 1 ].Right then
58601 Changes := Changes + [ ChgR ];
58602 if Rects[ 0 ].Bottom <> Rects[ 1 ].Bottom then
58603 Changes := Changes + [ ChgB ];
58604 Resizing := Changes * [ ChgL, ChgT ] <> [ ];
58605 if Resizing and not Sender.fNotUseAlign then
58606 begin
58607 EntireRect := GetClientAfter;
58608 OffsetRect( EntireRect, -EntireRect.Left, -EntireRect.Top );
58609 if EntireRect.Right - EntireRect.Left < Rects[ 2 ].Right - Rects[ 2 ].Left then
58610 EntireRect.Right := Rects[ 2 ].Right - Rects[ 2 ].Left;
58611 if EntireRect.Bottom - EntireRect.Top < Rects[ 2 ].Bottom - Rects[ 2 ].Top then
58612 EntireRect.Bottom := Rects[ 2 ].Bottom - Rects[ 2 ].Top;
58613 X := Min( Rects[ 0 ].Left, Rects[ 1 ].Left ) + Rects[ 2 ].Left - Rects[ 1 ].Left;
58614 Y := Min( Rects[ 0 ].Top, Rects[ 1 ].Top ) + Rects[ 2 ].Top - Rects[ 2 ].Top;
58615 OffsetRect( EntireRect, X, Y );
58616 DX := 0; DY := 0;
58617 if ChgL in Changes then
58618 DX := Rects[ 0 ].Left - Rects[ 1 ].Left;
58619 if ChgR in Changes then
58620 DX := Rects[ 0 ].Right - Rects[ 1 ].Right;
58621 if ChgT in Changes then
58622 DY := Rects[ 0 ].Top - Rects[ 1 ].Top;
58623 if ChgB in Changes then
58624 DY := Rects[ 0 ].Bottom - Rects[ 1 ].Bottom;
58625 DoResize( Sender, Changes );
58626 if (Changes = [ChgL]) {and (Rects[0].Left <> Rects[1].Left)} then
58627 begin
58628 Rslt := WVR_VALIDRECTS;
58629 Src := Rects[ 2 ];
58630 Dst := GetClientAfter;
58631 Src.Right := Src.Left - DX;
58632 Dst.Right := Dst.Left - DX;
58633 Rects[ 1 ] := Src;
58634 Rects[ 2 ] := Dst;
58636 else
58637 if (Changes = [ChgR]) {and (Rects[0].Right > Rects[1].Right)} then
58638 begin
58639 Rslt := WVR_VALIDRECTS;
58640 Src := Rects[ 2 ];
58641 Dst := GetClientAfter;
58642 Src.Left := Src.Right - DX;
58643 Dst.Left := Dst.Right - DX;
58644 Rects[ 1 ] := Src;
58645 Rects[ 2 ] := Dst;
58647 else
58648 if (Changes = [ChgT]) {and (Rects[0].Top <> Rects[1].Top)} then
58649 begin
58650 Rslt := WVR_VALIDRECTS;
58651 Src := Rects[ 2 ];
58652 Dst := GetClientAfter;
58653 Src.Bottom := Src.Top - DY;
58654 Dst.Bottom := Dst.Top - DY;
58655 Rects[ 1 ] := Src;
58656 Rects[ 2 ] := Dst;
58658 else
58659 if Changes = [ChgL,ChgT] then
58660 begin
58661 Rslt := WVR_VALIDRECTS;
58662 Src := Rects[ 2 ];
58663 Dst := GetClientAfter;
58664 Src.Left := Src.Right - DX;
58665 Dst.Left := Dst.Right - DX;
58666 Src.Bottom := Src.Top - DY;
58667 Dst.Bottom := Dst.Top - DY;
58668 Rects[ 1 ] := Src;
58669 Rects[ 2 ] := Dst;
58670 end;
58671 PostMessage( Sender.fHandle, CM_UPDATE, 0, 0 );
58673 {else
58674 if Sender.fNotUseAlign then
58675 begin
58676 end};
58677 end;
58678 CM_UPDATE:
58679 begin
58680 if Sender.fNotUpdate then
58681 begin
58682 Sender.fNotUpdate := False;
58683 Sender.Invalidate;
58684 end;
58685 Sender.Update;
58686 end;
58687 WM_SIZING:
58688 begin
58689 if (Msg.wParam = WMSZ_TOPLEFT) or (Msg.wParam = WMSZ_BOTTOMLEFT) or (Msg.wParam = WMSZ_TOPRIGHT) then
58690 begin
58691 PR := Pointer( Msg.lParam );
58692 GetWindowRect( Sender.fHandle, R );
58693 PostMessage( Sender.fHandle, CM_SIZEPOS, LoWord( PR.Left) or (PR.Top shl 16),
58694 LoWord( PR.Right - PR.Left ) or ( (PR.Bottom - PR.Top) shl 16) );
58695 if Msg.wParam = WMSZ_TOPLEFT then
58696 if Abs( R.Top - PR.Top ) < Abs( R.Left - PR.Left ) then
58697 PR.Top := R.Top
58698 else
58699 PR.Left := R.Left
58700 else
58701 if Msg.wParam = WMSZ_BOTTOMLEFT then
58702 if Abs( R.Bottom - PR.Bottom ) < Abs( R.Left - PR.Left ) then
58703 PR.Bottom := R.Bottom
58704 else
58705 PR.Left := R.Left
58706 else // WMSZ_TOPRIGHT
58707 if Abs( R.Top - PR.Top ) < Abs( R.Right - PR.Right ) then
58708 PR.Top := R.Top
58709 else
58710 PR.Right := R.Right;
58711 Sender.fNotUpdate := True;
58712 Rslt := 1;
58713 Result := TRUE;
58714 end;
58715 end;
58716 CM_SIZEPOS:
58717 begin
58718 Sender.fNotUpdate := False;
58719 SetWindowPos( Sender.fHandle, 0, SmallInt( LoWord( Msg.wParam ) ),
58720 SmallInt( HiWord( Msg.wParam ) ), SmallInt( LoWord( Msg.lParam ) ),
58721 SmallInt( HiWord( Msg.lParam ) ), SWP_NOZORDER or SWP_NOACTIVATE );
58722 end;
58723 WM_PAINT:
58724 begin
58725 if Sender.fNotUpdate then
58726 begin
58727 Rslt := 0;
58728 Result := True;
58729 end;
58730 end;
58731 WM_ERASEBKGND:
58732 begin
58733 if Sender.fNotUpdate then
58734 begin
58735 Rslt := 1;
58736 Result := True;
58737 end;
58738 end;
58739 end;
58740 end;
58743 //[function TControl.PreventResizeFlicks]
58744 function TControl.PreventResizeFlicks: PControl;
58745 begin
58746 fWndProcResizeFlicks := WndProcPreventResizeFlicks;
58747 Result := @Self;
58748 end;
58751 //[procedure TControl.Update]
58752 procedure TControl.Update;
58753 var I: Integer;
58754 C: PControl;
58755 begin
58756 if fUpdateCount > 0 then
58757 Exit;
58758 if fNotUpdate then Exit;
58759 if fHandle = 0 then Exit;
58760 UpdateWindow( fHandle );
58761 for I := 0 to fChildren.fCount - 1 do
58762 begin
58763 C := fChildren.fItems[ I ];
58764 C.Update;
58765 end;
58766 end;
58768 //[FUNCTION WndProcUpdate]
58769 {$IFDEF ASM_VERSION}
58770 function WndProcUpdate( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
58771 asm //cmd //opd
58772 PUSH EBX
58773 XCHG EBX, EAX
58774 MOV EAX, [EBX].TControl.fUpdateCount
58775 TEST EAX, EAX
58776 JZ @@exit
58778 XOR EAX, EAX
58779 MOV EDX, [EDX].TMsg.message
58780 CMP DX, WM_PAINT
58781 JNE @@chk_erasebkgnd
58783 MOV [ECX], EAX
58784 PUSH EAX
58785 PUSH [EBX].TControl.fHandle
58786 CALL ValidateRect
58787 JMP @@rslt_1
58788 @@chk_erasebkgnd:
58789 CMP DX, WM_ERASEBKGND
58790 JNE @@exit
58791 INC EAX
58792 MOV [ECX], EAX
58793 @@rslt_1:
58794 MOV AL, 1
58795 @@exit:
58796 POP EBX
58797 end;
58798 {$ELSE ASM_VERSION} //Pascal
58799 function WndProcUpdate( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
58800 begin
58801 if Sender.fUpdateCount > 0 then
58802 begin
58803 case Msg.message of
58804 WM_PAINT:
58805 begin
58806 ValidateRect( Sender.Handle, nil );
58807 Rslt := 0;
58808 end;
58809 WM_ERASEBKGND: Rslt := 1;
58810 else begin
58811 Result := FALSE;
58812 Exit;
58813 end;
58814 end;
58815 Result := TRUE;
58817 else Result := FALSE;
58818 end;
58819 {$ENDIF ASM_VERSION}
58820 //[END WndProcUpdate]
58822 //[procedure TControl.BeginUpdate]
58823 procedure TControl.BeginUpdate;
58824 begin
58825 Inc( fUpdateCount );
58826 AttachProc( @WndProcUpdate );
58827 end;
58829 //[procedure TControl.EndUpdate]
58830 procedure TControl.EndUpdate;
58831 begin
58832 Dec( fUpdateCount );
58833 if fUpdateCount <= 0 then
58834 begin
58835 Invalidate;
58836 //Update;
58837 end;
58838 end;
58841 //[function TControl.GetSelection]
58842 function TControl.GetSelection: String;
58843 var L: Integer;
58844 begin
58845 if fCommandActions.aGetSelection <> 0 then
58846 begin
58847 L := SelLength;
58848 SetString( Result, nil, L + 1 );
58849 Perform( fCommandActions.aGetSelection, 0, Integer( @Result[ 1 ] ) );
58851 else
58852 Result := Copy( Text, SelStart + 1, SelLength );
58853 end;
58856 //[procedure TControl.SetSelection]
58857 procedure TControl.SetSelection(const Value: String);
58858 begin
58859 ReplaceSelection( Value, True );
58860 end;
58863 //[procedure TControl.ReplaceSelection]
58864 procedure TControl.ReplaceSelection(const Value: String; aCanUndo: Boolean);
58865 begin
58866 if fCommandActions.aReplaceSel <> 0 then
58867 begin
58868 Perform( fCommandActions.aReplaceSel, Integer( aCanUndo ), Integer( Pchar( Value ) ) );
58869 end;
58870 end;
58872 //[procedure TControl.DeleteLines]
58873 procedure TControl.DeleteLines(FromLine, ToLine: Integer);
58874 var I1, I2: Integer;
58875 SStart, SLength: Integer;
58876 begin
58877 if FromLine > ToLine then Exit;
58878 Assert( FromLine >= 0, 'Incorrect line index' );
58879 I1 := Item2Pos( FromLine );
58880 I2 := Item2Pos( ToLine+1 );
58881 SStart := SelStart;
58882 SLength := SelLength;
58883 SelStart := I1;
58884 SelLength := I2 - I1;
58885 ReplaceSelection( '', TRUE );
58886 if SStart >= I2 then
58887 begin
58888 SStart := SStart - (I2 - I1);
58890 else
58891 if SStart >= I1 then
58892 begin
58893 SLength := SLength - (I2 - SStart);
58894 SStart := I1;
58896 else
58897 if SStart + SLength >= I2 then
58898 begin
58899 SLength := SLength - (I2 - I1);
58901 else
58902 if SStart + SLength >= I1 then
58903 begin
58904 SLength := I1 - SLength;
58905 end;
58906 SelStart := SStart;
58907 SelLength := Max( 0, SLength );
58908 end;
58911 //[procedure TControl.SetTabOrder]
58912 procedure TControl.SetTabOrder(const Value: Integer);
58913 var CL: PList;
58914 I : Integer;
58915 C: PControl;
58916 begin
58917 if Value = fTabOrder then Exit;
58918 CL := CollectTabControls( ParentForm );
58919 for I := 0 to CL.fCount - 1 do
58920 begin
58921 C := CL.fItems[ I ];
58922 if C.fTabOrder >= Value then
58923 Inc( C.fTabOrder );
58924 end;
58925 fTabOrder := Value;
58926 CL.Free;
58927 end;
58930 //[function TControl.GetFocused]
58931 function TControl.GetFocused: Boolean;
58932 begin
58933 if fIsControl then
58934 Result := ParentForm.fCurrentControl = @Self
58935 else
58936 Result := GetForegroundWindow = fHandle;
58937 end;
58940 //[procedure TControl.SetFocused]
58941 procedure TControl.SetFocused(const Value: Boolean);
58942 begin
58943 if not Value then Exit;
58944 if fIsControl then
58945 begin
58946 ParentForm.fCurrentControl := @Self;
58947 SetFocus( GetWindowHandle );
58949 else
58950 begin
58951 SetForegroundWindow( GetWindowHandle );
58952 end;
58953 end;
58955 type
58956 PCharFormat = ^TCharFormat;
58963 //////////////////////////////////////////////////////////////////////
58966 // R I C H E D I T
58969 //////////////////////////////////////////////////////////////////////
58971 { -- rich edit -- }
58974 //[function TControl.REGetFont]
58975 function TControl.REGetFont: PGraphicTool;
58976 var CF: PCharFormat;
58977 FS: TFontStyle;
58978 begin
58979 CF := @fRECharFormatRec;
58980 FillChar( CF^, 82 {sizeof( TCharFormat2 )}, 0 );
58981 CF.cbSize := sizeof( RichEdit.TCharFormat ) + fCharFmtDeltaSz;
58982 if fTmpFont = nil then
58983 fTmpFont := NewFont;
58984 Result := fTmpFont;
58985 Result.OnChange := nil;
58986 Perform( EM_GETCHARFORMAT, 1, Integer( CF ) );
58987 Result.FontHeight := CF.yHeight;
58988 FS := [ ];
58989 if LongBool(CF.dwEffects and CFE_BOLD) then
58990 FS := [ fsBold ];
58991 if LongBool(CF.dwEffects and CFE_ITALIC) then
58992 FS := FS + [ fsItalic ];
58993 if LongBool(CF.dwEffects and CFE_STRIKEOUT) then
58994 FS := FS + [ fsStrikeOut ];
58995 if LongBool(CF.dwEffects and CFE_UNDERLINE) then
58996 FS := FS + [ fsUnderline ];
58997 Result.FontStyle := FS;
58998 if not LongBool(CF.dwEffects and CFE_AUTOCOLOR) then
58999 Result.Color := CF.crTextColor;
59000 Result.FontPitch := TFontPitch( CF.bPitchAndFamily and 3 );
59001 Result.FontCharset := CF.bCharSet;
59002 Result.FontName := CF.szFaceName;
59003 Result.OnChange := RESetFont;
59004 end;
59006 const RichAreas: array[ TRichFmtArea ] of Integer = ( SCF_SELECTION,
59007 SCF_WORD, 4 {SCF_ALL} );
59010 //[procedure TControl.RESetFontEx]
59011 procedure TControl.RESetFontEx(const Index: Integer);
59012 var CF: PCharFormat;
59013 FS: TFontStyle;
59014 begin
59015 CF := @fRECharFormatRec;
59016 FillChar( CF^, {82} sizeof( TCharFormat2 ), 0 );
59017 CF.cbSize := 60 { sizeof( TCharFormat ) } + fCharFmtDeltaSz;
59018 CF.dwMask := CFM_BOLD or CFM_COLOR or CFM_FACE or CFM_ITALIC
59019 or CFM_SIZE or CFM_STRIKEOUT or CFM_UNDERLINE;
59020 CF.yHeight := fTmpFont.FontHeight;
59021 FS := fTmpFont.FontStyle;
59022 if fsBold in FS then CF.dwEffects := CFE_BOLD;
59023 if fsItalic in FS then CF.dwEffects := CF.dwEffects or CFE_ITALIC;
59024 if fsStrikeOut in FS then CF.dwEffects := CF.dwEffects or CFE_STRIKEOUT;
59025 if fsUnderline in FS then CF.dwEffects := CF.dwEffects or CFE_UNDERLINE;
59026 CF.crTextColor := Color2RGB(fTmpFont.Color);
59027 CF.bCharSet := fTmpFont.FontCharset;
59028 CF.bPitchAndFamily := Ord( fTmpFont.FontPitch );
59029 StrLCopy( CF.szFaceName, PChar( fTmpFont.FontName ), 31 );
59030 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( CF ) );
59031 end;
59034 //[procedure TControl.RESetFont]
59035 procedure TControl.RESetFont(Value: PGraphicTool);
59036 var H: Integer;
59037 begin
59038 if Value <> fTmpFont then
59039 REGetFont;
59040 H := fTmpFont.fData.Font.Height;
59041 fTmpFont := fTmpFont.Assign( Value );
59042 if fTmpFont.fData.Font.Height = 0 then
59043 fTmpFont.fData.Font.Height := H;
59044 RESetFontEx( Integer( CFM_BOLD or CFM_COLOR or CFM_FACE or CFM_ITALIC
59045 or CFM_SIZE or CFM_STRIKEOUT or CFM_UNDERLINE ) );
59046 end;
59049 //[function TControl.REGetFontMask]
59050 function TControl.REGetFontMask( const Index: Integer ): Boolean;
59051 begin
59052 REGetFont;
59053 Result := LongBool( fRECharFormatRec.dwMask and Index );
59054 end;
59057 //[function TControl.REGetFontEffects]
59058 function TControl.REGetFontEffects(const Index: Integer): Boolean;
59059 begin
59060 REGetFont;
59061 Result := LongBool( fRECharFormatRec.dwEffects and Index );
59062 end;
59065 //[procedure TControl.RESetFontEffect]
59066 procedure TControl.RESetFontEffect(const Index: Integer;
59067 const Value: Boolean);
59068 var CF: PCharFormat;
59069 begin
59070 ReGetFont;
59071 CF := @fRECharFormatRec;
59072 CF.dwEffects := $FFFFFFFF and Index;
59073 if not Value then CF.dwEffects := 0;
59074 CF.dwMask := Index;
59075 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( CF ) );
59076 end;
59079 //[function TControl.REGetFontAttr]
59080 function TControl.REGetFontAttr(const Index: Integer): Integer;
59081 var CF: PDWORD;
59082 Mask: DWORD;
59083 begin
59084 REGetFont;
59085 CF := Pointer( Integer( @fRECharFormatRec ) + (HiWord(Index) and $7E) );
59086 Mask := $FFFFFFFF;
59087 if LongBool( HiWord(Index) and $1 ) then
59088 Mask := $FF;
59089 Result := CF^ and Mask;
59090 end;
59093 //[procedure TControl.RESetFontAttr]
59094 procedure TControl.RESetFontAttr(const Index, Value: Integer);
59095 {const
59096 CFE_MASK = CFE_AUTOCOLOR or CFE_BOLD or CFE_ITALIC or CFE_PROTECTED or CFE_STRIKEOUT or
59097 CFE_UNDERLINE or CFE_LINK or CFE_SUBSCRIPT or CFE_SUPERSCRIPT or}
59098 var CF: PDWORD;
59099 Mask: DWORD;
59100 begin
59101 REGetFont;
59102 CF := Pointer( Integer( @fRECharFormatRec ) + (HiWord(Index) and $7E) );
59103 Mask := 0;
59104 if LongBool( HiWord(Index) and $1 ) then
59105 Mask := $FFFFFF00;
59106 CF^ := CF^ and Mask or DWORD(Value);
59107 fRECharFormatRec.dwMask := Index and $FF81FFFF;
59108 if LongBool( fRECharFormatRec.dwMask and (CFM_COLOR or CFM_BACKCOLOR) ) then
59109 fRECharFormatRec.dwEffects := fRECharFormatRec.dwEffects and
59110 not (CFE_AUTOCOLOR or CFE_AUTOBACKCOLOR);
59111 {fRECharFormatRec.dwEffects := fRECharFormatRec.dwEffects and CFE_MASK;}
59112 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @fRECharFormatRec ) );
59113 end;
59115 //[procedure TControl.RESetFontAttr1]
59116 procedure TControl.RESetFontAttr1(const Index, Value: Integer);
59117 begin
59118 RESetFontAttr( Index, Color2RGB( Value ) );
59119 end;
59122 //[function TControl.REGetFontSizeValid]
59123 function TControl.REGetFontSizeValid: Boolean;
59124 begin
59125 Result := REGetFontMask( Integer( CFM_SIZE ) );
59126 end;
59129 //[function TControl.REGetFontName]
59130 function TControl.REGetFontName: String;
59131 begin
59132 ReGetFont;
59133 Result := fRECharFormatRec.szFaceName;
59134 end;
59137 //[procedure TControl.RESetFontName]
59138 procedure TControl.RESetFontName(const Value: String);
59139 begin
59140 ReGetFont;
59141 StrLCopy( fRECharFormatRec.szFaceName, PChar( Value ), Sizeof( fRECharFormatRec.szFaceName ) - 1 );
59142 fRECharFormatRec.dwMask := CFM_FACE;
59143 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @fRECharFormatRec ) );
59144 end;
59147 //[procedure TControl.SelectAll]
59148 procedure TControl.SelectAll;
59149 begin
59150 SelStart := 0;
59151 SelLength := -1; // this can be not working for some controls... //*//*
59152 end;
59155 //[function TControl.REGetCharformat]
59156 function TControl.REGetCharformat: TCharFormat;
59157 begin
59158 REGetFont;
59159 Result := fRECharFormatRec;
59160 end;
59163 //[procedure TControl.RESetCharFormat]
59164 procedure TControl.RESetCharFormat(const Value: TCharFormat);
59165 begin
59166 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @Value ) );
59167 end;
59170 //[function REOut2Stream]
59171 function REOut2Stream( Sender: PControl; Buf: PByte; Sz: DWORD; pSz: PInteger )
59172 :DWORD; stdcall;
59173 begin
59174 if Sz + Sender.fREStream.Position > Sender.fREStream.Size then
59175 Sender.fREStream.Size := Sender.fREStream.Size + DWORD( {Min(} Sz {, 8192 )} );
59176 pSz^ := Sender.fREStream.Write( Buf^, Sz );
59177 if Assigned( Sender.fOnProgress ) then
59178 Sender.fOnProgress( Sender );
59179 Result := 0;
59180 end;
59182 const TextTypes: array[ TRETextFormat ] of WORD = ( SF_RTF, SF_TEXT,
59183 SF_RTF or SFF_PLAINRTF, SF_RTFNOOBJS, SF_RTFNOOBJS or SFF_PLAINRTF,
59184 SF_TEXTIZED );
59187 //[function TControl.RE_SaveToStream]
59188 function TControl.RE_SaveToStream(Stream: PStream; Format: TRETextFormat;
59189 SelectionOnly: Boolean): Boolean;
59190 var ES: TEditStream;
59191 SelFlag: Integer;
59192 begin
59193 fREStream := Stream;
59194 ES.dwCookie := Integer( @Self );
59195 ES.dwError := 0;
59196 ES.pfnCallback := @REOut2Stream;
59197 SelFlag := 0;
59198 if SelectionOnly then
59199 SelFlag := SFF_SELECTION;
59200 Perform( EM_STREAMOUT, TextTypes[ Format ] or SelFlag, Integer( @ES ) );
59201 fREStream := nil;
59202 fREError := ES.dwError;
59203 Result := fREError = 0;
59204 end;
59206 //[procedure RE_AddText]
59207 procedure RE_AddText( Self_: PControl; const S: String );
59208 begin
59209 Self_.SelStart := Self_.TextSize;
59210 Self_.RE_Text[ reText, True ] := S;
59211 end;
59214 //[function TControl.REReadText]
59215 function TControl.REReadText(Format: TRETextFormat;
59216 SelectionOnly: Boolean): String;
59217 var B0: Integer;
59218 MS: PStream;
59219 begin
59220 fCommandActions.aAddText := RE_AddText;
59221 MS := NewMemoryStream;
59222 RE_SaveToStream( MS, Format, SelectionOnly );
59223 B0 := 0;
59224 MS.Write( B0, 1 );
59225 Result := PChar( MS.fMemory );
59226 MS.Free;
59227 end;
59230 //[function REInFromStream]
59231 function REInFromStream( Sender: PControl; Buf: PByte; Sz: DWORD; pSz: PInteger )
59232 :DWORD; stdcall;
59233 begin
59234 {$IFDEF _D3} if Sender.fREStrLoadLen >= 0 then {$ENDIF}
59235 if Sz > Sender.fREStrLoadLen then
59236 Sz := Sender.fREStrLoadLen;
59237 pSz^ := Sender.fREStream.Read( Buf^, Sz );
59238 Dec( Sender.fREStrLoadLen, pSz^ );
59239 if Assigned( Sender.fOnProgress ) then
59240 Sender.fOnProgress( Sender );
59241 Result := 0;
59242 end;
59245 //[function TControl.RE_LoadFromStream]
59246 function TControl.RE_LoadFromStream(Stream: PStream; Length: Integer;
59247 Format: TRETextFormat; SelectionOnly: Boolean): Boolean;
59248 var ES: TEditStream;
59249 SelFlag: Integer;
59250 begin
59251 fREStream := Stream;
59252 fREStrLoadLen := DWORD( Length );
59253 ES.dwCookie := Integer( @Self );
59254 ES.dwError := 0;
59255 ES.pfnCallback := @REInFromStream;
59256 SelFlag := 0;
59257 if SelectionOnly then
59258 SelFlag := SFF_SELECTION;
59259 Perform( EM_STREAMIN, TextTypes[ Format ] or SelFlag, Integer( @ES ) );
59260 fREStream := nil;
59261 fREError := ES.dwError;
59262 Result := fREError = 0;
59263 end;
59266 //[procedure TControl.REWriteText]
59267 procedure TControl.REWriteText(Format: TRETextFormat;
59268 SelectionOnly: Boolean; const Value: String);
59269 var MS: PStream;
59270 begin
59271 fCommandActions.aAddText := RE_AddText;
59272 MS := NewMemoryStream;
59273 MS.fMemory := PChar( Value );
59274 MS.fData.fSize := Length( Value );
59275 MS.fData.fCapacity := MS.fData.fSize;
59276 RE_LoadFromStream( MS, MS.fData.fSize, Format, SelectionOnly );
59277 MS.fMemory := nil;
59278 MS.Free;
59279 end;
59282 //[function TControl.RE_LoadFromFile]
59283 function TControl.RE_LoadFromFile(const Filename: String;
59284 Format: TRETextFormat; SelectionOnly: Boolean): Boolean;
59285 var Strm: PStream;
59286 begin
59287 Strm := NewReadFileStream( Filename );
59288 Result := RE_LoadFromStream( Strm, -1, Format, SelectionOnly );
59289 Strm.Free;
59290 end;
59293 //[function TControl.RE_SaveToFile]
59294 function TControl.RE_SaveToFile(const Filename: String;
59295 Format: TRETextFormat; SelectionOnly: Boolean): Boolean;
59296 var Strm: PStream;
59297 begin
59298 Strm := NewWriteFileStream( Filename );
59299 Result := RE_SaveToStream( Strm, Format, SelectionOnly );
59300 Strm.Free;
59301 end;
59304 //[function TControl.REGetParaFmt]
59305 function TControl.REGetParaFmt: TParaFormat;
59306 begin
59307 FillChar( Result, sizeof( TParaFormat2 ), 0 );
59308 Result.cbSize := sizeof( RichEdit.TParaFormat ) + fParaFmtDeltaSz;
59309 Perform( EM_GETPARAFORMAT, 0, Integer( @Result ) );
59310 end;
59313 //[procedure TControl.RESetParaFmt]
59314 procedure TControl.RESetParaFmt(const Value: TParaFormat);
59315 begin
59316 //Value.cbSize := szTParaFmtRec;
59317 Perform( EM_SETPARAFORMAT, 0, Integer( @Value ) );
59318 end;
59321 //[function TControl.REGetNumbering]
59322 function TControl.REGetNumbering: Boolean;
59323 begin
59324 Result := LongBool( ReGetParaAttr( 9 shl 16 ) );
59325 end;
59328 //[function TControl.REGetParaAttr]
59329 function TControl.REGetParaAttr( const Index: Integer ): Integer;
59330 var pDw : PDWORD;
59331 begin
59332 fREParaFmtRec := REGetParaFmt;
59333 pDw := Pointer( Integer( @fREParaFmtRec ) + ( HiWord( Index ) and $7E ) );
59334 Result := pDw^;
59335 if LongBool( HiWord( Index ) and 1 ) then
59336 Result := Result and $FFFF;
59337 end;
59340 //[function TControl.REGetParaAttrValid]
59341 function TControl.REGetParaAttrValid( const Index: Integer ): Boolean;
59342 begin
59343 Result := LongBool( ReGetParaAttr( 4 shl 16 ) and Index );
59344 end;
59347 //[function TControl.REGetTabCount]
59348 function TControl.REGetTabCount: Integer;
59349 begin
59350 Result := ReGetParaAttr( 27 shl 16 );
59351 end;
59354 //[function TControl.REGetTabs]
59355 function TControl.REGetTabs(Idx: Integer): Integer;
59356 begin
59357 Result := ReGetParaAttr( (28 + 4 * Idx) shl 16 );
59358 end;
59361 //[function TControl.REGetTextAlign]
59362 function TControl.REGetTextAlign: TRichTextAlign;
59363 begin
59364 Result := TRichTextAlign( ReGetParaAttr( 25 shl 16 ) - 1 );
59365 end;
59368 //[procedure TControl.RESetNumbering]
59369 procedure TControl.RESetNumbering(const Value: Boolean);
59370 begin
59371 RESetParaAttr( (9 shl 16) or PFM_NUMBERING, Integer( Value ) );
59372 end;
59375 //[procedure TControl.RESetParaAttr]
59376 procedure TControl.RESetParaAttr(const Index, Value: Integer);
59377 var pDw: PDWORD;
59378 Mask: Integer;
59379 begin
59380 REGetParaAttr( 0 );
59381 pDw := Pointer( Integer( @fREParaFmtRec ) + ( HiWord( Index ) and $7E ) );
59382 Mask := 0;
59383 if LongBool( HiWord( Index ) and 1 ) then
59384 Mask := Integer( $FFFF0000 );
59385 pDw^ := pDw^ and Mask or DWORD(Value);
59386 //////////////////////////////////////////////////////////////////////////////
59387 fREParaFmtRec.dwMask := Index and $8000FFFF;
59388 //////////////////////////////////////////////////////////////////////////////
59389 //fREParaFmtRec.dwMask := DWORD( Index ) or $8000FFFF; //
59390 //////////////////////////////////////////////////////////////////////////////
59391 RESetParaFmt( fREParaFmtRec );
59392 end;
59395 //[procedure TControl.RESetTabCount]
59396 procedure TControl.RESetTabCount(const Value: Integer);
59397 begin
59398 REGetParaAttr( 0 );
59399 RESetParaAttr( (27 shl 16) or PFM_TABSTOPS, Value );
59400 end;
59403 //[procedure TControl.RESetTabs]
59404 procedure TControl.RESetTabs(Idx: Integer; const Value: Integer);
59405 begin
59406 REGetParaAttr( 0 );
59407 RESetParaAttr( (28 + 4 * Idx) or PFM_TABSTOPS, Value );
59408 end;
59411 //[procedure TControl.RESetTextAlign]
59412 procedure TControl.RESetTextAlign(const Value: TRichTextAlign);
59413 begin
59414 RESetParaAttr( (25 shl 16) or PFM_ALIGNMENT, Ord( Value ) + 1 );
59415 end;
59418 //[function TControl.REGetStartIndentValid]
59419 function TControl.REGetStartIndentValid: Boolean;
59420 begin
59421 Result := REGetParaAttrValid( Integer( PFM_STARTINDENT ) );
59422 end;
59425 //[procedure TControl.RE_HideSelection]
59426 procedure TControl.RE_HideSelection(aHide: Boolean);
59427 begin
59428 Perform( EM_HIDESELECTION, Integer( aHide ), 1 );
59429 end;
59432 //[function TControl.RE_SearchText]
59433 function TControl.RE_SearchText(const Value: String; MatchCase,
59434 WholeWord, ScanForward: Boolean; SearchFrom, SearchTo: Integer): Integer;
59435 var Flags: Integer;
59436 FT: TFindText;
59437 begin
59438 Flags := Integer( ScanForward );
59439 if WholeWord then Flags := Flags or FT_WHOLEWORD;
59440 if MatchCase then Flags := Flags or FT_MATCHCASE;
59441 FT.chrg.cpMin := SearchFrom;
59442 FT.chrg.cpMax := SearchTo;
59443 FT.lpstrText := PChar( Value );
59444 Result := Perform( EM_FINDTEXT, Flags, Integer( @FT ) );
59445 end;
59448 //[function TControl.CanUndo]
59449 function TControl.CanUndo: Boolean;
59450 begin
59451 Result := LongBool( Perform( EM_CANUNDO, 0, 0 ) );
59452 end;
59455 //[procedure TControl.EmptyUndoBuffer]
59456 procedure TControl.EmptyUndoBuffer;
59457 begin
59458 Perform( EM_EMPTYUNDOBUFFER, 0, 0 );
59459 end;
59462 //[function TControl.Undo]
59463 function TControl.Undo: Boolean;
59464 begin
59465 Result := LongBool( Perform( EM_UNDO, 0, 0 ) );
59466 end;
59469 //[function TControl.RE_Redo]
59470 function TControl.RE_Redo: Boolean;
59471 begin
59472 Result := LongBool( Perform( EM_REDO, 0, 0 ) );
59473 end;
59476 //[function TControl.REGetAutoURLDetect]
59477 function TControl.REGetAutoURLDetect: Boolean;
59478 begin
59479 Result := LongBool( Perform( EM_GETAUTOURLDETECT, 0, 0 ) );
59480 end;
59483 //[procedure TControl.RESetAutoURLDetect]
59484 procedure TControl.RESetAutoURLDetect(const Value: Boolean);
59485 begin
59486 AttachProc( WndProc_RE_LinkNotify );
59487 Perform( EM_AUTOURLDETECT, Integer( Value ), 0 );
59488 end;
59491 //[function TControl.GetMaxTextSize]
59492 function TControl.GetMaxTextSize: DWORD;
59493 begin
59494 Result := Perform( EM_GETLIMITTEXT, 0, 0 );
59495 end;
59498 //[procedure TControl.SetMaxTextSize]
59499 procedure TControl.SetMaxTextSize(const Value: DWORD);
59500 var V1, V2: Integer;
59501 begin
59502 if fCommandActions.aSetLimit <> 0 then
59503 begin
59504 V1 := 0; V2 := Value;
59505 if fCommandActions.aSetLimit = EM_SETLIMITTEXT then
59506 begin
59507 V1 := Value; V2 := 0;
59508 end;
59509 Perform( fCommandActions.aSetLimit, V1, V2 );
59510 end;
59511 end;
59514 //[function WndProc_REFmt]
59515 function WndProc_REFmt( _Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59516 var Mask: Integer;
59517 Shft, Flg: Boolean;
59518 Delta: Integer;
59519 TA: TRichTextAlign;
59520 ChgTA: Boolean;
59521 US: TRichUnderline;
59522 NS: TRichNumbering;
59523 NB: TRichNumBrackets;
59524 Side: TBorderEdge;
59525 Param: DWORD;
59526 begin
59527 Result := False;
59528 if Msg.message = WM_CHAR then
59529 if _Self_.FSupressTab then
59530 begin
59531 _Self_.FSupressTab := FALSE;
59532 if Msg.wParam = 9 then
59533 begin
59534 Result := TRUE;
59535 Exit;
59536 end;
59537 end;
59539 if Msg.message = WM_KEYDOWN then
59540 if GetKeyState( VK_CONTROL ) < 0 then
59541 begin
59542 Shft := GetKeyState( VK_SHIFT ) < 0;
59543 Rslt := 0;
59544 Result := True;
59545 Mask := 0;
59546 ChgTA := False; TA := raLeft;
59547 Param := Msg.wParam;
59548 //Msg.wParam := 0;
59549 case Param of
59550 Integer('Z'):
59551 begin
59552 if Shft then
59553 begin
59554 _Self_.RE_Redo;
59555 Exit;
59556 end;
59557 Result := False;
59558 end;
59560 Integer('L'): begin ChgTA := True; TA := raLeft; end;
59561 Integer('R'): begin ChgTA := True; TA := raRight; end;
59562 Integer('E'): begin ChgTA := True; TA := raCenter; end;
59563 Integer('J'): begin ChgTA := True; TA := raJustify; end;
59564 Integer('N'): begin
59565 if Shft then
59566 begin
59567 NS := _Self_.RE_NumStyle;
59568 NB := _Self_.RE_NumBrackets;
59569 if NS = rnBullets then
59570 begin
59571 _Self_.RE_NumStyle := rnNone;
59572 Exit;
59573 end;
59574 if NS = rnNone then
59575 begin
59576 _Self_.RE_NumStyle := rnBullets;
59577 //NB := rnbPlain;
59578 Exit;
59580 else
59581 if Ord( NB ) = 0 then
59582 NB := High(NB) else
59583 NB := Pred(NB);
59584 _Self_.RE_NumBrackets := NB;
59586 else
59587 begin
59588 NS := _Self_.RE_NumStyle;
59589 if Ord( NS ) = 0 then
59590 begin
59591 NS := rnURoman; //rnULetter; //High( NS );
59592 { because rnLRoman, rnURoman, rnNoNumber are not shown
59593 in RichEdit. }
59594 _Self_.RE_NumBrackets := rnbPeriod;
59595 end else
59596 NS := Pred(NS);
59597 _Self_.RE_NumStyle := NS;
59598 if NS in [ rnLRoman, rnURoman, rnArabic ] then
59599 _Self_.RE_NumStart := 1;
59600 end;
59601 Exit;
59602 end;
59603 Integer('W'): begin
59604 Delta := _Self_.RE_BorderWidth[ beLeft ] + 4;
59605 if Shft then Delta := -1;
59606 for Side := Low(Side) to High(Side) do
59607 begin
59608 if Delta < 0 then
59609 _Self_.RE_BorderStyle[ Side ] := _Self_.RE_BorderStyle[ Side ] + 1
59610 else
59611 begin
59612 _Self_.RE_BorderWidth[ Side ] := Delta;
59613 _Self_.RE_BorderSpace[ Side ] := Delta;
59614 end;
59615 end;
59616 Exit;
59617 end;
59618 (* TABLES STUFF -- to try, uncomment it and press CTRL+T in RichEdit.
59619 (and uncomment declaration for Tmp above).
59621 Not finished, and seems no way to figure it out - even RichEdit20.dll
59622 (i.e. Rich Edit v3.0) can not display tables properly formatted. :(((
59624 Integer('T'): begin
59625 if _Self_.RE_Table then
59626 begin
59627 //MsgOK( 'table' );
59628 end;
59629 Tmp := _Self_.REReadText( reRTF, True );
59630 if StrIsStartingFrom( PChar(Tmp), '{\rtf' )
59631 and (CopyTail( Tmp, 3 ) = '}'#$D#$A) then
59632 begin
59633 //Tmp := Copy( Tmp, 1, Length(Tmp) - 3 );
59634 _Self_.RE_Text[ reRTF, True ] := '{\rtf1' + //Copy( Tmp, 1, 6 ) +
59635 '\trowd' +
59636 //'\lytcalctblwd' +
59637 //'\oldlinewrap' +
59638 //'\alntblind' +
59639 //'\trgaph108' +
59640 '\trleft-108' +
59641 {'\trbrdrt\brdrs\brdrw10' +
59642 '\trbrdrl\brdrs\brdrw10' +
59643 '\trbrdrb\brdrs\brdrw10' +
59644 '\trbrdrr\brdrs\brdrw10' +
59645 '\trbrdrh\brdrs\brdrw10' +
59646 '\trbrdrv\brdrs\brdrw10' +}
59647 //'\clvertalt' +
59648 {'\clbrdrt\brdrs\brdrw10' +
59649 '\clbrdrl\brdrs\brdrw10' +
59650 '\clbrdrb\brdrs\brdrw10' +
59651 '\clbrdrr\brdrs\brdrw10' +}
59652 //'\cltxlrtb' +
59653 '\cellx1414' +
59654 //'\pard' +
59655 //'\plain' +
59656 //'\widctlpar' +
59657 '\trautofit1' +
59658 '\intbl' +
59659 //'\adjustright' +
59660 //'\fs20\lang1049' +
59661 //'\cgrid' +
59662 '\trrh0' +
59663 '{\clFitText{{\box\brdrs\brdrw20\brsp20}'+
59664 '\par}\cell\row}' +
59665 //'\pard\widctlpar' +
59666 //'\intbl'+
59667 //'\adjustright'+
59668 //'{\row}' +
59669 '\pard\widctlpar' +
59670 '}'#$D#$A;
59671 _Self_.Perform( WM_KEYDOWN, VK_UP, 0 );
59672 _Self_.Perform( WM_KEYUP, VK_UP, 0 );
59673 end;
59674 Exit;
59675 end;
59677 Integer('B'): Mask := CFM_BOLD;
59678 Integer('I'):
59679 begin
59680 Mask := CFM_ITALIC;
59681 _Self_.FSupressTab := TRUE;
59682 end;
59683 Integer('U'):
59684 begin
59685 if Shft then
59686 begin
59687 US := _Self_.RE_FmtUnderlineStyle;
59688 if Ord(US) = 0 then US := High(TRichUnderLine)
59689 else US := Pred( US );
59690 _Self_.RE_FmtUnderlineStyle := US;
59691 Exit;
59692 end;
59693 Mask := CFM_UNDERLINE;
59694 end;
59695 Integer('O'): Mask := CFM_STRIKEOUT;
59696 VK_SUBTRACT, VK_ADD: Mask := Integer( CFM_SIZE );
59697 else
59698 begin
59699 Result := False;
59700 Msg.wParam := Param;
59701 end;
59702 end;
59703 if not Result then Exit;
59705 if ChgTA then
59706 begin
59707 if Shft then Result := False
59708 else _Self_.RE_TextAlign := TA;
59709 Exit;
59710 end;
59712 _Self_.REGetFont;
59713 if Mask > 0 then
59714 begin
59715 if Shft then Result := False
59716 else begin
59717 Flg := _Self_.REGetFontEffects( Mask );
59718 if not Flg then
59719 _Self_.fRECharFormatRec.dwEffects := _Self_.fRECharFormatRec.dwEffects and not Mask;
59720 _Self_.fRECharFormatRec.dwEffects := _Self_.fRECharFormatRec.dwEffects xor DWORD(Mask);
59721 end;
59723 else
59724 begin
59725 if Msg.wParam = VK_SUBTRACT then
59726 Delta := -1
59727 else
59728 Delta := 1;
59729 if Shft then
59730 Mask := CFM_OFFSET;
59731 if Shft then
59732 Inc( _Self_.fRECharFormatRec.yOffset, Delta * _Self_.fRECharFormatRec.yHeight div 3 )
59733 else
59734 Inc( _Self_.fRECharFormatRec.yHeight, Delta * _Self_.fRECharFormatRec.yHeight div 8 );
59735 Flg := LongBool( _Self_.fRECharFormatRec.dwMask and Mask );
59736 if not Flg then
59737 _Self_.fRECharFormatRec.yOffset := 0;
59738 end;
59739 _Self_.fRECharFormatRec.dwMask := Mask;
59740 _Self_.Perform( EM_SETCHARFORMAT, SCF_SELECTION { RichAreas[ _Self_.fRECharArea ] }, Integer( @_Self_.fRECharFormatRec ) );
59741 end;
59742 end;
59745 //[function TControl.RE_FmtStandard]
59746 function TControl.RE_FmtStandard: PControl;
59747 begin
59748 AttachProc( WndProc_REFmt );
59749 Result := @Self;
59750 end;
59752 //[FUNCTION EnumDynHandlers]
59753 {$IFDEF ASM_VERSION}
59754 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59755 asm //cmd //opd
59756 CMP [EAX].TControl.fRefCount, 0
59757 JL @@fin_false
59758 PUSHAD
59759 MOV EBX, EAX
59760 MOV EBP, ECX
59761 MOV ECX, [EBX].TControl.fDynHandlers
59762 JECXZ @@ret_false
59763 MOV ESI, ECX
59764 MOV ECX, [ESI].TList.fCount
59765 JECXZ @@ret_false
59766 MOV EDI, ECX
59767 SHR EDI, 1
59768 CALL TControl.RefInc
59769 @@loo: DEC EDI
59770 JS @@e_loo
59771 PUSH EDX
59772 PUSH EBX
59773 {$IFNDEF ENUM_DYN_HANDLERS_AFTER_RUN}
59774 XOR EAX, EAX
59775 CMP [AppletTerminated], AL
59776 JZ @@do_call
59777 MOV ECX, [ESI].TList.fItems
59778 MOV ECX, [ECX+EDI*8+4]
59779 JECXZ @@skip_call
59780 {$ENDIF}
59781 @@do_call:
59782 MOV EAX, [ESI].TList.fItems
59783 MOV EAX, [EAX+EDI*8]
59784 XCHG EAX, EBX
59785 MOV ECX, EBP
59786 CALL EBX
59787 @@skip_call:
59788 POP EBX
59789 POP EDX
59790 TEST AL, AL
59791 JZ @@loo
59792 @@ret_true:
59793 MOV EAX, EBX
59794 CALL TControl.RefDec
59795 POPAD
59796 MOV AL, 1
59798 @@e_loo:
59799 XOR EAX, EAX
59800 INC EAX
59801 CMP [EBX].TControl.fRefCount, EAX
59802 JE @@ret_true
59803 MOV EAX, EBX
59804 CALL TControl.RefDec
59805 @@ret_false:
59806 POPAD
59807 @@fin_false:
59808 XOR EAX, EAX
59809 end;
59810 {$ELSE ASM_VERSION} //Pascal
59811 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59812 var I: Integer;
59813 Proc: TWindowFunc;
59814 begin
59815 Result := False;
59816 if Self_.fRefCount < 0 then Exit;
59817 if (Self_.fDynHandlers = nil) or (Self_.fDynHandlers.fCount = 0) then Exit;
59818 Self_.RefInc; // Prevent destroying Self_
59819 for I := Self_.fDynHandlers.fCount div 2 - 1 downto 0 do
59820 begin
59821 Proc := Self_.fDynHandlers.fItems[ I * 2 ];
59822 {$IFNDEF ENUM_DYN_HANDLERS_AFTER_RUN}
59823 if not AppletTerminated or (Self_.fDynHandlers.fItems[ I * 2 + 1 ] <> nil) then
59824 {$ENDIF}
59825 if Proc( Self_, Msg, Rslt ) then
59826 begin
59827 Result := True;
59828 break;
59829 end;
59830 end;
59831 {$IFDEF DEBUG_ENDSESSION}
59832 if EndSession_Initiated then
59833 begin
59834 LogFileOutput( GetStartDir + 'es_debug.txt',
59835 'ENUM_DYN_HANDLERS: Self_:' + Int2Hex( DWORD( Self_ ), 8 ) );
59836 LogFileOutput( GetStartDir + 'es_debug.txt',
59837 'ENUM_DYN_HANDLERS: Self_.fRefCount:' + Int2Str( Self_.fRefCount ) );
59838 end;
59839 {$ENDIF}
59840 if LongBool(Self_.fRefCount and 1) then
59841 Result := True; // If Self_ will be destroyed now, stop further processing
59842 Self_.RefDec; // Destroy Self_, if Free was called for it while processing attached procedures
59843 end;
59844 {$ENDIF ASM_VERSION}
59845 //[END EnumDynHandlers]
59847 {$IFDEF ASM_VERSION}
59848 //[procedure TControl.AttachProcEx]
59849 procedure TControl.AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );
59850 asm //cmd //opd
59851 PUSH EBX
59852 PUSH EDI
59853 PUSH ECX
59854 XCHG EBX, EAX
59855 MOV EDI, EDX
59856 MOV [EBX].fOnDynHandlers, offset[EnumDynHandlers]
59857 MOV ECX, [EBX].TControl.fDynHandlers
59858 INC ECX
59859 LOOP @@1
59860 CALL NewList
59861 XCHG ECX, EAX
59862 MOV [EBX].TControl.fDynHandlers, ECX
59863 @@1:
59864 PUSH ECX
59865 MOV EAX, EBX
59866 MOV EDX, EDI
59867 CALL TControl.IsProcAttached
59868 TEST AL, AL
59869 POP EBX
59870 JNZ @@exit
59871 MOV EAX, EBX
59872 MOV EDX, EDI
59873 CALL TList.Add
59874 XCHG EAX, EBX
59875 POP EDX
59876 PUSH EDX
59877 CALL TList.Add
59878 @@exit:
59879 POP ECX
59880 POP EDI
59881 POP EBX
59882 end;
59883 {$ELSE ASM_VERSION} //Pascal
59884 procedure TControl.AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );
59885 begin
59886 if fDynHandlers = nil then
59887 fDynHandlers := NewList;
59888 if not IsProcAttached( Proc ) then
59889 begin
59890 fDynHandlers.Add( @Proc );
59891 fDynHandlers.Add( Pointer( Integer( ExecuteAfterAppletTerminated ) ) );
59892 end;
59893 fOnDynHandlers := EnumDynHandlers;
59894 end;
59895 {$ENDIF ASM_VERSION}
59897 //[procedure TControl.AttachProc]
59898 procedure TControl.AttachProc(Proc: TWindowFunc);
59899 begin
59900 AttachProcEx( Proc, FALSE );
59901 end;
59904 //[procedure TControl.DetachProc]
59905 procedure TControl.DetachProc(Proc: TWindowFunc);
59906 var I: Integer;
59907 begin
59908 if fDynHandlers = nil then Exit;
59909 I := fDynHandlers.IndexOf( @Proc );
59910 if I >=0 then
59911 begin
59912 fDynHandlers.Delete( I );
59913 fDynHandlers.Delete( I );
59914 end;
59915 end;
59917 {$IFDEF ASM_VERSION}
59918 //[function TControl.IsProcAttached]
59919 function TControl.IsProcAttached(Proc: TWindowFunc): Boolean;
59920 asm //cmd //opd
59921 MOV ECX, [EAX].TControl.fDynHandlers
59922 JECXZ @@exit
59923 XCHG EAX, ECX
59924 CALL TList.IndexOf
59925 TEST EAX, EAX
59926 SETGE CL
59927 @@exit: XCHG EAX, ECX
59928 end;
59929 {$ELSE ASM_VERSION} //Pascal
59930 function TControl.IsProcAttached(Proc: TWindowFunc): Boolean;
59931 var I: Integer;
59932 begin
59933 Result := False;
59934 if fDynHandlers = nil then Exit;
59935 I := fDynHandlers.IndexOf( @Proc );
59936 Result := I >=0;
59937 end;
59938 {$ENDIF ASM_VERSION}
59940 //[function WndProcAutoPopupMenu]
59941 function WndProcAutoPopupMenu( Control: PControl; var Msg: TMsg; var MsgRslt: Integer ): Boolean;
59942 var R: TRect;
59943 M: Word;
59944 I: Integer;
59945 P: TPoint;
59946 begin
59947 if (Msg.message = WM_CONTEXTMENU) and
59948 (Control.fAutoPopupMenu <> nil) then
59949 begin
59950 {$IFDEF USE_MENU_CURCTL}
59951 PMenu( Control.fAutoPopupMenu ).fCurCtl := Control;
59952 {$ENDIF USE_MENU_CURCTL}
59953 P.X := SmallInt( LoWord( Msg.lParam ) );
59954 P.Y := SmallInt( HiWord( Msg.lParam ) );
59955 if (Msg.lParam = -1) then
59956 begin
59957 I := Control.CurIndex;
59958 M := Control.fCommandActions.aItem2XY;
59959 if (I >= 0) and (M <> 0) then
59960 begin
59961 CASE M OF
59962 EM_POSFROMCHAR:
59963 begin
59964 I := Control.SelStart + Control.SelLength;
59965 // Edit or Rich Edit 2:
59966 I := Control.Perform( M, I, 1 );
59967 P.X := SmallInt( LoWord( I ) );
59968 P.Y := SmallInt( HiWord( I ) );
59969 end;
59970 LB_GETITEMRECT, LVM_GETITEMRECT, TCM_GETITEMRECT:
59971 begin
59972 R.Left := LVIR_BOUNDS;
59973 Control.Perform( M, I, Integer( @ R ) );
59974 P.X := R.Left;
59975 P.Y := R.Bottom;
59976 end;
59977 TVM_GETITEMRECT:
59978 begin
59979 I := Control.TVSelected;
59980 R.Left := I;
59981 Control.Perform( M, 1, Integer( @ R ) );
59982 P.X := R.Left;
59983 P.Y := R.Bottom;
59984 end;
59985 END;
59986 R := Control.ClientRect;
59987 if P.X < R.Left then P.X := R.Left;
59988 if P.X > R.Right then P.X := R.Right;
59989 if P.Y < R.Top then P.Y := R.Top;
59990 if P.Y > R.Bottom then P.Y := R.Bottom;
59991 end;
59992 P := Control.Client2Screen( P );
59993 end;
59994 PMenu( Control.fAutoPopupMenu ).Popup( P.X, P.Y );
59995 Result := TRUE;
59997 else
59998 Result := FALSE;
59999 end;
60001 //[procedure TControl.SetAutoPopupMenu]
60002 procedure TControl.SetAutoPopupMenu(PopupMenu: PObj);
60003 { new version - by Alexander Pravdin. Allows to attach a submenu (e.g. of the
60004 main menu) as a popup menu to a control, to avoid duplicating menu object,
60005 if it is the same already as desired. }
60006 var pm: PMenu;
60007 begin
60008 if PopupMenu <> nil then
60009 {$IFDEF USE_MENU_CURCTL}
60010 begin
60011 pm := PMenu( PopupMenu );
60012 if ( pm.FParent <> nil ) then
60013 begin
60014 while pm.FControl = nil do
60015 pm := pm.FParent;
60016 PMenu( PopupMenu ).FControl := pm.FControl;
60018 else
60019 begin
60020 PMenu( PopupMenu ).FControl := @Self;
60021 end;
60022 AttachProc(WndProcAutoPopupMenu);
60023 AttachProc(WndProcMenu)
60025 else begin
60026 DetachProc(WndProcAutoPopupMenu);
60027 DetachProc(WndProcMenu);
60028 end;
60029 {$ELSE}
60030 begin
60031 pm := PMenu( PopupMenu );
60032 while pm.FControl = nil do pm := pm.Parent;
60033 PMenu( PopupMenu ).FControl := pm.FControl;
60034 end;
60035 {$ENDIF}
60036 fAutoPopupMenu := PopupMenu;
60037 {$IFNDEF USE_MENU_CURCTL}
60038 AttachProc( WndProcAutoPopupMenu );
60039 {$ENDIF}
60040 end;
60042 //[function SearchAnsiMnemonics]
60043 function SearchAnsiMnemonics( const S: String ): String;
60044 var I: Integer;
60045 Sh: ShortInt;
60046 begin
60047 Result := S;
60048 for I := 1 to Length( Result ) do
60049 begin
60050 Sh := VkKeyScanEx( Result[ I ], MnemonicsLocale );
60051 if Sh <> -1 then
60052 Result[ I ] := Char( Sh );
60053 end;
60054 end;
60056 //[procedure SupportAnsiMnemonics]
60057 procedure SupportAnsiMnemonics( LocaleID: Integer );
60058 begin
60059 MnemonicsLocale := LocaleID;
60060 SearchMnemonics := SearchAnsiMnemonics;
60061 end;
60063 //[function WndProcMnemonics]
60064 function WndProcMnemonics( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60065 var Form: PControl;
60067 function HandleMnenonic( Prnt: PControl ): Boolean;
60068 var C: PControl;
60069 XY: Integer;
60070 procedure DoPressMnemonic;
60071 begin
60072 if Msg.message = WM_SYSKEYDOWN then
60073 begin
60074 Form.FPressedMnemonic := Msg.wParam;
60075 C.Perform( WM_LBUTTONDOWN, MK_LBUTTON, XY );
60077 else
60078 begin
60079 Form.FPressedMnemonic := 0;
60080 C.Perform( WM_LBUTTONUP, MK_LBUTTON, XY );
60081 end;
60082 end;
60083 var I, J: Integer;
60084 R: TRect;
60085 begin
60086 for I := 0 to Prnt.ChildCount-1 do
60087 begin
60088 C := Prnt.Children[ I ];
60089 if C.IsButton then
60090 if C.Enabled then
60091 begin
60092 if C.fCommandActions.aGetCount = TB_BUTTONCOUNT then
60093 for J := 0 to C.Count-1 do
60094 begin
60095 if C.TBButtonEnabled[ J ] then
60096 if pos( '&' + Char( Msg.wParam ), SearchMnemonics( C.TBButtonText[ J ] ) ) > 0 then
60097 begin
60098 C.fCurIndex := J;
60099 C.fCurItem := C.TBIndex2Item( J );
60100 R := C.TBButtonRect[ J ];
60101 XY := R.Left or (R.Top shl 16);
60102 DoPressMnemonic;
60103 Result := TRUE;
60104 Exit;
60105 end;
60106 end;
60107 if pos( '&' + Char( Msg.wParam ), SearchMnemonics( C.Caption ) ) > 0 then
60108 begin
60109 XY := 0;
60110 DoPressMnemonic;
60111 Result := TRUE;
60112 Exit;
60113 end;
60114 end;
60115 if HandleMnenonic( C ) then
60116 begin
60117 Result := TRUE;
60118 Exit;
60119 end;
60120 end;
60121 Result := FALSE;
60122 end;
60124 {$IFDEF NEW_MENU_ACCELL}
60125 function FindByCtlRef(C: PControl; Accell: TMenuAccelerator): Boolean;
60127 function FindInMenu(M: PMenu): PMenu;
60129 I: Integer;
60130 SM: PMenu;
60131 begin
60132 for I := 0 to M.FItems.Count - 1 do begin
60133 Result := M.FItems.Items[I];
60134 if (Cardinal(Result.Accelerator) = Cardinal(Accell)) and Result.Enabled then
60135 Exit;
60136 end;
60137 Result := nil;
60138 for I := 0 to M.FItems.Count - 1 do begin
60139 SM := PMenu(M.FItems.Items[I]);
60140 if (SM.FItems.Count > 0) then
60141 Result := FindInMenu(SM);
60142 if (Result <> nil) then
60143 Break;
60144 end;
60145 end;
60147 function FindInMenu2(M: PMenu): Boolean;
60149 MI: PMenu;
60150 begin
60151 if (M <> nil) then begin
60152 MI := FindInMenu(M);
60153 if (MI <> nil) then begin
60154 //M.FControl.Perform(WM_COMMAND, MI.FId, 0);
60155 C.Perform(WM_COMMAND, MI.FId, 0); // fixed
60156 Result := True;
60157 Exit;
60158 end;
60159 end;
60160 Result := False;
60161 end;
60164 Parent: PControl;
60165 begin
60166 Result := False;
60167 if not FindInMenu2(PMenu(C.fAutoPopupMenu)) then
60168 if not FindInMenu2(PMenu(C.fMenuObj)) then begin
60169 Parent := C.Parent;
60170 if (Parent <> nil) then
60171 Result := FindByCtlRef(Parent, Accell);
60172 end;
60173 end;
60176 Ac: TMenuAccelerator;
60177 {$ENDIF}
60178 begin
60179 Result := FALSE;
60180 if (Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST) then
60181 begin
60182 {$IFDEF NEW_MENU_ACCELL}
60183 Ac := MakeAccelerator(FVIRTKEY or GetShiftState, Msg.wParam);
60184 Result := FindByCtlRef(Sender, Ac);
60185 {$ELSE}
60186 if Sender.fAccelTable <> 0 then
60187 Result := LongBool( TranslateAccelerator( Sender.fHandle, Sender.fAccelTable, Msg ) );
60188 if not Result then
60189 begin
60190 if Sender.fCurrentControl <> nil then
60191 if Sender.fCurrentControl.fAccelTable <> 0 then
60192 Result := LongBool( TranslateAccelerator( Sender.fCurrentControl.fHandle,
60193 Sender.fCurrentControl.fAccelTable, Msg ) );
60194 end;
60195 if not Result then
60196 begin
60197 Form := Sender.ParentForm;
60198 if Form <> nil then
60199 if Form.fAccelTable <> 0 then
60200 Result := LongBool( TranslateAccelerator( Form.fHandle,
60201 Form.fAccelTable, Msg ) );
60202 end;
60203 {$ENDIF}
60204 end;
60205 if Result then Exit;
60206 if (Msg.message = WM_SYSKEYUP) or
60207 (Msg.message = WM_SYSKEYDOWN) and (GetKeyState( VK_MENU ) < 0) then
60208 begin
60209 Rslt := 0;
60210 Form := Sender.ParentForm;
60211 if Form <> nil then
60212 begin
60213 { ----------------------- }
60214 //Form.Caption := Form.Caption + '<';
60215 if Char( Msg.wParam ) in [ 'A'..'Z', '0'..'9' ] then
60216 begin
60217 if HandleMnenonic( Form ) then
60218 begin
60219 Result := TRUE;
60220 Exit;
60222 else
60223 begin
60224 { ---------------------- }
60225 //Form.Caption := Form.Caption + '?';
60226 end;
60227 end;
60228 end;
60230 else
60231 if Msg.message = WM_KEYUP then
60232 begin
60233 Rslt := 0;
60234 Form := Sender.ParentForm;
60235 if Form <> nil then
60236 begin
60237 { ------------------------ }
60238 //Form.Caption := Form.Caption + '>';
60239 if Msg.wParam = VK_MENU then
60240 begin
60241 if Form.FPressedMnemonic <> 0 then
60242 Form.FPressedMnemonic := Form.FPressedMnemonic or $80000000;
60244 else
60245 if Char( Msg.wParam ) in [ 'A'..'Z', '0'..'9' ] then
60246 begin
60247 if HandleMnenonic( Form ) then
60248 begin
60249 Result := TRUE;
60250 Exit;
60252 else
60253 begin
60254 { --------------------- }
60255 //Form.Caption := form.Caption + '-';
60256 end;
60257 end;
60258 end;
60259 end;
60260 Result := FALSE;
60261 end;
60263 //[function TControl.SupportMnemonics]
60264 function TControl.SupportMnemonics: PControl;
60265 begin
60266 fGlobalProcKeybd := WndProcMnemonics;
60267 Result := @Self;
60268 end;
60271 //[API RevokeDragDrop]
60272 function RevokeDragDrop(wnd: HWnd): HResult; stdcall;
60273 external 'ole32.dll' name 'RevokeDragDrop';
60276 //[function TControl.RE_NoOLEDragDrop]
60277 function TControl.RE_NoOLEDragDrop: PControl;
60278 begin
60279 RevokeDragDrop( Handle );
60280 Result := @Self;
60281 end;
60284 //[function WndProcOnResize]
60285 function WndProcOnResize( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60286 begin
60287 if Msg.message = WM_SIZE then
60288 begin
60289 if Assigned( Self_.fOnResize ) then
60290 Self_.fOnResize( Self_ );
60291 end;
60292 Result := False;
60293 end;
60296 //[procedure TControl.SetOnResize]
60297 procedure TControl.SetOnResize(const Value: TOnEvent);
60298 begin
60299 FOnResize := Value;
60300 AttachProc( WndProcOnResize );
60301 end;
60303 //[function WndProcMove]
60304 function WndProcMove( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60305 begin
60306 if Msg.message = WM_MOVE then
60307 begin
60308 if Assigned( Self_.FOnMove ) then
60309 Self_.FOnMove( Self_ );
60310 end;
60311 Result := False;
60312 end;
60314 //[procedure TControl.SetOnMove]
60315 procedure TControl.SetOnMove(const Value: TOnEvent);
60316 begin
60317 FOnMove := Value;
60318 AttachProc( WndProcMove );
60319 end;
60321 //[function WndProc_REBottomless]
60322 function WndProc_REBottomless( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60323 begin
60324 if Msg.message = WM_SIZE then
60325 Self_.Perform( EM_REQUESTRESIZE, 0, 0 );
60326 Result := False;
60327 end;
60330 //[function TControl.RE_Bottomless]
60331 function TControl.RE_Bottomless: PControl;
60332 begin
60333 AttachProc( WndProc_REBottomless );
60334 Result := @Self;
60335 end;
60338 //[procedure TControl.RE_Append]
60339 procedure TControl.RE_Append(const S: String; ACanUndo: Boolean);
60340 begin
60341 SelStart := TextSize;
60342 if S <> '' then
60343 begin
60344 ReplaceSelection( S, ACanUndo );
60345 SelStart := TextSize;
60346 end;
60347 end;
60350 //[procedure TControl.RE_InsertRTF]
60351 procedure TControl.RE_InsertRTF(const S: String);
60352 var MS: PStream;
60353 begin
60354 MS := NewMemoryStream;
60355 MS.Size := Length( S ) + 1;
60356 Move( S[ 1 ], MS.Memory^, Length( S ) + 1 );
60357 RE_LoadFromStream( MS, Length( S ), reRTF, TRUE );
60358 MS.Free;
60359 end;
60362 //[procedure TControl.DoSelChange]
60363 procedure TControl.DoSelChange;
60364 begin
60365 if Assigned( fOnSelChange ) then fOnSelChange( @Self )
60366 else
60367 if Assigned( fOnChange ) then fOnChange( @Self );
60368 end;
60371 //[function TControl.REGetUnderlineEx]
60372 function TControl.REGetUnderlineEx: TRichUnderline;
60373 begin
60374 Result := TRichUnderline( REGetFontAttr( (81 shl 16) or CFM_UNDERLINETYPE ) - 1 );
60375 end;
60378 //[procedure TControl.RESetUnderlineEx]
60379 procedure TControl.RESetUnderlineEx(const Value: TRichUnderline);
60380 begin
60381 RESetFontAttr( (81 shl 16) or CFM_UNDERLINETYPE, Ord( Value ) + 1 );
60382 RESetFontEffect( CFM_UNDERLINE, True );
60383 end;
60386 //[function TControl.GetTextSize]
60387 function TControl.GetTextSize: Integer;
60388 begin
60389 Result := 0;
60390 if fHandle <> 0 then
60391 Result := GetWindowTextLength( fHandle );
60392 end;
60395 //[function TControl.REGetTextSize]
60396 function TControl.REGetTextSize(Units: TRichTextSize): Integer;
60397 const TextLengthFlags: array[ TRichTextSizes ] of Integer =
60398 ( not GTL_UseCRLF, not GTL_Precise, GTL_Close, GTL_NUMBytes );
60399 var GTL: TGetTextLengthEx;
60400 begin
60401 GTL.flags := MakeFlags( @Units, TextLengthFlags );
60402 if not(rtsBytes in Units) then
60403 GTL.flags := GTL.flags or GTL_NUMCHARS;
60404 GTL.codepage := CP_ACP;
60405 Result := Perform( EM_GETTEXTLENGTHEX, Integer( @GTL ), 0 );
60406 end;
60408 //[function TControl.RE_TextSizePrecise]
60409 function TControl.RE_TextSizePrecise: Integer;
60410 var gtlex : TGetTextLengthEx;
60411 begin
60412 gtlex.flags := GTL_PRECISE;
60413 gtlex.codepage := CP_ACP;
60414 Result := Perform(EM_GETTEXTLENGTHEX,WPARAM(@gtlex), 0 );
60415 end;
60418 //[function TControl.REGetNumStyle]
60419 function TControl.REGetNumStyle: TRichNumbering;
60420 begin
60421 Result := TRichNumbering( ReGetParaAttr( 9 shl 16 ) );
60422 end;
60425 //[procedure TControl.RESetNumStyle]
60426 procedure TControl.RESetNumStyle(const Value: TRichNumbering);
60427 begin
60428 RESetParaAttr( (9 shl 16) or PFM_NUMBERING, Ord( Value ) );
60429 end;
60432 //[function TControl.REGetNumBrackets]
60433 function TControl.REGetNumBrackets: TRichNumBrackets;
60434 begin
60435 REGetParaAttr( 0 );
60436 Result := TRichNumBrackets( (fREParaFmtRec.wNumberingStyle shr 8) {and 3} );
60437 end;
60440 //[procedure TControl.RESetNumBrackets]
60441 procedure TControl.RESetNumBrackets(const Value: TRichNumBrackets);
60442 begin
60443 REGetParaAttr( 0 );
60444 fREParaFmtRec.wNumberingStyle := fREParaFmtRec.wNumberingStyle and $F8FF
60445 or Word( Ord( Value ) shl 8 );
60446 fREParaFmtRec.dwMask := PFM_NUMBERINGSTYLE;
60447 RE_ParaFmt := fREParaFmtRec;
60448 end;
60451 //[function TControl.REGetNumTab]
60452 function TControl.REGetNumTab: Integer;
60453 begin
60454 REGetParaAttr( 0 );
60455 Result := fREParaFmtRec.wNumberingTab;
60456 end;
60459 //[procedure TControl.RESetNumTab]
60460 procedure TControl.RESetNumTab(const Value: Integer);
60461 begin
60462 REGetParaAttr( 0 );
60463 fREParaFmtRec.wNumberingTab := Value;
60464 fREParaFmtRec.dwMask := PFM_NUMBERINGTAB;
60465 RE_ParaFmt := fREParaFmtRec;
60466 end;
60469 //[function TControl.REGetNumStart]
60470 function TControl.REGetNumStart: Integer;
60471 begin
60472 REGetParaAttr( 0 );
60473 Result := fREParaFmtRec.wNumberingStart;
60474 end;
60477 //[procedure TControl.RESetNumStart]
60478 procedure TControl.RESetNumStart(const Value: Integer);
60479 begin
60480 REGetParaAttr( 0 );
60481 fREParaFmtRec.wNumberingStart := Value;
60482 fREParaFmtRec.dwMask := PFM_NUMBERINGSTART;
60483 RE_ParaFmt := fREParaFmtRec;
60484 end;
60487 //[function TControl.REGetSpacing]
60488 function TControl.REGetSpacing( const Index: Integer ): Integer;
60489 begin
60490 REGetParaAttr( 0 );
60491 Result := PInteger( Integer(@fREParaFmtRec.dySpaceBefore) + (Index and $F) )^;
60492 end;
60495 //[procedure TControl.RESetSpacing]
60496 procedure TControl.RESetSpacing(const Index, Value: Integer);
60497 begin
60498 REGetParaAttr( 0 );
60499 PInteger( Integer(@fREParaFmtRec.dySpaceBefore) + (Index and $F) )^ := Value;
60500 fREParaFmtRec.dwMask := Index and not $F;
60501 RE_ParaFmt := fREParaFmtRec;
60502 end;
60505 //[function TControl.REGetSpacingRule]
60506 function TControl.REGetSpacingRule: Integer;
60507 begin
60508 REGetParaAttr( 0 );
60509 Result := fREParaFmtRec.bLineSpacingRule;
60510 end;
60513 //[procedure TControl.RESetSpacingRule]
60514 procedure TControl.RESetSpacingRule(const Value: Integer);
60515 begin
60516 REGetParaAttr( 0 );
60517 fREParaFmtRec.bLineSpacingRule := Value;
60518 fREParaFmtRec.dwMask := PFM_LINESPACING;
60519 RE_ParaFmt := fREParaFmtRec;
60520 end;
60523 //[function TControl.REGetLevel]
60524 function TControl.REGetLevel: Integer;
60525 begin
60526 REGetParaAttr( 0 );
60527 Result := fREParaFmtRec.bCRC;
60528 end;
60531 //[function TControl.REGetBorder]
60532 function TControl.REGetBorder(Side: TBorderEdge; const Index: Integer): Integer;
60533 begin
60534 REGetParaAttr( 0 );
60535 Result := PWORD( Integer(@fREParaFmtRec.wBorderSpace) + Index )^ shr (Ord(Side) * 4);
60536 end;
60539 //[procedure TControl.RESetBorder]
60540 procedure TControl.RESetBorder(Side: TBorderEdge; const Index: Integer;
60541 const Value: Integer);
60542 var Mask: Word;
60543 pW : PWord;
60544 begin
60545 REGetParaAttr( 0 );
60546 pw := PWORD( Integer(@fREParaFmtRec.wBorderSpace) + Index );
60547 Mask := $F shl (Ord(Side) * 4);
60548 pw^ := pw^ and not Mask or (Value shl (4 * Ord(Side)) );
60549 fREParaFmtRec.dwMask := PFM_BORDER;
60550 RE_ParaFmt := fREParaFmtRec;
60551 end;
60554 //[function TControl.REGetParaEffect]
60555 function TControl.REGetParaEffect(const Index: Integer): Boolean;
60556 begin
60557 Result := LongBool( HiWord( REGetParaAttr( 8 shl 16 ) ) and Index );
60558 end;
60561 //[procedure TControl.RESetParaEffect]
60562 procedure TControl.RESetParaEffect(const Index: Integer;
60563 const Value: Boolean);
60564 var Idx: Integer;
60565 begin
60566 REGetParaAttr( 0 );
60567 fREParaFmtRec.wReserved := Index;
60568 Idx := Index;
60569 //if Idx >= $4000 then Idx := $4000;
60570 fREParaFmtRec.dwMask := Idx shl 16;
60571 RE_ParaFmt := fREParaFmtRec;
60572 end;
60575 //[function WndProc_REMonitorIns]
60576 function WndProc_REMonitorIns( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60577 begin
60578 Result := False;
60579 if (Msg.message = WM_KEYDOWN) and (Msg.wParam = VK_INSERT) and
60580 ((GetKeyState(VK_CONTROL) or GetKeyState(VK_SHIFT) or GetKeyState(VK_MENU)) >= 0) then
60581 begin
60582 if not Self_.fReOvrDisable then
60583 Self_.fREOvr := not Self_.fREOvr
60584 else
60585 Result := True;
60586 if assigned( Self_.fOnREInsModeChg ) then
60587 Self_.fOnREInsModeChg( Self_ );
60588 end;
60589 end;
60592 //[function TControl.REGetOverwite]
60593 function TControl.REGetOverwite: Boolean;
60594 begin
60595 AttachProc( WndProc_REMonitorIns );
60596 Result := fREOvr;
60597 end;
60600 //[procedure TControl.RESetOverwrite]
60601 procedure TControl.RESetOverwrite(const Value: Boolean);
60602 begin
60603 if fREOvr = Value then Exit;
60604 Perform( WM_KEYDOWN, VK_INSERT, 0 );
60605 Perform( WM_KEYUP, VK_INSERT, 0 );
60606 end;
60609 //[procedure TControl.RESetOvrDisable]
60610 procedure TControl.RESetOvrDisable(const Value: Boolean);
60611 begin
60612 REGetOverwite;
60613 fReOvrDisable := Value;
60614 end;
60617 //[function WndProc_RichEdTransp_ParentPaint]
60618 function WndProc_RichEdTransp_ParentPaint( Self_:PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60619 var I: Integer;
60620 C: PControl;
60621 begin
60622 if (Msg.message = WM_PAINT) and (Msg.wParam = 0) then
60623 begin
60624 for I := 0 to Self_.fChildren.fCount - 1 do
60625 begin
60626 C := Self_.fChildren.fItems[ I ];
60627 if C.fIsCommonControl then
60628 begin
60629 Inc( C.fUpdCount );
60630 PostMessage( C.fHandle, CM_NCUPDATE, C.fUpdCount, WM_PAINT );
60631 InvalidateRect( C.fHandle, nil, False );
60632 end;
60633 end;
60634 end;
60635 Result := False;
60636 end;
60639 //[function WndProc_RichEdTransp_Update]
60640 function WndProc_RichEdTransp_Update( Self_:PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60641 var Rgn, Rgn1: HRgn;
60642 R, CR: TRect;
60643 Pt: TPoint;
60644 VW, HH, VH, HW: Integer;
60645 begin
60646 case Msg.message of
60647 WM_CHAR, WM_KILLFOCUS, WM_SETFOCUS:
60648 begin
60649 PostMessage( Self_.fHandle, CM_INVALIDATE, 0, 0 );
60650 end;
60651 WM_PAINT:
60652 if Msg.wParam = 0 then
60653 begin
60654 Inc( Self_.fUpdCount );
60655 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
60656 end;
60657 WM_SIZE:
60658 begin
60659 Inc( Self_.fUpdCount );
60660 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
60661 PostMessage( Self_.fHandle, CM_INVALIDATE, 0, 0 );
60662 end;
60663 WM_ERASEBKGND:
60664 if Msg.wParam = 0 then
60665 begin
60666 Inc( Self_.fUpdCount );
60667 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
60668 end;
60669 WM_HSCROLL, WM_VSCROLL:
60670 begin
60671 Self_.fREScrolling := LoWord( Msg.wParam ) <> SB_ENDSCROLL;
60672 Inc( Self_.fUpdCount );
60673 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
60674 if Self_.fREScrolling then
60675 Self_.Invalidate;
60676 end;
60677 CM_INVALIDATE:
60678 begin
60679 //Self_.Update;
60680 Self_.Parent.Invalidate;
60681 Self_.Invalidate;
60682 //Inc( Self_.fUpdCount );
60683 //PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
60684 end;
60685 CM_NCUPDATE:
60686 if Msg.wParam = Self_.fUpdCount then
60687 begin
60688 //if Msg.lParam = WM_PAINT then
60689 // UpdateWindow( Self_.fHandle );
60690 GetWindowRect( Self_.fHandle, R );
60691 Windows.GetClientRect( Self_.fHandle, CR );
60692 Pt.x := 0; Pt.y := 0;
60693 Pt := Self_.Client2Screen( Pt );
60694 OffsetRect( CR, Pt.x, Pt.y );
60695 Rgn := CreateRectRgn( R.Left, R.Top, R.Right, R.Bottom );
60696 if Self_.fREScrolling then
60697 begin
60698 VW := GetSystemMetrics( SM_CXVSCROLL );
60699 HH := GetSystemMetrics( SM_CYHSCROLL );
60700 VH := GetSystemMetrics( SM_CYVSCROLL );
60701 HW := GetSystemMetrics( SM_CXHSCROLL );
60702 if CR.Right + VW <= R.Right then
60703 begin
60704 Rgn1 := CreateRectRgn( CR.Right, CR.Top + VH, CR.Right + VW, CR.Bottom - VH );
60705 CombineRgn( Rgn, Rgn, Rgn1, RGN_DIFF );
60706 DeleteObject( Rgn1 );
60707 end;
60708 if CR.Bottom + HH <= R.Bottom then
60709 begin
60710 Rgn1 := CreateRectRgn( CR.Left + HW, CR.Bottom, CR.Right - HW, CR.Bottom + HH );
60711 CombineRgn( Rgn, Rgn, Rgn1, RGN_DIFF );
60712 DeleteObject( Rgn1 );
60713 end;
60714 end;
60715 Self_.Perform( WM_NCPAINT, Rgn, 0 );
60716 DeleteObject( Rgn ); // Unremarked By M.Gerasimov
60717 end;
60718 end;
60719 Result := False;
60720 end;
60723 //[function TControl.REGetTransparent]
60724 function TControl.REGetTransparent: Boolean;
60725 begin
60726 Result := Longbool(ExStyle and WS_EX_TRANSPARENT);
60727 end;
60730 //[procedure TControl.RESetTransparent]
60731 procedure TControl.RESetTransparent(const Value: Boolean);
60732 begin
60733 ExStyle := ExStyle or WS_EX_TRANSPARENT;
60734 fParent.AttachProc( WndProc_RichEdTransp_ParentPaint );
60735 AttachProc( WndProc_RichEdTransp_Update );
60736 fTransparent := Value;
60737 end;
60740 //[procedure TControl.RESetOnURL]
60741 procedure TControl.RESetOnURL(const Index: Integer; const Value: TOnEvent);
60742 begin
60743 if Index = 0 then
60744 fOnREOverURL := Value
60745 else
60746 fOnREURLClick := Value;
60747 RE_AutoURLDetect := assigned(fOnREOverURL) or assigned(fOnREURLClick);
60748 end;
60750 {$IFDEF F_P}
60751 //[function TControl.REGetOnURL]
60752 function TControl.REGetOnURL(const Index: Integer): TOnEvent;
60753 begin
60754 CASE Index OF
60755 0: Result := fOnREOverURL;
60756 else Result := fOnREURLClick;
60757 END;
60758 end;
60759 {$ENDIF F_P}
60762 //[function TControl.REGetLangOptions]
60763 function TControl.REGetLangOptions(const Index: Integer): Boolean;
60764 begin
60765 Result := LongBool( Perform( EM_GETLANGOPTIONS, 0, 0 ) and Index);
60766 end;
60769 //[procedure TControl.RESetLangOptions]
60770 procedure TControl.RESetLangOptions(const Index: Integer;
60771 const Value: Boolean);
60772 var Mask: Integer;
60773 begin
60774 Mask := -1;
60775 if not Value then Inc( Mask );
60776 Perform( EM_SETLANGOPTIONS, 0, Perform( EM_GETLANGOPTIONS, 0, 0 ) and
60777 not Index or (Mask and Index) );
60778 end;
60780 //[API _TrackMouseEvent]
60781 function _TrackMouseEvent(lpEventTrack: PTrackMouseEvent): BOOL;
60782 external cctrl name '_TrackMouseEvent';
60784 //[function DoTrackMouseEvent]
60785 function DoTrackMouseEvent(lpEventTrack: PTrackMouseEvent): BOOL;
60786 var FunTrack: function(lpEventTrack: PTrackMouseEvent): BOOL; stdcall;
60787 ComCtlModule: THandle;
60788 begin
60789 Result := FALSE;
60790 ComCtlModule := GetModuleHandle( cctrl );
60791 if ComCtlModule = 0 then Exit;
60792 FunTrack := GetProcAddress( ComCtlModule, '_TrackMouseEvent' );
60793 if not Assigned( FunTrack ) then Exit;
60794 Result := FunTrack( lpEventTrack );
60795 end;
60798 //[function WndProcMouseEnterLeave]
60799 function WndProcMouseEnterLeave( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60800 var P: TPoint;
60801 MouseWasInControl: Boolean;
60802 Yes: Boolean;
60803 Track: TTrackMouseEvent;
60804 begin
60805 case Msg.message of
60806 WM_MOUSEFIRST..WM_MOUSELAST:
60807 begin
60808 MouseWasInControl := Self_.MouseInControl;
60809 if Assigned( Self_.fOnTestMouseOver ) then
60810 Yes := Self_.fOnTestMouseOver( Self_ )
60811 else
60812 begin
60813 GetCursorPos( P );
60814 P := Self_.Screen2Client( P );
60815 Yes := PointInRect( P, Self_.ClientRect );
60816 end;
60817 if MouseWasInControl <> Yes then
60818 begin
60819 Self_.Invalidate;
60820 if Yes then
60821 begin
60822 Self_.fMouseInControl := TRUE;
60823 if Assigned( Self_.fOnMouseEnter ) then
60824 Self_.fOnMouseEnter( Self_ );
60825 Track.cbSize := Sizeof( Track );
60826 Track.dwFlags := TME_LEAVE;
60827 Track.hwndTrack := Self_.Handle;
60828 //Track.dwHoverTime := 0;
60829 DoTrackMouseEvent( @ Track );
60830 Self_.Invalidate;
60832 else
60833 begin
60834 Self_.fMouseInControl := FALSE;
60835 Track.cbSize := Sizeof( Track );
60836 Track.dwFlags := TME_LEAVE or TME_CANCEL;
60837 Track.hwndTrack := Self_.Handle;
60838 //Track.dwHoverTime := 0;
60839 DoTrackMouseEvent( @ Track );
60840 if Assigned( Self_.fOnMouseLeave ) then
60841 Self_.fOnMouseLeave( Self_ );
60842 Self_.Invalidate;
60843 end;
60844 end;
60845 end;
60846 WM_MOUSELEAVE:
60847 begin
60848 if Self_.fMouseInControl then
60849 begin
60850 Self_.fMouseInControl := FALSE;
60851 if Assigned( Self_.fOnMouseLeave ) then
60852 Self_.fOnMouseLeave( Self_ );
60853 Self_.Invalidate;
60854 end;
60855 end;
60856 end;
60857 Result := False;
60858 end;
60860 //[procedure ProvideMouseEnterLeave]
60861 procedure ProvideMouseEnterLeave( Self_: PControl );
60862 begin
60863 InitCommonControls;
60864 Self_.AttachProc( WndProcMouseEnterLeave );
60865 Self_.Invalidate;
60866 end;
60868 //[procedure TControl.SetFlat]
60869 procedure TControl.SetFlat(const Value: Boolean);
60870 begin
60871 //if fFlat = Value then Exit;
60872 fFlat := Value;
60873 fMouseInControl := FALSE;
60874 ProvideMouseEnterLeave( @Self );
60875 Invalidate;
60876 end;
60878 //[procedure TControl.SetOnMouseEnter]
60879 procedure TControl.SetOnMouseEnter(const Value: TOnEvent);
60880 begin
60881 fOnMouseEnter := Value;
60882 ProvideMouseEnterLeave( @Self );
60883 end;
60885 //[procedure TControl.SetOnMouseLeave]
60886 procedure TControl.SetOnMouseLeave(const Value: TOnEvent);
60887 begin
60888 fOnMouseLeave := Value;
60889 ProvideMouseEnterLeave( @Self );
60890 end;
60892 //[procedure TControl.SetOnTestMouseOver]
60893 procedure TControl.SetOnTestMouseOver(const Value: TOnTestMouseOver);
60894 begin
60895 fOnTestMouseOver := Value;
60896 ProvideMouseEnterLeave( @Self );
60897 end;
60899 //[function WndProcEdTransparent]
60900 function WndProcEdTransparent( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60901 begin
60902 if (Msg.message = WM_KEYDOWN) or
60903 (Msg.message = WM_MOUSEMOVE) and (GetKeyState( VK_LBUTTON ) < 0) or
60904 (Msg.message = WM_LBUTTONUP) or (Msg.message = WM_LBUTTONDOWN) then
60905 Self_.Invalidate;
60906 Result := False; // continue handling of a message anyway
60907 end;
60909 //[procedure TControl.EdSetTransparent]
60910 procedure TControl.EdSetTransparent(const Value: Boolean);
60911 begin
60912 Transparent := Value;
60913 AttachProc( WndProcEdTransparent );
60914 end;
60916 //[function WndProcSpeedButton]
60917 function WndProcSpeedButton( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60918 begin
60919 Result := False;
60920 if Msg.message = WM_SETFOCUS then
60921 begin
60922 Result := TRUE;
60923 Rslt := 0;
60924 end;
60925 end;
60927 //[function TControl.LikeSpeedButton]
60928 function TControl.LikeSpeedButton: PControl;
60929 var Form: PControl;
60930 begin
60931 AttachProc( WndProcSpeedButton );
60932 fTabstop := False;
60933 Style := Style and not WS_TABSTOP;
60934 Form := ParentForm;
60935 if Form <> nil then
60936 if Form.fCurrentControl = @Self then
60937 begin
60938 Form.GotoControl( VK_TAB );
60939 if Form.fCurrentControl = @Self then
60940 Form.fCurrentControl := nil;
60941 end;
60942 Result := @Self;
60943 end;
60945 { -- Unicode -- }
60946 //[function TControl.SetUnicode]
60947 function TControl.SetUnicode(Unicode: Boolean): PControl;
60948 begin
60949 Perform( CCM_SETUNICODEFORMAT, Integer( Unicode ), 0 );
60950 Result := @ Self;
60951 end;
60953 { -- TabControl -- }
60955 //[function TControl.GetPages]
60956 function TControl.GetPages(Idx: Integer): PControl;
60957 var Item: TTCItem;
60958 begin
60959 Item.mask := TCIF_PARAM;
60960 if Perform( TCM_GETITEM, Idx, Integer( @Item ) ) = 0 then
60961 Result := nil
60962 else
60963 Result := Pointer( Item.lParam );
60964 end;
60966 //[function TControl.TCGetItemText]
60967 function TControl.TCGetItemText(Idx: Integer): String;
60968 var TI: TTCItem;
60969 Buffer: array[ 0..1023 ] of Char;
60970 begin
60971 TI.mask := TCIF_TEXT;
60972 TI.pszText := @Buffer[ 0 ];
60973 TI.cchTextMax := sizeof( Buffer );
60974 Buffer[ 0 ] := #0;
60975 Perform( TCM_GETITEM, Idx, Integer( @TI ) );
60976 Result := Buffer;
60977 end;
60979 //[procedure TControl.TCSetItemText]
60980 procedure TControl.TCSetItemText(Idx: Integer; const Value: String);
60981 var TI: TTCItem;
60982 begin
60983 TI.mask := TCIF_TEXT;
60984 TI.pszText := PChar( Value );
60985 Perform( TCM_SETITEM, Idx, Integer( @TI ) );
60986 end;
60988 //[function TControl.TCGetItemImgIDx]
60989 function TControl.TCGetItemImgIDx(Idx: Integer): Integer;
60990 var TI: TTCItem;
60991 begin
60992 TI.mask := TCIF_IMAGE;
60993 if Perform( TCM_GETITEM, Idx, Integer( @TI ) ) = 0 then
60994 Result := -1
60995 else
60996 Result := TI.iImage;
60997 end;
60999 //[procedure TControl.TCSetItemImgIdx]
61000 procedure TControl.TCSetItemImgIdx(Idx: Integer; const Value: Integer);
61001 var TI: TTCItem;
61002 begin
61003 TI.mask := TCIF_IMAGE;
61004 TI.iImage := Value;
61005 Perform( TCM_SETITEM, Idx, Integer( @TI ) );
61006 end;
61008 //[function TControl.TCGetItemRect]
61009 function TControl.TCGetItemRect(Idx: Integer): TRect;
61010 begin
61011 if Perform( TCM_GETITEMRECT, Idx, Integer( @Result ) ) = 0 then
61012 begin
61013 Result.Left := 0;
61014 Result.Right := 0;
61015 Result.Top := 0;
61016 Result.Bottom := 0;
61017 end;
61018 end;
61020 //[procedure TControl.TC_SetPadding]
61021 procedure TControl.TC_SetPadding(cx, cy: Integer);
61022 begin
61023 Perform( TCM_SETPADDING, 0, cx or (cy shl 16) );
61024 end;
61026 //[function TControl.TC_TabAtPos]
61027 function TControl.TC_TabAtPos(x, y: Integer): Integer;
61028 type TTCHittestInfo = packed record
61029 Pt: TPoint;
61030 Fl: DWORD;
61031 end;
61032 var HTI: TTCHitTestInfo;
61033 begin
61034 HTI.Pt.x := x;
61035 HTI.Pt.y := y;
61036 Result := Perform( TCM_HITTEST, 0, Integer( @HTI ) );
61037 end;
61039 //[function TControl.TC_DisplayRect]
61040 function TControl.TC_DisplayRect: TRect;
61041 begin
61042 Windows.GetClientRect( fHandle, Result );
61043 Perform( TCM_ADJUSTRECT, 0, Integer( @Result ) );
61044 end;
61046 //[function TControl.TC_IndexOf]
61047 function TControl.TC_IndexOf(const S: String): Integer;
61048 begin
61049 Result := TC_SearchFor( S, -1, FALSE );
61050 end;
61052 //[function TControl.TC_SearchFor]
61053 function TControl.TC_SearchFor(const S: String; StartAfter: Integer;
61054 Partial: Boolean): Integer;
61055 var I: Integer;
61056 begin
61057 Result := -1;
61058 for I := StartAfter+1 to Count-1 do
61059 begin
61060 if Partial and ( Copy( TC_Items[ I ], 1, Length( S ) ) = S ) or
61061 ( TC_Items[ I ] = S ) then
61062 begin
61063 Result := I;
61064 break;
61065 end;
61066 end;
61067 end;
61069 //[function TControl.TC_Insert]
61070 function TControl.TC_Insert(Idx: Integer; const TabText: String;
61071 TabImgIdx: Integer): PControl;
61072 var TI: TTCItem;
61073 begin
61074 Result := NewPanel( @Self, esNone );
61075 Result.FAlign := caClient;
61076 Result.fNotUseAlign := True;
61077 Result.fVisibleWoParent := TRUE;
61078 Result.Visible := Count = 0;
61079 TI.mask := TCIF_TEXT or TCIF_IMAGE or TCIF_PARAM;
61080 TI.iImage := TabImgIdx;
61081 TI.pszText := PChar( TabText );
61082 TI.lParam := Integer( Result );
61083 Perform( TCM_INSERTITEM, Idx, Integer( @TI ) );
61084 Result.BoundsRect := TC_DisplayRect;
61085 end;
61087 //[procedure TControl.TC_Delete]
61088 procedure TControl.TC_Delete(Idx: Integer);
61089 var Page: PControl;
61090 begin
61091 Page := TC_Pages[ Idx ];
61092 if Page = nil then Exit;
61093 Perform( TCM_DELETEITEM, Idx, 0 );
61094 Page.Free;
61095 end;
61097 { -- TreeView -- }
61099 //[function TControl.TVGetItemIdx]
61100 function TControl.TVGetItemIdx(const Index: Integer): THandle;
61101 begin
61102 Result := Perform( TVM_GETNEXTITEM, Index, 0 );
61103 end;
61105 //[procedure TControl.TVSetItemIdx]
61106 procedure TControl.TVSetItemIdx(const Index: Integer;
61107 const Value: THandle);
61108 begin
61109 Perform( TVM_SELECTITEM, Index, Value );
61110 end;
61112 //[function TControl.TVGetItemNext]
61113 function TControl.TVGetItemNext(Item: THandle; const Index: Integer): THandle;
61114 begin
61115 Result := Perform( TVM_GETNEXTITEM, Index, Item );
61116 end;
61118 //[function TControl.TVGetItemRect]
61119 function TControl.TVGetItemRect(Item: THandle; TextOnly: Boolean): TRect;
61120 begin
61121 Result.Left := Item;
61122 if Perform( TVM_GETITEMRECT, Integer( TextOnly ), Integer( @Result ) ) = 0 then
61123 begin
61124 Result.Left := 0;
61125 Result.Right := 0;
61126 Result.Top := 0;
61127 Result.Bottom := 0;
61128 end;
61129 end;
61131 //[function TControl.TVGetItemVisible]
61132 function TControl.TVGetItemVisible(Item: THandle): Boolean;
61133 var R: TRect;
61134 begin
61135 R := TVItemRect[ Item, False ];
61136 Result := R.Bottom > R.Top;
61137 end;
61139 //[procedure TControl.TVSetItemVisible]
61140 procedure TControl.TVSetItemVisible(Item: THandle; const Value: Boolean);
61141 begin
61142 if Value then
61143 Perform( TVM_ENSUREVISIBLE, 0, Item );
61144 end;
61146 //[function TControl.TVGetItemStateFlg]
61147 function TControl.TVGetItemStateFlg(Item: THandle; const Index: Integer): Boolean;
61148 var TVI: TTVItem;
61149 begin
61150 TVI.mask := TVIF_HANDLE or TVIF_STATE;
61151 TVI.hItem := Item;
61152 TVI.stateMask := Index;
61153 Result := False;
61154 if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then
61155 Result := (TVI.state and Index) <> 0;
61156 end;
61158 //[procedure TControl.TVSetItemStateFlg]
61159 procedure TControl.TVSetItemStateFlg(Item: THandle; const Index: Integer;
61160 const Value: Boolean);
61161 var TVI: TTVItem;
61162 begin
61163 TVI.mask := TVIF_HANDLE or TVIF_STATE;
61164 TVI.hItem := Item;
61165 TVI.stateMask := Index;
61166 TVI.state := $FFFFFFFF and Index;
61167 if not Value then
61168 TVI.state := 0;
61169 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
61170 end;
61172 //[function TControl.TVGetItemImage]
61173 function TControl.TVGetItemImage(Item: THandle; const Index: Integer): Integer;
61174 var TVI: TTVItem;
61175 begin
61176 TVI.mask := TVIF_HANDLE or Loword( Index );
61177 TVI.hItem := Item;
61178 if Hiword( Index ) <> 0 then
61179 begin
61180 TVI.mask := TVIF_STATE or TVIF_HANDLE;
61181 TVI.stateMask := Loword( Index );
61182 end;
61183 Result := -1;
61184 if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then
61185 begin
61186 if Hiword( Index ) <> 0 then
61187 Result := (TVI.state shr Hiword( Index )) and $F
61188 else
61189 if Loword( Index ) = TVIF_IMAGE then
61190 Result := TVI.iImage
61191 else
61192 Result := TVI.iSelectedImage;
61193 end;
61194 end;
61196 //[procedure TControl.TVSetItemImage]
61197 procedure TControl.TVSetItemImage(Item: THandle; const Index: Integer;
61198 const Value: Integer);
61199 var TVI: TTVItem;
61200 begin
61201 TVI.mask := TVIF_HANDLE or Loword( Index );
61202 TVI.hItem := Item;
61203 TVI.iImage := Value;
61204 TVI.iSelectedImage := Value;
61205 if Hiword( Index ) <> 0 then
61206 begin
61207 TVI.mask := TVIF_STATE or TVIF_HANDLE;
61208 TVI.stateMask := Loword( Index );
61209 TVI.state := Value shl Hiword( Index );
61210 end;
61211 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
61212 end;
61214 //[function TControl.TVGetItemText]
61215 function TControl.TVGetItemText(Item: THandle): String;
61216 var TVI: TTVItem;
61217 Buffer: array[ 0..4095 ] of Char;
61218 begin
61219 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
61220 TVI.hItem := Item;
61221 TVI.pszText := @Buffer[ 0 ];
61222 Buffer[ 0 ] := #0;
61223 TVI.cchTextMax := Sizeof( Buffer );
61224 Perform( TVM_GETITEM, 0, Integer( @TVI ) );
61225 Result := Buffer;
61226 end;
61228 //[procedure TControl.TVSetItemText]
61229 procedure TControl.TVSetItemText(Item: THandle; const Value: String);
61230 var TVI: TTVItem;
61231 begin
61232 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
61233 TVI.hItem := Item;
61234 TVI.pszText := PChar( Value );
61235 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
61236 end;
61238 {$IFNDEF _FPC}
61239 {$IFNDEF _D2}
61240 //[function TControl.TVGetItemTextW]
61241 function TControl.TVGetItemTextW(Item: THandle): WideString;
61242 var TVI: TTVItemW;
61243 Buffer: array[ 0..4095 ] of WideChar;
61244 begin
61245 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
61246 TVI.hItem := Item;
61247 TVI.pszText := @Buffer[ 0 ];
61248 Buffer[ 0 ] := #0;
61249 TVI.cchTextMax := High( Buffer ) + 1;
61250 Perform( TVM_GETITEMW, 0, Integer( @TVI ) );
61251 Result := Buffer;
61252 end;
61254 //[procedure TControl.TVSetItemTextW]
61255 procedure TControl.TVSetItemTextW(Item: THandle; const Value: WideString);
61256 var TVI: TTVItemW;
61257 begin
61258 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
61259 TVI.hItem := Item;
61260 TVI.pszText := PWideChar( Value );
61261 Perform( TVM_SETITEMW, 0, Integer( @TVI ) );
61262 end;
61263 {$ENDIF _D2}
61264 {$ENDIF _FPC}
61266 //[function TControl.TVItemPath]
61267 function TControl.TVItemPath(Item: THandle; Delimiter: Char): String;
61268 begin
61269 if Item = 0 then
61270 Item := TVSelected;
61271 Result := '';
61272 while Item <> 0 do
61273 begin
61274 if Result <> '' then
61275 Result := Delimiter + Result;
61276 Result := TVItemText[ Item ] + Result;
61277 Item := TVItemParent[ Item ];
61278 end;
61279 end;
61281 {$IFNDEF _FPC}
61282 {$IFNDEF _D2}
61283 //[function TControl.TVItemPathW]
61284 function TControl.TVItemPathW(Item: THandle;
61285 Delimiter: WideChar): WideString;
61286 begin
61287 if Item = 0 then
61288 Item := TVSelected;
61289 Result := '';
61290 while Item <> 0 do
61291 begin
61292 if Result <> '' then
61293 Result := {$IFDEF _D3} '' + {$ENDIF} Delimiter + Result;
61294 Result := TVItemTextW[ Item ] + Result;
61295 Item := TVItemParent[ Item ];
61296 end;
61297 end;
61298 {$ENDIF _D2}
61299 {$ENDIF _FPC}
61301 //[function TControl.TV_GetItemHasChildren]
61302 function TControl.TV_GetItemHasChildren(Item: THandle): Boolean;
61303 var TVI: TTVItem;
61304 begin
61305 TVI.mask := TVIF_HANDLE or TVIF_CHILDREN;
61306 TVI.hItem := Item;
61307 Perform( TVM_GETITEM, 0, Integer( @TVI ) );
61308 Result := TVI.cChildren = 1;
61309 end;
61311 //[procedure TControl.TV_GetItemChildCount]
61312 function TControl.TV_GetItemChildCount(Item: THandle): Integer;
61313 var Node: THandle;
61314 begin
61315 Result := 0;
61316 Node := TVItemChild[ Item ];
61317 while Node <> 0 do
61318 begin
61319 Inc( Result );
61320 Node := TVItemNext[ Node ];
61321 end;
61322 end;
61324 //[procedure TControl.TV_SetItemHasChildren]
61325 procedure TControl.TV_SetItemHasChildren(Item: THandle;
61326 const Value: Boolean);
61327 var TVI: TTVItem;
61328 begin
61329 TVI.mask := TVIF_HANDLE or TVIF_CHILDREN;
61330 TVI.hItem := Item;
61331 TVI.cChildren := 1 and Integer( Value );
61332 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
61333 end;
61335 //[function TControl.TVItemAtPos]
61336 function TControl.TVItemAtPos(x, y: Integer; var Where: DWORD): THandle;
61337 var HTI: TTVHitTestInfo;
61338 begin
61339 HTI.pt.x := x;
61340 HTI.pt.y := y;
61341 Result := Perform( TVM_HITTEST, 0, Integer( @HTI ) );
61342 Where := HTI.fl;
61343 end;
61345 type
61346 TTVInsertStruct = packed Record
61347 hParent: THandle;
61348 hAfter : THandle;
61349 item: TTVItem;
61350 end;
61351 TTVInsertStructEx = packed Record
61352 hParent: THandle;
61353 hAfter : THandle;
61354 item: TTVItemEx;
61355 end;
61357 //[function TControl.TVInsert]
61358 function TControl.TVInsert(nParent, nAfter: THandle;
61359 const Txt: String): THandle;
61360 var TVIns: TTVInsertStruct;
61361 begin
61362 TVIns.hParent := nParent;
61363 TVIns.hAfter := nAfter;
61364 TVIns.item.mask := TVIF_TEXT;
61365 TVIns.item.pszText := PChar( Txt );
61366 Result := Perform( TVM_INSERTITEM, 0, Integer( @TVIns ) );
61367 Invalidate;
61368 end;
61370 {$IFNDEF _FPC}
61371 {$IFNDEF _D2}
61372 type
61373 TTVInsertStructW = packed Record
61374 hParent: THandle;
61375 hAfter : THandle;
61376 item: TTVItemW;
61377 end;
61378 TTVInsertStructExW = packed Record
61379 hParent: THandle;
61380 hAfter : THandle;
61381 item: TTVItemExW;
61382 end;
61384 //[function TControl.TVInsertW]
61385 function TControl.TVInsertW(nParent, nAfter: THandle;
61386 const Txt: WideString): THandle;
61387 var TVIns: TTVInsertStructW;
61388 begin
61389 TVIns.hParent := nParent;
61390 TVIns.hAfter := nAfter;
61391 TVIns.item.mask := TVIF_TEXT;
61392 if Txt = '' then TVIns.item.pszText := nil
61393 else TVIns.item.pszText := PWideChar( @ Txt[ 1 ] );
61394 Result := Perform( TVM_INSERTITEMW, 0, Integer( @ TVIns ) );
61395 Invalidate;
61396 end;
61397 {$ENDIF _D2}
61398 {$ENDIF _FPC}
61400 //[procedure TControl.TVExpand]
61401 procedure TControl.TVExpand(Item: THandle; Flags: DWORD);
61402 begin
61403 Perform( TVM_EXPAND, Flags, Item );
61404 end;
61406 //[procedure TControl.TVSort]
61407 procedure TControl.TVSort( N: THandle );
61408 var a: Cardinal;
61409 b: Boolean;
61410 begin
61411 b := N = 0;
61412 if b then
61413 begin
61414 N := TVRoot;
61415 end;
61416 while N <> 0 do
61417 begin
61418 a := TVItemChild[N];
61419 if a > 0 then
61420 TVSort(a);
61421 Perform(TVM_SORTCHILDREN, 0, N);
61422 N := TVItemNext[N];
61423 end;
61424 if b then //moved by Truf
61425 Perform(TVM_SORTCHILDREN, 0, 0); //+ by YS
61426 end;
61428 //[procedure TControl.TVDelete]
61429 procedure TControl.TVDelete(Item: THandle);
61430 begin
61431 Perform( TVM_DELETEITEM, 0, Item );
61432 Invalidate;
61433 end;
61435 //[function TControl.TVGetItemData]
61436 function TControl.TVGetItemData(Item: THandle): Pointer;
61437 var TVI: TTVItem;
61438 begin
61439 TVI.mask := TVIF_HANDLE or TVIF_PARAM;
61440 TVI.hItem := Item;
61441 Result := nil;
61442 if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then
61443 Result := Pointer( TVI.lParam );
61444 end;
61446 //[procedure TControl.TVSetItemData]
61447 procedure TControl.TVSetItemData(Item: THandle; const Value: Pointer);
61448 var TVI: TTVItem;
61449 begin
61450 TVI.mask := TVIF_HANDLE or TVIF_PARAM;
61451 TVI.hItem := Item;
61452 TVI.lParam := Integer( Value );
61453 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
61454 end;
61456 //[procedure TControl.TVEditItem]
61457 procedure TControl.TVEditItem(Item: THandle);
61458 begin
61459 Perform( TVM_EDITLABEL, 0, Item );
61460 end;
61462 //[procedure TControl.TVStopEdit]
61463 procedure TControl.TVStopEdit(Cancel: Boolean);
61464 begin
61465 Perform( TVM_ENDEDITLABELNOW, Integer( Cancel ), 0 );
61466 end;
61468 //[function WndProcTVRightClickSelect]
61469 function WndProcTVRightClickSelect( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;
61470 var I: Integer;
61471 Where: DWORD;
61472 begin
61473 if Msg.message = WM_RBUTTONDOWN then
61474 begin
61475 I := Sender.TVItemAtPos( SmallInt( Msg.lParam and $FFFF ),
61476 SmallInt( Msg.lParam shr 16 ), Where );
61477 if I <> 0 then
61478 Sender.TVSelected := I;
61479 end;
61480 Result := FALSE;
61481 end;
61483 //[procedure TControl.SetTVRightClickSelect]
61484 procedure TControl.SetTVRightClickSelect(const Value: Boolean);
61485 begin
61486 fTVRightClickSelect := Value;
61487 if Value then
61488 AttachProc( @WndProcTVRightClickSelect );
61489 end;
61491 //[procedure TControl.SetOnTVDelete]
61492 procedure TControl.SetOnTVDelete( const Value: TOnTVDelete );
61493 begin
61494 fOnTVDelete := Value;
61495 if fParent <> nil then
61496 begin
61497 fParent.Add2AutoFreeEx( Clear );
61498 fParent.DetachProc( WndProcNotify );
61499 fParent.AttachProcEx( WndProcNotify, TRUE );
61500 end;
61501 AttachProcEx( ProcTVDeleteItem, TRUE );
61502 end;
61504 //[function Clipboard2Text]
61505 function Clipboard2Text: String;
61506 var gbl: THandle;
61507 str: PChar;
61508 begin
61509 Result := '';
61510 if OpenClipboard( 0 ) then
61511 begin
61512 if IsClipboardFormatAvailable( CF_TEXT ) then
61513 begin
61514 gbl := GetClipboardData( CF_TEXT );
61515 if gbl <> 0 then
61516 begin
61517 str := GlobalLock( gbl );
61518 if str <> nil then
61519 begin
61520 Result := str;
61521 GlobalUnlock( gbl );
61522 end;
61523 end;
61524 end;
61525 CloseClipboard;
61526 end;
61527 end;
61530 {$IFNDEF _D2}
61531 //[function Clipboard2WText]
61532 function Clipboard2WText: WideString;
61533 var gbl: THandle;
61534 str: PWideChar;
61535 begin
61536 Result := '';
61537 if OpenClipboard( 0 ) then
61538 begin
61539 if IsClipboardFormatAvailable( CF_UNICODETEXT ) then
61540 begin
61541 gbl := GetClipboardData( CF_UNICODETEXT );
61542 if gbl <> 0 then
61543 begin
61544 str := GlobalLock( gbl );
61545 if str <> nil then
61546 begin
61547 Result := str;
61548 GlobalUnlock( gbl );
61549 end;
61550 end;
61551 end;
61552 CloseClipboard;
61553 end;
61554 end;
61555 {$ENDIF}
61558 //[function Text2Clipboard]
61559 function Text2Clipboard( const S: String ): Boolean;
61560 var gbl: THandle;
61561 str: PChar;
61562 begin
61563 Result := False;
61564 if not OpenClipboard( 0 ) then Exit;
61565 EmptyClipboard;
61566 if S <> '' then
61567 begin
61568 gbl := GlobalAlloc( GMEM_DDESHARE, Length( S ) + 1 );
61569 if gbl <> 0 then
61570 begin
61571 str := GlobalLock( gbl );
61572 Move( S[ 1 ], str^, Length( S ) + 1 );
61573 GlobalUnlock( gbl );
61574 Result := SetClipboardData( CF_TEXT, gbl ) <> 0;
61575 end;
61577 else
61578 Result := True;
61579 CloseClipboard;
61580 end;
61583 {$IFNDEF _D2}
61584 //[function WText2Clipboard]
61585 function WText2Clipboard( const WS: WideString ): Boolean;
61586 var gbl: THandle;
61587 str: PChar;
61588 begin
61589 Result := False;
61590 if not OpenClipboard( 0 ) then Exit;
61591 EmptyClipboard;
61592 if WS <> '' then
61593 begin
61594 gbl := GlobalAlloc( GMEM_DDESHARE, (Length( WS ) + 1) * 2 );
61595 if gbl <> 0 then
61596 begin
61597 str := GlobalLock( gbl );
61598 Move( WS[ 1 ], str^, (Length( WS ) + 1) * 2 );
61599 GlobalUnlock( gbl );
61600 Result := SetClipboardData( CF_UNICODETEXT, gbl ) <> 0;
61601 end;
61603 else
61604 Result := True;
61605 CloseClipboard;
61606 end;
61607 {$ENDIF}
61610 //[function TControl.Size]
61611 function TControl.Size(W, H: Integer): PControl;
61612 var C, P: PControl;
61613 dW, dH: Integer;
61614 begin
61615 C := @Self;
61616 while True do
61617 begin
61618 dW := 0; dH := 0;
61619 P := C.FParent;
61620 if C.ToBeVisible {or C.fCreateHidden {or (P <> nil) and (P.fVisible)} then
61621 begin
61622 if C.fAlign in [caLeft, caRight, caClient] then
61623 begin
61624 if H > 0 then
61625 begin
61626 dH := H - C.Height; H := 0;
61627 end;
61628 end;
61629 if C.fAlign in [caTop, caBottom, caClient] then
61630 begin
61631 if W > 0 then
61632 begin
61633 dW := W - C.Width; W := 0;
61634 end;
61635 end;
61636 end;
61637 if (W > 0) or (H > 0) then
61638 begin
61639 C.SetSize( W, H );
61640 if (P <> nil) // {Ralf Junker}
61641 and not P.IsApplet then
61642 C.ResizeParent;
61644 if P <> nil then
61645 begin
61646 if not (C.FAlign in [caLeft,caRight,caClient]) then
61647 C.ResizeParentRight;
61648 if not (C.FAlign in [caTop,caBottom,caClient]) then
61649 C.ResizeParentBottom;
61650 end;
61652 end;
61653 if (dW = 0) and (dH = 0) then break;
61654 C := P; //C.FParent;
61655 if C = nil then break;
61656 //if not C.fIsControl then break;
61657 if C.IsApplet then break;
61658 W := C.Width + dW;
61659 H := C.Height + dH;
61660 end;
61661 Result := @Self;
61662 end;
61664 //[procedure AutoSzProc]
61665 procedure AutoSzProc( Self_: PControl );
61666 var DeltaX, DeltaY: Integer;
61667 SZ: TSize; PT: TPoint;
61668 Txt: String;
61669 Chg: Boolean;
61670 begin
61671 Txt := Self_.fCaption;
61672 SZ.cx := 0;
61673 SZ.cy := 0;
61674 if Txt <> '' then
61675 begin
61676 if Assigned( Self_.fFont ) then
61677 if Self_.fFont.fData.Font.Italic then
61678 Txt := Txt + ' ';
61679 Self_.GetWindowHandle; // this line must be here.
61680 //-- otherwise, when handle is not yet allocated,
61681 // it is requested in TCanvas.GetHandle, and in result
61682 // of unpredictable recursion some memory can be currupted.
61683 Self_.Canvas.TextArea( Txt, SZ, PT );
61684 end;
61685 Chg := FALSE;
61686 if Self_.FAlign in [ caNone, caLeft, caRight ] then
61687 begin
61688 DeltaX := Self_.fCommandActions.aAutoSzX;
61689 if DeltaX > 0 then
61690 begin
61691 Self_.Width := SZ.cx + DeltaX;
61692 Chg := TRUE;
61693 end;
61694 end;
61695 if Self_.FAlign in [ caNone, caTop, caBottom ] then
61696 begin
61697 DeltaY := Self_.fCommandActions.aAutoSzY;
61698 if DeltaY > 0 then
61699 begin
61700 Self_.Height := SZ.cy + DeltaY;
61701 Chg := TRUE;
61702 end;
61703 end;
61704 if Chg then
61705 begin
61706 if Self_.fParent <> nil then
61707 Global_Align( Self_.fParent );
61708 Global_Align( Self_ );
61709 end;
61710 end;
61712 //[function TControl.AutoSize]
61713 function TControl.AutoSize(AutoSzOn: Boolean): PControl;
61714 begin
61715 if AutoSzOn then
61716 begin
61717 fAutoSize := AutoSzProc;
61718 fAutoSize( @Self );
61720 else
61721 fAutoSize := nil;
61722 Result := @Self;
61723 end;
61725 //[function TControl.IsAutoSize]
61726 function TControl.IsAutoSize: Boolean;
61727 begin
61728 Result := Assigned( fAutoSize );
61729 end;
61732 //[function TControl.GetToBeVisible]
61733 function TControl.GetToBeVisible: Boolean;
61734 begin
61735 Result := fVisible or fCreateHidden or fVisibleWoParent;
61736 if fIsControl then
61737 if Parent <> nil then
61738 begin
61739 if fVisibleWoParent then
61740 Result := fVisible
61741 else
61742 begin
61743 Parent.Visible; // needed to provide correct fVisible for a form!
61744 Result := Result and Parent.ToBeVisible;
61745 end;
61746 end;
61747 end;
61749 { -- TTree -- }
61751 {$IFDEF USE_CONSTRUCTORS}
61752 //[function NewTree]
61753 function NewTree( AParent: PTree; const AName: String ): PTree;
61754 begin
61755 New( Result, CreateTree( AParent, AName ) );
61756 end;
61757 //[END NewTree]
61758 {$ELSE not_USE_CONSTRUCTORS}
61759 //[function NewTree]
61760 function NewTree( AParent: PTree; const AName: String ): PTree;
61761 begin
61763 New( Result, Create );
61764 {+}{++}(*Result := PTree.Create;*){--}
61765 if AParent <> nil then
61766 AParent.Add( Result );
61767 Result.fParent := AParent;
61768 Result.fName := AName;
61769 end;
61770 //[END NewTree]
61771 {$ENDIF USE_CONSTRUCTORS}
61773 { TTree }
61775 //[procedure TTree.Add]
61776 procedure TTree.Add(Node: PTree);
61777 var Previous: PTree;
61778 begin
61779 Node.Unlink;
61780 if fChildren = nil then
61781 fChildren := NewList;
61782 Previous := nil;
61783 if fChildren.fCount > 0 then
61784 Previous := fChildren.fItems[ fChildren.fCount - 1 ];
61785 if Previous <> nil then
61786 begin
61787 Previous.fNext := Node;
61788 Node.fPrev := Previous;
61789 end;
61790 fChildren.Add( Node );
61791 Node.fParent := @Self;
61792 end;
61794 //[procedure TTree.Clear]
61795 procedure TTree.Clear;
61796 var I: Integer;
61797 begin
61798 if fChildren = nil then Exit;
61799 for I := fChildren.fCount - 1 downto 0 do
61800 PTree( fChildren.fItems[ I ] ).Free;
61801 end;
61803 {$IFDEF USE_CONSTRUCTORS}
61804 //[constructor TTree.CreateTree]
61805 constructor TTree.CreateTree(AParent: PTree; const AName: String);
61806 begin
61807 inherited Create;
61808 if AParent <> nil then
61809 AParent.Add( @Self );
61810 fParent := AParent;
61811 fName := AName;
61812 end;
61813 {$ENDIF}
61815 //[destructor TTree.Destroy]
61816 destructor TTree.Destroy;
61817 begin
61818 Unlink;
61819 Clear;
61820 fName := '';
61821 inherited;
61822 end;
61824 //[function TTree.GetCount]
61825 function TTree.GetCount: Integer;
61826 begin
61827 Result := 0;
61828 if fChildren = nil then Exit;
61829 Result := fChildren.fCount;
61830 end;
61832 //[function TTree.GetIndexAmongSiblings]
61833 function TTree.GetIndexAmongSiblings: Integer;
61834 begin
61835 Result := -1;
61836 if fParent = nil then Exit;
61837 Result := fParent.fChildren.IndexOf( @Self );
61838 end;
61840 //[function TTree.GetItems]
61841 function TTree.GetItems(Idx: Integer): PTree;
61842 begin
61843 Result := nil;
61844 if fChildren = nil then Exit;
61845 Result := fChildren.Items[ Idx ];
61846 end;
61848 //[function TTree.GetLevel]
61849 function TTree.GetLevel: Integer;
61850 var Node: PTree;
61851 begin
61852 Result := 0;
61853 Node := fParent;
61854 while Node <> nil do
61855 begin
61856 Inc( Result );
61857 Node := Node.fParent;
61858 end;
61859 end;
61861 //[function TTree.GetRoot]
61862 function TTree.GetRoot: PTree;
61863 begin
61864 Result := @Self;
61865 while Result.fParent <> nil do
61866 Result := Result.fParent;
61867 end;
61869 //[function TTree.GetTotal]
61870 function TTree.GetTotal: Integer;
61871 var I: Integer;
61872 begin
61873 Result := Count;
61874 if Result <> 0 then
61875 begin
61876 for I := 0 to Count - 1 do
61877 Result := Result + Items[ I ].Total;
61878 end;
61879 end;
61881 //[procedure TTree.Init]
61882 procedure TTree.Init;
61883 begin
61884 if FParent <> nil then
61885 FParent.Add( @Self );
61886 end;
61888 //[procedure TTree.Insert]
61889 procedure TTree.Insert(Before, Node: PTree);
61890 var Previous: PTree;
61891 begin
61892 Node.Unlink;
61893 if fChildren = nil then
61894 fChildren := NewList;
61895 Previous := nil;
61896 if Before <> nil then
61897 Previous := Before.fPrev;
61898 if Previous <> nil then
61899 begin
61900 Previous.fNext := Node;
61901 Node.fPrev := Previous;
61902 end;
61903 if Before <> nil then
61904 begin
61905 Node.fNext := Before;
61906 Before.fPrev := Node;
61907 fChildren.Insert( fChildren.IndexOf( Before ), Node );
61909 else
61910 fChildren.Add( Node );
61911 Node.fParent := @Self;
61912 end;
61914 //[function CompareTreeNodes]
61915 function CompareTreeNodes( const Data: Pointer; const e1, e2: DWORD ): Integer;
61916 var List: PList;
61917 begin
61918 List := Data;
61919 Result := AnsiCompareStr( PTree( List.fItems[ e1 ] ).fName,
61920 PTree( List.fItems[ e2 ] ).fName );
61921 end;
61923 //[procedure SwapTreeNodes]
61924 procedure SwapTreeNodes( const Data: Pointer; const e1, e2: DWORD );
61925 var List: PList;
61926 begin
61927 List := Data;
61928 List.Swap( e1, e2 );
61929 end;
61931 //[procedure TTree.SwapNodes]
61932 procedure TTree.SwapNodes( i1, i2: Integer );
61933 begin
61934 fChildren.Swap( i1, i2 );
61935 end;
61937 //[procedure TTree.SortByName]
61938 procedure TTree.SortByName;
61939 begin
61940 if Count <= 1 then Exit;
61941 SortData( fChildren, fChildren.fCount, CompareTreeNodes, SwapTreeNodes );
61942 end;
61944 //[procedure TTree.Unlink]
61945 procedure TTree.Unlink;
61946 var I: Integer;
61947 begin
61948 if fPrev <> nil then
61949 fPrev.fNext := fNext;
61950 if fNext <> nil then
61951 fNext.fPrev := fPrev;
61952 if (fParent <> nil) then
61953 begin
61954 I := fParent.fChildren.IndexOf( @Self );
61955 fParent.fChildren.Delete( I );
61956 if fParent.fChildren.fCount = 0 then
61957 begin
61958 fParent.fChildren.Free;
61959 fParent.fChildren := nil;
61960 end;
61961 end;
61962 fPrev := nil;
61963 fNext := nil;
61964 fParent := nil;
61965 end;
61967 //[function TTree.IsParentOfNode]
61968 function TTree.IsParentOfNode(Node: PTree): Boolean;
61969 begin
61970 Result := TRUE;
61971 while Node <> nil do
61972 begin
61973 if Node = @ Self then Exit;
61974 Node := Node.Parent;
61975 end;
61976 Result := FALSE;
61977 end;
61979 //[function TTree.IndexOf]
61980 function TTree.IndexOf(Node: PTree): Integer;
61981 begin
61982 Result := -1;
61983 if not IsParentOfNode( Node ) then Exit;
61984 while Node <> @ Self do
61985 begin
61986 Inc( Result );
61987 while Node.PrevSibling <> nil do
61988 begin
61989 Node := Node.PrevSibling;
61990 Inc( Result, 1 + Node.Total );
61991 end;
61992 Node := Node.Parent;
61993 end;
61994 end;
61997 //[procedure TControl.ProcessPendingMessages]
61998 procedure TControl.ProcessPendingMessages;
61999 var Msg: TMsg;
62000 begin
62001 if LOWORD( GetQueueStatus( QS_ALLINPUT ) ) <> 0 then
62002 if PeekMessage( Msg, 0, 0, 0, PM_NOREMOVE {or PM_NOYIELD} )
62003 or PeekMessage( Msg, HWnd(-1), 0, 0, PM_NOREMOVE {or PM_NOYIELD} )
62004 then
62005 Applet.ProcessMessages;
62006 end;
62008 //[procedure TControl.ProcessPaintMessages]
62009 procedure TControl.ProcessPaintMessages;
62010 var Msg: TMsg;
62011 begin
62012 while PeekMessage( Msg, Handle, 15, 15, PM_NOREMOVE ) do
62013 //while GetQueueStatus( QS_PAINT ) <> 0 do
62014 Applet.ProcessMessage;
62015 end;
62025 ///////////////////////////////////////////////////////////////////////
62028 // W I N D O W S
62031 ///////////////////////////////////////////////////////////////////////
62035 { -- Set of window-related utility functions. -- }
62036 type
62037 PGUIThreadInfo = ^TGUIThreadInfo;
62038 tagGUITHREADINFO = packed record
62039 cbSize: DWORD;
62040 flags: DWORD;
62041 hwndActive: HWND;
62042 hwndFocus: HWND;
62043 hwndCapture: HWND;
62044 hwndMenuOwner: HWND;
62045 hwndMoveSize: HWND;
62046 hwndCaret: HWND;
62047 rcCaret: TRect;
62048 end;
62049 TGUIThreadInfo = tagGUITHREADINFO;
62051 const
62052 GUI_CARETBLINKING = $00000001;
62053 GUI_INMOVESIZE = $00000002;
62054 GUI_INMENUMODE = $00000004;
62055 GUI_SYSTEMMENUMODE = $00000008;
62056 GUI_POPUPMENUMODE = $00000010;
62058 {function GetGUIThreadInfo (idThread: DWORD; var pgui: TGUIThreadinfo): BOOL; stdcall;
62059 external user32 name 'GetGUIThreadInfo';}
62061 type TGUIThreadInfo_Proc = function( ThreadID: THandle; var GTI: TGUIThreadInfo )
62062 : Boolean; stdcall;
62064 var Proc_GetGUIThreadInfo: TGuiThreadInfo_Proc;
62066 //[function GetWindowChild]
62067 function GetWindowChild( Wnd: HWnd; Kind: TWindowChildKind ): HWnd;
62068 var GTI: TGuiThreadInfo;
62069 ThreadID: THandle;
62070 Module: THandle;
62071 begin
62072 if not Assigned( Proc_GetGUIThreadInfo ) then
62073 begin
62074 Module := GetModuleHandle( 'User32' );
62075 Proc_GetGUIThreadInfo := GetProcAddress( Module, 'GetGUIThreadInfoA' );
62076 if not Assigned( Proc_GetGUIThreadInfo ) then
62077 Proc_GetGUIThreadInfo := Pointer( -1 );
62078 end;
62079 Result := Wnd;
62080 if Integer( @Proc_GetGUIThreadInfo ) = -1 then
62081 Exit;
62082 Result := 0;
62083 if Wnd = 0 then
62084 ThreadID := GetCurrentThreadID
62085 else
62086 ThreadID := GetWindowThreadProcessID( Wnd, nil );
62087 if ThreadID = 0 then Exit;
62088 GTI.cbSize := Sizeof( GTI );
62089 if Proc_GetGUIThreadInfo( ThreadId, GTI ) then
62090 begin
62091 case Kind of
62092 wcActive: Result := GTI.hwndActive;
62093 wcFocus: Result := GTI.hwndFocus;
62094 wcCapture: Result := GTI.hwndCapture;
62095 wcMenuOwner: Result := GTI.hwndMenuOwner;
62096 wcMoveSize: Result := GTI.hwndMoveSize;
62097 wcCaret: Result := GTI.hwndCaret;
62098 end;
62099 end;
62100 end;
62102 //[function GetFocusedChild]
62103 function GetFocusedChild( Wnd: HWnd ): HWnd;
62104 var Tr1, Tr2: THandle;
62105 begin
62106 Result := 0;
62107 Tr1 := GetCurrentThreadId;
62108 Tr2 := GetWindowThreadProcessId( Wnd, nil );
62109 if Tr1 = Tr2 then
62110 Result := GetFocus
62111 else
62112 if AttachThreadInput( Tr2, Tr1, True ) then
62113 begin
62114 Result := GetFocus;
62115 AttachThreadInput( Tr2, Tr1, False );
62116 end;
62117 end;
62119 //[function WaitFocusedWndChild]
62120 function WaitFocusedWndChild( Wnd: HWnd ): HWnd;
62121 var T1, T2: Integer;
62122 W: HWnd;
62123 begin
62124 Sleep( 50 );
62125 T1 := GetTickCount;
62126 while True do
62127 begin
62128 W := GetTopWindow( Wnd );
62129 if W = 0 then W := Wnd;
62130 W := GetFocusedChild( W );
62131 if W <> 0 then
62132 begin
62133 Wnd := W;
62134 break;
62135 end;
62136 T2 := GetTickCount;
62137 if Abs( T1 - T2 ) > 100 then break;
62138 end;
62139 Result := Wnd;
62140 end;
62142 //[function Stroke2Window]
62143 function Stroke2Window( Wnd: HWnd; const S: String ): Boolean;
62144 var P: PChar;
62145 begin
62146 Result := False;
62147 //Wnd := GetTopWindow( Wnd );
62148 Wnd := WaitFocusedWndChild( Wnd );
62149 if Wnd = 0 then Exit;
62150 P := PChar( S );
62151 while P^ <> #0 do
62152 begin
62153 PostMessage( Wnd, WM_CHAR, Integer( P^ ), 1 );
62154 Inc( P );
62155 end;
62156 Result := True;
62157 end;
62159 //[function Stroke2WindowEx]
62160 function Stroke2WindowEx( Wnd: HWnd; const S: String; Wait: Boolean ): Boolean;
62161 var P: PChar;
62162 EndChar: Char;
62163 MsgDn, MsgUp, SCA: Integer;
62165 function Compare( Pattern: PChar ): Boolean;
62166 var Pos: PChar;
62167 C1, C2: Char;
62168 begin
62169 Pos := P;
62170 while Pattern^ <> #0 do
62171 begin
62172 C1 := Pattern^;
62173 C2 := Pos^;
62174 if C1 in [ 'a'..'z' ] then
62175 C1 := Char( Ord( C1 ) - $20 );
62176 if C2 in [ 'a'..'z' ] then
62177 C2 := Char( Ord( C2 ) - $20 );
62178 if C1 <> C2 then
62179 begin
62180 Result := False;
62181 Exit;
62182 end;
62183 Inc( Pos );
62184 Inc( Pattern );
62185 end;
62186 while Pos^ = ' ' do Inc( Pos );
62187 P := Pos;
62188 Result := True;
62189 end;
62191 procedure Send( Msg, KeyCode: Integer );
62192 var lParam: Integer;
62193 begin
62194 Wnd := WaitFocusedWndChild( Wnd );
62195 if Wnd = 0 then Exit;
62196 lParam := 1;
62197 if longBool( SCA and 4 ) then
62198 lParam := $20000001;
62199 if Msg = MsgUp then
62200 lParam := lParam or Integer($D0000000);
62201 PostMessage( Wnd, Msg, KeyCode, lParam );
62202 Applet.ProcessMessages;
62203 if Wait then
62204 Sleep( 50 );
62205 end;
62207 function CompareSend( Pattern: PChar; Value2Send: Integer ): Boolean;
62208 begin
62209 if Compare( Pattern ) then
62210 begin
62211 Send( MsgDn, Value2Send );
62212 Send( MsgUp, Value2Send );
62213 Result := True;
62215 else
62216 Result := False;
62217 end;
62219 function ParseKeys( EndChar: Char ): PChar;
62220 var FN: Integer;
62221 begin
62222 SCA := 0;
62223 while not (P^ in [ #0, EndChar ]) do
62224 begin
62225 if Compare( 'Shift' ) then SCA := SCA or 1
62226 else
62227 if Compare( 'Ctrl' ) then SCA := SCA or 2
62228 else
62229 if Compare( 'Alt' ) then SCA := SCA or 4
62230 else
62231 break;
62232 end;
62233 MsgDn := WM_KEYDOWN;
62234 MsgUp := WM_KEYUP;
62235 if LongBool( SCA and 4 ) then
62236 begin
62237 MsgDn := WM_SYSKEYDOWN;
62238 MsgUp := WM_SYSKEYUP;
62239 keybd_event( VK_MENU, 0, 0, 0 );
62240 Send( WM_SYSKEYDOWN, VK_MENU );
62241 end;
62242 if LongBool( SCA and 2 ) then
62243 begin
62244 keybd_event( VK_CONTROL, 0, 0, 0 );
62245 Send( WM_KEYDOWN, VK_CONTROL );
62246 end;
62247 if Longbool( SCA and 1 ) then
62248 begin
62249 keybd_event( VK_SHIFT, 0, 0, 0 );
62250 Send( WM_KEYDOWN, VK_SHIFT );
62251 end;
62252 while not (P^ in [ #0, EndChar ]) do
62253 begin
62254 if (P^ = 'F') and (P[ 1 ] in [ '1'..'9' ]) then
62255 begin
62256 Inc( P );
62257 FN := Ord( P^ ) - Ord( '0' );
62258 if (FN = 1) and (P[ 1 ] in [ '0'..'2' ]) then
62259 begin
62260 Inc( P );
62261 FN := 10 + Ord( P^ ) - Ord( '0' );
62262 end;
62263 repeat Inc( P ) until P^ <> ' ';
62264 FN := FN + $6F;
62265 Send( MsgDn, FN );
62266 Send( MsgUp, FN );
62268 else
62269 if Compare( 'Numpad' ) then
62270 begin
62271 if P^ in [ '0'..'9' ] then
62272 begin
62273 FN := Ord( P^ ) - Ord( '0' ) + $60;
62274 repeat Inc( P^ ) until P^ <> ' ';
62275 Send( MsgDn, FN );
62276 Send( MsgUp, FN );
62277 end;
62279 else
62280 if not (CompareSend( 'Add', $6B ) or
62281 CompareSend( 'Gray+', $6B ) or
62282 CompareSend( 'Apps', $5D ) or
62283 CompareSend( 'BackSpace', $08 ) or
62284 CompareSend( 'BkSp', $08 ) or
62285 CompareSend( 'BS', $08 ) or
62286 CompareSend( 'Break', $13 ) or
62287 CompareSend( 'CapsLock', $14 ) or
62288 CompareSend( 'Clear', $0C ) or
62289 CompareSend( 'Decimal', $6E ) or
62290 CompareSend( 'Del', $2E ) or
62291 CompareSend( 'Delete', $2E ) or
62292 CompareSend( 'Divide', $6F ) or
62293 CompareSend( 'Gray/', $6F ) or
62294 CompareSend( 'Down', $28 ) or
62295 CompareSend( 'End', $23 ) or
62296 CompareSend( 'Enter', $0D ) or
62297 CompareSend( 'Return', $0D ) or
62298 CompareSend( 'CR', $0D ) or
62299 CompareSend( 'Esc', $1B ) or
62300 CompareSend( 'Escape', $1B ) or
62301 CompareSend( 'Help', $2F ) or
62302 CompareSend( 'Home', $24 ) or
62303 CompareSend( 'Ins', $2D ) or
62304 CompareSend( 'Insert', $2D ) or
62305 CompareSend( 'Left', $25 ) or
62306 CompareSend( 'LWin', $5B ) or
62307 CompareSend( 'Multiply', $6A ) or
62308 CompareSend( 'Gray*', $6A ) or
62309 CompareSend( 'NumLock', $90 ) or
62310 CompareSend( 'PgDn', $22 ) or
62311 CompareSend( 'PgUp', $21 ) or
62312 CompareSend( 'PrintScrn', $2C ) or
62313 CompareSend( 'Right', $27 ) or
62314 CompareSend( 'RWin', $5C ) or
62315 CompareSend( 'Separator', $6C ) or
62316 CompareSend( 'ScrollLock', $91 ) or
62317 CompareSend( 'Subtract', $6D ) or
62318 CompareSend( 'Tab', $09 ) or
62319 CompareSend( 'Gray-', $6D ) or
62320 CompareSend( 'Up', $26 )) then break;
62321 end;
62322 while not (P^ in [ #0, EndChar ]) do
62323 begin
62324 if P^ in [ 'A'..'Z', '0'..'9' ] then
62325 begin
62326 Send( MsgDn, Integer( P^ ) );
62327 Send( MsgUp, Integer( P^ ) );
62329 else
62330 if P^ in [ #1..#255 ] then
62331 Stroke2Window( Wnd, '' + P^ );
62332 repeat Inc( P ) until (P^ <> ' ');
62333 end;
62334 if P^ = EndChar then
62335 Inc( P );
62336 if Longbool( SCA and 1 ) then
62337 begin
62338 Send( WM_KEYUP, VK_SHIFT );
62339 keybd_event( VK_SHIFT, 0, KEYEVENTF_KEYUP, 0 );
62340 end;
62341 if LongBool( SCA and 2 ) then
62342 begin
62343 Send( WM_KEYUP, VK_CONTROL );
62344 keybd_event( VK_CONTROL, 0, KEYEVENTF_KEYUP, 0 );
62345 end;
62346 if LongBool( SCA and 4 ) then
62347 begin
62348 Send( WM_SYSKEYUP, VK_MENU );
62349 keybd_event( VK_MENU, 0, KEYEVENTF_KEYUP, 0 );
62350 end;
62351 Result := P;
62352 end;
62354 begin
62355 Result := False;
62356 Wnd := GetTopWindow( Wnd );
62357 Wnd := GetFocusedChild( Wnd );
62358 if Wnd = 0 then Exit;
62359 P := PChar( S );
62360 while P^ <> #0 do
62361 begin
62362 if not (P^ in [ '[', '{' ]) then
62363 begin
62364 Stroke2Window( Wnd, '' + P^ );
62365 Inc( P );
62367 else
62368 begin
62369 if P^ = '[' then
62370 EndChar := ']'
62371 else
62372 EndChar := '}';
62373 Inc( P );
62374 P := ParseKeys( EndChar );
62375 end;
62376 end;
62377 Result := True;
62378 end;
62380 type
62381 PHWnd = ^HWnd;
62383 TFindWndRec = packed Record
62384 ThreadID : DWord;
62385 WndFound : HWnd;
62386 end;
62387 PFindWndRec = ^TFindWndRec;
62389 //[function EnumWindowsProc]
62390 function EnumWindowsProc( Wnd : HWnd; Find : PFindWndRec ) : Boolean;
62391 stdcall;
62392 var Id : DWord;
62393 begin
62394 Result := True;
62395 Id := GetWindowThreadProcessId( Wnd, @Id );
62396 if Id = Find.ThreadID then
62397 begin
62398 Find.WndFound := Wnd;
62399 Result := False;
62400 end;
62401 end;
62403 //[function FindWindowByThreadID]
62404 function FindWindowByThreadID( ThreadID : DWORD ) : HWnd;
62405 var Find : TFindWndRec;
62406 begin
62407 Find.ThreadID := ThreadID;
62408 Find.WndFound := 0;
62409 EnumWindows( @EnumWindowsProc, Integer( @Find ) );
62410 Result := Find.WndFound;
62411 end;
62413 //[function GetDesktopRect]
62414 function GetDesktopRect : TRect;
62415 var W1, W2 : HWnd;
62416 begin
62417 Result := MakeRect( 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) );
62418 W2 := findwindow(nil,'Program Manager');
62419 W1 := findwindowex(W2,0,'SHELLDLL_DefView',nil);
62420 if W1 = 0 then Exit;
62421 GetWindowRect( W1, Result );
62422 end;
62424 //[function GetWorkArea]
62425 function GetWorkArea: TRect;
62426 begin
62427 SystemParametersInfo( SPI_GETWORKAREA, 0, @ Result, 0 );
62428 end;
62430 //[function ExecuteWait]
62431 function ExecuteWait( const AppPath, CmdLine, DfltDirectory: String;
62432 Show: DWORD; TimeOut: DWORD; ProcID: PDWORD ): Boolean;
62433 var Flags: DWORD;
62434 Startup: TStartupInfo;
62435 ProcInf: TProcessInformation;
62436 DfltDir: PChar;
62437 App: String;
62438 begin
62439 Result := FALSE;
62440 Flags := CREATE_NEW_CONSOLE;
62441 if Show = SW_HIDE then
62442 Flags := Flags or {$IFDEF F_P}$08000000{$ELSE}CREATE_NO_WINDOW{$ENDIF};
62443 FillChar( Startup, SizeOf( Startup ), 0 );
62444 Startup.cb := Sizeof( Startup );
62445 Startup.wShowWindow := Show;
62446 Startup.dwFlags := STARTF_USESHOWWINDOW;
62447 if ProcID <> nil then
62448 ProcID^ := 0;
62449 DfltDir := nil;
62450 if DfltDirectory <> '' then
62451 DfltDir := PChar( DfltDirectory );
62452 if ProcID <> nil then
62453 ProcID^ := 0;
62454 App := AppPath;
62455 if (pos( ' ', App ) > 0) and (pos( '"', App ) <= 0) then
62456 App := '"' + App + '"';
62457 if (App <> '') and (CmdLine <> '') then
62458 App := App + ' ';
62459 if CreateProcess( nil, PChar( App + CmdLine ), nil,
62460 nil, FALSE, Flags, nil, DfltDir, Startup,
62461 ProcInf ) then
62462 begin
62463 if WaitForSingleObject( ProcInf.hProcess, TimeOut ) = WAIT_OBJECT_0 then
62464 begin
62465 CloseHandle( ProcInf.hProcess );
62466 Result := TRUE;
62468 else
62469 begin
62470 if ProcID <> nil then
62471 ProcID^ := ProcInf.hProcess;
62472 end;
62473 CloseHandle( ProcInf.hThread );
62474 end;
62475 end;
62477 //[function ExecuteIORedirect]
62478 function ExecuteIORedirect( const AppPath, CmdLine, DfltDirectory: String;
62479 Show: DWORD; ProcID: PDWORD; InPipe, OutPipeWr, OutPipeRd: PHandle ): Boolean;
62480 var Flags: DWORD;
62481 Startup: TStartupInfo;
62482 ProcInf: TProcessInformation;
62483 DfltDir: PChar;
62484 SecurityAttributes: TSecurityAttributes;
62485 SaveStdOut, SaveStdIn: THandle;
62486 ChildStdOutRd, ChildStdOutWr: THandle;
62487 ChildStdInRd, ChildStdInWr: THandle;
62488 ChildStdOutRdDup: THandle;
62489 ChildStdInWrDup: THandle;
62491 procedure Do_CloseHandle( var Handle: THandle );
62492 begin
62493 if Handle <> 0 then
62494 begin
62495 CloseHandle( Handle );
62496 Handle := 0;
62497 end;
62498 end;
62500 procedure Close_Handles;
62501 begin
62502 Do_CloseHandle( ChildStdOutRd );
62503 Do_CloseHandle( ChildStdOutWr );
62504 Do_CloseHandle( ChildStdInRd );
62505 Do_CloseHandle( ChildStdInWr );
62506 end;
62508 function RedirectInputOutput: Boolean;
62509 begin
62510 Result := FALSE;
62511 if (OutPipeRd <> nil) or (OutPipeWr <> nil) then
62512 begin
62513 // redirect output
62514 SaveStdOut := GetStdHandle(STD_OUTPUT_HANDLE);
62515 if not CreatePipe( ChildStdOutRd, ChildStdOutWr, @ SecurityAttributes, 0 ) then
62516 Exit;
62517 if not SetStdHandle( STD_OUTPUT_HANDLE, ChildStdOutWr ) then
62518 Exit;
62519 if not DuplicateHandle( GetCurrentProcess, ChildStdOutRd,
62520 GetCurrentProcess, @ ChildStdOutRdDup, 0, FALSE,
62521 2 {DUPLICATE_SAME_ACCESS} ) then
62522 Exit;
62523 Do_CloseHandle( ChildStdOutRd );
62524 if OutPipeRd <> nil then
62525 OutPipeRd^ := ChildStdOutRdDup;
62526 if OutPipeWr <> nil then
62527 OutPipeWr^ := ChildStdOutWr;
62528 end;
62529 if InPipe <> nil then
62530 begin
62531 // redirect input
62532 SaveStdIn := GetStdHandle(STD_INPUT_HANDLE);
62533 if not CreatePipe( ChildStdInRd, ChildStdInWr, @ SecurityAttributes, 0 ) then
62534 Exit;
62535 if not SetStdHandle( STD_INPUT_HANDLE, ChildStdInRd ) then
62536 Exit;
62537 if not DuplicateHandle( GetCurrentProcess, ChildStdInWr,
62538 GetCurrentProcess, @ ChildStdInWrDup, 0, FALSE,
62539 2 {DUPLICATE_SAME_ACCESS} ) then
62540 Exit;
62541 Do_CloseHandle( ChildStdInWr );
62542 if InPipe <> nil then
62543 InPipe^ := ChildStdInWrDup;
62544 Do_CloseHandle( ChildStdInRd );
62545 end;
62546 Result := TRUE;
62547 end;
62549 procedure Restore_Saved_StdInOut;
62550 begin
62551 //if SaveStdOut <> 0 then
62552 SetStdHandle( STD_OUTPUT_HANDLE, SaveStdOut );
62553 //if SaveStdin <> 0 then
62554 SetStdHandle( STD_INPUT_HANDLE, SaveStdIn );
62555 end;
62557 begin
62558 Result := FALSE;
62559 Flags := 0;
62560 if Show = SW_HIDE then
62561 Flags := Flags or {$IFDEF F_P}$08000000{$ELSE}CREATE_NO_WINDOW{$ENDIF};
62562 FillChar( Startup, SizeOf( Startup ), 0 );
62563 Startup.cb := Sizeof( Startup );
62564 {Startup.wShowWindow := Show;
62565 Startup.dwFlags := STARTF_USESHOWWINDOW;}
62566 if ProcID <> nil then
62567 ProcID^ := 0;
62568 DfltDir := nil;
62569 SecurityAttributes.nLength := Sizeof( SecurityAttributes );
62570 SecurityAttributes.lpSecurityDescriptor := nil;
62571 SecurityAttributes.bInheritHandle := TRUE;
62572 SaveStdOut := 0;
62573 SaveStdIn := 0;
62574 ChildStdOutRd := 0;
62575 ChildStdOutWr := 0;
62576 ChildStdInRd := 0;
62577 ChildStdInWr := 0;
62578 if not RedirectInputOutput then
62579 begin
62580 Close_Handles;
62581 Exit;
62582 end;;
62583 if DfltDirectory <> '' then
62584 DfltDir := PChar( DfltDirectory );
62585 if CreateProcess( nil, PChar( '"' + AppPath + '" ' + CmdLine ),
62586 nil, nil, TRUE, Flags, nil, DfltDir, Startup,
62587 ProcInf ) then
62588 begin
62589 if ProcID <> nil then
62590 ProcID^ := ProcInf.hProcess
62591 else
62592 CloseHandle( ProcInf.hProcess );
62593 CloseHandle( ProcInf.hThread );
62594 Restore_Saved_StdInOut;
62595 Result := TRUE;
62597 else
62598 begin
62599 Restore_Saved_StdInOut;
62600 Close_Handles;
62601 Exit;
62602 end;
62603 end;
62605 //[function ExecuteConsoleAppIORedirect]
62606 function ExecuteConsoleAppIORedirect( const AppPath, CmdLine, DfltDirectory: String;
62607 Show: DWORD; const InStr: String; var OutStr: String; WaitTimeout: DWORD ): Boolean;
62608 var PipeIn, PipeOutRd, PipeOutWr: THandle;
62609 ProcID: DWORD;
62610 BytesCount: DWORD;
62611 Buffer: array[ 0..4096 ] of Char;
62612 BufStr: String;
62613 PPipeIn: PHandle;
62614 begin
62615 Result := FALSE;
62616 PPipeIn := @ PipeIn;
62617 if InStr = '' then
62618 PPipeIn := nil;
62619 PipeOutRd := 0;
62620 PipeOutWr := 0;
62621 if not ExecuteIORedirect( AppPath, CmdLine, DfltDirectory, Show, @ ProcID,
62622 PPipeIn, @ PipeOutWr, @ PipeOutRd ) then Exit;
62623 if PPipeIn <> nil then
62624 begin
62625 if InStr <> '' then
62626 WriteFile( PipeIn, InStr[ 1 ], Length( InStr ), BytesCount, nil );
62627 CloseHandle( PipeIn );
62628 end;
62629 OutStr := '';
62630 if WaitForSingleObject( ProcID, WaitTimeOut ) = WAIT_OBJECT_0 then
62631 begin
62632 CloseHandle( ProcID );
62633 CloseHandle( PipeOutWr );
62634 while ReadFile( PipeOutRd, Buffer, Sizeof( Buffer ), BytesCount, nil ) do
62635 begin
62636 SetLength( BufStr, BytesCount );
62637 Move( Buffer[ 0 ], BufStr[ 1 ], BytesCount );
62638 OutStr := OutStr + BufStr;
62639 end;
62641 else
62642 CloseHandle( PipeOutWr );
62643 CloseHandle( PipeOutRd );
62644 Result := TRUE;
62645 end;
62647 {$IFDEF _D2}
62648 //[API OpenProcessToken]
62649 function OpenProcessToken(ProcessHandle: THandle; DesiredAccess: DWORD;
62650 var TokenHandle: THandle): BOOL; stdcall;
62651 external advapi32 name 'OpenProcessToken';
62652 {$ENDIF}
62654 //[function WindowsShutdown]
62655 function WindowsShutdown( const Machine : String; Force, Reboot : Boolean ) : Boolean;
62657 hToken: THandle;
62658 tkp, tkp_prev: TTokenPrivileges;
62659 dwRetLen :DWORD;
62660 Flags: Integer;
62661 begin
62662 Result := False;
62663 if Integer( GetVersion ) < 0 then // Windows95/98/Me
62664 begin
62665 if Machine <> '' then Exit;
62666 Flags := EWX_SHUTDOWN;
62667 if Reboot then
62668 Flags := Flags or EWX_REBOOT;
62669 if Force then
62670 Flags := Flags or EWX_FORCE;
62671 Result := ExitWindowsEx( Flags, 0 );
62672 Exit;
62673 end;
62675 OpenProcessToken(GetCurrentProcess(),
62676 TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
62677 hToken);
62679 if not LookupPrivilegeValue(PChar(Machine),
62680 'SeShutdownPrivilege',tkp.Privileges[0].Luid)
62681 then
62682 Exit;
62684 tkp_prev:=tkp;
62685 tkp.PrivilegeCount:=1;
62686 tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
62687 AdjustTokenPrivileges(hToken, FALSE, tkp, sizeof(tkp), tkp_prev,
62688 dwRetLen);
62690 if not LookupPrivilegeValue(PChar(Machine),
62691 'SeRemoteShutdownPrivilege',
62692 tkp.Privileges[0].Luid)
62693 then
62694 Exit;
62696 tkp.PrivilegeCount:=1;
62697 tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
62698 AdjustTokenPrivileges(hToken, FALSE, tkp, sizeof(tkp), tkp_prev,
62699 dwRetLen);
62701 Result := InitiateSystemShutdown(PChar(Machine),nil, 0, Force, Reboot);
62702 end;
62704 var SaveWinVer: Byte = $FF;
62706 //[function WinVer]
62707 function WinVer : TWindowsVersion;
62708 {* Returns Windows version. }
62709 var OVI: TOsVersionInfo;
62710 begin
62711 if SaveWinVer <> $FF then Result := TWindowsVersion( SaveWinVer )
62712 else
62713 begin
62714 OVI.dwOSVersionInfoSize := Sizeof( OVI );
62715 GetVersionEx( OVI );
62716 with OVI do
62717 if dwPlatformId = VER_PLATFORM_WIN32_NT then
62718 begin
62719 Result := wvNT;
62720 if dwMajorVersion >= 6 then
62721 Result := wvLongHorn
62722 else begin
62723 if dwMajorVersion >= 5 then
62724 if dwMinorVersion >=1 then
62725 Result := wvXP
62726 else
62727 Result := wvY2K;
62728 end;
62730 {if dwPlatformId = VER_PLATFORM_WIN32_NT then
62731 begin
62732 Result := wvNT;
62733 if dwMajorVersion >= 5 then
62734 Result := wvY2K;
62735 end}
62736 else
62737 if dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then
62738 begin
62739 Result := wv95;
62740 if (dwMajorVersion > 4) or (dwMajorVersion = 4)
62741 and (dwMinorVersion >= 10) then
62742 Result := wv98;
62744 else
62745 Result := wv31; // Windows 3.1 (WIN32s)
62746 SaveWinVer := Ord( Result );
62747 end;
62748 end;
62750 //[function IsWinVer]
62751 function IsWinVer( Ver : TWindowsVersions ) : Boolean;
62752 {* Returns True if Windows version is in given range of values. }
62753 begin
62754 Result := WinVer in Ver;
62755 end;
62757 //[procedure TControl.SetAlphaBlend]
62758 procedure TControl.SetAlphaBlend(const Value: Integer);
62759 const
62760 LWA_COLORKEY=$00000001;
62761 LWA_ALPHA=$00000002;
62762 ULW_COLORKEY=$00000001;
62763 ULW_ALPHA=$00000002;
62764 ULW_OPAQUE=$00000004;
62765 WS_EX_LAYERED=$00080000;
62766 type
62767 TSetLayeredWindowAttributes=
62768 function( hwnd: Integer; crKey: TColor; bAlpha: Byte; dwFlags: DWORD )
62769 : Boolean; stdcall;
62771 SetLayeredWindowAttributes: TSetLayeredWindowAttributes;
62772 User32: THandle;
62773 dw: DWORD;
62774 begin
62775 if Value = fAlphaBlend then Exit;
62776 fAlphaBlend := Value;
62777 User32 := GetModuleHandle( 'User32' );
62778 SetLayeredWindowAttributes := GetProcAddress( User32,
62779 'SetLayeredWindowAttributes' );
62780 if Assigned( SetLayeredWindowAttributes ) then
62781 begin
62782 dw := GetWindowLong( GetWindowHandle, GWL_EXSTYLE );
62783 if Byte( Value ) < 255 then
62784 begin
62785 SetWindowLong( fHandle, GWL_EXSTYLE, dw or WS_EX_LAYERED );
62786 SetLayeredWindowAttributes( fHandle, 0, Value and $FF, LWA_ALPHA);
62788 else
62789 SetWindowLong( fHandle, GWL_EXSTYLE, dw and not WS_EX_LAYERED );
62790 end;
62791 end;
62793 //[function TControl.SetPosition]
62794 function TControl.SetPosition( X, Y: Integer ): PControl;
62795 begin
62796 Left := X;
62797 Top := Y;
62798 Result := @Self;
62799 end;
62801 //[function NewColorDialog]
62802 function NewColorDialog( FullOpen: TColorCustomOption ): PColorDialog;
62803 var I: Integer;
62804 begin
62806 New( Result, Create );
62807 {+}{++}(*Result := PColorDialog.Create;*){--}
62808 Result.ColorCustomOption := FullOpen;
62809 for I := 1 to 16 do
62810 Result.CustomColors[ I ] := clWhite;
62811 end;
62812 //[END NewColorDialog]
62814 { TColorDialog }
62816 //[function TColorDialog.Execute]
62817 function TColorDialog.Execute: Boolean;
62818 var CD: TChooseColor;
62819 begin
62820 CD.lStructSize := Sizeof( CD );
62821 CD.hWndOwner := OwnerWindow;
62822 //CD.hInstance := 0;
62823 CD.rgbResult := Color2RGB( Color );
62824 CD.lpCustColors := @CustomColors[ 1 ];
62825 CD.Flags := CC_RGBINIT;
62826 case ColorCustomOption of
62827 ccoFullOpen: CD.Flags := CD.Flags or CC_FULLOPEN;
62828 ccoPreventFullOpen: CD.Flags := CD.Flags or CC_PREVENTFULLOPEN;
62829 end;
62830 Result := ChooseColor( CD );
62831 if Result then
62832 Color := CD.rgbResult;
62833 end;
62835 //[procedure TControl.SetMaxProgress]
62836 procedure TControl.SetMaxProgress(const Index, Value: Integer);
62837 begin
62838 // ignore index, and set Value via PBM_SETRANGE32: ()
62839 Perform( PBM_SETRANGE32, 0, Value );
62840 end;
62842 //[procedure TControl.SetDroppedWidth]
62843 procedure TControl.SetDroppedWidth(const Value: Integer);
62844 begin
62845 FDroppedWidth := Value;
62846 Perform( CB_SETDROPPEDWIDTH, Value, 0 );
62847 end;
62849 //[function TControl.LVGetItemState]
62850 function TControl.LVGetItemState(Idx: Integer): TListViewItemState;
62851 type
62852 PListViewItemState = ^TListViewItemState;
62853 var I: Byte;
62854 begin
62855 I := Perform( LVM_GETITEMSTATE, Idx,
62856 LVIS_CUT or LVIS_DROPHILITED or LVIS_FOCUSED or LVIS_SELECTED );
62857 Result := PListViewItemState( @ I )^;
62858 end;
62860 //[procedure TControl.LVSetItemState]
62861 procedure TControl.LVSetItemState(Idx: Integer; const Value: TListViewItemState);
62862 var Data: TLVItem;
62863 begin
62864 //FillChar( Data, Sizeof( Data ), 0 );
62865 //Data.mask := LVIF_DI_SETITEM or LVIF_STATE;
62866 Data.stateMask := LVIS_FOCUSED or LVIS_SELECTED or LVIS_CUT or LVIS_DROPHILITED;
62867 Data.state := PByte( @ Value )^;
62868 //Data.iItem := Idx;
62869 Perform( LVM_SETITEMSTATE, Idx, Integer( @Data ) );
62870 end;
62872 //[procedure TControl.LVSelectAll]
62873 procedure TControl.LVSelectAll;
62874 begin
62875 LVSetItemState( -1, [ lvisSelect ] );
62876 end;
62878 //[function TControl.LVItemInsert]
62879 function TControl.LVItemInsert(Idx: Integer; const aText: String): Integer;
62880 var LVI: TLVItem;
62881 begin
62882 LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;
62883 LVI.iItem := Idx;
62884 LVI.iSubItem := 0;
62885 LVI.pszText := PChar( aText );
62886 Result := Perform( LVM_INSERTITEM, 0, Integer( @LVI ) );
62887 end;
62889 {$IFNDEF _FPC}
62890 {$IFNDEF _D2}
62891 //[function TControl.LVItemInsertW]
62892 function TControl.LVItemInsertW(Idx: Integer;
62893 const aText: WideString): Integer;
62894 var LVI: TLVItemW;
62895 begin
62896 LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;
62897 LVI.iItem := Idx;
62898 LVI.iSubItem := 0;
62899 LVI.pszText := PWideChar( aText );
62900 Result := Perform( LVM_INSERTITEMW, 0, Integer( @LVI ) );
62901 end;
62902 {$ENDIF _D2}
62903 {$ENDIF _FPC}
62905 //[function TControl.LVItemAdd]
62906 function TControl.LVItemAdd(const aText: String): Integer;
62907 begin
62908 Result := LVItemInsert( Count, aText );
62909 end;
62911 {$IFNDEF _FPC}
62912 {$IFNDEF _D2}
62913 //[function TControl.LVItemAddW]
62914 function TControl.LVItemAddW(const aText: WideString): Integer;
62915 begin
62916 Result := LVItemInsertW( Count, aText );
62917 end;
62918 {$ENDIF _D2}
62919 {$ENDIF _FPC}
62921 //[function TControl.LVGetSttImgIdx]
62922 function TControl.LVGetSttImgIdx(Idx: Integer): Integer;
62923 begin
62924 Result := Perform( LVM_GETITEMSTATE, Idx, LVIS_STATEIMAGEMASK ) shr 12;
62925 end;
62927 //[procedure TControl.LVSetSttImgIdx]
62928 procedure TControl.LVSetSttImgIdx(Idx: Integer; const Value: Integer);
62929 var LVI: TLVItem;
62930 begin
62931 LVI.stateMask := LVIS_STATEIMAGEMASK;
62932 LVI.state := Value shl 12;
62933 Perform( LVM_SETITEMSTATE, Idx, Integer( @LVI ) );
62934 end;
62936 //[function TControl.LVGetOvlImgIdx]
62937 function TControl.LVGetOvlImgIdx(Idx: Integer): Integer;
62938 begin
62939 Result := Perform( LVM_GETITEMSTATE, Idx, LVIS_OVERLAYMASK ) shr 8;
62940 end;
62942 //[procedure TControl.LVSetOvlImgIdx]
62943 procedure TControl.LVSetOvlImgIdx(Idx: Integer; const Value: Integer);
62944 var LVI: TLVItem;
62945 begin
62946 LVI.stateMask := LVIS_OVERLAYMASK;
62947 LVI.state := Value shl 8;
62948 Perform( LVM_SETITEMSTATE, Idx, Integer( @LVI ) );
62949 end;
62951 //[function TControl.LVGetItemData]
62952 function TControl.LVGetItemData(Idx: Integer): DWORD;
62953 var LVI: TLVItem;
62954 begin
62955 LVI.mask := LVIF_PARAM;
62956 LVI.iItem := Idx;
62957 LVI.iSubItem := 0;
62958 Perform( LVM_GETITEM, 0, Integer( @LVI ) );
62959 Result := LVI.lParam;
62960 end;
62962 //[procedure TControl.LVSetItemData]
62963 procedure TControl.LVSetItemData(Idx: Integer; const Value: DWORD);
62964 var LVI: TLVItem;
62965 begin
62966 LVI.mask := LVIF_PARAM;
62967 LVI.iItem := Idx;
62968 LVI.iSubItem := 0;
62969 LVI.lParam := Value;
62970 Perform( LVM_SETITEM, 0, Integer( @LVI ) );
62971 end;
62973 //[function TControl.LVGetItemIndent]
62974 function TControl.LVGetItemIndent(Idx: Integer): Integer;
62975 var LI: TLVItem;
62976 begin
62977 LI.mask := LVIF_INDENT;
62978 LI.iItem := Idx;
62979 LI.iSubItem := 0;
62980 Perform( LVM_GETITEM, 0, Integer( @LI ) );
62981 Result := LI.iIndent;
62982 end;
62984 //[procedure TControl.LVSetItemIndent]
62985 procedure TControl.LVSetItemIndent(Idx: Integer; const Value: Integer);
62986 var LI: TLVItem;
62987 begin
62988 LI.mask := LVIF_INDENT or LVIF_DI_SETITEM;
62989 LI.iItem := Idx;
62990 LI.iSubItem := 0;
62991 LI.iIndent := Value;
62992 Perform( LVM_SETITEM, 0, Integer( @LI ) );
62993 end;
62995 type
62996 TNMLISTVIEW = packed Record
62997 hdr: TNMHDR;
62998 iItem: Integer;
62999 iSubItem: Integer;
63000 uNewState: Integer;
63001 uOldState: Integer;
63002 uChanged: Integer;
63003 ptAction: Integer;
63004 lParam: DWORD;
63005 end;
63006 PNMLISTVIEW = ^TNMLISTVIEW;
63008 //[function WndProc_LVDeleteItem]
63009 function WndProc_LVDeleteItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
63010 : Boolean;
63011 var Hdr: PNMHDR;
63012 LV: PNMListView;
63013 begin
63014 Result := FALSE;
63015 if Msg.message = WM_NOTIFY then
63016 begin
63017 Hdr := Pointer(Msg.lParam);
63018 if Hdr.hwndFrom = Sender.Handle then
63019 begin
63020 LV := Pointer( Hdr );
63021 if Hdr.code = LVN_DELETEITEM then
63022 begin
63023 if Assigned( Sender.OnDeleteLVItem ) then
63024 Sender.OnDeleteLVItem( Sender, LV.iItem );
63025 Result := TRUE;
63027 else
63028 if Hdr.code = LVN_DELETEALLITEMS then
63029 begin
63030 if Assigned( Sender.OnDeleteAllLVItems ) then
63031 begin
63032 Sender.OnDeleteAllLVItems( Sender );
63033 Rslt := 0;
63034 if Assigned( Sender.OnDeleteLVItem ) then
63035 Rslt := 1;
63036 end;
63037 Result := TRUE;
63038 end;
63039 end;
63040 end;
63041 end;
63043 //[procedure TControl.SetOnDeleteAllLVItems]
63044 procedure TControl.SetOnDeleteAllLVItems(const Value: TOnEvent);
63045 begin
63046 fOnDeleteAllLVItems := Value;
63047 AttachProc( @WndProc_LVDeleteItem );
63048 end;
63050 //[procedure TControl.SetOnDeleteLVItem]
63051 procedure TControl.SetOnDeleteLVItem(const Value: TOnDeleteLVItem);
63052 begin
63053 fOnDeleteLVItem := Value;
63054 AttachProc( @WndProc_LVDeleteItem );
63055 end;
63057 //[function WndProc_LVData]
63058 function WndProc_LVData( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
63059 : Boolean;
63060 var Hdr: PNMHDR;
63061 DI: PLVDispInfo;
63062 Store: Boolean;
63063 Txt: String;
63064 LV: PControl;
63065 {$IFDEF UNICODE_CTRLS}
63066 TxtW: WideString;
63067 {$ENDIF UNICODE_CTRLS}
63068 begin
63069 Result := FALSE;
63070 if Msg.message = WM_NOTIFY then
63071 begin
63072 Hdr := Pointer(Msg.lParam);
63073 if Hdr.hwndFrom = Sender.Handle then
63074 begin
63075 if (Hdr.code = LVN_GETDISPINFO)
63076 {$IFDEF UNICODE_CTRLS}
63077 or (Hdr.code = LVN_GETDISPINFOW)
63078 {$ENDIF UNICODE_CTRLS}
63079 then
63080 begin
63081 DI := Pointer( Hdr );
63082 LV := Sender;
63083 if LV <> nil then
63084 begin
63085 Txt := '';
63086 DI.item.iImage := -1;
63087 DI.item.state := 0;
63088 Store := FALSE;
63089 if (Assigned( LV.OnLVData )
63090 {$IFDEF UNICODE_CTRLS}
63091 or Assigned( LV.OnLVDataW )
63092 {$ENDIF UNICODE_CTRLS}
63094 and (DI.item.iItem >= 0) then
63095 begin
63096 {$IFDEF UNICODE_CTRLS}
63097 TxtW := '';
63098 if Assigned( LV.ONLVDataW ) then
63099 LV.OnLVDataW( LV, DI.item.iItem, DI.item.iSubItem, TxtW,
63100 DI.item.iImage, DWORD( DI.item.state ), Store )
63101 else
63102 {$ENDIF UNICODE_CTRLS}
63103 LV.OnLVData( LV, DI.item.iItem, DI.item.iSubItem, Txt,
63104 DI.item.iImage, DWORD( DI.item.state ), Store );
63105 {$IFNDEF UNICODE_CTRLS}
63106 if (LV.fCaption = nil) or (Integer( StrLen( LV.fCaption ) ) <=
63107 Length( Txt ) ) then
63108 {$ENDIF UNICODE_CTRLS}
63109 begin
63110 if LV.fCaption <> nil then
63111 FreeMem( LV.fCaption );
63112 {$IFDEF UNICODE_CTRLS}
63113 GetMem( LV.fCaption, (Length( Txt ) + Length( TxtW ) + 1)
63114 * Sizeof( WideChar ) );
63115 {$ELSE NOT_UNICODE_CTRLS}
63116 GetMem( LV.fCaption, Length( Txt ) + 1 );
63117 {$ENDIF NOT_UNICODE_CTRLS}
63118 end;
63119 {$IFDEF UNICODE_CTRLS}
63120 PWord( @ LV.fCaption[ 0 ] )^ := 0;
63121 {$ELSE}
63122 LV.fCaption[ 0 ] := #0;
63123 {$ENDIF}
63124 if Txt {$IFDEF UNICODE_CTRLS} + TxtW {$ENDIF UNICODE_CTRLS}
63125 <> '' then
63126 begin
63127 {$IFDEF UNICODE_CTRLS}
63128 if Hdr.code = LVN_GETDISPINFOW then
63129 begin
63130 if Txt <> '' then
63131 TxtW := Txt;
63132 Move( TxtW[ 1 ], LV.fCaption[ 0 ], (Length( TxtW ) + 1) * Sizeof( WideChar ) );
63133 end else
63134 {$ENDIF UNICODE_CTRLS}
63135 StrCopy( LV.fCaption, @Txt[ 1 ] );
63136 end;
63137 DI.item.pszText := LV.fCaption;
63138 if Store then
63139 DI.item.mask := DI.item.mask or LVIF_DI_SETITEM;
63140 end;
63141 Result := TRUE;
63142 end;
63143 end;
63144 end;
63145 end;
63146 end;
63148 //[procedure TControl.SetOnLVData]
63149 procedure TControl.SetOnLVData(const Value: TOnLVData);
63150 begin
63151 fOnLVData := Value;
63152 AttachProc( @WndProc_LVData );
63153 Perform( LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK or LVIS_STATEIMAGEMASK, 0 );
63154 end;
63156 {$IFNDEF _FPC}
63157 {$IFNDEF _D2}
63158 //[procedure TControl.SetOnLVDataW]
63159 procedure TControl.SetOnLVDataW(const Value: TOnLVDataW);
63160 begin
63161 fOnLVDataW := Value;
63162 AttachProc( @WndProc_LVData );
63163 Perform( LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK or LVIS_STATEIMAGEMASK, 0 );
63164 end;
63165 {$ENDIF _D2}
63166 {$ENDIF _FPC}
63168 //[function WndProc_LVCustomDraw]
63169 function WndProc_LVCustomDraw( Sender: PControl; var Msg: TMsg;
63170 var Rslt: Integer ): Boolean;
63171 var NMCustDraw: PNMLVCustomDraw;
63172 NMHdr: PNMHdr;
63173 ItemIdx, SubItemIdx: Integer;
63174 S: TListViewItemState;
63175 ItemState: TDrawState;
63176 begin
63177 Result := FALSE;
63178 if Msg.message = WM_NOTIFY then
63179 begin
63180 NMHdr := Pointer( Msg.lParam );
63181 if (NMHdr.code = NM_CUSTOMDRAW) and Assigned( Sender.fOnLVCustomDraw ) then
63182 begin
63183 NMCustDraw := Pointer( Msg.lParam );
63184 ItemIdx := -1;
63185 SubItemIdx := -1;
63186 if LongBool( NMCustDraw.nmcd.dwDrawStage and CDDS_ITEM ) then
63187 ItemIdx := NMCustDraw.nmcd.dwItemSpec;
63188 if LongBool( NMCustDraw.nmcd.dwDrawStage and CDDS_SUBITEM ) then
63189 SubItemIdx := NMCustDraw.iSubItem;
63190 ItemState := [ ];
63191 if ItemIdx >= 0 then
63192 begin
63193 S := Sender.LVItemState[ ItemIdx ];
63194 if lvisFocus in S then
63195 ItemState := ItemState + [ odsFocused ];
63196 if lvisSelect in S then
63197 ItemState := ItemState + [ odsSelected ];
63198 if lvisBlend in S then
63199 ItemState := ItemState + [ odsGrayed ];
63200 if lvisHighlight in S then
63201 ItemState := ItemState + [ odsMarked ];
63202 end;
63204 Sender.Canvas;
63206 Rslt := Sender.FOnLVCustomDraw( Sender, {Sender.Canvas.Handle} NMCustDraw.nmcd.hdc,
63207 NMCustDraw.nmcd.dwDrawStage, ItemIdx, SubItemIdx, NMCustDraw.nmcd.rc,
63208 ItemState, TColor( NMCustDraw.clrText ), TColor( NMCustDraw.clrTextBk ) );
63210 Result := TRUE;
63211 end;
63212 end;
63213 end;
63215 //[procedure TControl.SetOnLVCustomDraw]
63216 procedure TControl.SetOnLVCustomDraw(const Value: TOnLVCustomDraw);
63217 begin
63218 fOnLVCustomDraw := Value;
63219 AttachProc( @WndProc_LVCustomDraw );
63220 end;
63222 //[function CompareLVItems]
63223 function CompareLVItems( Idx1, Idx2: Integer; ListView: PControl ): Integer; stdcall;
63224 begin
63225 if Assigned( ListView.fOnCompareLVItems ) then
63226 Result := ListView.fOnCompareLVItems( ListView, Idx1, Idx2 )
63227 else
63228 Result := 0;
63229 end;
63231 //[procedure TControl.LVSort]
63232 procedure TControl.LVSort;
63233 begin
63234 Perform( LVM_SORTITEMSEX, Integer(@Self), Integer(@CompareLVItems) );
63235 end;
63237 //[function CompareLVItemsData]
63238 function CompareLVItemsData( D1, D2: DWORD; ListView: PControl ): Integer; stdcall;
63239 begin
63240 if Assigned( ListView.fOnCompareLVItems ) then
63241 Result := ListView.fOnCompareLVItems( ListView, D1, D2 )
63242 else
63243 Result := 0;
63244 end;
63246 //[procedure TControl.LVSortData]
63247 procedure TControl.LVSortData;
63248 begin
63249 Perform( LVM_SORTITEMS, Integer( @Self ), Integer( @CompareLVItemsData ) );
63250 end;
63252 //[function WndProc_LVColumnClick]
63253 function WndProc_LVColumnClick( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
63254 : Boolean;
63255 var Hdr: PNMHDR;
63256 LV: PNMListView;
63257 begin
63258 Result := FALSE;
63259 if Msg.message = WM_NOTIFY then
63260 begin
63261 Hdr := Pointer(Msg.lParam);
63262 if Hdr.hwndFrom = Sender.Handle then
63263 begin
63264 LV := Pointer( Hdr );
63265 if Hdr.code = LVN_COLUMNCLICK then
63266 begin
63267 if Assigned( Sender.OnColumnClick ) then
63268 Sender.OnColumnClick( Sender, LV.iSubItem );
63269 Result := TRUE;
63270 end;
63271 end;
63272 end;
63273 end;
63275 //[procedure TControl.SetOnColumnClick]
63276 procedure TControl.SetOnColumnClick(const Value: TOnLVColumnClick);
63277 begin
63278 fOnColumnClick := Value;
63279 AttachProc( @WndProc_LVColumnClick );
63280 end;
63282 //[function WndProc_LVStateChange]
63283 function WndProc_LVStateChange( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;
63284 var NMOD: PNMLVODStateChange;
63285 NMLV: PNMLISTVIEW;
63286 begin
63287 if Msg.message = WM_NOTIFY then
63288 begin
63289 NMOD := Pointer( Msg.lParam );
63290 NMLV := Pointer( Msg.lParam );
63291 if NMOD.hdr.code = LVN_ODSTATECHANGED then
63292 begin
63293 if Assigned( Sender.OnLVStateChange ) then
63294 Sender.OnLVStateChange( Sender, NMOD.iFrom, NMOD.iTo,
63295 NMOD.uOldState, NMOD.uNewState );
63297 else
63298 if NMLV.hdr.code = LVN_ITEMCHANGED then
63299 begin
63300 if Assigned( Sender.OnLVStateChange ) then
63301 Sender.OnLVStateChange( Sender, NMLV.iItem, NMLV.iItem,
63302 NMLV.uOldState, NMLV.uNewState );
63303 end;
63304 end;
63305 Result := FALSE;
63306 end;
63308 //[procedure TControl.SetOnLVStateChange]
63309 procedure TControl.SetOnLVStateChange(const Value: TOnLVStateChange);
63310 begin
63311 FOnLVStateChange := Value;
63312 AttachProc( WndProc_LVStateChange );
63313 end;
63315 //[function WndProc_LVDelete]
63316 function WndProc_LVDelete( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;
63317 var NMLV: PNMLISTVIEW;
63318 begin
63319 if Msg.message = WM_NOTIFY then
63320 begin
63321 NMLV := Pointer( Msg.lParam );
63322 if NMLV.hdr.code = LVN_DELETEITEM then
63323 begin
63324 if Assigned( Sender.OnLVDelete ) then
63325 Sender.OnLVDelete( Sender, NMLV.iItem );
63326 end;
63327 end;
63328 Result := FALSE;
63329 end;
63331 //[procedure TControl.SetOnLVDelete]
63332 procedure TControl.SetOnLVDelete(const Value: TOnLVDelete);
63333 begin
63334 FOnLVDelete := Value;
63335 Add2AutoFreeEx( Clear );
63336 AttachProcEx( WndProc_LVDelete, TRUE );
63337 if fParent <> nil then
63338 begin
63339 fParent.DetachProc( WndProcNotify );
63340 fParent.AttachProcEx( WndProcNotify, TRUE );
63341 end;
63342 end;
63344 //[function CompareLVColumns]
63345 function CompareLVColumns( Idx1, Idx2: Integer; Sender: PControl ): Integer; stdcall;
63346 var S1, S2: String;
63347 begin
63348 //--- changed by Mike Gerasimov:
63349 S1 := Sender.LVItems[ Idx1, Sender.fColumn ];
63350 S2 := Sender.LVItems[ Idx2, Sender.fColumn ];
63351 If lvoSortAscending in Sender.fLVOptions Then
63352 Result := AnsiCompareStrNoCase( S1, S2 )
63353 Else
63354 If lvoSortDescending in Sender.fLVOptions Then
63355 Result := AnsiCompareStrNoCase( S2, S1 )
63356 Else
63357 Result:=0;
63358 end;
63360 //[procedure TControl.LVSortColumn]
63361 procedure TControl.LVSortColumn(Idx: Integer);
63362 begin
63363 fColumn := Idx;
63364 Perform( LVM_SORTITEMSEX, Integer(@Self), Integer(@CompareLVColumns) );
63365 end;
63367 //[function TControl.LVIndexOf]
63368 function TControl.LVIndexOf(const S: String): Integer;
63369 begin
63370 Result := LVSearchFor( S, -1, FALSE );
63371 end;
63373 {$IFNDEF _FPC}
63374 {$IFNDEF _D2}
63375 //[function TControl.LVIndexOfW]
63376 function TControl.LVIndexOfW(const S: WideString): Integer;
63377 begin
63378 Result := LVSearchForW( S, -1, FALSE );
63379 end;
63380 {$ENDIF _D2}
63381 {$ENDIF _FPC}
63383 //[function TControl.LVSearchFor]
63384 function TControl.LVSearchFor(const S: String; StartAfter: Integer;
63385 Partial: Boolean): Integer;
63386 var f: TLVFindInfo;
63387 begin
63388 f.lParam := 0;
63389 f.flags := LVFI_STRING;
63390 if Partial then
63391 f.flags := LVFI_STRING or LVFI_PARTIAL;
63392 f.psz := @s[1];
63393 result := Perform(LVM_FINDITEM,StartAfter,integer(@f));
63394 end;
63396 {$IFNDEF _FPC}
63397 {$IFNDEF _D2}
63398 //[function TControl.LVSearchForW]
63399 function TControl.LVSearchForW(const S: WideString; StartAfter: Integer;
63400 Partial: Boolean): Integer;
63401 var f: TLVFindInfoW;
63402 begin
63403 f.lParam := 0;
63404 f.flags := LVFI_STRING;
63405 if Partial then
63406 f.flags := LVFI_STRING or LVFI_PARTIAL;
63407 f.psz := @s[1];
63408 result := Perform(LVM_FINDITEMW,StartAfter,integer(@f));
63409 end;
63410 {$ENDIF _D2}
63411 {$ENDIF _FPC}
63413 function WndProcLVMeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63414 const
63415 ClsName: PChar = 'obj_SysListView32'#0;
63417 pMI: PMeasureItemStruct;
63418 pLV: PControl;
63419 H: Integer;
63420 wnd: HWND;
63421 wId: DWORD;
63423 begin
63425 Result := FALSE;
63426 if Msg.message = WM_MEASUREITEM then begin
63427 pMI := Pointer(Msg.lParam);
63428 with pMI^ do begin
63429 if CtlType=ODT_LISTVIEW then begin
63430 wnd := 0;
63432 repeat
63433 wnd := FindWindowEx(Sender.GetWindowHandle,wnd,ClsName,nil);
63434 wId := GetWindowLong(wnd,GWL_ID);
63435 if CtlID = wId then begin
63436 pLV := Pointer(GetProp(wnd,ID_SELF));
63437 if pLV <> nil then begin
63438 H := pLV.Perform(WM_MEASUREITEM,0,0);
63439 if H > 0 then begin
63440 itemHeight := H;
63441 Rslt:=1;
63442 Result := TRUE;
63443 end;
63444 break;
63445 end;
63446 end;
63447 until wnd = 0;
63449 end;
63450 end;
63451 end;
63452 end;
63454 function WndProcLVMeasureItem2( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63455 begin
63456 Result := FALSE;
63457 if (Msg.message = WM_MEASUREITEM) and (Msg.wParam = 0) then begin
63458 Rslt := Sender.fLVItemHeight;
63459 Result := TRUE;
63460 end;
63462 end;
63464 function TControl.SetLVItemHeight(Value: Integer): PControl;
63465 begin
63466 Set_LVItemHeight( Value );
63467 Result := @ Self;
63468 end;
63470 procedure TControl.Set_LVItemHeight(Value: Integer);
63471 begin
63472 if fLVItemHeight <> Value then begin
63473 if fLVItemHeight = 0 then begin
63474 Parent.AttachProc(WndProcLVMeasureItem);
63475 AttachProc(WndProcLVMeasureItem2);
63476 end;
63477 fLVItemHeight := Value;
63478 end;
63479 end;
63481 //[function TControl.IndexOf]
63482 function TControl.IndexOf(const S: String): Integer;
63483 begin
63484 Result := SearchFor( S, -1, FALSE );
63485 end;
63487 //[function TControl.SearchFor]
63488 function TControl.SearchFor(const S: String; StartAfter: Integer;
63489 Partial: Boolean): Integer;
63490 var Cmd: Integer;
63491 I: Integer;
63492 begin
63493 Cmd := fCommandActions.aFindItem;
63494 if Partial then
63495 Cmd := fCommandActions.aFindPartial;
63496 if Cmd <> 0 then
63497 Result := Perform( Cmd, StartAfter, Integer( PChar( S ) ) )
63498 else
63499 begin
63500 Result := -1;
63501 for I := StartAfter+1 to Count-1 do
63502 begin
63503 if Partial and ( Copy( Items[ I ], 1, Length( S ) ) = S ) or
63504 ( Items[ I ] = S ) then
63505 begin
63506 Result := I;
63507 break;
63508 end;
63509 end;
63510 end;
63511 end;
63513 //[function TControl.DefaultBtnProc]
63514 function TControl.DefaultBtnProc(var Msg: TMsg;
63515 var Rslt: Integer): Boolean;
63516 var Btn: PControl;
63517 F: PControl;
63518 //Msg1: TMsg;
63519 begin
63520 if Assigned( fOldOnMessage ) then
63521 begin
63522 Result := fOldOnMessage( Msg, Rslt );
63523 if Result then Exit;
63524 end;
63525 Result := FALSE;
63526 if AppletTerminated then Exit;
63527 F := Applet;
63528 if not F.fIsForm then
63529 begin
63530 F := F.fCurrentControl;
63531 if F = nil then Exit;
63532 end;
63533 Btn := nil;
63534 if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_KEYUP)) and
63535 ((Msg.wParam = VK_RETURN) or (Msg.wParam = VK_ESCAPE)) then
63536 begin
63537 if (Msg.wParam = VK_RETURN) and
63538 (F.fDefaultBtnCtl <> nil) and
63539 F.fDefaultBtnCtl.ToBeVisible and
63540 F.fDefaultBtnCtl.Enabled and
63541 ((F.fCurrentControl=nil) or (not F.fCurrentControl.fCancelBtn and
63542 not F.fCurrentControl.fIgnoreDefault)
63543 or (F.fCurrentControl = F.fDefaultBtnCtl)
63544 ) then
63545 Btn := F.fDefaultBtnCtl
63546 else
63547 if (Msg.wParam = VK_ESCAPE) and
63548 (F.fCancelBtnCtl <> nil) and
63549 F.fCancelBtnCtl.ToBeVisible and
63550 F.fCancelBtnCtl.Enabled then
63551 Btn := F.fCancelBtnCtl
63552 else
63553 if (Msg.wParam = VK_RETURN) and
63554 (F.fAllBtnReturnClick or fAllBtnReturnClick) and
63555 (F.ActiveControl <> nil) and
63556 (F.ActiveControl.IsButton) and
63557 (F.ActiveControl.Count = 0) then
63558 Btn := F.ActiveControl;
63559 if Btn <> nil then
63560 begin
63561 if Msg.message = WM_KEYDOWN then
63562 Btn.Focused := TRUE;
63563 Btn.Perform( Msg.message, DWORD( ' ' ), Msg.lParam );
63564 Msg.wParam := 0;
63565 Result := TRUE;
63566 Rslt := 0;
63567 Exit;
63569 end;
63570 Result := FALSE;
63571 end;
63573 //[procedure TControl.SetDefaultBtn]
63574 procedure TControl.SetDefaultBtn(const Index: Integer;
63575 const Value: Boolean);
63576 var F, C: PControl;
63577 begin
63578 if Index = 13 then
63579 begin
63580 fDefaultBtn := Value;
63581 fCancelBtn := FALSE;
63583 else
63584 if Index = 27 then
63585 begin
63586 fCancelBtn := Value;
63587 fDefaultBtn := FALSE;
63588 end;
63589 if Applet = nil then Exit;
63590 F := ParentForm;
63591 if F <> nil then
63592 begin
63593 if Value then
63594 begin
63595 if @ Applet.fOnMessage <> @ TControl.DefaultBtnProc then
63596 Applet.fOldOnMessage := Applet.fOnMessage; // fixed by YS
63597 Applet.fOnMessage := Applet.DefaultBtnProc;
63599 else
63600 begin
63601 Applet.fOnMessage := Applet.fOldOnMessage;
63602 Applet.fOldOnMessage := nil;
63603 end;
63604 C := nil;
63605 if Value then C := @ Self;
63606 if Index = 13 then
63607 begin
63608 F.fDefaultBtnCtl := C;
63609 if Value then
63610 Style := Style or BS_DEFPUSHBUTTON
63611 else
63612 Style := Style and not BS_DEFPUSHBUTTON;
63614 else
63615 if Index = 27 then
63616 F.fCancelBtnCtl := C;
63617 end;
63618 end;
63620 {$IFDEF F_P}
63621 //[function TControl.GetDefaultBtn]
63622 function TControl.GetDefaultBtn(const Index: Integer): Boolean;
63623 begin
63624 CASE Index OF
63625 13: Result := fDefaultBtn;
63626 27: Result := fCancelBtn;
63627 END;
63628 end;
63629 {$ENDIF F_P}
63631 //[function TControl.AllBtnReturnClick]
63632 function TControl.AllBtnReturnClick: PControl;
63633 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
63634 begin
63635 // nothing: already implemented in WndProcBtnReturnClick
63636 Result := @ Self;
63637 end;
63638 {$ELSE}
63639 var F: PControl;
63640 begin
63641 SetDefaultBtn( 0, TRUE );
63642 F := ParentForm;
63643 if F <> nil then
63644 F.fAllBtnReturnClick := TRUE;
63645 Result := @ Self;
63646 end;
63647 {$ENDIF}
63649 //[function WndProc_CNDrawItem]
63650 function WndProc_CNDrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
63651 : Boolean;
63652 type PDrawAction = ^TDrawAction;
63653 PDrawState = ^TDrawState;
63654 var DI: PDrawItemStruct;
63655 begin
63656 Result := FALSE;
63657 if Msg.message = CN_DRAWITEM then
63658 begin
63659 DI := Pointer( Msg.lParam );
63660 if Assigned( Sender.OnDrawItem ) then
63661 begin
63662 if Sender.OnDrawItem( Sender, DI.hDC, DI.rcItem, DI.itemID,
63663 PDrawAction( @ DI.itemAction )^,
63664 PDrawState( @ DI.itemState )^ )
63665 then Rslt := 1
63666 else Rslt := 0;
63667 Result := TRUE;
63669 else Rslt := 0;
63670 end;
63671 end;
63673 //[procedure TControl.SetOnDrawItem]
63674 procedure TControl.SetOnDrawItem(const Value: TOnDrawItem);
63675 begin
63676 fOnDrawItem := Value;
63677 if Parent <> nil then
63678 Parent.AttachProc( @WndProc_DrawItem );
63679 AttachProc( @WndProc_CNDrawItem );
63680 end;
63682 //[function WndProc_MeasureItem]
63683 function WndProc_MeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
63684 : Boolean;
63685 var MI: PMeasureItemStruct;
63686 Control: PControl;
63687 I: Integer;
63688 begin
63689 Result := FALSE;
63690 if Msg.message = WM_MEASUREITEM then
63691 begin
63692 MI := Pointer( Msg.lParam );
63693 for I := 0 to Sender.ChildCount - 1 do
63694 begin
63695 Control := Sender.Children[ I ];
63696 if Control.Menu = MI.CtlID then
63697 begin
63698 if Assigned( Control.OnMeasureItem ) then
63699 begin
63700 MI.itemHeight := Control.OnMeasureItem( Control, MI.itemID );
63701 if MI.itemHeight > 0 then
63702 begin
63703 Rslt := 1;
63704 Result := TRUE;
63705 end;
63706 end;
63707 break;
63708 end;
63709 end;
63710 end;
63711 end;
63713 //[procedure TControl.SetOnMeasureItem]
63714 procedure TControl.SetOnMeasureItem(const Value: TOnMeasureItem);
63715 begin
63716 fOnMeasureItem := Value;
63717 if Parent <> nil then
63718 Parent.AttachProc( @WndProc_MeasureItem );
63719 end;
63721 //[function TControl.GetItemData]
63722 function TControl.GetItemData(Idx: Integer): DWORD;
63723 begin
63724 Result := 0;
63725 if fCommandActions.aGetItemData <> 0 then
63726 Result := Perform( fCommandActions.aGetItemData, Idx, 0 );
63727 end;
63729 //[procedure TControl.SetItemData]
63730 procedure TControl.SetItemData(Idx: Integer; const Value: DWORD);
63731 begin
63732 if fCommandActions.aSetItemData <> 0 then
63733 Perform( fCommandActions.aSetItemData, Idx, Value );
63734 end;
63736 //[function TControl.GetLVCurItem]
63737 function TControl.GetLVCurItem: Integer;
63738 begin
63739 Result := Perform( LVM_GETNEXTITEM, -1, LVNI_SELECTED );
63740 end;
63742 //[procedure TControl.SetLVCurItem]
63743 procedure TControl.SetLVCurItem(const Value: Integer);
63744 begin
63745 if (lvoMultiselect in LVOptions) or (Value <> LVCurItem ) then
63746 LVItemState[ -1 ] := [ ];
63747 if Value >= 0 then
63748 LVItemState[ Value ] := [ lvisSelect, lvisFocus ];
63749 end;
63751 //[function TControl.LVNextItem]
63752 function TControl.LVNextItem(IdxPrev: Integer; Attrs: DWORD): Integer;
63753 begin
63754 Result := Perform( LVM_GETNEXTITEM, IdxPrev, Attrs );
63755 end;
63757 //[function TControl.LVNextSelected]
63758 function TControl.LVNextSelected(IdxPrev: Integer): Integer;
63759 begin
63760 Result := Perform( LVM_GETNEXTITEM, IdxPrev, LVNI_SELECTED );
63761 end;
63763 //[procedure TControl.Close]
63764 procedure TControl.Close;
63765 begin
63766 PostMessage( Handle, WM_CLOSE, 0, 0 );
63767 end;
63769 //[function WndProcMinimize]
63770 function WndProcMinimize( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63771 var Wnd: PControl;
63772 begin
63773 Result := FALSE;
63774 if (Msg.message = WM_SYSCOMMAND) and ((Msg.wParam and $FFF0) = SC_MINIMIZE)then
63775 begin
63776 if Applet <> nil then
63777 begin
63778 Wnd := Applet.FMinimizeWnd;
63779 if Wnd <> nil then
63780 SetWindowPos( Applet.Handle, 0, Wnd.Left, Wnd.Top, Wnd.Width, 0,
63781 SWP_NOZORDER or SWP_NOREDRAW);
63782 end;
63783 end;
63784 end;
63786 //[procedure TControl.MinimizeNormalAnimated]
63787 procedure TControl.MinimizeNormalAnimated;
63788 var App: PControl;
63789 begin
63790 App := Applet;
63791 if App = nil then
63792 App := @Self;
63793 App.FMinimizeWnd := @Self;
63794 App.AttachProc( @WndProcMinimize );
63795 end;
63797 //[function WndProcDropFiles]
63798 function WndProcDropFiles( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63799 var hDrop: THandle;
63800 Pt: TPoint;
63801 FList: String;
63802 I, N: Integer;
63803 Buf: array[ 0..MAX_PATH ] of Char;
63804 begin
63805 if Msg.message = WM_DROPFILES then
63806 if Assigned( Sender.FOnDropFiles ) then
63807 begin
63808 hDrop := Msg.wParam;
63809 DragQueryPoint( hDrop, Pt );
63810 N := DragQueryFile( hDrop, $FFFFffff, nil, 0 );
63811 FList := '';
63812 for I := 0 to N-1 do
63813 begin
63814 if FList <> '' then
63815 FList := FList + #13;
63816 DragQueryFile( hDrop, I, Buf, Sizeof( Buf ) );
63817 FList := FList + Buf;
63818 end;
63819 DragFinish( hDrop );
63820 Sender.FOnDropFiles( Sender, FList, Pt );
63821 Rslt := 0;
63822 Result := TRUE;
63823 Exit;
63824 end;
63825 Result := FALSE;
63826 end;
63828 //[procedure TControl.SetOnDropFiles]
63829 procedure TControl.SetOnDropFiles(const Value: TOnDropFiles);
63830 begin
63831 FOnDropFiles := Value;
63832 AttachProc( @WndProcDropFiles );
63833 DragAcceptFiles( GetWindowHandle, Assigned( Value ) );
63834 end;
63836 //[function WndProcShowHide]
63837 function WndProcShowHide( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63838 var IsVisible: Boolean;
63839 begin
63840 if Msg.message = WM_SHOWWINDOW then
63841 if Msg.hwnd = Sender.Handle then
63842 begin
63843 IsVisible := IsWindowVisible( Sender.Handle );
63844 if LongBool( Msg.wParam ) then
63845 begin
63846 Sender.fVisible := TRUE;
63847 if not IsVisible then
63848 if Assigned( Sender.FOnShow ) then
63849 Sender.FOnShow( Sender );
63851 else
63852 begin
63853 Sender.fVisible := FALSE;
63854 if IsVisible then
63855 if Assigned( Sender.FOnHide ) then
63856 Sender.FOnHide( Sender );
63857 end;
63858 end;
63859 Result := FALSE;
63860 end;
63862 //[procedure TControl.SetOnHide]
63863 procedure TControl.SetOnHide(const Value: TOnEvent);
63864 begin
63865 FOnHide := Value;
63866 AttachProc( WndProcShowHide );
63867 end;
63869 //[procedure TControl.SetOnShow]
63870 procedure TControl.SetOnShow(const Value: TOnEvent);
63871 begin
63872 FOnShow := Value;
63873 AttachProc( WndProcShowHide );
63874 end;
63876 //[function TControl.BringToFront]
63877 function TControl.BringToFront: PControl;
63878 begin
63879 SetWindowPos( GetWindowHandle, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or
63880 SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_SHOWWINDOW );
63881 Result := @Self;
63882 end;
63884 //[function TControl.SendToBack]
63885 function TControl.SendToBack: PControl;
63886 begin
63887 SetWindowPos( GetWindowHandle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or
63888 SWP_NOACTIVATE or SWP_NOOWNERZORDER );
63889 Result := @Self;
63890 end;
63892 //[procedure TControl.DragStart]
63893 procedure TControl.DragStart;
63894 begin
63895 PostMessage( GetWindowHandle, WM_SYSCOMMAND, $F012, 0 );
63896 end;
63898 //[function WndProcDragWindow]
63899 function WndProcDragWindow( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63900 var P: TPoint;
63901 begin
63902 if Msg.message = WM_MOUSEMOVE then
63903 begin
63904 if Sender.FDragging then
63905 begin
63906 GetCursorPos( P );
63907 P.x := P.x - Sender.fMouseStartPos.x + Sender.fDragStartPos.x;
63908 P.y := P.y - Sender.fMouseStartPos.y + Sender.fDragStartPos.y;
63909 Sender.Position := P;
63910 end;
63911 end;
63912 Result := FALSE;
63913 end;
63915 //[procedure TControl.DragStartEx]
63916 procedure TControl.DragStartEx;
63917 var StartBounds: TRect;
63918 begin
63919 GetCursorPos( fMouseStartPos );
63920 StartBounds := BoundsRect;
63921 fDragStartPos.x := StartBounds.Left;
63922 fDragStartPos.y := StartBounds.Top;
63923 SetCapture( GetWindowHandle );
63924 fDragging := TRUE;
63925 AttachProc( WndProcDragWindow );
63926 end;
63928 //[procedure TControl.DragStopEx]
63929 procedure TControl.DragStopEx;
63930 begin
63931 if FDragging then
63932 begin
63933 ReleaseCapture;
63934 FDragging := FALSE;
63935 end;
63936 end;
63938 //[function CallDragCallBack]
63939 function CallDragCallBack( Sender: PControl; var Stop: Boolean ): Boolean;
63940 var P: TPoint;
63941 Shape, ShapeWas: Integer;
63942 begin
63943 GetCursorPos( P );
63944 Shape := LoadCursor( 0, IDC_HAND );
63945 ShapeWas := Shape;
63946 Result := Sender.fDragCallback( Sender, P.x, P.y, Shape, Stop );
63947 if not Stop then
63948 begin
63949 if not Result then
63950 if Shape = ShapeWas then
63951 Shape := LoadCursor( 0, IDC_NO );
63952 ScreenCursor := Shape;
63954 else
63955 begin
63956 ScreenCursor := 0;
63957 Shape := Sender.fCursor;
63958 end;
63959 Windows.SetCursor( Shape );
63960 end;
63962 //[function WndProcDrag]
63963 function WndProcDrag( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63964 var Stop: Boolean;
63965 begin
63966 if Sender.fDragging then
63967 begin
63968 Stop := FALSE;
63969 case Msg.message of
63970 WM_MOUSEMOVE:
63971 CallDragCallBack( Sender, Stop );
63972 WM_LBUTTONUP, WM_RBUTTONUP:
63973 begin
63974 Stop := TRUE;
63975 CallDragCallBack( Sender, Stop );
63976 end;
63977 else
63978 begin
63979 Result := FALSE;
63980 Exit;
63981 end;
63982 end;
63983 if Stop then
63984 begin
63985 ReleaseCapture;
63986 Sender.fDragging := FALSE;
63988 else
63989 begin
63990 Result := TRUE;
63991 exit;
63992 end;
63993 end;
63994 Result := FALSE;
63995 end;
63997 //[procedure TControl.DragItem]
63998 procedure TControl.DragItem(OnDrag: TOnDrag);
63999 begin
64000 fDragCallback := OnDrag;
64001 fDragging := TRUE;
64002 SetCapture( GetWindowHandle );
64003 AttachProc( WndProcDrag );
64004 end;
64007 {$IFDEF USE_CONSTRUCTORS} //****************************************************//
64009 //[constructor TControl.CreateWindowed]
64010 constructor TControl.CreateWindowed(AParent: PControl; AClassName: PChar; //
64011 ACtl3D: Boolean); //
64012 begin //
64013 CreateParented( AParent ); //
64014 fOnDynHandlers := WndProcDummy; //
64015 fWndProcKeybd := WndProcDummy; //
64016 fWndProcResizeFlicks := WndProcDummy; //
64017 fCommandActions.aClear := ClearText; //
64018 fWindowed := True; //
64019 fControlClassName := AClassName; //
64021 fControlClick := DummyObjProc; //
64023 fColor := clBtnFace; //
64024 fTextColor := clWindowText; //
64025 fMargin := 2; //
64026 fCtl3D := True; //
64027 fCtl3Dchild := True; //
64028 if AParent <> nil then //
64029 begin //
64030 fWndProcResizeFlicks := AParent.fWndProcResizeFlicks; //
64031 fGotoControl := AParent.fGotoControl; //
64032 fDoubleBuffered := AParent.fDoubleBuffered; //
64033 fTransparent := AParent.fTransparent; //
64034 fCtl3Dchild := AParent.fCtl3Dchild; //
64035 if AParent.fCtl3Dchild then //
64036 fCtl3D := ACtl3D //
64037 else //
64038 fCtl3D := False; //
64039 fMargin := AParent.fMargin; //
64040 with fBoundsRect do //
64041 begin //
64042 Left := AParent.fMargin + AParent.fClientLeft; //
64043 Top := AParent.fMargin + AParent.fClientTop; //
64044 Right := Left + 64; //
64045 Bottom := Top + 64; //
64046 end; //
64047 fTextColor := AParent.fTextColor; //
64048 fFont := fFont.Assign( AParent.fFont ); //
64049 if fFont <> nil then //
64050 begin //
64051 fFont.fOnChange := FontChanged; //
64052 FontChanged( fFont ); //
64053 end; //
64054 fColor := AParent.fColor; //
64055 fBrush := fBrush.Assign( AParent.fBrush ); //
64056 if fBrush <> nil then //
64057 begin //
64058 fBrush.fOnChange := BrushChanged; //
64059 BrushChanged( fBrush ); //
64060 end; //
64061 end; //
64062 end; //
64064 //[constructor TControl.CreateApplet]
64065 constructor TControl.CreateApplet(const ACaption: String); //
64066 begin //
64067 AppButtonUsed := True; //
64068 CreateWindowed( nil, 'App', TRUE ); //
64069 FIsApplet := TRUE; //
64070 fStyle := WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX //
64071 or WS_CAPTION; //
64072 fExStyle := WS_EX_APPWINDOW; //
64073 FCreateWndExt := CreateAppButton; //
64074 AttachProc( WndProcApp ); //
64075 Caption := ACaption; //
64076 end; //
64078 //[constructor TControl.CreateForm]
64079 constructor TControl.CreateForm(AParent: PControl; const ACaption: String); //
64080 begin //
64081 CreateWindowed( AParent, 'Form', TRUE ); //
64082 AttachProc( WndProcForm ); //
64083 AttachProc( WndProcDoEraseBkgnd ); //
64084 Caption := ACaption; //
64085 end; //
64087 //[constructor TControl.CreateControl]
64088 constructor TControl.CreateControl(AParent: PControl; AClassName: PChar; //
64089 AStyle: DWORD; ACtl3D: Boolean; Actions: PCommandActions); //
64090 var Form: PControl; //
64091 begin //
64092 CreateWindowed( AParent, AClassName, ACtl3D ); //
64093 if Actions <> nil then //
64094 fCommandActions := Actions^; //
64095 fIsControl := True; //
64096 fStyle := AStyle or WS_CLIPSIBLINGS or WS_CLIPCHILDREN; //
64097 fVisible := (Style and WS_VISIBLE) <> 0; //
64098 fTabstop := (Style and WS_TABSTOP) <> 0; //
64099 if (AParent <> nil) then //
64100 begin //
64101 Inc( AParent.ParentForm.fTabOrder ); //
64102 fTabOrder := AParent.ParentForm.fTabOrder; //
64103 end; //
64104 fLookTabKeys := [ tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn ]; //
64105 if fCtl3D then //
64106 begin //
64107 fStyle := fStyle and not WS_BORDER; //
64108 fExStyle := fExStyle or WS_EX_CLIENTEDGE; //
64109 end; //
64110 if (Style and WS_TABSTOP) <> 0 then //
64111 begin //
64112 Form := ParentForm; //
64113 if Form <> nil then //
64114 if Form.FCurrentControl = nil then //
64115 Form.FCurrentControl := @Self; //
64116 end; //
64117 //fCreateParamsExt := CreateParams2; //
64118 fMenu := CtlIdCount; //
64119 Inc( CtlIdCount ); //
64120 AttachProc( WndProcCtrl ); //
64121 end; //
64123 //[constructor TControl.CreateButton]
64124 constructor TControl.CreateButton(AParent: PControl; //
64125 const ACaption: String); //
64126 begin //
64127 CreateControl( AParent, 'BUTTON', //
64128 WS_VISIBLE or WS_CHILD or //
64129 BS_PUSHLIKE or WS_TABSTOP, False, @ButtonActions ); //
64130 with fBoundsRect do //
64131 Bottom := Top + 22; //
64132 fTextAlign := taCenter; //
64133 Caption := ACaption; //
64134 end; //
64136 //[constructor TControl.CreateBitBtn]
64137 constructor TControl.CreateBitBtn(AParent: PControl; //
64138 const ACaption: String; AOptions: TBitBtnOptions; ALayout: TGlyphLayout; //
64139 AGlyphBitmap: HBitmap; AGlyphCount: Integer); //
64140 var //
64141 B: TBitmapInfo; //
64142 W, H: Integer; //
64143 begin //
64144 CreateControl( AParent, 'BUTTON', WS_VISIBLE or WS_CHILD or //
64145 WS_TABSTOP or BS_OWNERDRAW, False, @ButtonActions ); //
64146 fBitBtnOptions := AOptions; //
64147 fGlyphLayout := ALayout; //
64148 fGlyphBitmap := AGlyphBitmap; //
64149 with fBoundsRect do //
64150 begin //
64151 Bottom := Top + 22; //
64152 W := 0; H := 0; //
64153 if AGlyphBitmap <> 0 then //
64154 begin //
64155 if bboImageList in AOptions then //
64156 ImageList_GetIconSize( AGlyphBitmap, W, H ) //
64157 else //
64158 begin //
64159 if GetObject( AGlyphBitmap, Sizeof(B), @B ) > 0 then //
64160 begin //
64161 W := B.bmiHeader.biWidth; //
64162 H := B.bmiHeader.biHeight; //
64163 if AGlyphCount = 0 then //
64164 AGlyphCount := W div H; //
64165 if AGlyphCount > 1 then //
64166 W := W div AGlyphCount; //
64167 end; //
64168 end; //
64169 if W > 0 then //
64170 if ACaption = '' then //
64171 Right := Left + W //
64172 else //
64173 Right := Right + W; //
64174 if H > 0 then //
64175 Bottom := Top + H; //
64176 if not ( bboNoBorder in AOptions ) then //
64177 begin //
64178 if W > 0 then //
64179 Inc( Right, 2 ); //
64180 if H > 0 then //
64181 Inc( Bottom, 2 ); //
64182 end; //
64183 end; //
64184 fGlyphWidth := W; //
64185 fGlyphHeight := H; //
64186 end; //
64187 fGlyphCount := AGlyphCount; //
64188 if AParent <> nil then //
64189 AParent.AttachProc( WndProc_DrawItem ); //
64190 AttachProc( WndProcBitBtn ); //
64191 fTextAlign := taCenter; //
64192 Caption := ACaption; //
64193 end; //
64195 //[constructor TControl.CreateLabel]
64196 constructor TControl.CreateLabel(AParent: PControl; //
64197 const ACaption: String); //
64198 begin //
64199 CreateControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or //
64200 SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY, //
64201 False, @LabelActions ); //
64202 fIsStaticControl := True; //
64203 fSizeRedraw := True; //
64204 fBoundsRect.Bottom := fBoundsRect.Top + 22; //
64205 Caption := ACaption; //
64206 end; //
64208 //[constructor TControl.CreateWordWrapLabel]
64209 constructor TControl.CreateWordWrapLabel(AParent: PControl; //
64210 const ACaption: String); //
64211 begin //
64212 CreateLabel( AParent, ACaption ); //
64213 fBoundsRect.Bottom := fBoundsRect.Top + 44; //
64214 fStyle := fStyle and not SS_LEFTNOWORDWRAP; //
64215 end; //
64217 //[constructor TControl.CreateLabelEffect]
64218 constructor TControl.CreateLabelEffect(AParent: PControl; ACaption: String; //
64219 AShadowDeep: Integer); //
64220 begin //
64221 CreateLabel( AParent, ACaption ); //
64222 fIsStaticControl := False; //
64223 AttachProc( WndProcLabelEffect ); //
64224 fTextAlign := taCenter; //
64225 fTextColor := clBtnShadow; //
64226 fShadowDeep := AShadowDeep; //
64227 fIgnoreWndCaption := True; //
64228 with fBoundsRect do //
64229 begin //
64230 Bottom := Top + 40; //
64231 end; //
64232 end; //
64234 //[constructor TControl.CreatePaintBox]
64235 constructor TControl.CreatePaintBox(AParent: PControl); //
64236 begin //
64237 CreateLabel( AParent, '' ); //
64238 with fBoundsRect do //
64239 begin //
64240 Right := Left + 40; //
64241 Bottom := Top + 40; //
64242 end; //
64243 end; //
64245 {$IFDEF ASM_VERSION} //
64246 //[constructor TControl.CreateGradientPanel]
64247 constructor TControl.CreateGradientPanel(AParent: PControl; AColor1, //
64248 AColor2: TColor); //
64249 asm //cmd //opd //
64250 XOR EDX, EDX //
64251 PUSH EDX //
64252 CALL CreateLabel //
64253 MOV ECX, AColor1 //
64254 MOV [EAX].fColor1, ECX //
64255 MOV ECX, AColor2 //
64256 MOV [EAX].fColor2, ECX //
64257 MOV EDX, [EAX].fBoundsRect.Left //
64258 ADD EDX, 40 //
64259 MOV [EAX].fBoundsRect.Right, EDX //
64260 MOV EDX, [EAX].fBoundsRect.Top //
64261 ADD EDX, 40 //
64262 MOV [EAX].fBoundsRect.Bottom, EDX //
64263 PUSH EAX //
64264 MOV EDX, offset[ WndProcGradient ] //
64265 CALL AttachProc //
64266 POP EAX //
64267 end; //
64268 {$ELSE ASM_VERSION} //Pascal //
64269 constructor TControl.CreateGradientPanel(AParent: PControl; AColor1, //
64270 AColor2: TColor); //
64271 begin //
64272 CreateLabel( AParent, '' ); //
64273 AttachProc( WndProcGradient ); //
64274 fColor2 := AColor2; //
64275 fColor1 := AColor1; //
64276 with fBoundsRect do //
64277 begin //
64278 Right := Left + 40; //
64279 Bottom := Top + 40; //
64280 end; //
64281 end; //
64282 {$ENDIF ASM_VERSION} //
64284 //[constructor TControl.CreateGradientPanelEx]
64285 constructor TControl.CreateGradientPanelEx(AParent: PControl; AColor1, //
64286 AColor2: TColor; AStyle: TGradientStyle; ALayout: TGradientLayout); //
64287 begin //
64288 CreateLabel( AParent, '' ); //
64289 AttachProc( WndProcGradientEx ); //
64290 fColor2 := AColor2; //
64291 fColor1 := AColor1; //
64292 fGradientStyle := AStyle; //
64293 fGradientLayout := ALayout; //
64294 with fBoundsRect do //
64295 begin //
64296 Right := Left + 40; //
64297 Bottom := Top + 40; //
64298 end; //
64299 end; //
64301 //[constructor TControl.CreateGroupbox]
64302 constructor TControl.CreateGroupbox(AParent: PControl; //
64303 const ACaption: String); //
64304 begin //
64305 CreateButton( AParent, ACaption ); //
64306 with fBoundsRect do //
64307 begin //
64308 Right := Left + 100; //
64309 Bottom := Top + 100; //
64310 end; //
64311 fStyle := WS_VISIBLE or WS_CHILD or BS_GROUPBOX or WS_TABSTOP; //
64312 fClientTop := 22; //
64313 fClientLeft := 2; //
64314 fClientBottom := 2; //
64315 fClientRight := 2; //
64316 fTabstop := False; //
64317 //AttachProc( WndProcGroupBox ); //
64318 end; //
64320 //[constructor TControl.CreateCheckbox]
64321 constructor TControl.CreateCheckbox(AParent: PControl; //
64322 const ACaption: String); //
64323 begin //
64324 CreateButton( AParent, ACaption ); //
64325 with fBoundsRect do //
64326 begin //
64327 Right := Left + 72; //
64328 end; //
64329 fStyle := WS_VISIBLE or WS_CHILD or //
64330 BS_AUTOCHECKBOX or WS_TABSTOP; //
64331 end; //
64333 //[constructor TControl.CreateRadiobox]
64334 constructor TControl.CreateRadiobox(AParent: PControl; //
64335 const ACaption: String); //
64336 begin //
64337 CreateCheckbox( AParent, ACaption ); //
64338 fStyle := WS_VISIBLE or WS_CHILD or //
64339 BS_RADIOBUTTON or WS_TABSTOP or WS_GROUP; //
64340 fControlClick := ClickRadio; //
64341 if AParent <> nil then //
64342 begin //
64343 AParent.fRadioLast := fMenu; //
64344 if AParent.fRadio1st = 0 then //
64345 begin //
64346 AParent.fRadio1st := fMenu; //
64347 SetRadioChecked; //
64348 end; //
64349 end; //
64350 end; //
64352 //[constructor TControl.CreateEditbox]
64353 constructor TControl.CreateEditbox(AParent: PControl; //
64354 AOptions: TEditOptions); //
64355 var Flags: Integer; //
64356 begin //
64357 Flags := MakeFlags( @AOptions, EditFlags ); //
64358 if not(eoMultiline in AOptions) then //
64359 Flags := Flags and not(WS_HSCROLL or WS_VSCROLL); //
64360 CreateControl( AParent, 'EDIT', WS_VISIBLE or WS_CHILD or WS_TABSTOP //
64361 or WS_BORDER or Flags, True, @EditActions ); //
64362 //YS fCursor := LoadCursor( 0, IDC_IBEAM ); // //YS
64363 with fBoundsRect do //
64364 begin //
64365 Right := Left + 100; //
64366 Bottom := Top + 22; //
64367 if eoMultiline in AOptions then //
64368 begin //
64369 Right := Right + 100; //
64370 Bottom := Top + 200; //
64371 end; //
64372 end; //
64373 fColor := clWindow; //
64374 fLookTabKeys := [ tkTab, tkUpDown, tkPageUpPageDn ]; //
64375 if eoMultiline in AOptions then //
64376 fLookTabKeys := [ tkTab ]; //
64377 if eoWantTab in AOptions then //
64378 fLookTabKeys := fLookTabKeys - [ tkTab ]; //
64379 end; //
64381 //[constructor TControl.CreatePanel]
64382 constructor TControl.CreatePanel(AParent: PControl; AStyle: TEdgeStyle); //
64383 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 ); //
64384 begin //
64385 CreateControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or //
64386 SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY, False, //
64387 @LabelActions ); //
64388 with fBoundsRect do //
64389 begin //
64390 Right := Left + 100; //
64391 Bottom := Top + 100; //
64392 end; //
64393 Style := Style or Edgestyles[ AStyle ]; //
64394 ExStyle := ExStyle or WS_EX_CONTROLPARENT; //
64395 end; //
64397 //[constructor TControl.CreateSplitter]
64398 constructor TControl.CreateSplitter(AParent: PControl; AMinSizePrev, //
64399 AMinSizeNext: Integer; EdgeStyle: TEdgeStyle); //
64400 var PrevCtrl: PControl; //
64401 Sz0: Integer; //
64402 begin //
64403 CreatePanel( AParent, EdgeStyle ); //
64404 fSplitMinSize1 := AMinSizePrev; //
64405 fSplitMinSize2 := AMinSizeNext; //
64406 Sz0 := 4; //
64407 with fBoundsRect do //
64408 begin //
64409 Right := Left + Sz0; //
64410 Bottom := Top + Sz0; //
64411 end; //
64412 if AParent <> nil then //
64413 begin //
64414 if AParent.fChildren.fCount > 1 then //
64415 begin //
64416 PrevCtrl := AParent.fChildren.fItems[ AParent.fChildren.fCount - 2 ]; //
64417 case PrevCtrl.FAlign of //
64418 caLeft, caRight: //
64419 begin //
64420 fCursor := LoadCursor( 0, IDC_SIZEWE ); //
64421 end; //
64422 caTop, caBottom: //
64423 begin //
64424 fCursor := LoadCursor( 0, IDC_SIZENS ); //
64425 end; //
64426 end; //
64427 Align := PrevCtrl.FAlign; //
64428 end; //
64429 end; //
64430 AttachProc( WndProcSplitter ); //
64431 end; //
64433 //[constructor TControl.CreateListbox]
64434 constructor TControl.CreateListbox(AParent: PControl; //
64435 AOptions: TListOptions); //
64436 var Flags: Integer; //
64437 begin //
64438 Flags := MakeFlags( @AOptions, ListFlags ); //
64439 CreateControl( AParent, 'LISTBOX', WS_VISIBLE or WS_CHILD or WS_TABSTOP //
64440 or WS_BORDER or WS_VSCROLL //
64441 or LBS_NOTIFY or Flags, True, @ListActions ); //
64442 with fBoundsRect do //
64443 begin //
64444 Right := Right + 100; //
64445 Bottom := Top + 200; //
64446 end; //
64447 fColor := clWindow; //
64448 fLookTabKeys := [ tkTab, tkLeftRight ]; //
64449 end; //
64451 //[constructor TControl.CreateCombobox]
64452 constructor TControl.CreateCombobox(AParent: PControl; //
64453 AOptions: TComboOptions); //
64454 var Flags: Integer; //
64455 begin //
64456 Flags := MakeFlags( @AOptions, ComboFlags ); //
64457 CreateControl( AParent, 'COMBOBOX', //
64458 WS_VISIBLE or WS_CHILD or WS_VSCROLL or //
64459 CBS_DROPDOWN or CBS_HASSTRINGS or WS_TABSTOP or Flags, //
64460 True, @ComboActions ); //
64461 fCreateWndExt := CreateComboboxWnd; //
64462 fDropDownProc := ComboboxDropDown; //
64463 fClsStyle := fClsStyle or CS_DBLCLKS; //
64464 with fBoundsRect do //
64465 begin //
64466 Right := Left + 100; //
64467 Bottom := Top + 22; //
64468 end; //
64469 fColor := clWindow; //
64470 fLookTabKeys := [ tkTab ]; //
64471 if coReadOnly in AOptions then //
64472 fLookTabKeys := [ tkTab, tkLeftRight ]; //
64473 end; //
64475 //[constructor TControl.CreateCommonControl]
64476 constructor TControl.CreateCommonControl(AParent: PControl; //
64477 AClassName: PChar; AStyle: DWORD; ACtl3D: Boolean; //
64478 Actions: PCommandActions); //
64479 begin //
64480 {*************} DoInitCommonControls( ICC_WIN95_CLASSES ); //
64481 CreateControl( AParent, AClassName, AStyle, ACtl3D, Actions ); //
64482 fIsCommonControl := True; //
64483 if AParent <> nil then //
64484 begin //
64485 AttachProc( WndProcParentResize ); //
64486 AParent.AttachProc( WndProcResize ); //
64487 AttachProc( WndProcCommonNotify ); //
64488 AParent.AttachProc( WndProcNotify ); //
64489 end; //
64490 end; //
64492 //[constructor TControl.CreateRichEdit1]
64493 constructor TControl.CreateRichEdit1(AParent: PControl; //
64494 AOptions: TEditOptions); //
64495 var Flags, I: Integer; //
64496 begin //
64497 if FRichEditModule = 0 then //
64498 begin //
64499 for I := 0 to 2 do //
64500 begin //
64501 FRichEditModule := LoadLibrary( RichEditLibnames[ I ] ); //
64502 if FRichEditModule > HINSTANCE_ERROR then break; //
64503 RichEditClass := 'RichEdit'; //
64504 end; //
64505 if FRichEditModule <= HINSTANCE_ERROR then //
64506 FRichEditModule := 0; //
64507 end; //
64508 Flags := MakeFlags( @AOptions, RichEditFlags ); //
64509 CreateCommonControl( AParent, RichEditClass, WS_VISIBLE or WS_CHILD //
64510 or WS_TABSTOP or WS_BORDER or ES_MULTILINE or Flags, //
64511 True, @RichEditActions ); //
64513 AttachProc( WndProcRichEditNotify ); //
64514 fDoubleBuffered := False; //
64515 fCannotDoubleBuf := True; //
64516 with fBoundsRect do //
64517 begin //
64518 Right := Right + 100; //
64519 Bottom := Top + 200; //
64520 end; //
64521 fColor := clWindow; //
64522 fLookTabKeys := [ tkTab ]; //
64523 if eoWantTab in AOptions then //
64524 fLookTabKeys := [ ]; //
64525 Perform( EM_SETEVENTMASK, 0, //
64526 ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or //
64527 ENM_PROTECTED or $04000000 {ENM_LINK} ); //
64528 Perform( EM_SETBKGNDCOLOR, 0, Color2RGB(fColor)); //
64529 end; //
64532 //[constructor TControl.CreateRichEdit]
64533 constructor TControl.CreateRichEdit(AParent: PControl; //
64534 AOptions: TEditOptions); //
64535 var OldRichEditClass, OldRichEditLib: PChar; //
64536 begin //
64537 if OleInit then //
64538 begin //
64539 OldRichEditClass := RichEditClass; //
64540 RichEditClass := 'RichEdit20A'; //
64541 OldRichEditLib := RichEditLib; //
64542 RichEditLib := 'RICHED20.DLL'; //
64543 CreateRichEdit1( AParent, AOptions ); //
64544 fCharFmtDeltaSz := 24; //
64545 // sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat ); //
64546 fParaFmtDeltaSz := sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat ); //
64547 RichEditClass := OldRichEditClass; //
64548 RichEditLib := OldRichEditLib; //
64549 end //
64550 else //
64551 CreateRichEdit1( AParent, AOptions ); //
64552 end; //
64554 //[constructor TControl.CreateProgressbar]
64555 constructor TControl.CreateProgressbar(AParent: PControl); //
64556 const ProgressBarFlags: array[ TProgressbarOption ] of Integer = //
64557 (PBS_VERTICAL, PBS_SMOOTH ); //
64558 begin //
64559 CreateCommonControl( AParent, PROGRESS_CLASS, //
64560 WS_CHILD or WS_VISIBLE, True, nil ); //
64561 with fBoundsRect do //
64562 begin //
64563 Right := Left + 300; //
64564 Bottom := Top + 20; //
64565 end; //
64566 fMenu := 0; //
64567 fTextColor := clHighlight; //
64568 end; //
64570 //[constructor TControl.CreateProgressbarEx]
64571 constructor TControl.CreateProgressbarEx(AParent: PControl; //
64572 AOptions: TProgressbarOptions); //
64573 const ProgressBarFlags: array[ TProgressbarOption ] of Integer = //
64574 (PBS_VERTICAL, PBS_SMOOTH ); //
64575 begin //
64576 CreateProgressbar( AParent ); //
64577 fStyle := fStyle or DWORD( MakeFlags( @AOptions, ProgressBarFlags ) ); //
64578 end; //
64580 //[constructor TControl.CreateListView]
64581 constructor TControl.CreateListView(AParent: PControl; //
64582 AStyle: TListViewStyle; AOptions: TListViewOptions; AImageListSmall, //
64583 AImageListNormal, AImageListState: PImageList); //
64584 begin //
64585 CreateCommonControl( AParent, WC_LISTVIEW, ListViewStyles[ AStyle ] or //
64586 LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP, //
64587 True, @ListViewActions ); //
64588 fLVOptions := AOptions; //
64589 fLVStyle := AStyle; //
64590 fCreateWndExt := ApplyImageLists2ListView; //
64591 with fBoundsRect do //
64592 begin //
64593 Right := Left + 200; //
64594 Bottom := Top + 150; //
64595 end; //
64596 ImageListSmall := AImageListSmall; //
64597 ImageListNormal := AImageListNormal; //
64598 ImageListState := AImageListState; //
64599 fLVTextBkColor := clWindow; //
64600 fLookTabKeys := [ tkTab ]; //
64601 end; //
64603 //[constructor TControl.CreateTreeView]
64604 constructor TControl.CreateTreeView(AParent: PControl; //
64605 AOptions: TTreeViewOptions; AImgListNormal, AImgListState: PImageList); //
64606 var Flags: Integer; //
64607 begin //
64608 Flags := MakeFlags( @AOptions, TreeViewFlags ); //
64609 CreateCommonControl( AParent, WC_TREEVIEW, Flags or WS_VISIBLE or //
64610 WS_CHILD or WS_TABSTOP, True, @TreeViewActions ); //
64611 fCreateWndExt := ApplyImageLists2Control; //
64612 fColor := clWindow; //
64613 AttachProc( WndProcTreeView ); //
64614 with fBoundsRect do //
64615 begin //
64616 Right := Left + 150; //
64617 Bottom := Top + 200; //
64618 end; //
64619 ImageListNormal := AImgListNormal; //
64620 ImageListState := AImgListState; //
64621 fLookTabKeys := [ tkTab ]; //
64622 end; //
64624 //[constructor TControl.CreateTabControl]
64625 constructor TControl.CreateTabControl(AParent: PControl; ATabs: array of String;//
64626 AOptions: TTabControlOptions; //
64627 AImgList: PImageList; AImgList1stIdx: Integer); //
64628 var I, II : Integer; //
64629 Flags: Integer; //
64630 begin //
64631 Flags := MakeFlags( @AOptions, TabControlFlags ); //
64632 if tcoFocusTabs in AOptions then //
64633 Flags := Flags or (WS_TABSTOP or TCS_FOCUSONBUTTONDOWN); //
64634 CreateCommonControl( AParent, WC_TABCONTROL, //
64635 Flags or (WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or //
64636 WS_VISIBLE), True, @TabControlActions ); //
64637 if not( tcoBorder in AOptions ) then //
64638 fExStyle := fExStyle and not WS_EX_CLIENTEDGE; //
64639 AttachProc( WndProcTabControl ); //
64640 with fBoundsRect do //
64641 begin //
64642 Right := Left + 100; //
64643 Bottom := Top + 100; //
64644 end; //
64645 if AImgList <> nil then //
64646 Perform( TCM_SETIMAGELIST, 0, AImgList.Handle ); //
64647 II := AImgList1stIdx; //
64648 for I := 0 to High( ATabs ) do //
64649 begin //
64650 TC_Insert( I, ATabs[ I ], II ); //
64651 Inc( II ); //
64652 end; //
64653 fLookTabKeys := [ tkTab ]; //
64654 end; //
64656 //[constructor TControl.CreateToolbar]
64657 constructor TControl.CreateToolbar(AParent: PControl; //
64658 AAlign: TControlAlign; AOptions: TToolbarOptions; ABitmap: HBitmap; //
64659 AButtons: array of PChar; ABtnImgIdxArray: array of Integer); //
64660 var Flags: DWORD; //
64661 begin //
64662 if not( tboTextBottom in AOptions ) then //
64663 AOptions := AOptions + [ tboTextRight ]; //
64664 if tboTextRight in AOptions then //
64665 AOptions := AOptions - [ tboTextBottom ]; //
64666 Flags := MakeFlags( @AOptions, ToolbarOptions ); //
64667 CreateCommonControl( AParent, TOOLBARCLASSNAME, ToolbarAligns[ Align ] or //
64668 WS_CHILD or WS_VISIBLE {or WS_TABSTOP} //
64669 or TBSTYLE_TOOLTIPS or Flags, //
64670 (not (Align in [caNone])) and //
64671 not (tboNoDivider in AOptions), nil ); //
64672 fCommandActions.aClear := ClearToolbar; //
64673 fCommandActions.aGetCount := TB_BUTTONCOUNT; //
64674 with fBoundsRect do //
64675 begin //
64676 if AAlign in [ caNone ] then //
64677 begin //
64678 Bottom := Top + 26; //
64679 Right := Left + 1000; //
64680 end //
64681 else //
64682 begin //
64683 Left := 0; Right := 0; //
64684 Top := 0; Bottom := 0; //
64685 end; //
64686 end; //
64687 Perform(TB_SETEXTENDEDSTYLE, 0, Perform(TB_GETEXTENDEDSTYLE, 0, 0) or //
64688 TBSTYLE_EX_DRAWDDARROWS); //
64690 AttachProc( WndProcToolbarCtrl ); //
64691 Perform( TB_BUTTONSTRUCTSIZE, Sizeof( TTBButton ), 0 ); //
64692 Perform( TB_SETINDENT, fMargin, 0 ); //
64693 with fBoundsRect do //
64694 begin //
64695 if AAlign in [ caLeft, caRight ] then //
64696 Right := Left + 24 //
64697 else if not (AAlign in [caNone]) then //
64698 Bottom := Top + 22; //
64699 end; //
64700 if ABitmap <> 0 then //
64701 TBAddBitmap( ABitmap ); //
64702 TBAddButtons( AButtons, ABtnImgIdxArray ); //
64703 Perform( WM_SIZE, 0, 0 ); //
64704 end; //
64706 //[constructor TImageList.CreateImageList]
64707 constructor TImageList.CreateImageList(POwner: Pointer); //
64708 var AOwner: PControl; //
64709 begin //
64710 {*************} DoInitCommonControls( ICC_WIN95_CLASSES ); //
64711 Create; //
64712 FAllocBy := 1; //
64713 FMasked := True; //
64714 if POwner = nil then exit; //
64715 FBkColor := TColor( CLR_NONE );
64716 //ImageList_SetBkColor( FHandle, CLR_NONE );
64718 AOwner := POwner; //
64719 FControl := AOwner; //
64720 fNext := PImageList( AOwner.fImageList ); //
64721 if AOwner.fImageList <> nil then //
64722 PImageList( AOwner.fImageList ).fPrev := @Self; //
64723 AOwner.fImageList := @Self; //
64724 end; //
64726 //[constructor TThread.ThreadCreate]
64727 constructor TThread.ThreadCreate; //
64728 begin //
64729 IsMultiThread := True; //
64730 Create; //
64731 FSuspended := True; //
64732 FHandle := CreateThread( nil, // no security //
64733 0, // the same stack size //
64734 @ThreadFunc, // thread entry point //
64735 @Self, // parameter to pass to ThreadFunc //
64736 CREATE_SUSPENDED, // always SUSPENDED //
64737 FThreadID ); // receive thread ID //
64738 end; //
64740 //[constructor TThread.ThreadCreateEx]
64741 constructor TThread.ThreadCreateEx( const Proc: TOnThreadExecute ); //
64742 begin //
64743 ThreadCreate; //
64744 OnExecute := Proc; //
64745 Resume; //
64746 end; //
64748 {$ENDIF USE_CONSTRUCTORS} //****************************************************//
64751 { TCABFile }
64753 //[function OpenCABFile]
64754 function OpenCABFile( const APaths: array of String ): PCABFile;
64755 var I: Integer;
64756 begin
64758 New( Result, Create );
64759 {+}{++}(*Result := PCABFile.Create;*){--}
64760 Result.FSetupapi := LoadLibrary( 'setupapi.dll' );
64761 Result.FNames := NewStrList;
64762 Result.FPaths := NewStrList;
64763 for I := 0 to High( APaths ) do
64764 Result.FPaths.Add( APaths[ I ] );
64765 end;
64767 //[destructor TCABFile.Destroy]
64768 destructor TCABFile.Destroy;
64769 begin
64770 FNames.Free;
64771 FPaths.Free;
64772 FTargetPath := '';
64773 if FSetupapi <> 0 then
64774 FreeLibrary( FSetupapi );
64775 inherited;
64776 end;
64778 const
64779 SPFILENOTIFY_FILEINCABINET = $11;
64780 SPFILENOTIFY_NEEDNEWCABINET = $12;
64782 type
64783 PSP_FILE_CALLBACK = function( Context: Pointer; Notification, Param1, Param2: DWORD ): DWORD;
64784 stdcall;
64786 TSetupIterateCabinet = function ( CabinetFile: PChar; Reserved: DWORD;
64787 MsgHandler: PSP_FILE_CALLBACK; Context: Pointer ): Boolean; stdcall;
64788 //external 'setupapi.dll' name 'SetupIterateCabinetA';
64790 TSetupPromptDisk = function (
64791 hwndParent: HWND; // parent window of the dialog box
64792 DialogTitle: PChar; // optional, title of the dialog box
64793 DiskName: PChar; // optional, name of disk to insert
64794 PathToSource: PChar;// optional, expected source path
64795 FileSought: PChar; // name of file needed
64796 TagFile: PChar; // optional, source media tag file
64797 DiskPromptStyle: DWORD; // specifies dialog box behavior
64798 PathBuffer: PChar; // receives the source location
64799 PathBufferSize: DWORD; // size of the supplied buffer
64800 PathRequiredSize: PDWORD // optional, buffer size needed
64801 ): DWORD; stdcall;
64802 //external 'setupapi.dll' name 'SetupPromptForDiskA';
64804 type
64805 TCabinetInfo = packed record
64806 CabinetPath: PChar;
64807 CabinetFile: PChar;
64808 DiskName: PChar;
64809 SetId: WORD;
64810 CabinetNumber: WORD;
64811 end;
64812 PCabinetInfo = ^TCabinetInfo;
64814 TFileInCabinetInfo = packed record
64815 NameInCabinet: PChar;
64816 FileSize: DWORD;
64817 Win32Error: DWORD;
64818 DosDate: WORD;
64819 DosTime: WORD;
64820 DosAttribs: WORD;
64821 FullTargetName: array[0..MAX_PATH-1] of Char;
64822 end;
64823 PFileInCabinetInfo = ^TFileInCabinetInfo;
64825 //[function CABCallback]
64826 function CABCallback( Context: Pointer; Notification, Param1, Param2: DWORD ): DWORD;
64827 stdcall;
64828 var CAB: PCABFile;
64829 CABPath, OldPath: String;
64830 CABInfo: PCabinetInfo;
64831 CABFileInfo: PFileInCabinetInfo;
64832 hr: Integer;
64833 SetupPromptProc: TSetupPromptDisk;
64834 begin
64835 Result := 0;
64836 CAB := Context;
64837 case Notification of
64838 SPFILENOTIFY_NEEDNEWCABINET:
64839 begin
64840 OldPath := CAB.FPaths.Items[ CAB.FCurCAB ];
64841 Inc( CAB.FCurCAB );
64842 if CAB.FCurCAB = CAB.FPaths.Count then
64843 CAB.FPaths.Add( '?' );
64844 CABPath := CAB.FPaths.Items[ CAB.FCurCAB ];
64845 if CABPath = '?' then
64846 begin
64847 if Assigned( CAB.FOnNextCAB ) then
64848 CAB.FPaths.Items[CAB.FCurCAB ] := CAB.FOnNextCAB( CAB );
64849 CABPath := CAB.FPaths.Items[ CAB.FCurCAB ];
64850 if CABPath = '?' then
64851 begin
64852 SetLength( CABPath, MAX_PATH );
64853 CABInfo := Pointer( Param1 );
64854 if CAB.FSetupapi <> 0 then
64855 SetupPromptProc := GetProcAddress( CAB.FSetupapi, 'SetupPromptForDiskA' )
64856 else
64857 SetupPromptProc := nil;
64858 if Assigned( SetupPromptProc ) then
64859 begin
64860 hr := SetupPromptProc( 0, nil, nil, PChar( ExtractFilePath( OldPath ) ),
64861 CABInfo.CabinetFile, nil, 2 {IDF_NOSKIP}, @CabPath[ 1 ], MAX_PATH, nil );
64862 case hr of
64863 0: // success
64864 begin
64865 StrCopy( PChar( Param2 ), PChar( CABPath ) );
64866 Result := 0;
64867 end;
64868 2: // skip file
64869 Result := 0;
64870 else // cancel
64871 Result := ERROR_FILE_NOT_FOUND;
64872 end;
64873 end;
64875 else
64876 begin
64877 StrCopy( PChar( Param2 ), PChar( CABPath ) );
64878 Result := 0;
64879 end;
64880 end;
64881 end;
64882 SPFILENOTIFY_FILEINCABINET:
64883 begin
64884 CABFileInfo := Pointer( Param1 );
64885 if CAB.FGettingNames then
64886 begin
64887 CAB.FNames.Add( CABFileInfo.NameInCabinet );
64888 Result := 2; // FILEOP_SKIP
64890 else
64891 begin
64892 CABPath := CABFileInfo.NameInCabinet;
64893 if Assigned( CAB.FOnFile ) then
64894 begin
64895 if CAB.FOnFile( CAB, CABPath ) then
64896 begin
64897 if ExtractFilePath( CABPath ) = '' then
64898 if CAB.FTargetPath <> '' then
64899 CABPath := CAB.TargetPath + CABPath;
64900 StrCopy( @CABFileInfo.FullTargetName[ 0 ], PChar( CABPath ) );
64901 Result := 1; // FILEOP_DOIT
64903 else
64904 Result := 2
64906 else
64907 begin
64908 if CAB.FTargetPath <> '' then
64909 StrCopy( @CABFileInfo.FullTargetName[ 0 ], PChar( CAB.TargetPath + CABPath ) );
64910 Result := 1;
64911 end;
64912 end;
64913 end;
64914 end;
64915 end;
64917 //[function TCABFile.Execute]
64918 function TCABFile.Execute: Boolean;
64919 var SetupIterateProc: TSetupIterateCabinet;
64920 begin
64921 FCurCAB := 0;
64922 Result := FALSE;
64923 if FSetupapi = 0 then Exit;
64924 SetupIterateProc := GetProcAddress( FSetupapi, 'SetupIterateCabinetA' );
64925 if not Assigned( SetupIterateProc ) then Exit;
64926 Result := SetupIterateProc( PChar( FPaths.Items[ 0 ] ), 0, CABCallback, @Self );
64927 end;
64929 //[function TCABFile.GetCount]
64930 function TCABFile.GetCount: Integer;
64931 begin
64932 GetNames( 0 );
64933 Result := FNames.Count;
64934 end;
64936 //[function TCABFile.GetNames]
64937 function TCABFile.GetNames(Idx: Integer): String;
64938 begin
64939 if FNames.Count = 0 then
64940 begin
64941 FGettingNames := TRUE;
64942 Execute;
64943 FGettingNames := FALSE;
64944 end;
64945 Result := '';
64946 if Idx < FNames.Count then
64947 Result := FNames.Items[ Idx ];
64948 end;
64950 //[function TCABFile.GetPaths]
64951 function TCABFile.GetPaths(Idx: Integer): String;
64952 begin
64953 Result := FPaths.Items[ Idx ];
64954 end;
64956 //[function TCABFile.GetTargetPath]
64957 function TCABFile.GetTargetPath: String;
64958 begin
64959 Result := FTargetPath;
64960 if Result <> '' then
64961 if Result[ Length( Result ) ] <> '\' then
64962 Result := Result + '\';
64963 end;
64965 //[procedure InvalidateExW]
64966 procedure InvalidateExW( Wnd: HWnd );
64967 begin
64968 InvalidateRect( Wnd, nil, TRUE );
64969 Wnd := GetWindow( Wnd, GW_CHILD );
64970 while Wnd <> 0 do
64971 begin
64972 InvalidateExW( Wnd );
64973 Wnd := GetWindow( Wnd, GW_HWNDNEXT );
64974 end;
64975 end;
64977 //[procedure TControl.InvalidateEx]
64978 procedure TControl.InvalidateEx;
64979 begin
64980 if fHandle = 0 then Exit;
64981 InvalidateExW( fHandle );
64982 end;
64984 //[procedure InvalidateNCW]
64985 procedure InvalidateNCW( Wnd: HWnd; Recursive: Boolean );
64986 begin
64987 SendMessage( Wnd, WM_NCPAINT, 1, 0 );
64988 if not Recursive then Exit;
64989 Wnd := GetWindow( Wnd, GW_CHILD );
64990 while Wnd <> 0 do
64991 begin
64992 InvalidateNCW( Wnd, Recursive );
64993 Wnd := GetWindow( Wnd, GW_HWNDNEXT );
64994 end;
64995 end;
64997 //[procedure TControl.InvalidateNC]
64998 procedure TControl.InvalidateNC(Recursive: Boolean);
64999 begin
65000 if fHandle = 0 then Exit;
65001 InvalidateNCW( fHandle, Recursive );
65002 end;
65004 //[procedure TControl.SetClientMargin]
65005 procedure TControl.SetClientMargin(const Index, Value: Integer);
65006 begin
65007 case Index of
65008 1: fClientTop := Value;
65009 2: fClientBottom := Value;
65010 3: fClientLeft := Value;
65011 4: fClientRight := Value;
65012 end;
65013 Global_Align( @Self );
65014 end;
65016 {$IFDEF F_P}
65017 //[function TControl.GetClientMargin]
65018 function TControl.GetClientMargin(const Index: Integer): Integer;
65019 begin
65020 CASE Index OF
65021 1: Result := fClientTop;
65022 2: Result := fClientBottom;
65023 3: Result := fClientLeft;
65024 4: Result := fClientRight;
65025 END;
65026 end;
65027 {$ENDIF F_P}
65029 { TBits }
65031 //[function NewBits]
65032 function NewBits: PBits;
65033 begin
65035 new( Result, Create );
65036 {+}{++}(*Result := PBits.Create;*){--}
65037 Result.fList := NewList;
65038 //Result.fList.fAddBy := 1;
65039 end;
65041 //[procedure TBits.AssignBits]
65042 procedure TBits.AssignBits(ToIdx: Integer; FromBits: PBits; FromIdx,
65043 N: Integer);
65044 var i: Integer;
65045 NewCount: Integer;
65046 begin
65047 if FromIdx >= FromBits.Count then Exit;
65048 if FromIdx + N > FromBits.Count then
65049 N := FromBits.Count - FromIdx;
65050 Capacity := (ToIdx + N + 8) div 8;
65051 NewCount := Max( Count, ToIdx + N - 1 );
65052 fCount := Max( NewCount, fCount );
65053 fList.fCount := (Capacity + 3) div 4;
65054 while ToIdx and $1F <> 0 do
65055 begin
65056 Bits[ ToIdx ] := FromBits.Bits[ FromIdx ];
65057 Inc( ToIdx );
65058 Inc( FromIdx );
65059 Dec( N );
65060 if N = 0 then Exit;
65061 end;
65062 Move( PByte( Integer( FromBits.fList.fItems ) + (FromIdx + 31) div 32 )^,
65063 PByte( Integer( fList.fItems ) + ToIdx div 32 )^, (N + 31) div 32 );
65064 FromIdx := FromIdx and $1F;
65065 if FromIdx <> 0 then
65066 begin // shift data by (Idx and $1F) bits right
65067 for i := ToIdx div 32 to fList.Count-2 do
65068 fList.Items[ i ] := Pointer(
65069 (DWORD( fList.Items[ i ] ) shr FromIdx) or
65070 (DWORD( fList.Items[ i+1 ] ) shl (32 - FromIdx))
65072 fList.Items[ fList.Count-1 ] := Pointer(
65073 DWORD( fList.Items[ fList.Count-1 ] ) shr FromIdx
65075 end;
65076 end;
65078 //[function TBits.Copy]
65079 procedure TBits.Clear;
65080 begin
65081 fList.Clear;
65082 end;
65084 function TBits.Copy(From, BitsCount: Integer): PBits;
65085 var Shift, N: Integer;
65086 FirstItemPtr: Pointer;
65087 begin
65088 Result := NewBits;
65089 if BitsCount = 0 then Exit;
65090 Result.Capacity := BitsCount + 32;
65091 Result.fCount := BitsCount;
65092 Move( fList.fItems[ From shr 5 ], Result.fList.fItems[ 0 ], (Count + 31) div 32 );
65093 Shift := From and $1F;
65094 if Shift <> 1 then
65095 begin
65096 N := (BitsCount + 31) div 32;
65097 FirstItemPtr := @ Result.fList.fItems[ N - 1 ];
65099 PUSH ESI
65100 PUSH EDI
65101 MOV ESI, FirstItemPtr
65102 MOV EDI, ESI
65104 MOV ECX, N
65105 XOR EAX, EAX
65107 @@1:
65108 PUSH ECX
65109 LODSD
65110 MOV ECX, Shift
65111 SHRD EAX, EDX, CL
65112 STOSD
65113 SUB ECX, 32
65114 NEG ECX
65115 SHR EDX, CL
65116 POP ECX
65118 LOOP @@1
65121 POP EDI
65122 POP ESI
65123 end {$IFDEF F_P} ['EAX','EDX','ECX'] {$ENDIF};
65124 end;
65125 end;
65127 //[destructor TBits.Destroy]
65128 destructor TBits.Destroy;
65129 begin
65130 fList.Free;
65131 inherited;
65132 end;
65134 //[function TBits.GetBit]
65135 function TBits.GetBit(Idx: Integer): Boolean;
65136 begin
65137 if Idx >= Count then Result := FALSE else
65138 Result := ( ( DWORD( fList.fItems[ Idx shr 5 ] ) shr (Idx and $1F)) and 1 ) <> 0;
65139 end;
65141 //[function TBits.GetCapacity]
65142 function TBits.GetCapacity: Integer;
65143 begin
65144 Result := fList.Capacity * 32;
65145 end;
65147 //[function TBits.GetSize]
65148 function TBits.GetSize: Integer;
65149 begin
65150 Result := (fList.fCount + 3) div 4;
65151 end;
65153 {$IFDEF ASM_noVERSION}
65154 //[function TBits.IndexOf]
65155 function TBits.IndexOf(Value: Boolean): Integer;
65156 asm //cmd //opd
65157 PUSH EDI
65158 MOV EDI, [EAX].fList
65159 MOV ECX, [EDI].TList.fCount
65160 @@ret_1:
65161 OR EAX, -1
65162 JECXZ @@ret_EAX
65163 MOV EDI, [EDI].TList.fItems
65164 TEST DL, DL
65165 MOV EDX, EDI
65166 JE @@of_false
65167 INC EAX
65168 REPZ SCASD
65169 JE @@ret_1
65170 MOV EAX, [EDI-4]
65171 NOT EAX
65172 JMP @@calc_offset
65173 BSF EAX, EAX
65174 SUB EDI, EDX
65175 SHR EDI, 2
65176 ADD EAX, EDI
65177 JMP @@ret_EAX
65178 @@of_false:
65179 REPE SCASD
65180 JE @@ret_1
65181 MOV EAX, [EDI-4]
65182 @@calc_offset:
65183 BSF EAX, EAX
65184 DEC EAX
65185 SUB EDI, 4
65186 SUB EDI, EDX
65187 SHL EDI, 3
65188 ADD EAX, EDI
65189 @@ret_EAX:
65190 POP EDI
65191 end;
65192 {$ELSE ASM_VERSION} //Pascal
65193 function TBits.IndexOf(Value: Boolean): Integer;
65194 var I: Integer;
65195 D: DWORD;
65196 begin
65197 Result := -1;
65198 if Value then
65199 begin
65200 for I := 0 to fList.Count-1 do
65201 begin
65202 D := DWORD( fList.fItems[ I ] );
65203 if D <> 0 then
65204 begin
65206 MOV EAX, D
65207 BSF EAX, EAX
65208 MOV D, EAX
65209 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};
65210 Result := I * 32 + Integer( D );
65211 break;
65212 end;
65213 end;
65215 else
65216 begin
65217 for I := 0 to fList.fCount-1 do
65218 begin
65219 D := DWORD( fList.fItems[ I ] );
65220 if D <> $FFFFFFFF then
65221 begin
65223 MOV EAX, D
65224 NOT EAX
65225 BSF EAX, EAX
65226 MOV D, EAX
65227 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};
65228 Result := I * 32 + Integer( D );
65229 break;
65230 end;
65231 end;
65232 end;
65233 end;
65234 {$ENDIF ASM_VERSION}
65236 //[function TBits.LoadFromStream]
65237 function TBits.LoadFromStream(strm: PStream): Integer;
65239 i: Integer;
65240 begin
65241 Result := strm.Read( i, 4 );
65242 if Result < 4 then Exit;
65244 bits[ i]:= false; //by miek
65245 fcount:= i;
65247 i := (i + 7) div 8;
65248 Inc( Result, strm.Read( fList.fItems^, i ) );
65249 end;
65251 //[function TBits.OpenBit]
65252 function TBits.OpenBit: Integer;
65253 begin
65254 Result := IndexOf( FALSE );
65255 if Result < 0 then Result := Count;
65256 end;
65258 //[function TBits.Range]
65259 function TBits.Range(Idx, N: Integer): PBits;
65260 begin
65261 Result := NewBits;
65262 Result.AssignBits( 0, @ Self, Idx, N );
65263 end;
65265 //[function TBits.SaveToStream]
65266 function TBits.SaveToStream(strm: PStream): Integer;
65267 begin
65268 Result := strm.Write( fCount, 4 );
65269 if fCount = 0 then Exit;
65270 Inc( Result, strm.Write( fList.fItems^, (fCount + 7) div 8 ) );
65271 end;
65273 //[procedure TBits.SetBit]
65274 procedure TBits.SetBit(Idx: Integer; const Value: Boolean);
65275 var Msk: DWORD;
65276 begin
65277 if Idx >= Capacity then
65278 Capacity := Idx + 1;
65279 Msk := 1 shl (Idx and $1F);
65280 if Value then
65281 fList.fItems[ Idx shr 5 ] := Pointer(
65282 DWORD(fList.fItems[ Idx shr 5 ]) or Msk)
65283 else
65284 fList.fItems[ Idx shr 5 ] := Pointer(
65285 DWORD(fList.fItems[ Idx shr 5 ]) and not Msk);
65286 if Idx >= fCount then
65287 fCount := Idx + 1;
65288 end;
65290 //[procedure TBits.SetCapacity]
65291 procedure TBits.SetCapacity(const Value: Integer);
65292 var OldCap: Integer;
65293 begin
65294 OldCap := fList.Capacity;
65295 fList.Capacity := (Value + 31) div 32;
65296 if OldCap < fList.Capacity then
65297 FillChar( PChar( Integer( fList.fItems ) + OldCap * Sizeof( Pointer ) )^,
65298 (fList.Capacity - OldCap) * sizeof( Pointer ), 0 );
65299 end;
65301 { ----------------------------------------------------------------------
65303 TAction and TActionList
65305 ----------------------------------------------------------------------- }
65306 //[function NewActionList]
65307 function NewActionList(AOwner: PControl): PActionList;
65308 begin
65310 New( Result, Create );
65311 {+} {++}(* Result := PActionList.Create; *){--}
65312 with Result{-}^{+} do begin
65313 FActions:=NewList;
65314 FOwner:=AOwner;
65315 RegisterIdleHandler(DoUpdateActions);
65316 end;
65317 end;
65318 //[END NewActionList]
65320 //[function NewAction]
65321 function NewAction(const ACaption, AHint: string; AOnExecute: TOnEvent): PAction;
65322 begin
65324 New( Result, Create );
65325 {+} {++}(* Result := PAction.Create; *){--}
65326 with Result{-}^{+} do begin
65327 FControls:=NewList;
65328 Enabled:=True;
65329 Visible:=True;
65330 Caption:=ACaption;
65331 Hint:=AHint;
65332 OnExecute:=AOnExecute;
65333 end;
65334 end;
65335 //[END NewAction]
65337 { TAction }
65339 //[procedure TAction.LinkCtrl]
65340 procedure TAction.LinkCtrl(ACtrl: PObj; ACtrlKind: TCtrlKind; AItemID: integer; AUpdateProc: TOnUpdateCtrlEvent);
65342 cr: PControlRec;
65343 begin
65344 New(cr);
65345 with cr^ do begin
65346 Ctrl:=ACtrl;
65347 CtrlKind:=ACtrlKind;
65348 ItemID:=AItemID;
65349 UpdateProc:=AUpdateProc;
65350 end;
65351 FControls.Add(cr);
65352 AUpdateProc(cr);
65353 end;
65355 //[procedure TAction.LinkControl]
65356 procedure TAction.LinkControl(Ctrl: PControl);
65357 begin
65358 LinkCtrl(Ctrl, ckControl, 0, UpdateCtrl);
65359 Ctrl.OnClick:=DoOnControlClick;
65360 end;
65362 //[procedure TAction.LinkMenuItem]
65363 procedure TAction.LinkMenuItem(Menu: PMenu; MenuItemIdx: integer);
65364 {$IFDEF _FPC}
65366 arr1_DoOnMenuItem: array[ 0..0 ] of TOnMenuItem;
65367 {$ENDIF _FPC}
65368 begin
65369 LinkCtrl(Menu, ckMenu, MenuItemIdx, UpdateMenu);
65370 {$IFDEF _FPC}
65371 arr1_DoOnMenuItem[ 0 ] := DoOnMenuItem;
65372 Menu.AssignEvents(MenuItemIdx, arr1_DoOnMenuItem);
65373 {$ELSE}
65374 Menu.AssignEvents(MenuItemIdx, [ DoOnMenuItem ]);
65375 {$ENDIF}
65376 end;
65378 //[procedure TAction.LinkToolbarButton]
65379 procedure TAction.LinkToolbarButton(Toolbar: PControl; ButtonIdx: integer);
65380 {$IFDEF _FPC}
65382 arr1_DoOnToolbarButtonClick: array[ 0..0 ] of TOnToolbarButtonClick;
65383 {$ENDIF _FPC}
65384 begin
65385 LinkCtrl(Toolbar, ckToolbar, ButtonIdx, UpdateToolbar);
65386 {$IFDEF _FPC}
65387 arr1_DoOnToolbarButtonClick[ 0 ] := DoOnToolbarButtonClick;
65388 Toolbar.TBAssignEvents(ButtonIdx, arr1_DoOnToolbarButtonClick);
65389 {$ELSE}
65390 Toolbar.TBAssignEvents(ButtonIdx, [DoOnToolbarButtonClick]);
65391 {$ENDIF}
65392 end;
65394 //[destructor TAction.Destroy]
65395 destructor TAction.Destroy;
65396 begin
65397 FControls.Release;
65398 FCaption:='';
65399 FShortCut:='';
65400 FHint:='';
65401 inherited;
65402 end;
65404 //[procedure TAction.DoOnControlClick]
65405 procedure TAction.DoOnControlClick(Sender: PObj);
65406 begin
65407 Execute;
65408 end;
65410 //[procedure TAction.DoOnMenuItem]
65411 procedure TAction.DoOnMenuItem(Sender: PMenu; Item: Integer);
65412 begin
65413 Execute;
65414 end;
65416 //[procedure TAction.DoOnToolbarButtonClick]
65417 procedure TAction.DoOnToolbarButtonClick(Sender: PControl; BtnID: Integer);
65418 begin
65419 Execute;
65420 end;
65422 //[procedure TAction.Execute]
65423 procedure TAction.Execute;
65424 begin
65425 if Assigned(FOnExecute) and FEnabled then
65426 FOnExecute(PObj( @Self ));
65427 end;
65429 //[procedure TAction.SetCaption]
65430 procedure TAction.SetCaption(const Value: string);
65432 i: integer;
65433 c, ss: string;
65435 begin
65436 i:=Pos(#9, Value);
65437 if i <> 0 then begin
65438 c:=Copy(Value, 1, i - 1);
65439 ss:=Copy(Value, i + 1, MaxInt);
65441 else begin
65442 c:=Value;
65443 ss:='';
65444 end;
65445 if (FCaption = c) and (FShortCut = ss) then exit;
65446 FCaption:=c;
65447 FShortCut:=ss;
65448 UpdateControls;
65449 end;
65451 //[procedure TAction.SetChecked]
65452 procedure TAction.SetChecked(const Value: boolean);
65453 begin
65454 if FChecked = Value then exit;
65455 FChecked := Value;
65456 UpdateControls;
65457 end;
65459 //[procedure TAction.SetEnabled]
65460 procedure TAction.SetEnabled(const Value: boolean);
65461 begin
65462 if FEnabled = Value then exit;
65463 FEnabled := Value;
65464 UpdateControls;
65465 end;
65467 //[procedure TAction.SetHelpContext]
65468 procedure TAction.SetHelpContext(const Value: integer);
65469 begin
65470 if FHelpContext = Value then exit;
65471 FHelpContext := Value;
65472 UpdateControls;
65473 end;
65475 //[procedure TAction.SetHint]
65476 procedure TAction.SetHint(const Value: string);
65477 begin
65478 if FHint = Value then exit;
65479 FHint := Value;
65480 UpdateControls;
65481 end;
65483 //[procedure TAction.SetOnExecute]
65484 procedure TAction.SetOnExecute(const Value: TOnEvent);
65485 begin
65486 if @FOnExecute = @Value then exit;
65487 FOnExecute:=Value;
65488 UpdateControls;
65489 end;
65491 //[procedure TAction.SetVisible]
65492 procedure TAction.SetVisible(const Value: boolean);
65493 begin
65494 if FVisible = Value then exit;
65495 FVisible := Value;
65496 UpdateControls;
65497 end;
65499 //[procedure TAction.UpdateControls]
65500 procedure TAction.UpdateControls;
65502 i: integer;
65503 begin
65504 with FControls{-}^{+} do
65505 for i:=0 to Count - 1 do
65506 PControlRec(Items[i]).UpdateProc(Items[i]);
65507 end;
65509 //[procedure TAction.UpdateCtrl]
65510 procedure TAction.UpdateCtrl(Sender: PControlRec);
65511 begin
65512 with Sender^, PControl(Ctrl){-}^{+} do begin
65513 if Caption <> Self.FCaption then
65514 Caption:=Self.FCaption;
65515 if Enabled <> Self.FEnabled then
65516 Enabled:=Self.FEnabled;
65517 if Checked <> Self.FChecked then
65518 Checked:=Self.FChecked;
65519 if Visible <> Self.FVisible then
65520 Visible:=Self.FVisible;
65521 end;
65522 end;
65524 //[procedure TAction.UpdateMenu]
65525 procedure TAction.UpdateMenu(Sender: PControlRec);
65527 s: string;
65528 begin
65529 with Sender^, PMenu(Ctrl).Items[ItemID]{-}^{+} do begin
65530 s:=Self.FCaption;
65531 if Self.FShortCut <> '' then
65532 s:=s + #9 + Self.FShortCut;
65533 if Caption <> s then
65534 Caption:=s;
65535 if Enabled <> Self.FEnabled then
65536 Enabled:=Self.FEnabled;
65537 if Checked <> Self.FChecked then
65538 Checked:=Self.FChecked;
65539 if Visible <> Self.FVisible then
65540 Visible:=Self.FVisible;
65541 if HelpContext <> Self.FHelpContext then
65542 HelpContext:=Self.FHelpContext;
65543 if Self.FAccelerator.Key <> 0 then {YS} // Äîáàâèòü
65544 Accelerator:=Self.FAccelerator;
65545 end;
65546 end;
65548 //[procedure TAction.UpdateToolbar]
65549 procedure TAction.UpdateToolbar(Sender: PControlRec);
65551 i: integer;
65552 s: string;
65553 begin
65554 with Sender^, PControl(Ctrl){-}^{+} do begin
65555 i:=TBIndex2Item(ItemID);
65556 s:=TBButtonText[i];
65557 if (s <> '') and (s <> Self.FCaption) then
65558 TBButtonText[i]:=Self.FCaption;
65559 TBSetTooltips(i, [PChar(Self.FHint)]);
65560 if TBButtonEnabled[ItemID] <> Self.FEnabled then
65561 TBButtonEnabled[ItemID]:=Self.FEnabled;
65562 if TBButtonVisible[ItemID] <> Self.FVisible then
65563 TBButtonVisible[ItemID]:=Self.FVisible;
65564 if TBButtonChecked[ItemID] <> Self.FChecked then
65565 TBButtonChecked[ItemID]:=Self.FChecked;
65566 end;
65567 end;
65569 //[procedure TAction.SetAccelerator]
65570 procedure TAction.SetAccelerator(const Value: TMenuAccelerator);
65571 begin
65572 if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then exit;
65573 FAccelerator := Value;
65574 FShortCut:=GetAcceleratorText(FAccelerator); // {YS}
65575 UpdateControls;
65576 end;
65578 { TActionList }
65580 //[function TActionList.Add]
65581 function TActionList.Add(const ACaption, AHint: string; OnExecute: TOnEvent): PAction;
65582 begin
65583 Result:=NewAction(ACaption, AHint, OnExecute);
65584 FActions.Add(Result);
65585 end;
65587 //[procedure TActionList.Clear]
65588 procedure TActionList.Clear;
65589 begin
65590 while FActions.Count > 0 do
65591 Delete(0);
65592 FActions.Clear;
65593 end;
65595 //[procedure TActionList.Delete]
65596 procedure TActionList.Delete(Idx: integer);
65597 begin
65598 Actions[Idx].Free;
65599 FActions.Delete(Idx);
65600 end;
65602 //[destructor TActionList.Destroy]
65603 destructor TActionList.Destroy;
65604 begin
65605 UnRegisterIdleHandler(DoUpdateActions);
65606 Clear;
65607 FActions.Free;
65608 inherited;
65609 end;
65611 //[procedure TActionList.DoUpdateActions]
65612 procedure TActionList.DoUpdateActions(Sender: PObj);
65613 begin
65614 if Assigned(FOnUpdateActions) and (GetActiveWindow = FOwner.Handle) then
65615 FOnUpdateActions(PObj( @Self ));
65616 end;
65618 //[function TActionList.GetActions]
65619 function TActionList.GetActions(Idx: integer): PAction;
65620 begin
65621 Result:=FActions.Items[Idx];
65622 end;
65624 //[function TActionList.GetCount]
65625 function TActionList.GetCount: integer;
65626 begin
65627 Result:=FActions.Count;
65628 end;
65630 {$IFDEF USE_CUSTOMEXTENSIONS}
65631 {$I CUSTOM_CODE_EXTENSION.inc} // See comments in TControl
65632 {$ENDIF USE_CUSTOMEXTENSIONS}
65634 //[initialization]
65635 initialization
65636 //[finalization]
65637 finalization
65638 {$IFDEF UNLOAD_RICHEDITLIB}
65639 if FRichEditModule <> 0 then
65640 FreeLibrary( FRichEditModule );
65641 {$ENDIF UNLOAD_RICHEDITLIB}
65643 //[END OF KOL.pas]
65644 end.