initial commit
[rofl0r-KOL.git] / KO208L.pas
blob00fa61d2441b752956d3f011faecf0df874679e3
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.08
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_NAMES - to use property Name with any TObj. This makes also
127 available global function FindObj( name ): PObj.
128 (USE_CONSTRUCTORS - to use constructors like in VCL. Note: this option is
129 not carefully tested!)
130 USE_CUSTOMEXTENSIONS - to extend TControl with custom additions.
131 UNICODE_CTRLS - to use Unicode versions of controls (WM_XXXXW messages,
132 etc.)
133 USE_MHTOOLTIP - to use MHTOOLTIP.
134 NOT_USE_OnIdle - to stop using OnIdle event (to make code smaller
135 if it is not used actually).
136 USE_ASM_DODRAG - to use assembler version of code for DoDrag.
137 ENUM_DYN_HANDLERS_AFTER_RUN - to allow all the events handling even when
138 AppletTerminated become TRUE.
139 ALL_BUTTONS_RESPOND_TO_ENTER - obvious (by default, buttons respond to key
140 SPACE, since those are working this way in Windows).
141 ESC_CLOSE_DIALOGS - to allow closing all dialogs with ESCAPE.
142 KEY_PREVIEW - form also receive WM_KEYDOWN (OnKeyDown event fired)
143 OpenSaveDialog_Extended - to allow using custom extensions for OpenSaveDialog.
144 AUTO_CONTEXT_HELP - to use automatic respond to WM_CONTEXTMENU to call
145 context help.
146 NOT_FIX_CURINDEX - to use old version of TControl.SetItems, which could
147 lead to loose CurIndex value (e.g. for Combobox)
148 NOT_FIX_MODAL - not to fix modal (if fixed, click on any window
149 activates the application. If not fixed, code is
150 smaller very a little, but only click on modal form
151 activates the application).
152 NEW_MODAL - to use extended modalness.
153 USE_SETMODALRESULT - to guarantee ModalResult property assigninig handling.
154 USE_MENU_CURCTL - to use CurCtl property in popup menu to detect which
155 control initiated a pop-up.
156 NEW_MENU_ACCELL - to use another menu accelerators handling, without
157 AcceleratorTable
158 USE_DROPDOWNCOUNT - to force setting combobox dropdown count.
159 NOT_UNLOAD_RICHEDITLIB - to stop unload Rich Edit library in finalization
160 section (to economy several byte of code).
161 DEBUG_GDIOBJECTS - to allow counting all the GDI objects used.
162 CHK_BITBLT - to check BitBlt operations.
163 DEBUG_ENDSESSION - to allow debugging WM_ENDSESSION handling.
164 DEBUG_CREATEWINDOW - to debug CreateWindow.
165 TEST_CLOSE - to debug Close.
166 DEBUG_MENU - to debug menu.
167 DEBUG_DBLBUFF - to debug DoubleBuffered.
168 DEBUG - other debugging.
170 PROVIDE_EXITCODE - PostQuitMessage( value ) assigns value to ExitCode
171 INITIALFORMSIZE_FIXMENU - form size initially is really the same as defined at
172 design time even for forms having main menu bar
174 GRAPHCTL_XPSTYLES - to use XP themed Visual styles for drawing graphic
175 controls. This does not affect windowed controls
176 which visual style is controlled by the manifest.
177 GRAPHCTL_HOTTRACK - to use hot-tracking also together with XP themed
178 graphic controls (otherwise only static XP themed
179 view is provided). Also, turn this option on if you
180 want to handle OnMouseEnter and OnMouseLeabe events
181 for graphic controls.
183 |</pre>
185 {= K.O.L - êëþ÷åâàÿ áèáëèîòåêà îáúåêòîâ. (C) Êëàäîâ Âëàäèìèð, 2000-2003.
188 //[OPTIONS]
189 {$A-} // align off, otherwise code is not good
192 {$Q-} // no overflow check: this option makes code wrong
193 {$R-} // no range checking: this option makes code wrong
194 {$T-} // not typed @-operator
195 //{$D+}
196 {$IFDEF INPACKAGE} // use this symbol in packages requiring kol.pas
197 {$WARNINGS OFF}
198 {$ENDIF}
199 {$IFDEF _D7orHigher}
200 {$WARN UNSAFE_TYPE OFF} // Too many such warnings in Delphi7
201 {$WARN UNSAFE_CODE OFF}
202 {$WARN UNSAFE_CAST OFF}
203 {$ENDIF}
206 //[START OF INTERFACE]
207 interface
209 //{$DEFINE DEBUG_GDIOBJECTS}
210 //{$DEFINE CHK_GDI}
212 //[USES]
213 uses
214 messages, windows, RichEdit {$IFDEF CHK_GDI}, ChkGdi {$ENDIF};
215 //[END OF USES]
217 {$IFDEF DEBUG_GDIOBJECTS}
219 BrushCount: Integer;
220 FontCount: Integer;
221 PenCount: Integer;
222 {$ENDIF}
225 //{_#IF [DELPHI]}
226 {$INCLUDE delphicommctrl.inc}
227 //{_#ENDIF}
229 type
230 //[_TObj DEFINITION]
233 _TObj = object
234 {* auxiliary object type. See TObj. }
235 protected
236 procedure Init; virtual;
237 {* Is called from a constructor to initialize created object instance
238 filling its fields with 0. Can be overriden in descendant objects
239 to add another initialization code there. (Main reason of intending
240 is what constructors can not be virtual in poor objects). }
241 {= Âûçûâàåòñÿ äëÿ èíèöèàëèçàöèè îáúåêòà. }
242 public
243 function VmtAddr: Pointer;
244 {* Returns addres of virtual methods table of object. ? }
245 {= âîçâðàùàåò àäðåñ òàáëèöû âèðòóàëüíûõ ìåòîäîâ (VMT). ? }
246 end;
249 {++}(* TObj = class;*){--}
250 PObj = {-}^{+}TObj;
251 {* }
253 {++}(* TList = class;*){--}
254 PList = {-}^{+}TList;
255 {* }
257 //[TObjectMethod DECLARATION]
258 TObjectMethod = procedure of object;
259 {* }
260 TOnEvent = procedure( Sender: PObj ) of object;
261 {* This type of event is the most common - event handler when called can
262 know only what object was a sender of this call. Replaces good known
263 VCL TNotifyEvent event type. }
265 //[TPointerList DECLARATION]
266 PPointerList = ^TPointerList;
267 TPointerList = array[0..MaxInt div 4 - 1] of Pointer;
269 { ---------------------------------------------------------------------
271 TObj - base object to derive all others
273 ---------------------------------------------------------------------- }
274 //[TObj DEFINITION]
275 TObj = {-} object( _TObj ) {+}{++}(*class*){--}
276 {* Prototype for all objects of KOL. All its methods are important to
277 implement objects in a manner similar to Delphi TObject class. }
278 {= Áàçîâûé êëàññ äëÿ âñåõ ïðî÷èõ îáúåêòîâ KOL. }
279 protected
280 fRefCount: Integer;
281 fOnDestroy: TOnEvent;
282 procedure DoDestroy;
283 protected
284 fAutoFree: PList;
285 {* Is called from a constructor to initialize created object instance
286 filling its fields with 0. Can be overriden in descendant objects
287 to add another initialization code there. (Main reason of intending
288 is what constructors can not be virtual in poor objects). }
289 {= Âûçûâàåòñÿ äëÿ èíèöèàëèçàöèè îáúåêòà. }
290 fTag: DWORD;
291 {* Custom data. }
292 {++}(*public*){--}
293 destructor Destroy; {-} virtual; {+}{++}(* override; *){--}
294 {* Disposes memory, allocated to an object. Does not release huge strings,
295 dynamic arrays and so on. Such memory should be freeing in overriden
296 destructor. }
297 {= Îñâîáîæäàåò ïàìÿòü, âûäåëåííóþ äëÿ îáúåêòà. Íå îñâîáîæäàåò ïàìÿòü, âûäåëåííóþ
298 äëÿ ñòðîê, äèíàìè÷èñêèõ ìàññèâîâ è ò.ï. Òàêàÿ ïàìÿòü äîëæíà áûòü îñâîáîæäåíà
299 â ïåðåîïðåäåëåííîì äåñòðóêòîðå îáúåêòà. }
300 {++}(*protected*){--}
301 {++}(*
302 procedure Init; virtual;
303 {* Can be overriden in descendant objects
304 to add initialization code there. (Main reason of intending
305 is what constructors can not be virtual in poor objects). }
306 *){--}
307 procedure Final;
308 {* It is called in destructor to perform OnDestroy event call and to
309 released objects, added to fAutoFree list. }
310 public
311 procedure Free;
312 {* Before calling destructor of object, checks if passed pointer is not
313 nil - similar what is done in VCL for TObject. It is ALWAYS recommended
314 to use Free instead of Destroy - see also comments to RefInc, RefDec. }
315 {= Äî âûçîâà äåñòðóêòîðà, ïðîâåðÿåò, íå ïåðåäàí ëè nil â êà÷åñòâå ïàðàìåòðà.
316 ÂÑÅÃÄÀ ðåêîìåíäóåòñÿ èñïîëüçîâàòü Free âìåñòî Destroy - ñì. òàê æå RefInc,
317 RefDec. }
320 // By Vyacheslav Gavrik:
321 function InstanceSize: Integer;
322 {* Returns a size of object instance. }
325 constructor Create;
326 {* Constructor. Do not call it. Instead, use New<objectname> function
327 call for certain object, e.g., NewLabel( AParent, 'caption' ); }
328 {= Êîíñòðóêòîð. Íå ñëåäóåò âûçûâàòü åãî. Äëÿ êîíñòðóèðîâàíèÿ îáúåêòîâ,
329 âûçûâàéòå ñîîòâåòñòâóþùóþ ãëîáàëüíóþ ôóíêöèþ New<èìÿ-îáúåêòà>. Íàïðèìåð,
330 NewLabel( MyForm, 'Ìåòêà¹1' ); }
332 class function AncestorOfObject( Obj: Pointer ): Boolean;
333 {* Is intended to replace 'is' operator, which is not applicable to objects. }
334 {= }
335 function VmtAddr: Pointer;
336 {* Returns addres of virtual methods table of object. }
337 {= âîçâðàùàåò àëðåñ òàáëèöû âèðòóàëüíûõ ìåòîäîâ (VMT). }
339 procedure RefInc;
340 {* See comments below. }
341 {= Ñì. RefDec íèæå. }
342 procedure RefDec;
343 {* Decrements reference count. If it is becoming <0, and Free
344 method was already called, object is (self-) destroyed. Otherwise,
345 Free method does not destroy object, but only sets flag
346 "Free was called".
347 |<br>
348 Use RefInc..RefDec to provide a block of code, where
349 object can not be destroyed by call of Free method.
350 This makes code more safe from intersecting flows of processing,
351 where some code want to destroy object, but others suppose that it
352 is yet existing.
353 |<br>
354 If You want to release object at the end of block RefInc..RefDec,
355 do it immediately BEFORE call of last RefDec (to avoid situation,
356 when object is released in result of RefDec, and attempt to
357 destroy it follow leads to AV exception).
359 {= Óìåíüøàåò ñ÷åò÷èê èñïîëüçîâàíèÿ. Åñëè â ðåçóëüòàòå ñ÷åò÷èê ñòàíîâèòñÿ
360 < 0, è ìåòîä Free óæå áûë âûçâàí, îáúåêò (ñàìî-) ðàçðóøàåòñÿ. Èíà÷å,
361 ìåòîä Free íå ðàçðóøàåò îáúåêò, à òîëüêî óñòàíàâëèâàåò ôëàã "Free áûë
362 âûçâàí".
363 |<br>
364 Èñïîëüçóéòå RefInc..RefDec äëÿ ïðåäîòâðàùåíèÿ ðàçðóøåíèÿ îáúåêòà íà
365 íåêîòîðîì ó÷àñòêå êîäà (åñëè åñòü òàêàÿ íåîáõîäèìîñòü).
366 |<br>
367 Åñëè íóæíî óáèòü (âðåìåííûé) îáúåêò âìåñòå ñ ïîñëåäíèì RefDec, ñäåëàéòå
368 âûçîâ Free íåìåäëåííî ÏÅÐÅÄ ïîñëåäíèì RefDec. }
369 property RefCount: Integer read fRefCount;
370 {* }
371 property OnDestroy: TOnEvent read fOnDestroy write fOnDestroy;
372 {* This event is provided for any KOL object, so You can provide your own
373 OnDestroy event for it. }
374 {= Äàííîå ñîáûòèå îáåñïå÷èâàåòñÿ äëÿ âñåõ îáúåêòîâ KOL. Ïîçâîëÿåò ñäåëàòü
375 ÷òî-íèáóäü â ñâÿçè ñ ðàçðóøåíèåì îáúåêòà. }
376 procedure Add2AutoFree( Obj: PObj );
377 {* Adds an object to the list of objects, destroyed automatically
378 when the object is destroyed. Do not add here child controls of
379 the TControl (these are destroyed by another way). Only non-control
380 objects, which are not destroyed automatically, should be added here. }
381 procedure Add2AutoFreeEx( Proc: TObjectMethod );
382 {* Adds an event handler to the list of events, called in destructor.
383 This method is mainly for internal use, and allows to auto-destroy
384 VCL components, located on KOL form at design time (in MCK project). }
385 property Tag: DWORD read fTag write fTag;
386 {* Custom data field. }
387 protected
388 {$IFDEF USE_NAMES}
389 FName: String;
390 procedure SetName( const NewName: String );
391 {$ENDIF}
392 public
393 {$IFDEF USE_NAMES}
394 property Name: String read FName write SetName;
395 {$ENDIF}
396 end;
397 //[END OF TObj DEFINITION]
399 { ---------------------------------------------------------------------
401 TList - object to implement list of pointers (or dwords)
403 ---------------------------------------------------------------------- }
404 //[TList DEFINITION]
405 TList = object( TObj )
406 {* Simple list of pointers. It is used in KOL instead of standard VCL
407 TList to store any kind data (or pointers to these ones). Can be created
408 calling function NewList. }
409 {= Ïðîñòîé ñïèñîê óêàçàòåëåé. }
410 protected
411 fItems: PPointerList;
412 fCount: Integer;
413 fCapacity: Integer;
414 fAddBy: Integer;
415 procedure SetCount(const Value: Integer);
416 procedure SetAddBy(Value: Integer);
417 {++}(*public*){--}
418 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
419 {* Destroys list, freeing memory, allocated for pointers. Programmer
420 is resposible for destroying of data, referenced by the pointers. }
421 {= }
422 {++}(*protected*){--}
423 procedure SetCapacity( Value: Integer );
424 function Get( Idx: Integer ): Pointer;
425 procedure Put( Idx: Integer; Value: Pointer );
426 {$IFDEF USE_CONSTRUCTORS}
427 procedure Init; virtual;
428 {$ENDIF USE_CONSTRUCTORS}
429 public
430 procedure Clear;
431 {* Makes Count equal to 0. Not responsible for freeing (or destroying)
432 data, referenced by released pointers. }
433 procedure Add( Value: Pointer );
434 {* Adds pointer to the end of list, increasing Count by one. }
435 procedure Insert( Idx: Integer; Value: Pointer );
436 {* Inserts pointer before given item. Returns Idx, i.e. index of
437 inserted item in the list. Indeces of items, located after insertion
438 point, are increasing. To add item to the end of list, pass Count
439 as index parameter. To insert item before first item, pass 0 there. }
440 function IndexOf( Value: Pointer ): Integer;
441 {* Searches first (from start) item pointer with given value and returns
442 its index (zero-based) if found. If not found, returns -1. }
443 procedure Delete( Idx: Integer );
444 {* Deletes given (by index) pointer item from the list, shifting all
445 follow item indeces up by one. }
446 procedure DeleteRange( Idx, Len: Integer );
447 {* Deletes Len items starting from Idx. }
448 procedure Remove( Value: Pointer );
449 {* Removes first entry of a Value in the list. }
450 property Count: Integer read fCount write SetCount;
451 {* Returns count of items in the list. It is possible to delete a number
452 of items at the end of the list, keeping only first Count items alive,
453 assigning new value to Count property (less then Count it is). }
454 property Capacity: Integer read fCapacity write SetCapacity;
455 {* Returns number of pointers which could be stored in the list
456 without reallocating of memory. It is possible change this value
457 for optimize usage of the list (for minimize number of reallocating
458 memory operations). }
459 property Items[ Idx: Integer ]: Pointer read Get write Put; default;
460 {* Provides access (read and write) to items of the list. Please note,
461 that TList is not responsible for freeing memory, referenced by stored
462 pointers. }
463 function Last: Pointer;
464 {* Returns the last item (or nil, if the list is empty). }
465 procedure Swap( Idx1, Idx2: Integer );
466 {* Swaps two items in list directly (fast, but without testing of
467 index bounds). }
468 procedure MoveItem( OldIdx, NewIdx: Integer );
469 {* Moves item to new position. Pass NewIdx >= Count to move item
470 after the last one. }
471 procedure Release;
472 {* Especially for lists of pointers to dynamically allocated memory.
473 Releases all pointed memory blocks and destroys object itself. }
474 procedure ReleaseObjects;
475 {* Especially for a list of objects derived from TObj.
476 Calls Free for every of the object in the list, and then calls
477 Free for the object itself. }
478 property AddBy: Integer read fAddBy write SetAddBy;
479 {* Value to increment capacity when new items are added or inserted
480 and capacity need to be increased. }
481 property DataMemory: PPointerList read fItems;
482 {* Raw data memory. Can be used for direct access to items of a list. }
483 procedure Assign( SrcList: PList );
484 {* Copies all source list items. }
485 {$IFDEF _D4orHigher}
486 procedure AddItems( const AItems: array of Pointer );
487 {* Adds a list of items given by a dynamic array. }
488 {$ENDIF}
489 end;
490 //[END OF TList DEFINITION]
492 //[NewList DECLARATION]
493 function NewList: PList;
494 {* Returns pointer to newly created TList object. Use it instead usual
495 TList.Create as it is done in VCL or XCL. }
497 {$IFDEF _D4orHigher}
498 function NewListInit( const AItems: array of Pointer ): PList;
499 {* Creates a list filling it initially with certain Items. }
500 {$ENDIF}
503 procedure FastIncNum2Elements( List: TList; FromIdx, Count, Value: Integer );
504 {* Very fast adds Value to List elements from List[FromIdx] to List[FromIdx+Count-1].
505 Given elements must exist. Count must be > 0. }
507 procedure Free_And_Nil( var Obj );
508 {* Obj.Free and Obj := nil, where Obj *MUST* be TObj or its descendant
509 (TControl, TMenu, etc.) This procedure is not compatible with VCL's
510 FreeAndNil, which works with TObject, since this it has another name. }
512 {$IFDEF USE_NAMES}
514 NamedObjectsList: PList;
516 function FindObj( const Name: String ): PObj;
517 {$ENDIF}
525 { -- tree (non-visual) -- }
527 type
528 //[TTree DEFINITION]
529 {++}(*TTree = class;*){--}
530 PTree = {-}^{+}TTree;
531 TTree = object( TObj )
532 {* Object to store tree-like data in memory (non-visual). }
533 protected
534 fParent: PTree;
535 fChildren: PList;
536 fPrev: PTree;
537 fNext: PTree;
538 fNodeName: String;
539 fData: Pointer;
540 function GetCount: Integer;
541 function GetItems(Idx: Integer): PTree;
542 procedure Unlink;
543 function GetRoot: PTree;
544 function GetLevel: Integer;
545 function GetTotal: Integer;
546 function GetIndexAmongSiblings: Integer;
547 protected
548 {$IFDEF USE_CONSTRUCTORS}
549 constructor CreateTree( AParent: PTree; const AName: String );
550 {* }
551 {$ENDIF}
552 {++}(*public*){--}
553 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
554 {* }
555 {++}(*protected*){--}
556 procedure Init; {-}virtual;{+}{++}(*override;*){--}
557 public
558 procedure Clear;
559 {* Destoyes all child nodes. }
560 property Name: String read fNodeName write fNodeName;
561 {* Optional node name. }
562 property Data: Pointer read fData write fData;
563 {* Optional user-defined pointer. }
564 property Count: Integer read GetCount;
565 {* Number of child nodes of given node. }
566 property Items[ Idx: Integer ]: PTree read GetItems;
567 {* Child nodes list items. }
568 procedure Add( Node: PTree );
569 {* Adds another node as a child of given tree node. This operation
570 as well as Insert can be used to move node together with its children
571 to another location of the same tree or even from another tree.
572 Anyway, added Node first correctly removed from old place (if it is
573 defined for it). But for simplest task, such as filling of tree with
574 nodes, code should looking as follows:
575 ! Node := NewTree( nil, 'test of creating node without parent' );
576 ! RootOfMyTree.Add( Node );
577 Though, this code gives the same result as:
578 ! Node := NewTree( RootOfMyTree, 'test of creatign node as a child' ); }
579 procedure Insert( Before, Node: PTree );
580 {* Inserts earlier created 'Node' just before given child node 'Before'
581 as a child of given tree node. See also Add method. }
582 property Parent: PTree read fParent;
583 {* Returns parent node (or nil, if there is no parent). }
584 property Index: Integer read GetIndexAmongSiblings;
585 {* Returns an index of the node in a list of nodes of the same parent
586 (or -1, if Parent is not defined). }
587 property PrevSibling: PTree read fPrev;
588 {* Returns previous node in a list of children of the Parent. Nil is
589 returned, if given node is the first child of the Parent or has
590 no Parent. }
591 property NextSibling: PTree read fNext;
592 {* Returns next node in a list of children of the Parent. Nil is returned,
593 if given node is the last child of the Parent or has no Parent at all. }
594 property Root: PTree read GetRoot;
595 {* Returns root node (i.e. the last Parent, enumerating parents recursively). }
596 property Level: Integer read GetLevel;
597 {* Returns level of the node, i.e. integer value, equal to 0 for root
598 of a tree, 1 for its children, etc. }
599 property Total: Integer read GetTotal;
600 {* Returns total number of children of the node and all its children
601 counting its recursively (but node itself is not considered, i.e.
602 Total for node without children is equal to 0). }
603 procedure SortByName;
604 {* Sorts children of the node in ascending order. Sorting is not
605 recursive, i.e. only immediate children are sorted. }
606 procedure SwapNodes( i1, i2: Integer );
607 {* Swaps two child nodes. }
608 function IsParentOfNode( Node: PTree ): Boolean;
609 {* Returns true, if Node is the tree itself or is a parent of the given node
610 on any level. }
611 function IndexOf( Node: PTree ): Integer;
612 {* Total index of the child node (on any level under this node). }
614 end;
615 //[END OF TTree DEFINITION]
617 //[NewTree DECLARATION]
618 function NewTree( AParent: PTree; const AName: String ): PTree;
619 {* Constructs tree node, adding it to the end of children list of
620 the AParent. If AParent is nil, new root tree node is created. }
628 //[DummyObjProc, DummyObjProcParam DECLARATION]
629 procedure DummyObjProc( Sender: PObj );
630 procedure DummyObjProcParam( Sender: PObj; Param: Pointer );
635 { --- threads --- }
636 //[THREADS]
638 const
639 ABOVE_NORMAL_PRIORITY_CLASS = $8000; // only for Windows 2K
640 BELOW_NORMAL_PRIORITY_CLASS = $4000; // and higher !
642 type
643 {++}(*TThread = class;*){--}
644 PThread = {-}^{+}TThread;
646 TThreadMethod = procedure of object;
647 TThreadMethodEx = procedure( Sender: PThread; Param: Pointer ) of object;
649 TOnThreadExecute = function(Sender:PThread): Integer of object;
650 {* Event to be called when Execute method is called for TThread }
652 { ---------------------------------------------------------------------
654 TThread object
656 ---------------------------------------------------------------------- }
657 //[TThread DEFINITION]
658 TThread = object(TObj)
659 {* Thread object. It is possible not to derive Your own thread-based
660 object, but instead create thread Suspended and assign event
661 OnExecute. To create, use one of NewThread of NewThreadEx functions,
662 or derive Your own descendant object and write creation function
663 (or constructor) for it.
664 |<br><br>
665 Aknowledgements. Originally class ZThread was developed for XCL:
666 |<br> * By: Tim Slusher : junior@nlcomm.com
667 |<br> * Home: http://www.nlcomm.com/~junior
669 protected
670 FSuspended,
671 FTerminated: boolean;
672 FHandle: THandle;
673 FThreadId: DWORD;
674 FOnSuspend: TObjectMethod;
675 FOnResume: TOnEvent;
676 FData : Pointer;
677 FOnExecute : TOnThreadExecute;
678 FMethod: TThreadMethod;
679 FMethodEx: TThreadMethodEx;
680 F_AutoFree: Boolean;
681 function GetPriorityCls: Integer;
682 function GetThrdPriority: Integer;
683 procedure SetPriorityCls(Value: Integer);
684 procedure SetThrdPriority(Value: Integer);
685 {++}(*public*){--}
686 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
687 {* }
688 public
689 function Execute: integer; virtual;
690 {* Executes thread. Do not call this method from another thread! (Even do
691 not call this method at all!) Instead, use Resume.
692 |<br>
693 Note also that in contrast to VCL, it is not necessary to create your
694 own descendant object from TThread and override Execute method. In KOL,
695 it is sufficient to create an instance of TThread object (see NewThread,
696 NewThreadEx, NewThreadAutoFree functions) and assign OnExecute event
697 handler for it. }
698 procedure Resume;
699 {* Continues executing. It is necessary to make call for every
700 nested Suspend. }
701 procedure Suspend;
702 {* Suspends thread until it will be resumed. Can be called from another
703 thread or from the thread itself. }
704 procedure Terminate;
705 {* Terminates thread. }
706 function WaitFor: Integer;
707 {* Waits (infinitively) until thead will be finished. }
709 property Handle: THandle read FHandle;
710 {* Thread handle. It is created immediately when object is created
711 (using NewThread). }
712 property Suspended: boolean read FSuspended;
713 {* True, if suspended. }
714 property Terminated: boolean read FTerminated;
715 {* True, if terminated. }
716 property ThreadId: DWORD read FThreadId;
717 {* Thread id. }
718 property PriorityClass: Integer read GetPriorityCls write SetPriorityCls;
719 {* Thread priority class. One of following values: HIGH_PRIORITY_CLASS,
720 IDLE_PRIORITY_CLASS, NORMAL_PRIORITY_CLASS, REALTIME_PRIORITY_CLASS. }
721 property ThreadPriority: Integer read GetThrdPriority write SetThrdPriority;
722 {* Thread priority value. One of following values: THREAD_PRIORITY_ABOVE_NORMAL,
723 THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_IDLE,
724 THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_TIME_CRITICAL. }
725 property Data : Pointer read FData write FData;
726 {* Custom data pointer. Use it for Youe own purpose. }
728 property OnExecute: TOnThreadExecute read FOnExecute write FOnExecute;
729 {* Is called, when Execute is starting. }
730 property OnSuspend: TObjectMethod read FOnSuspend write FOnSuspend;
731 {* Is called, when Suspend is performed. }
732 property OnResume: TOnEvent read FOnResume write FOnResume;
733 {* Is called, when resumed. }
734 procedure Synchronize( Method: TThreadMethod );
735 {* Call it to execute given method in main thread context. Applet variable
736 must exist for that time. }
737 procedure SynchronizeEx( Method: TThreadMethodEx; Param: Pointer );
738 {* Call it to execute given method in main thread context, with a given
739 parameter. Applet variable must exist for that time. Param must not be nil. }
740 {$IFDEF USE_CONSTRUCTORS}
741 constructor ThreadCreate;
742 constructor ThreadCreateEx( const Proc: TOnThreadExecute );
743 {$ENDIF USE_CONSTRUCTORS}
745 property AutoFree: Boolean read F_AutoFree write F_AutoFree;
746 {* Set this property to true to provide automatic destroying of thread
747 object when its executing is finished. }
748 end;
749 //[END OF TThread DEFINITION]
751 //[NewThread, NewThreadEx, NewThreadAutoFree, Global_Synchronized DECLARATIONS]
752 function NewThread: PThread;
753 {* Creates thread object (always suspended). After creating, set event
754 OnExecute and perform Resume operation. }
756 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
757 {* Creates thread object, assigns Proc to its OnExecute event and runs
758 it. }
760 function NewThreadAutoFree( const Proc: TOnThreadExecute ): PThread;
761 {* Creates thread object similar to NewThreadEx, but freeing automatically
762 when executing of such thread finished. Be sure that a thread is resumed
763 at least to provide its object keeper freeing. }
765 var Global_Synchronized: procedure( Sender: PObj; Param: Pointer ) = DummyObjProcParam;
766 // It is not necessary to declare it as threadvar.
781 { -- streams -- }
782 //[STREAMS]
784 type
785 TMoveMethod = ( spBegin, spCurrent, spEnd );
787 {++}(*TStream = class;*){--}
788 PStream = {-}^{+}TStream;
790 PStreamMethods = ^TStreamMethods;
791 TStreamMethods = Packed Record
792 fSeek: function( Strm: PStream; MoveTo: Integer; MoveMethod: TMoveMethod ): DWORD;
793 fGetSiz: function( Strm: PStream ): DWORD;
794 fSetSiz: procedure( Strm: PStream; Value: DWORD );
795 fRead: function( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
796 fWrite: function( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
797 fClose: procedure( Strm: PStream );
798 fCustom: Pointer;
799 fWait: procedure( Strm: PStream );
800 end;
802 TStreamData = Packed Record
803 fHandle: THandle;
804 fCapacity, fSize, fPosition: DWORD;
805 fThread: PThread;
806 end;
808 { ---------------------------------------------------------------------
810 TStream - streaming objects incapsulation
812 ---------------------------------------------------------------------- }
813 //[TStream DEFINITION]
814 TStream = object(TObj)
815 {* Simple stream object. Can be opened for file, or as memory stream (see
816 NewReadFileStream, NewWriteFileStream, NewMemoryStream, etc.). And, another
817 type of streaming object can be derived (without inheriting new object
818 type, just by writing another New...Stream method, which calls
819 _NewStream and pass methods record to it). }
820 protected
821 fPMethods: PStreamMethods;
822 fMethods: TStreamMethods;
823 fMemory: Pointer;
824 fData: TStreamData;
825 fParam1, fParam2: DWORD; // parameters to use in thread
826 function GetCapacity: DWORD;
827 procedure SetCapacity(const Value: DWORD);
828 function DoAsyncRead( Sender: PThread ): Integer;
829 function DoAsyncWrite( Sender: PThread ): Integer;
830 function DoAsyncSeek( Sender: PThread ): Integer;
831 protected
832 function GetFileStreamHandle: THandle;
833 procedure SetPosition(Value: DWord);
834 function GetPosition: DWord;
835 function GetSize: DWord;
836 procedure SetSize(NewSize: DWord);
837 {++}(*public*){--}
838 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
839 public
840 function Read(var Buffer; Count: DWord): DWord;
841 {* Reads Count bytes from a stream. Returns number of bytes read. }
842 function Seek(MoveTo: Integer; MoveMethod: TMoveMethod): DWord;
843 {* Allows to change current position or to obtain it. Property
844 Position uses this method both for get and set position. }
845 function Write(var Buffer; Count: DWord): DWord;
846 {* Writes Count bytes from Buffer, starting from current position
847 in a stream. Returns how much bytes are written. }
848 function WriteStr( S: String ): DWORD;
849 {* Writes string to the stream, not including ending #0. Exactly
850 Length( S ) characters are written. }
851 function WriteStrZ( S: String ): DWORD;
852 {* Writes string, adding #0. Number of bytes written is returned. }
853 function ReadStrZ: String;
854 {* Reads string, finished by #0. After reading, current position in
855 the stream is set to the byte, follows #0. }
856 function ReadStr: String;
857 {* Reads string, finished by #13, #10 or #13#10 symbols. Terminating symbols
858 #13 and/or #10 are not added to the end of returned string though
859 stream positioned follow it. }
860 function WriteStrEx(S: String): DWord;
861 {* Writes string S to stream, also saving its size for future use by
862 ReadStrEx* functions. Returns number of actually written characters. }
863 function ReadStrExVar(var S: String): DWord;
864 {* Reads string from stream and assigns it to S.
865 Returns number of actually read characters.
866 Note:
867 String must be written by using WriteStrEx function.
868 Return value is count of characters READ, not the length of string. }
869 function ReadStrEx: String;
870 {* Reads string from stream and returns it. }
871 function WriteStrPas( S: String ): DWORD;
872 {* Writes a string in Pascal short string format - 1 byte length, then string
873 itself without trailing #0 char. S parameter length should not exceed 255
874 chars, rest chars are truncated while writing. Total amount of bytes
875 written is returned. }
876 function ReadStrPas: String;
877 {* Reads 1 byte from a stream, then treat it as a length of following string
878 which is read and returned. A purpose of this function is reading strings
879 written using WriteStrPas. }
880 property Size: DWord read GetSize write SetSize;
881 {* Returns stream size. For some custom streams, can be slow
882 operation, or even always return undefined value (-1 recommended). }
883 property Position: DWord read GetPosition write SetPosition;
884 {* Current position. }
886 property Memory: Pointer read fMemory;
887 {* Only for memory stream. }
888 property Handle: THandle read GetFileStreamHandle;
889 {* Only for file stream. It is possible to check that Handle <>
890 INVALID_HANDLE_VALUE to ensure that file stream is created OK. }
892 //---------- for asynchronous operations (using thread - not tested):
893 procedure SeekAsync(MoveTo: Integer; MoveMethod: TMoveMethod);
894 {* Changes current position asynchronously. To wait for finishing the
895 operation, use method Wait. }
896 procedure ReadAsync(var Buffer; Count: DWord);
897 {* Reads Count bytes from a stream asynchronously. To wait finishing the
898 operation, use method Wait. }
899 procedure WriteAsync(var Buffer; Count: DWord);
900 {* Writes Count bytes from Buffer, starting from current position
901 in a stream - asynchronously. To wait finishing the operation,
902 use method Wait. }
903 function Busy: Boolean;
904 {* Returns TRUE until finishing the last asynchronous operation
905 started by calling SeekAsync, ReadAsync, WriteAsync methods. }
906 procedure Wait;
907 {* Waits for finishing the last asynchronous operation. }
909 property Methods: PStreamMethods read fPMethods;
910 {* Pointer to TStreamMethods record. Useful to implement custom-defined
911 streams, which can access its fCustom field, or even to change
912 methods when necessary. }
913 property Data: TStreamData read fData;
914 {* Pointer to TStreamData record. Useful to implement custom-defined
915 streams, which can access Data fields directly when implemented. }
917 property Capacity: DWORD read GetCapacity write SetCapacity;
918 {* Amound of memory allocated for data (MemoryStream). }
920 end;
921 //[END OF TStream DEFINITION]
923 //[_NewStream DECLARATION]
924 function _NewStream( const StreamMethods: TStreamMethods ): PStream;
925 {* Use this method only to define your own stream type. See also declared
926 below (in KOL.pas) methods used to implement standard KOL streams. You can use it in
927 your code to create streams, which are partially based on standard
928 methods. }
930 // Methods below are declared here to simplify creating your
931 // own streams with some methods standard and some non-standard
932 // together:
933 function SeekFileStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
934 function GetSizeFileStream( Strm: PStream ): DWORD;
935 function ReadFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
936 function WriteFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
937 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
938 procedure CloseFileStream( Strm: PStream );
939 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
940 function GetSizeMemStream( Strm: PStream ): DWORD;
941 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );
942 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
943 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
944 procedure CloseMemStream( Strm: PStream );
945 procedure SetSizeFileStream( Strm: PStream; NewSize: DWORD );
947 function DummyReadWrite( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
948 procedure DummySetSize( Strm: PStream; Value: DWORD );
949 procedure DummyStreamProc(Strm: PStream);
952 //[NewFileStream DECLARATION]
953 function NewFileStream( const FileName: String; Options: DWORD ): PStream;
954 {* Creates file stream for read and write. Exact set of open attributes
955 should be passed through Options parameter (see FileCreate where those
956 flags are listed). }
958 function NewReadFileStream( const FileName: String ): PStream;
959 {* Creates file stream for read only. }
961 function NewWriteFileStream( const FileName: String ): PStream;
962 {* Creates file stream for write only. Truncating of file (if needed)
963 is provided automatically. }
965 function NewReadWriteFileStream( const FileName: String ): PStream;
966 {* Creates stream for read and write file. To truncate file, if it is
967 necessary, change Size property. }
969 //[NewMemoryStream DECLARATION]
970 function NewMemoryStream: PStream;
971 {* Creates memory stream (read and write). }
973 function NewExMemoryStream( ExistingMem: Pointer; Size: DWORD ): PStream;
974 {* Creates memory stream on base of existing memory. It is not possible
975 to write out of top bound given by Size (i.e. memory can not be resized,
976 or reallocated. When stream object is destroyed this memory is not freed. }
978 //[Stream2Stream DECLARATION]
979 function Stream2Stream( Dst, Src: PStream; Count: DWORD ): DWORD;
980 {* Copies Count (or less, if the rest of Src is not sufficiently long)
981 bytes from Src to Dst, but with optimizing in cases, when Src or/and
982 Dst are memory streams (intermediate buffer is not allocated). }
983 function Stream2StreamEx( Dst, Src: PStream; Count: DWORD ): DWORD;
984 {* Copies Count bytes from Src to Dst, but without any optimization.
985 Unlike Stream2Stream function, it can be applied to very large streams.
986 See also Stream2StreamExBufSz. }
987 function Stream2StreamExBufSz( Dst, Src: PStream; Count, BufSz: DWORD ): DWORD;
988 {* Copies Count bytes from Src to Dst using buffer of given size, but without
989 other optimizations.
990 Unlike Stream2Stream function, it can be applied to very large streams }
992 //[Resource2Stream DECLARATION]
993 function Resource2Stream( DestStrm : PStream; Inst : HInst;
994 ResName : PChar; ResType : PChar ): Integer;
995 {* Loads given resource to DestStrm. Useful for non-standard
996 resources to load it into memory (use memory stream for such
997 purpose). Use one of following resource types to pass as ResType:
998 |<pre>
999 RT_ACCELERATOR Accelerator table
1000 RT_ANICURSOR Animated cursor
1001 RT_ANIICON Animated icon
1002 RT_BITMAP Bitmap resource
1003 RT_CURSOR Hardware-dependent cursor resource
1004 RT_DIALOG Dialog box
1005 RT_FONT Font resource
1006 RT_FONTDIR Font directory resource
1007 RT_GROUP_CURSOR Hardware-independent cursor resource
1008 RT_GROUP_ICON Hardware-independent icon resource
1009 RT_ICON Hardware-dependent icon resource
1010 RT_MENU Menu resource
1011 RT_MESSAGETABLE Message-table entry
1012 RT_RCDATA Application-defined resource (raw data)
1013 RT_STRING String-table entry
1014 RT_VERSION Version resource
1015 |</pre>
1016 |<br>For example:
1017 !var MemStrm: PStream;
1018 ! JpgObj: PJpeg;
1019 !......
1020 ! MemStrm := NewMemoryStream;
1021 ! JpgObj := NewJpeg;
1022 !......
1023 ! Resource2Stream( MemStrm, hInstance, 'MYJPEG', RT_RCDATA );
1024 ! MemStrm.Position := 0;
1025 ! JpgObj.LoadFromStream( MemStrm );
1026 ! MemStrm.Free;
1027 !......
1071 { -- string list objects -- }
1072 //[TStrList]
1074 type
1075 {++}(*TStrList = class;*){--}
1076 PStrList = {-}^{+}TStrList;
1077 { ---------------------------------------------------------------------
1079 TStrList - string list
1081 ---------------------------------------------------------------------- }
1082 //[TStrList DEFINITION]
1083 TStrList = object(TObj)
1084 {* Easy string list implementation (non-visual, just to store
1085 string data). It is well improved and has very high performance
1086 allowing to work fast with huge text files (more then megabyte
1087 of text data).
1089 Please note that #0 charaster if stored in string lines, will cut it
1090 preventing reading the rest of a line. Be careful, if your data
1091 contain such characters. }
1092 protected
1093 procedure Init; virtual;
1094 protected
1095 fList: PList;
1096 fCount: Integer;
1097 fCaseSensitiveSort: Boolean;
1098 fTextBuf: PChar;
1099 fTextSiz: DWORD;
1100 function GetPChars(Idx: Integer): PChar;
1101 //procedure AddTextBuf( Src: PChar; Len: DWORD );
1102 protected
1103 function Get(Idx: integer): string;
1104 function GetTextStr: string;
1105 procedure Put(Idx: integer; const Value: string);
1106 procedure SetTextStr(const Value: string);
1107 {++}(*public*){--}
1108 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1109 protected
1110 // by Dod:
1111 procedure SetValue(const AName, Value: string);
1112 function GetValue(const AName: string): string;
1113 public
1114 // by Dod:
1115 function IndexOfName(AName: string): Integer;
1116 {* by Dod. Returns index of line starting like Name=... }
1117 property Values[const AName: string]: string read GetValue write SetValue;
1118 {* by Dod. Returns right side of a line starting like Name=... }
1119 public
1120 function Add(const S: string): integer;
1121 {* Adds a string to list. }
1122 procedure AddStrings(Strings: PStrList);
1123 {* Merges string list with given one. Very fast - more preferrable to
1124 use than any loop with calling Add method. }
1125 procedure Assign(Strings: PStrList);
1126 {* Fills string list with strings from other one. The same as AddStrings,
1127 but Clear is called first. }
1128 procedure Clear;
1129 {* Makes string list empty. }
1130 procedure Delete(Idx: integer);
1131 {* Deletes string with given index (it *must* exist). }
1132 function IndexOf(const S: string): integer;
1133 {* Returns index of first string, equal to given one. }
1134 function IndexOf_NoCase(const S: string): integer;
1135 {* Returns index of first string, equal to given one (while comparing it
1136 without case sensitivity). }
1137 function IndexOfStrL_NoCase( Str: PChar; L: Integer ): integer;
1138 {* Returns index of first string, equal to given one (while comparing it
1139 without case sensitivity). }
1140 function Find(const S: String; var Index: Integer): Boolean;
1141 {* Returns Index of the first string, equal or greater to given pattern, but
1142 works only for sorted TStrList object. Returns TRUE if exact string found,
1143 otherwise nearest (greater then a pattern) string index is returned,
1144 and the result is FALSE. }
1145 procedure Insert(Idx: integer; const S: string);
1146 {* Inserts string before one with given index. }
1147 function LoadFromFile(const FileName: string): Boolean;
1148 {* Loads string list from a file. (If file does not exist, nothing
1149 happens). Very fast even for huge text files. }
1150 procedure LoadFromStream(Stream: PStream; Append2List: boolean);
1151 {* Loads string list from a stream (from current position to the end of
1152 a stream). Very fast even for huge text. }
1153 procedure MergeFromFile(const FileName: string);
1154 {* Merges string list with strings in a file. Fast. }
1155 procedure Move(CurIndex, NewIndex: integer);
1156 {* Moves string to another location. }
1157 procedure SetText(const S: string; Append2List: boolean);
1158 {* Allows to set strings of string list from given string (in which
1159 strings are separated by $0D,$0A or $0D characters). Text must not
1160 contain #0 characters. Works very fast. This method is used in
1161 all others, working with text arrays (LoadFromFile, MergeFromFile,
1162 Assign, AddStrings). }
1163 procedure SetUnixText( const S: String; Append2List: Boolean );
1164 {* Allows to assign UNIX-style text (with #10 as string separator). }
1165 function SaveToFile(const FileName: string): Boolean;
1166 {* Stores string list to a file. }
1167 procedure SaveToStream(Stream: PStream);
1168 {* Saves string list to a stream (from current position). }
1169 function AppendToFile(const FileName: string): Boolean;
1170 {* Appends strings of string list to the end of a file. }
1171 property Count: integer read fCount;
1172 {* Number of strings in a string list. }
1173 property Items[Idx: integer]: string read Get write Put; default;
1174 {* Strings array items. If item does not exist, empty string is returned.
1175 But for assign to property, string with given index *must* exist. }
1176 property ItemPtrs[ Idx: Integer ]: PChar read GetPChars;
1177 {* Fast access to item strings as PChars. }
1178 function Last: String;
1179 {* Last item (or '', if string list is empty). }
1180 property Text: string read GetTextStr write SetTextStr;
1181 {* Content of string list as a single string (where strings are separated
1182 by characters $0D,$0A). }
1183 procedure Swap( Idx1, Idx2 : Integer );
1184 {* Swaps to strings with given indeces. }
1185 procedure Sort( CaseSensitive: Boolean );
1186 {* Call it to sort string list. }
1187 procedure AnsiSort( CaseSensitive: Boolean );
1188 {* Call it to sort ANSI string list. }
1190 // by Alexander Pravdin:
1191 protected
1192 fNameDelim: Char;
1193 function GetLineName( Idx: Integer ): string;
1194 procedure SetLineName( Idx: Integer; const NV: string );
1195 function GetLineValue(Idx: Integer): string;
1196 procedure SetLineValue(Idx: Integer; const Value: string);
1197 public
1198 property LineName[ Idx: Integer ]: string read GetLineName write SetLineName;
1199 property LineValue[ Idx: Integer ]: string read GetLineValue write SetLineValue;
1200 property NameDelimiter: Char read fNameDelim write fNameDelim;
1201 function Join( const sep: String ): String;
1202 {* by Sergey Shishmintzev. }
1203 end;
1204 //[END OF TStrList DEFINITION]
1206 //[DefaultNameDelimiter]
1207 var DefaultNameDelimiter: Char = '=';
1208 ThsSeparator: Char = ',';
1210 //[NewStrList DECLARATION]
1211 function NewStrList: PStrList;
1212 {* Creates string list object. }
1214 function GetFileList(const dir: string): PStrList;
1215 {* By Alexander Shakhaylo. Returns list of file names of the given directory. }
1217 {$IFNDEF _FPC}
1218 function WStrLen( W: PWideChar ): Integer;
1219 {* Returns Length of null-terminated Unicode string. }
1220 {$ENDIF _FPC}
1222 //[TStrListEx]
1223 type
1224 {++}(*TStrListEx = class;*){--}
1225 PStrListEx = {-}^{+}TStrListEx;
1227 //[TStrListEx DEFINITION]
1228 TStrListEx = object( TStrList )
1229 {* Extended string list object. Has additional capability to associate
1230 numbers or objects with string list items. }
1231 protected
1232 FObjects: PList;
1233 function GetObjects(Idx: Integer): DWORD;
1234 procedure SetObjects(Idx: Integer; const Value: DWORD);
1235 procedure Init; {-}virtual;{+}{++}(*override;*){--}
1236 procedure ProvideObjCapacity( NewCap: Integer );
1237 public
1238 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1239 {* }
1240 property Objects[ Idx: Integer ]: DWORD read GetObjects write SetObjects;
1241 {* Objects are just 32-bit values. You can treat and use it as pointers to
1242 any other data in the memory. But it is your task to free allocated
1243 memory in such case therefore. }
1244 procedure AddStrings(Strings: PStrListEx);
1245 {* Merges string list with given one. Very fast - more preferrable to
1246 use than any loop with calling Add method. }
1247 procedure Assign(Strings: PStrListEx);
1248 {* Fills string list with strings from other one. The same as AddStrings,
1249 but Clear is called first. }
1250 procedure Clear;
1251 {* Makes string list empty. }
1252 procedure Delete(Idx: integer);
1253 {* Deletes string with given index (it *must* exist). }
1254 procedure Move(CurIndex, NewIndex: integer);
1255 {* Moves string to another location. }
1256 procedure Swap( Idx1, Idx2 : Integer );
1257 {* Swaps to strings with given indeces. }
1258 procedure Sort( CaseSensitive: Boolean );
1259 {* Call it to sort string list. }
1260 procedure AnsiSort( CaseSensitive: Boolean );
1261 {* Call it to sort ANSI string list. }
1262 function LastObj: DWORD;
1263 {* Object assotiated with the last string. }
1264 function AddObject( const S: String; Obj: DWORD ): Integer;
1265 {* Adds a string and associates given number with it. Index of the item added
1266 is returned. }
1267 procedure InsertObject( Before: Integer; const S: String; Obj: DWORD );
1268 {* Inserts a string together with object associated. }
1269 function IndexOfObj( Obj: Pointer ): Integer;
1270 {* Returns an index of a string associated with the object passed as a
1271 parameter. If there are no such strings, -1 is returned. }
1272 end;
1273 //[END OF TStrListEx DEFINITION]
1275 //[NewStrListEx DECLARATION]
1276 function NewStrListEx: PStrListEx;
1277 {* Creates extended string list object. }
1299 ////////////////////////////////////////////////////////////////////////////////
1300 // GRAPHIC OBJECTS //
1301 ////////////////////////////////////////////////////////////////////////////////
1302 //[GRAPHIC OBJECTS]
1304 It is very important, that the most of code, implementing graphic objets
1305 from this section, is included into executable ONLY if really accessed in your
1306 project directly (e.g., if Font or Brush properies of a control are accessed
1307 or changed).
1309 type
1310 TColor = Integer;
1312 const
1313 //[COLOR CONSTANTS]
1314 clScrollBar = TColor(COLOR_SCROLLBAR or $80000000);
1315 clBackground = TColor(COLOR_BACKGROUND or $80000000);
1316 clActiveCaption = TColor(COLOR_ACTIVECAPTION or $80000000);
1317 clInactiveCaption = TColor(COLOR_INACTIVECAPTION or $80000000);
1318 clMenu = TColor(COLOR_MENU or $80000000);
1319 clWindow = TColor(COLOR_WINDOW or $80000000);
1320 clWindowFrame = TColor(COLOR_WINDOWFRAME or $80000000);
1321 clMenuText = TColor(COLOR_MENUTEXT or $80000000);
1322 clWindowText = TColor(COLOR_WINDOWTEXT or $80000000);
1323 clCaptionText = TColor(COLOR_CAPTIONTEXT or $80000000);
1324 clActiveBorder = TColor(COLOR_ACTIVEBORDER or $80000000);
1325 clInactiveBorder = TColor(COLOR_INACTIVEBORDER or $80000000);
1326 clAppWorkSpace = TColor(COLOR_APPWORKSPACE or $80000000);
1327 clHighlight = TColor(COLOR_HIGHLIGHT or $80000000);
1328 clHighlightText = TColor(COLOR_HIGHLIGHTTEXT or $80000000);
1329 clBtnFace = TColor(COLOR_BTNFACE or $80000000);
1330 clBtnShadow = TColor(COLOR_BTNSHADOW or $80000000);
1331 clGrayText = TColor(COLOR_GRAYTEXT or $80000000);
1332 clBtnText = TColor(COLOR_BTNTEXT or $80000000);
1333 clInactiveCaptionText = TColor(COLOR_INACTIVECAPTIONTEXT or $80000000);
1334 clBtnHighlight = TColor(COLOR_BTNHIGHLIGHT or $80000000);
1335 cl3DDkShadow = TColor(COLOR_3DDKSHADOW or $80000000);
1336 cl3DLight = TColor(COLOR_3DLIGHT or $80000000);
1337 clInfoText = TColor(COLOR_INFOTEXT or $80000000);
1338 clInfoBk = TColor(COLOR_INFOBK or $80000000);
1340 clBlack = TColor($000000);
1341 clMaroon = TColor($000080);
1342 clGreen = TColor($008000);
1343 clOlive = TColor($008080);
1344 clNavy = TColor($800000);
1345 clPurple = TColor($800080);
1346 clTeal = TColor($808000);
1347 clGray = TColor($808080);
1348 clSilver = TColor($C0C0C0);
1349 clRed = TColor($0000FF);
1350 clLime = TColor($00FF00);
1351 clYellow = TColor($00FFFF);
1352 clBlue = TColor($FF0000);
1353 clFuchsia = TColor($FF00FF);
1354 clAqua = TColor($FFFF00);
1355 clLtGray = TColor($C0C0C0);
1356 clDkGray = TColor($808080);
1357 clWhite = TColor($FFFFFF);
1358 clNone = TColor($1FFFFFFF);
1359 clDefault = TColor($20000000);
1361 clMoneyGreen = TColor($C0DCC0);
1362 clSkyBlue = TColor($F0CAA6);
1363 clCream = TColor($F0FBFF);
1364 clMedGray = TColor($A4A0A0);
1365 //[END OF COLOR CONSTANTS]
1367 const
1368 //[TGraphicTool FIELD OFFSET CONSTANTS]
1369 go_Color = 0;
1370 go_FontHeight = 4;
1371 go_FontWidth = 8;
1372 go_FontEscapement = 12;
1373 go_FontOrientation = 16;
1374 go_FontWeight = 20;
1375 go_FontItalic = 24;
1376 go_FontUnderline = 25;
1377 go_FontStrikeOut = 26;
1378 go_FontCharSet = 27;
1379 go_FontOutPrecision = 28;
1380 go_FontClipPrecision = 29;
1381 go_FontQuality = 30;
1382 go_FontPitch = 31;
1383 go_FontName = 32;
1384 go_BrushBitmap = 4;
1385 go_BrushStyle = 8;
1386 go_BrushLineColor = 9;
1387 go_PenBrushBitmap = 4;
1388 go_PenBrushStyle = 8;
1389 go_PenStyle = 9;
1390 go_PenWidth = 10;
1391 go_PenMode = 14;
1392 go_PenGeometric = 15;
1393 go_PenEndCap = 16;
1394 go_PenJoin = 17;
1395 //[END OF TGraphicTool FIELD OFFSET CONSTANTS]
1397 //[TGraphicTool]
1398 type
1399 TGraphicToolType = ( gttBrush, gttFont, gttPen );
1400 {* Graphic object types, mainly for internal use. }
1402 {++}(*TGraphicTool = class;*){--}
1403 PGraphicTool = {-}^{+}TGraphicTool;
1404 {* }
1405 TOnGraphicChange = procedure ( Sender: PGraphicTool ) of object;
1406 {* An event mainly for internal use. }
1408 TBrushStyle = (bsSolid, bsClear, bsHorizontal, bsVertical,
1409 bsFDiagonal, bsBDiagonal, bsCross, bsDiagCross);
1410 {* Available brush styles. }
1412 TFontStyles = (fsBold, fsItalic, fsUnderline, fsStrikeOut);
1413 {* Available font styles. }
1414 TFontStyle = set of TFontStyles;
1415 {* Font style is representing as a set of XFontStyles. }
1416 TFontPitch = (fpDefault, fpFixed, fpVariable);
1417 {* Availabe font pitch values. }
1418 TFontName = type string;
1419 {* Font name is represented as a string. }
1420 TFontCharset = 0..255;
1421 {* Font charset is represented by number from 0 to 255. }
1422 TFontQuality = (fqDefault, fqDraft, fqProof, fqNonAntialiased, fqAntialiased);
1423 {* Font quality. }
1425 TPenStyle = (psSolid, psDash, psDot, psDashDot, psDashDotDot, psClear,
1426 psInsideFrame);
1427 {* Available pen styles. For more info see Delphi or Win32 help files. }
1428 TPenMode = (pmBlack, pmNotMerge, pmMaskNotPen, pmNotCopy, pmMaskPenNot,
1429 pmNot, pmXor, pmNotMask, pmMask, pmNotXor, pmNop, pmMergePenNot,
1430 pmCopy, pmMergeNotPen, pmMerge, pmWhite);
1431 {* Available pen modes. For more info see Delphi or Win32 help files. }
1432 TPenEndCap = (pecRound, pecSquare, pecFlat);
1433 {* Avalable (for geometric pen) end cap styles. }
1434 TPenJoin = (pjRound, pjBevel, pjMiter);
1435 {* Available (for geometric pen) join styles. }
1437 //[TGdiFont]
1438 TGDIFont = packed record
1439 Height: Integer;
1440 Width: Integer;
1441 Escapement: Integer;
1442 Orientation: Integer;
1443 Weight: Integer;
1444 Italic: Boolean;
1445 Underline: Boolean;
1446 StrikeOut: Boolean;
1447 CharSet: TFontCharset;
1448 OutPrecision: Byte;
1449 ClipPrecision: Byte;
1450 Quality: TFontQuality;
1451 Pitch: TFontPitch;
1452 Name: array[0..LF_FACESIZE - 1] of Char;
1453 end;
1455 //[TGDIBrush]
1456 TGDIBrush = packed record
1457 Bitmap: HBitmap;
1458 Style: TBrushStyle;
1459 LineColor: TColor;
1460 end;
1462 //[TGDIPen]
1463 TGDIPen = packed record
1464 BrushBitmap: HBitmap;
1465 BrushStyle: TBrushStyle;
1466 Style: TPenStyle;
1467 Width: Integer;
1468 Mode: TPenMode;
1469 Geometric: Boolean;
1470 EndCap: TPenEndCap;
1471 Join: TPenJoin;
1472 end;
1474 //[TGDIToolData]
1475 TGDIToolData = packed record
1476 Color: TColor;
1477 case Integer of
1478 1: (Font: TGDIFont);
1479 2: (Pen: TGDIPen);
1480 3: (Brush: TGDIBrush);
1481 end;
1483 //[TNewGraphicTool]
1484 TNewGraphicTool = function: PGraphicTool;
1486 { ---------------------------------------------------------------------
1488 TGraphicTool - object to implement GDI-tools (brush, pen, font)
1490 ---------------------------------------------------------------------- }
1491 //[TGraphicTool DEFINITION]
1492 TGraphicTool = object( TObj )
1493 {* Incapsulates all GDI objects: Pen, Brush and Font. }
1494 protected
1495 fType: TGraphicToolType;
1496 fHandle: THandle;
1497 fParentGDITool: PGraphicTool;
1498 fOnChange: TOnGraphicChange;
1499 fColorRGB: TColor;
1500 fData: TGDIToolData;
1502 fNewProc: TNewGraphicTool;
1503 fMakeHandleProc: function( Self_: PGraphicTool ): THandle;
1505 procedure SetInt( const Index: Integer; Value: Integer );
1506 {$IFDEF F_P}
1507 function GetInt( const Index: Integer ): Integer;
1508 {$ENDIF}
1509 procedure SetColor( Value: TColor );
1510 procedure SetBrushBitmap(const Value: HBitmap);
1511 procedure SetBrushStyle(const Value: TBrushStyle);
1512 procedure SetFontCharset(const Value: TFontCharset);
1513 procedure SetFontQuality(const Value: TFontQuality);
1514 function GetFontName: String;
1515 procedure SetFontName(const Value: String);
1516 procedure SetFontOrientation(Value: Integer);
1517 procedure SetFontPitch(const Value: TFontPitch);
1518 function GetFontStyle: TFontStyle;
1519 procedure SetFontStyle(const Value: TFontStyle);
1520 procedure SetPenMode(const Value: TPenMode);
1521 procedure SetPenStyle(const Value: TPenStyle);
1522 procedure SetGeometricPen(const Value: Boolean);
1523 procedure SetPenEndCap(const Value: TPenEndCap);
1524 procedure SetPenJoin(const Value: TPenJoin);
1525 procedure SetFontWeight(const Value: Integer);
1526 procedure SetLogFontStruct(const Value: TLogFont);
1527 function GetLogFontStruct: TLogFont;
1528 protected
1529 procedure Changed;
1530 {* }
1531 function GetHandle: THandle;
1532 {* }
1533 public
1534 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
1535 {* }
1536 property Handle: THandle read GetHandle;
1537 {* Every time, when accessed, real GDI object is created (if it is
1538 not yet created). So, to prevent creating of the handle, use
1539 HandleAllocated instead of comparing Handle with value 0. }
1540 function HandleAllocated: Boolean;
1541 {* Returns True, if handle is allocated (i.e., if real GDI
1542 objet is created. }
1543 property OnChange: TOnGraphicChange read fOnChange write fOnChange;
1544 {* Called, when object is changed. }
1545 function ReleaseHandle: Integer;
1546 {* Returns Handle value (if allocated), releasing it from the
1547 object (so, it is no more knows about this handle and its
1548 HandleAllocated function returns False. }
1549 property Color: TColor {index go_Color} read fData.Color write SetColor;
1550 {* Color is the most common property for all Pen, Brush and
1551 Font objects, so it is placed in its common for all of them. }
1552 function Assign( Value: PGraphicTool ): PGraphicTool;
1553 {* Assigns properties of the same (only) type graphic object,
1554 excluding Handle. If assigning is really leading to change
1555 object, procedure Changed is called. }
1556 procedure AssignHandle( NewHandle: Integer );
1557 {* Assigns value to Handle property. }
1559 property BrushBitmap: HBitmap read fData.Brush.Bitmap write SetBrushBitmap;
1560 {* Brush bitmap. For more info about using brush bitmap,
1561 see Delphi or Win32 help files. }
1562 property BrushStyle: TBrushStyle read fData.Brush.Style write SetBrushStyle;
1563 {* Brush style. }
1564 property BrushLineColor: TColor index go_BrushLineColor
1565 {$IFDEF F_P}
1566 read GetInt
1567 {$ELSE DELPHI}
1568 read fData.Brush.LineColor
1569 {$ENDIF F_P/DELPHI}
1570 write SetInt;
1571 {* Brush line color, used to represent lines in hatched brush. Default value is clBlack. }
1573 property FontHeight: Integer index go_FontHeight
1574 {$IFDEF F_P}
1575 read GetInt
1576 {$ELSE DELPHI}
1577 read fData.Font.Height
1578 {$ENDIF F_P/DELPHI}
1579 write SetInt;
1580 {* Font height. Value 0 (default) seys to use system default value,
1581 negative values are to represent font height in "points", positive
1582 - in pixels. In XCL usually positive values (if not 0) are used to
1583 make appearance independent from different local settings. }
1584 property FontWidth: Integer index go_FontWidth
1585 {$IFDEF F_P}
1586 read GetInt
1587 {$ELSE DELPHI}
1588 read fData.Font.Width
1589 {$ENDIF F_P/DELPHI}
1590 write SetInt;
1591 {* Font width in logical units. If FontWidth = 0, then as it is said
1592 in Win32.hlp, "the aspect ratio of the device is matched against the
1593 digitization aspect ratio of the available fonts to find the closest match,
1594 determined by the absolute value of the difference." }
1595 property FontPitch: TFontPitch read fData.Font.Pitch write SetFontPitch;
1596 {* Font pitch. Change it very rare. }
1597 property FontStyle: TFontStyle read GetFontStyle write SetFontStyle;
1598 {* Very useful property to control text appearance. }
1599 property FontCharset: TFontCharset read fData.Font.Charset write SetFontCharset;
1600 {* Do not change it if You do not know what You do. }
1601 property FontQuality: TFontQuality read fData.Font.Quality write SetFontQuality;
1602 {* Font quality. }
1603 property FontOrientation: Integer read fData.Font.Orientation write SetFontOrientation;
1604 {* It is possible to rotate text in XCL just by changing this
1605 property of a font (tenths of degree, i.e. value 900 represents
1606 90 degree - text written from bottom to top). }
1607 property FontWeight: Integer read fData.Font.Weight write SetFontWeight;
1608 {* Additional font weight for bold fonts (must be 0..1000). When set to
1609 value <> 0, fsBold is added to FontStyle. And otherwise, when set to 0,
1610 fsBold is removed from FontStyle. Value 700 corresponds to Bold,
1611 400 to Normal. }
1612 property FontName: String read GetFontName write SetFontName;
1613 {* Font face name. }
1614 function IsFontTrueType: Boolean;
1615 {* Returns True, if font is True Type. Requires of creating of a Handle,
1616 if it is not yet created. }
1618 property PenWidth: Integer index go_PenWidth
1619 {$IFDEF F_P}
1620 read GetInt
1621 {$ELSE DELPHI}
1622 read fData.Pen.Width
1623 {$ENDIF F_P/DELPHI}
1624 write SetInt;
1625 {* Value 0 means default pen width. }
1626 property PenStyle: TPenStyle read fData.Pen.Style write SetPenStyle;
1627 {* Pen style. }
1628 property PenMode: TPenMode read fData.Pen.Mode write SetPenMode;
1629 {* Pen mode. }
1631 property GeometricPen: Boolean read fData.Pen.Geometric write SetGeometricPen;
1632 {* True if Pen is geometric. Note, that under Win95/98 only pen styles
1633 psSolid, psNull, psInsideFrame are supported by OS. }
1634 property PenBrushStyle: TBrushStyle read fData.Pen.BrushStyle write SetBrushStyle;
1635 {* Brush style for hatched geometric pen. }
1636 property PenBrushBitmap: HBitmap read fData.Pen.BrushBitmap write SetBrushBitmap;
1637 {* Brush bitmap for geometric pen (if assigned Pen is functioning as
1638 its style = BS_PATTERN, regadless of PenBrushStyle value). }
1639 property PenEndCap: TPenEndCap read fData.Pen.EndCap write SetPenEndCap;
1640 {* Pen end cap mode - for GeometricPen only. }
1641 property PenJoin: TPenJoin read fData.Pen.Join write SetPenJoin;
1642 {* Pen join mode - for GeometricPen only. }
1643 property LogFontStruct: TLogFont read GetLogFontStruct write SetLogFontStruct;
1644 {* by Alex Pravdin: a property to change all font structure items at once. }
1645 end;
1646 //[END OF TGraphicTool DEFINITION]
1648 //[Color2XXX FUNCTIONS]
1649 function Color2RGB( Color: TColor ): TColor;
1650 {* Function to get RGB color from system color. Parameter can be also RGB
1651 color, in that case result is just equal to a parameter. }
1652 function ColorsMix( Color1, Color2: TColor ): TColor;
1653 {* Returns color, which RGB components are build as an (approximate)
1654 arithmetic mean of correspondent RGB components of both source
1655 colors (these both are first converted from system to RGB, and
1656 result is always RGB color). Please note: this function is fast,
1657 but can be not too exact. }
1658 function Color2RGBQuad( Color: TColor ): TRGBQuad;
1659 {* Converts color to RGB, used to represent RGB values in palette entries
1660 (actually swaps R and B bytes). }
1661 function Color2Color16( Color: TColor ): WORD;
1662 {* Converts Color to RGB, packed to word (as it is used in format pf16bit). }
1664 //[DefFont VARIABLE]
1665 var // New TFont instances are intialized with the values in this structure:
1666 DefFont: TGDIFont = (
1667 Height: 0;
1668 Width: 0;
1669 Escapement: 0;
1670 Orientation: 0;
1671 Weight: 0;
1672 Italic: FALSE;
1673 Underline: FALSE;
1674 StrikeOut: FALSE;
1675 CharSet: 1;
1676 OutPrecision: 0;
1677 ClipPrecision: 0;
1678 Quality: fqDefault;
1679 Pitch: fpDefault;
1680 Name: 'MS Sans Serif';
1682 DefFontColor: TColor = clWindowText;
1683 {* Default font color. }
1685 //[GlobalGraphics_UseFontOrient]
1686 GlobalGraphics_UseFontOrient: Boolean;
1687 {* Global flag. If stays False (default), Orientation property of Font
1688 objects is ignored. This flag is set to True automatically in
1689 RotateFonts add-on. }
1691 { -- Constructors for different GDI tools -- }
1693 //[New FUNCTIONS FOR TGraphicTool]
1694 function NewFont: PGraphicTool;
1695 {* Creates and returns font graphic tool object. }
1696 function NewBrush: PGraphicTool;
1697 {* Creates and returns new brush object. }
1698 function NewPen: PGraphicTool;
1699 {* Creates and returns new pen object. }
1714 { -- TCanvas object -- }
1715 //[TCanvas]
1716 const
1717 HandleValid = 1;
1718 PenValid = 2;
1719 BrushValid = 4;
1720 FontValid = 8;
1721 ChangingCanvas = 16;
1723 type
1724 TFillStyle = (fsSurface, fsBorder);
1725 {* Available filling styles. For more info see Win32 or Delphi help files. }
1726 TFillMode = (fmAlternate, fmWinding);
1727 {* Available filling modes. For more info see Win32 or Delphi help files. }
1728 TCopyMode = Integer;
1729 {* Available copying modes are following:
1730 | cmBlackness<br>
1731 | cmDstInvert<br>
1732 | cmMergeCopy<br>
1733 | cmMergePaint<br>
1734 | cmNotSrcCopy<br>
1735 | cmNotSrcErase<br>
1736 | cmPatCopy<br>
1737 | cmPatInvert<br>
1738 | cmPatPaint<br>
1739 | cmSrcAnd<br>
1740 | cmSrcCopy<br>
1741 | cmSrcErase<br>
1742 | cmSrcInvert<br>
1743 | cmSrcPaint<br>
1744 | cmWhiteness<br>&nbsp;&nbsp;&nbsp;
1745 Also it is possible to use any other available ROP2 modes. For more info,
1746 see Win32 help files. }
1748 const
1749 cmBlackness = BLACKNESS;
1750 cmDstInvert = DSTINVERT;
1751 cmMergeCopy = MERGECOPY;
1752 cmMergePaint = MERGEPAINT;
1753 cmNotSrcCopy = NOTSRCCOPY;
1754 cmNotSrcErase = NOTSRCERASE;
1755 cmPatCopy = PATCOPY;
1756 cmPatInvert = PATINVERT;
1757 cmPatPaint = PATPAINT;
1758 cmSrcAnd = SRCAND;
1759 cmSrcCopy = SRCCOPY;
1760 cmSrcErase = SRCERASE;
1761 cmSrcInvert = SRCINVERT;
1762 cmSrcPaint = SRCPAINT;
1763 cmWhiteness = WHITENESS;
1765 type
1766 {++}(*TCanvas = class;*){--}
1767 PCanvas = {-}^{+}TCanvas;
1768 {* }
1769 TOnGetHandle = function( Canvas: PCanvas ): HDC of object;
1770 {* For internal use mainly. }
1771 TOnTextArea = procedure( Sender: PCanvas; var Size : TSize; var P0 : TPoint );
1772 {* Event to calculate actual area, occupying by a text. It is used
1773 to optionally extend calculating of TextArea taking into considaration
1774 font Orientation property. }
1776 { ---------------------------------------------------------------------
1778 TCanvas - high-level drawing helper object
1780 ----------------------------------------------------------------------- }
1781 //[TCanvas DEFINITION]
1782 TCanvas = object( TObj )
1783 {* Very similar to VCL's TCanvas object. But with some changes, specific
1784 for KOL: there is no necessary to use canvases in all applications.
1785 And graphic tools objects are not created with canvas, but only
1786 if really accessed in program. (Actually, even if paint box used,
1787 only programmer decides, if to implement painting using Canvas or
1788 to call low level API drawing functions working directly with DC).
1789 Therefore TCanvas has some powerful extensions: rotated text support,
1790 geometric pen support - just by changing correspondent properties
1791 of certain graphic tool objects (Font.FontOrientation, Pen.GeometricPen).
1792 See also additional Font properties (Font.FontWeight, Font.FontQuality,
1793 etc. }
1794 protected
1795 fOwnerControl: Pointer; //PControl;
1796 fHandle : HDC;
1797 fPenPos : TPoint;
1798 fBrush, fFont, fPen : PGraphicTool; // order is important for ASM version
1799 fState : Byte;
1800 fCopyMode : TCopyMode;
1801 fOnChange: TOnEvent;
1802 fOnGetHandle: TOnGetHandle;
1803 procedure SetHandle( Value : HDC );
1804 procedure SetPenPos( const Value : TPoint );
1805 procedure CreatePen;
1806 procedure CreateBrush;
1807 procedure CreateFont;
1808 procedure ObjectChanged( Sender : PGraphicTool );
1809 procedure Changing;
1810 function GetBrush: PGraphicTool;
1811 function GetFont: PGraphicTool;
1812 function GetPen: PGraphicTool;
1813 function GetHandle: HDC;
1814 procedure AssignChangeEvents;
1815 function GetPixels(X, Y: Integer): TColor;
1816 procedure SetPixels(X, Y: Integer; const Value: TColor);
1817 protected
1818 fIsPaintDC : Boolean;
1819 {* TRUE, if DC obtained during current WM_PAINT (or WM_ERASEBKGND?)
1820 processing for a control. This affects a way how Handle is released. }
1821 {++}(*public*){--}
1822 destructor Destroy;{-}virtual;{+}{++}(*override;*){--}
1823 {* }
1824 {++}(*protected*){--}
1825 property OnGetHandle: TOnGetHandle read fOnGetHandle write fOnGetHandle;
1826 {* For internal use only. }
1827 public
1828 property Handle : HDC read GetHandle write SetHandle;
1829 {* GDI device context object handle. Never created by
1830 Canvas itself (to use Canvas with memory bitmaps,
1831 always create DC by yourself and assign it to the
1832 Handle property of Canvas object, or use property
1833 Canvas of a bitmap). }
1834 property PenPos : TPoint read FPenPos write SetPenPos;
1835 {* Position of a pen. }
1836 property Pen : PGraphicTool read GetPen;
1837 {* Pen of Canvas object. Do not change its Pen.OnChange event value. }
1838 property Brush : PGraphicTool read GetBrush;
1839 {* Brush of Canvas object. Do not change its Brush.OnChange event value. }
1840 property Font : PGraphicTool read GetFont;
1841 {* Font of Canvas object. Do not change its Font.OnChange event value. }
1842 procedure Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
1843 {* Draws arc. For more info, see Delphi TCanvas help. }
1844 procedure Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
1845 {* Draws chord. For more info, see Delphi TCanvas help. }
1846 procedure DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
1847 {* Draws rectangle to represent focused visual object.
1848 For more info, see Delphi TCanvas help. }
1849 procedure Ellipse(X1, Y1, X2, Y2: Integer);
1850 {* Draws an ellipse. For more info, see Delphi TCanvas help. }
1851 procedure FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
1852 {* Fills rectangle. For more info, see Delphi TCanvas help. }
1853 procedure FillRgn( const Rgn : HRgn );
1854 {* Fills region. For more info, see Delphi TCanvas help. }
1855 procedure FloodFill(X, Y: Integer; Color: TColor; FillStyle: TFillStyle);
1856 {* Fills a figure with givien color, floodfilling its surface.
1857 For more info, see Delphi TCanvas help. }
1858 procedure FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
1859 {* Draws a rectangle using Brush settings (color, etc.).
1860 For more info, see Delphi TCanvas help. }
1861 procedure MoveTo( X, Y : Integer );
1862 {* Moves current PenPos to a new position.
1863 For more info, see Delphi TCanvas help. }
1864 procedure LineTo( X, Y : Integer );
1865 {* Draws a line from current PenPos up to new position.
1866 For more info, see Delphi TCanvas help. }
1867 procedure Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
1868 {* Draws a pie. For more info, see Delphi TCanvas help. }
1869 procedure Polygon(const Points: array of TPoint);
1870 {* Draws a polygon. For more info, see Delphi TCanvas help. }
1871 procedure Polyline(const Points: array of TPoint);
1872 {* Draws a bound for polygon. For more info, see Delphi TCanvas help. }
1873 procedure Rectangle(X1, Y1, X2, Y2: Integer);
1874 {* Draws a rectangle using current Pen and/or Brush.
1875 For more info, see Delphi TCanvas help. }
1876 procedure RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
1877 {* Draws a rounded rectangle. For more info, see Delphi TCanvas help. }
1878 procedure TextOut(X, Y: Integer; const Text: String); stdcall;
1879 {* Draws a text. For more info, see Delphi TCanvas help. }
1880 procedure ExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect; const Text: String;
1881 const Spacing: array of Integer );
1882 {* }
1883 procedure DrawText(Text:String; var Rect:TRect; Flags:DWord);
1884 {* }
1885 procedure TextRect(const Rect: TRect; X, Y: Integer; const Text: string);
1886 {* Draws a text, clipping output into given rectangle.
1887 For more info, see Delphi TCanvas help. }
1888 function TextExtent(const Text: string): TSize;
1889 {* Calculates size of a Text, using current Font settings.
1890 Does not need in Handle for Canvas object (if it is not
1891 yet allocated, temporary device context is created and used. }
1892 procedure TextArea( const Text : String; var Sz : TSize; var P0 : TPoint );
1893 {* Calculates size and starting point to output Text,
1894 taking into considaration all Font attributes, including
1895 Orientation (only if GlobalGraphics_UseFontOrient flag
1896 is set to True, i.e. if rotated fonts are used).
1897 Like for TextExtent, does not need in Handle (and if this
1898 last is not yet allocated/assigned, temporary device context
1899 is created and used). }
1900 function TextWidth(const Text: string): Integer;
1901 {* Calculates text width (using TextArea). }
1902 function TextHeight(const Text: string): Integer;
1903 {* Calculates text height (using TextArea). }
1904 function ClipRect: TRect;
1905 {* returns ClipBox. by Dmitry Zharov. }
1907 {$IFNDEF _FPC}
1908 {$IFNDEF _D2} //------- WideString not supported in D2
1909 procedure WTextOut(X, Y: Integer; const WText: WideString); stdcall;
1910 {* Draws a Unicode text. }
1911 procedure WExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect;
1912 const WText: WideString; const Spacing: array of Integer );
1913 {* }
1914 procedure WDrawText(WText: WideString; var Rect:TRect; Flags:DWord);
1915 {* }
1916 procedure WTextRect(const Rect: TRect; X, Y: Integer;
1917 const WText: WideString);
1918 {* Draws a Unicode text, clipping output into given rectangle. }
1919 function WTextExtent( const WText: WideString ): TSize;
1920 {* Calculates Unicode text width and height. }
1921 function WTextWidth( const WText: WideString ): Integer;
1922 {* Calculates Unicode text width. }
1923 function WTextHeight( const WText: WideString ): Integer;
1924 {* Calculates Unicode text height. }
1925 {$ENDIF _D2}
1926 {$ENDIF _FPC}
1928 property ModeCopy : TCopyMode read fCopyMode write fCopyMode;
1929 {* Current copy mode. Is used in CopyRect method. }
1930 procedure CopyRect( const DstRect : TRect; SrcCanvas : PCanvas; const SrcRect : TRect );
1931 {* Copyes a rectangle from source to destination, using StretchBlt. }
1932 property OnChange: TOnEvent read fOnChange write fOnChange;
1933 {* }
1934 function Assign( SrcCanvas : PCanvas ) : Boolean;
1935 {* }
1936 function RequiredState( ReqState : DWORD ): Integer; stdcall;// public now
1937 {* It is possible to call this method before using Handle property
1938 to pass it into API calls - to provide valid combinations of
1939 pen, brush and font, selected into device context. This method
1940 can not provide valid Handle - You always must create it by
1941 yourself and assign to TCanvas.Handle property manually.
1942 To optimize assembler version, returns Handle value. }
1943 procedure DeselectHandles;
1944 {* Call this method to deselect all graphic tool objects from the canvas. }
1945 property Pixels[ X, Y: Integer ]: TColor read GetPixels write SetPixels;
1946 {* Obvious. }
1947 end;
1948 //[END OF TCanvas DEFINITION]
1950 //[GlobalCanvas_OnTextArea]
1952 GlobalCanvas_OnTextArea : TOnTextArea;
1953 {* Global event to extend Canvas with possible add-ons, applied
1954 when rotated fonts are used only (to take into consideration
1955 Font.Orientation property in TextArea method). }
1957 //[NewCanvas DECLARATION]
1958 function NewCanvas( DC: HDC ): PCanvas;
1959 {* Use to construct Canvas on base of memory DC. }
1961 //[Extended FUNCTIONS TO WORK WITH CANVAS]
1962 {++}(*
1963 {$IFDEF F_P}
1964 function Windows_Polygon(DC: HDC; var Points; Count: Integer): BOOL; stdcall;
1965 function Windows_Polyline(DC: HDC; var Points; Count: Integer): BOOL; stdcall;
1966 function FillRect(hDC: HDC; const lprc: TRect; hbr: HBRUSH): Integer; stdcall;
1967 function OffsetRect(var lprc: TRect; dx, dy: Integer): BOOL; stdcall;
1968 function CreateAcceleratorTable(var Accel; Count: Integer): HACCEL; stdcall;
1969 function TrackPopupMenu(hMenu: HMENU; uFlags: UINT; x, y, nReserved: Integer;
1970 hWnd: HWND; prcRect: PRect): BOOL; stdcall;
1971 function AdjustTokenPrivileges(TokenHandle: THandle; DisableAllPrivileges: BOOL;
1972 const NewState: TTokenPrivileges; BufferLength: DWORD;
1973 var PreviousState: TTokenPrivileges; var ReturnLength: DWORD): BOOL; stdcall;
1974 function InflateRect(var lprc: TRect; dx, dy: Integer): BOOL; stdcall;
1975 {$IFDEF F_P105ORBELOW}
1976 function InvalidateRect(hWnd: HWND; lpRect: PRect; bErase: BOOL): BOOL; stdcall;
1977 function ValidateRect(hWnd: HWND; lpRect: PRect): BOOL; stdcall;
1978 {$ENDIF F_P105ORBELOW}
1979 {$ENDIF}
1980 *){--}
1995 { -- Image list object -- }
1996 //[IMAGE LIST]
1998 type
1999 TImageListColors = (ilcColor,ilcColor4,ilcColor8,ilcColor16,
2000 ilcColor24,ilcColor32,ilcColorDDB,ilcDefault);
2001 {* ImageList color schemes available. }
2003 TDrawingStyles = ( dsBlend25, dsBlend50, dsMask, dsTransparent );
2004 {* ImageList drawing styles available. }
2005 TDrawingStyle = Set of TDrawingStyles;
2006 {* Style of drawing is a combination of all available drawing styles. }
2008 TImageType = (itBitmap,itIcon,itCursor);
2009 {* ImageList types available. }
2011 {++}(*TImageList = class;*){--}
2012 PImageList = {-}^{+}TImageList;
2013 {* }
2015 TImgLOVrlayIdx = 1..15;
2017 { ---------------------------------------------------------------------
2019 TImageList - images container
2021 ----------------------------------------------------------------------- }
2022 //[TImageList DEFINITION]
2023 TImageList = object( TObj )
2024 {* ImageList incapsulation. }
2025 protected
2026 FHandle: THandle;
2027 FControl: Pointer; // PControl;
2028 fPrev, fNext: PImageList;
2029 FColors: TImageListColors;
2030 FMasked: Boolean;
2031 FImgWidth: Integer;
2032 FImgHeight: Integer;
2033 FDrawingStyle: TDrawingStyle;
2034 FBlendColor: TColor;
2035 fBkColor: TColor;
2036 FAllocBy: Integer;
2037 FShareImages: Boolean;
2038 FOverlay: array[ TImgLOVrlayIdx ] of Integer;
2039 function HandleNeeded : Boolean;
2040 procedure SetColors(const Value: TImageListColors);
2041 procedure SetMasked(const Value: Boolean);
2042 procedure SetImgWidth(const Value: Integer);
2043 procedure SetImgHeight(const Value: Integer);
2044 function GetCount: Integer;
2045 function GetBkColor: TColor;
2046 procedure SetBkColor(const Value: TColor);
2047 function GetBitmap: HBitmap;
2048 function GetMask: HBitmap;
2049 function GetDrawStyle : DWord;
2050 procedure SetAllocBy(const Value: Integer);
2051 function GetHandle: THandle;
2052 function GetOverlay(Idx: TImgLOVrlayIdx): Integer;
2053 procedure SetOverlay(Idx: TImgLOVrlayIdx; const Value: Integer);
2054 protected
2055 procedure SetHandle(const Value: THandle);
2057 public
2058 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2060 property Handle : THandle read GetHandle write SetHandle;
2061 {* Handle of ImageList object. }
2062 property ShareImages : Boolean read FShareImages write FShareImages;
2063 {* True if images are shared between processes (it is set to True,
2064 if its Handle is assigned to given value, which is a handle of
2065 already existing ImageList object). }
2066 property Colors : TImageListColors read FColors write SetColors;
2067 {* Colors used to represent images. }
2068 property Masked : Boolean read FMasked write SetMasked;
2069 {* True, if mask is used. It is set to True, if first added image
2070 is icon, e.g. }
2071 property ImgWidth : Integer read FImgWidth write SetImgWidth;
2072 {* Width of every image in list. If change, ImageList is cleared. }
2073 property ImgHeight : Integer read FImgHeight write SetImgHeight;
2074 {* Height of every image in list. If change, ImageList is cleared. }
2075 property Count : Integer read GetCount;
2076 {* Number of images in list. }
2077 property AllocBy : Integer read FAllocBy write SetAllocBy;
2078 {* Allocation factor. Default is 1. Set it to size of ImageList if this
2079 value is known - to optimize speed of allocation. }
2080 property BkColor : TColor read GetBkColor write SetBkColor;
2081 {* Background color. }
2082 property BlendColor : TColor read FBlendColor write FBlendColor;
2083 {* Blend color. }
2085 property Bitmap : HBitmap read GetBitmap;
2086 {* Bitmap, containing all ImageList images (tiled horizontally). }
2087 property Mask : HBitmap read GetMask;
2088 {* Monochrome bitmap, containing masks for all images in list (if not
2089 Masked, always returns nil). }
2090 function ImgRect( Idx : Integer ) : TRect;
2091 {* Rectangle occupied of given image in ImageList. }
2093 function Add( Bmp, Msk : HBitmap ) : Integer;
2094 {* Adds bitmap and given mask to ImageList. }
2095 function AddMasked( Bmp : HBitmap; Color : TColor ) : Integer;
2096 {* Adds bitmap to ImageList, using given color to create mask. }
2097 function AddIcon( Ico : HIcon ) : Integer;
2098 {* Adds icon to ImageList (always masked). }
2099 procedure Delete( Idx : Integer );
2100 {* Deletes given image from ImageList. }
2101 procedure Clear;
2102 {* Makes ImageList empty. }
2103 function Replace( Idx : Integer; Bmp, Msk : HBitmap ) : Boolean;
2104 {* Replaces given (by index) image with bitmap and its mask with mask bitmap. }
2105 function ReplaceIcon( Idx : Integer; Ico : HIcon ) : Boolean;
2106 {* Replaces given (by index) image with an icon. }
2107 function Merge( Idx : Integer; ImgList2 : PImageList; Idx2 : Integer; X, Y : Integer )
2108 : PImageList;
2109 {* Merges two ImageList objects, returns resulting ImageList. }
2110 function ExtractIcon( Idx : Integer ) : HIcon;
2111 {* Extracts icon by index. }
2112 function ExtractIconEx( Idx : Integer ) : HIcon;
2113 {* Extracts icon (is created using current drawing style). }
2115 property DrawingStyle : TDrawingStyle read FDrawingStyle write FDrawingStyle;
2116 {* Drawing style. }
2117 procedure Draw( Idx : Integer; DC : HDC; X, Y : Integer );
2118 {* Draws given (by index) image from ImageList onto passed Device Context. }
2119 procedure StretchDraw( Idx : Integer; DC : HDC; const Rect : TRect );
2120 {* Draws given image with stratching. }
2122 function LoadBitmap( ResourceName : PChar; TranspColor : TColor ) : Boolean;
2123 {* Loads ImageList from resource. }
2124 //function LoadIcon( ResourceName : PChar ) : Boolean;
2125 //function LoadCursor( ResourceName : PChar ) : Boolean;
2126 function LoadFromFile( FileName : PChar; TranspColor : TColor; ImgType : TImageType ) : Boolean;
2127 {* Loads ImageList from file. }
2128 function LoadSystemIcons( SmallIcons : Boolean ) : Boolean;
2129 {* Assigns ImageList to system icons list (big or small). }
2131 property Overlay[ Idx: TImgLOVrlayIdx ]: Integer read GetOverlay write SetOverlay;
2132 {* Overlay images for image list (images, used as overlay images to draw over
2133 other images from the image list). These overalay images can be used in
2134 listview and treeview as overlaying images (up to four masks at the same
2135 time). }
2136 {$IFDEF USE_CONSTRUCTORS}
2137 constructor CreateImageList( POwner: Pointer );
2138 {$ENDIF USE_CONSTRUCTORS}
2139 end;
2140 //[END OF TImageList DEFINITION]
2142 //[IMAGE LIST API]
2144 const
2145 CLR_NONE = $FFFFFFFF;
2146 CLR_DEFAULT = $FF000000;
2148 type
2149 HImageList = THandle;
2151 const
2152 ILC_MASK = $0001;
2153 ILC_COLOR = $00FE;
2154 ILC_COLORDDB = $00FE;
2155 ILC_COLOR4 = $0004;
2156 ILC_COLOR8 = $0008;
2157 ILC_COLOR16 = $0010;
2158 ILC_COLOR24 = $0018;
2159 ILC_COLOR32 = $0020;
2160 ILC_PALETTE = $0800;
2162 const
2163 ILD_NORMAL = $0000;
2164 ILD_TRANSPARENT = $0001;
2165 ILD_MASK = $0010;
2166 ILD_IMAGE = $0020;
2167 ILD_BLEND25 = $0002;
2168 ILD_BLEND50 = $0004;
2169 ILD_OVERLAYMASK = $0F00;
2171 const
2172 ILD_SELECTED = ILD_BLEND50;
2173 ILD_FOCUS = ILD_BLEND25;
2174 ILD_BLEND = ILD_BLEND50;
2175 CLR_HILIGHT = CLR_DEFAULT;
2177 function ImageList_Create(CX, CY: Integer; Flags: UINT;
2178 Initial, Grow: Integer): HImageList; stdcall;
2179 function ImageList_Destroy(ImageList: HImageList): Bool; stdcall;
2180 function ImageList_GetImageCount(ImageList: HImageList): Integer; stdcall;
2181 function ImageList_SetImageCount(ImageList: HImageList; Count: Integer): Integer; stdcall;
2182 function ImageList_Add(ImageList: HImageList; Image, Mask: HBitmap): Integer; stdcall;
2183 function ImageList_ReplaceIcon(ImageList: HImageList; Index: Integer;
2184 Icon: HIcon): Integer; stdcall;
2185 function ImageList_SetBkColor(ImageList: HImageList; ClrBk: TColorRef): TColorRef; stdcall;
2186 function ImageList_GetBkColor(ImageList: HImageList): TColorRef; stdcall;
2187 function ImageList_SetOverlayImage(ImageList: HImageList; Image: Integer;
2188 Overlay: Integer): Bool; stdcall;
2190 function ImageList_AddIcon(ImageList: HImageList; Icon: HIcon): Integer;
2192 function Index2OverlayMask(Index: Integer): Integer;
2194 function ImageList_Draw(ImageList: HImageList; Index: Integer;
2195 Dest: HDC; X, Y: Integer; Style: UINT): Bool; stdcall;
2197 function ImageList_Replace(ImageList: HImageList; Index: Integer;
2198 Image, Mask: HBitmap): Bool; stdcall;
2199 function ImageList_AddMasked(ImageList: HImageList; Image: HBitmap;
2200 Mask: TColorRef): Integer; stdcall;
2201 function ImageList_DrawEx(ImageList: HImageList; Index: Integer;
2202 Dest: HDC; X, Y, DX, DY: Integer; Bk, Fg: TColorRef; Style: Cardinal): Bool; stdcall;
2203 function ImageList_Remove(ImageList: HImageList; Index: Integer): Bool; stdcall;
2204 function ImageList_GetIcon(ImageList: HImageList; Index: Integer;
2205 Flags: Cardinal): HIcon; stdcall;
2206 function ImageList_LoadImageA(Instance: THandle; Bmp: PAnsiChar; CX, Grow: Integer;
2207 Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;
2208 function ImageList_LoadImageW(Instance: THandle; Bmp: PWideChar; CX, Grow: Integer;
2209 Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;
2210 function ImageList_LoadImage(Instance: THandle; Bmp: PChar; CX, Grow: Integer;
2211 Mask: TColorRef; pType, Flags: Cardinal): HImageList; stdcall;
2212 function ImageList_BeginDrag(ImageList: HImageList; Track: Integer;
2213 XHotSpot, YHotSpot: Integer): Bool; stdcall;
2214 function ImageList_EndDrag: Bool; stdcall;
2215 function ImageList_DragEnter(LockWnd: HWnd; X, Y: Integer): Bool; stdcall;
2216 function ImageList_DragLeave(LockWnd: HWnd): Bool; stdcall;
2217 function ImageList_DragMove(X, Y: Integer): Bool; stdcall;
2218 function ImageList_SetDragCursorImage(ImageList: HImageList; Drag: Integer;
2219 XHotSpot, YHotSpot: Integer): Bool; stdcall;
2220 function ImageList_DragShowNolock(Show: Bool): Bool; stdcall;
2221 function ImageList_GetDragImage(Point, HotSpot: PPoint): HImageList; stdcall;
2223 { macros }
2224 procedure ImageList_RemoveAll(ImageList: HImageList); stdcall;
2225 function ImageList_ExtractIcon(Instance: THandle; ImageList: HImageList;
2226 Image: Integer): HIcon; stdcall;
2227 function ImageList_LoadBitmap(Instance: THandle; Bmp: PChar;
2228 CX, Grow: Integer; MasK: TColorRef): HImageList; stdcall;
2230 //function ImageList_Read(Stream: IStream): HImageList; stdcall;
2231 //function ImageList_Write(ImageList: HImageList; Stream: IStream): BOOL; stdcall;
2233 //[TImageInfo]
2234 type
2235 PImageInfo = ^TImageInfo;
2236 TImageInfo = packed record
2237 hbmImage: HBitmap;
2238 hbmMask: HBitmap;
2239 Unused1: Integer;
2240 Unused2: Integer;
2241 rcImage: TRect;
2242 end;
2244 function ImageList_GetIconSize(ImageList: HImageList; var CX, CY: Integer): Bool; stdcall;
2245 function ImageList_SetIconSize(ImageList: HImageList; CX, CY: Integer): Bool; stdcall;
2246 function ImageList_GetImageInfo(ImageList: HImageList; Index: Integer;
2247 var ImageInfo: TImageInfo): Bool; stdcall;
2248 function ImageList_Merge(ImageList1: HImageList; Index1: Integer;
2249 ImageList2: HImageList; Index2: Integer; DX, DY: Integer)://Bool - ERROR IN VCL
2250 HImageList; stdcall;
2252 //[LoadBmp]
2253 function LoadBmp( Instance: Integer; Rsrc: PChar; MasterObj: PObj ): HBitmap;
2268 //[BITMAPS]
2269 type
2270 tagBitmap = Windows.TBitmap;
2272 TPixelFormat = ( pfDevice, pf1bit, pf4bit, pf8bit, pf15bit, pf16bit, pf24bit,
2273 pf32bit, pfCustom );
2274 {* Available pixel formats. }
2275 TBitmapHandleType = ( bmDIB, bmDDB );
2276 {* Available bitmap handle types. }
2278 {++}(*TBitmap = class;*){--}
2279 PBitmap = {-}^{+}TBitmap;
2280 { ----------------------------------------------------------------------
2282 TBitmap - bitmap image
2284 ----------------------------------------------------------------------- }
2285 //[TBitmap DEFINITION]
2286 TBitmap = object( TObj )
2287 {* Bitmap incapsulation object. }
2288 protected
2289 fHeight: Integer;
2290 fWidth: Integer;
2291 fHandle: HBitmap;
2292 fCanvas: PCanvas;
2293 fScanLineSize: Integer;
2294 fBkColor: TColor;
2295 fApplyBkColor2Canvas: procedure( Sender: PBitmap );
2296 fDetachCanvas: procedure( Sender: PBitmap );
2297 fCanvasAttached : Integer;
2298 fHandleType: TBitmapHandleType;
2299 fDIBHeader: PBitmapInfo;
2300 fDIBBits: Pointer;
2301 fDIBSize: Integer;
2302 fNewPixelFormat: TPixelFormat;
2303 fFillWithBkColor: procedure( BmpObj: PBitmap; DC: HDC; oldW, oldH: Integer );
2304 //stdcall;
2305 fTransMaskBmp: PBitmap;
2306 fTransColor: TColor;
2307 fGetDIBPixels: function( Bmp: PBitmap; X, Y: Integer ): TColor;
2308 fSetDIBPixels: procedure( Bmp: PBitmap; X, Y: Integer; Value: TColor );
2309 fScanLine0: PByte;
2310 fScanLineDelta: Integer;
2311 fPixelMask: DWORD;
2312 fPixelsPerByteMask: Integer;
2313 fBytesPerPixel: Integer;
2314 fDIBAutoFree: Boolean;
2315 procedure SetHeight(const Value: Integer);
2316 procedure SetWidth(const Value: Integer);
2317 function GetEmpty: Boolean;
2318 function GetHandle: HBitmap;
2319 function GetHandleAllocated: Boolean;
2320 procedure SetHandle(const Value: HBitmap);
2321 procedure SetPixelFormat(Value: TPixelFormat);
2322 procedure FormatChanged;
2323 function GetCanvas: PCanvas;
2324 procedure CanvasChanged( Sender: PObj );
2325 function GetScanLine(Y: Integer): Pointer;
2326 function GetScanLineSize: Integer;
2327 procedure ClearData;
2328 procedure ClearTransImage;
2329 procedure SetBkColor(const Value: TColor);
2330 function GetDIBPalEntries(Idx: Integer): TColor;
2331 function GetDIBPalEntryCount: Integer;
2332 procedure SetDIBPalEntries(Idx: Integer; const Value: TColor);
2333 procedure SetHandleType(const Value: TBitmapHandleType);
2334 function GetPixelFormat: TPixelFormat;
2335 function GetPixels(X, Y: Integer): TColor;
2336 procedure SetPixels(X, Y: Integer; const Value: TColor);
2337 function GetDIBPixels(X, Y: Integer): TColor;
2338 procedure SetDIBPixels(X, Y: Integer; const Value: TColor);
2339 function GetBoundsRect: TRect;
2340 protected
2341 {++}(*public*){--}
2342 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2343 public
2344 property Width: Integer read fWidth write SetWidth;
2345 {* Width of bitmap. To make code smaller, avoid changing Width or Height
2346 after bitmap is created (using NewBitmap) or after it is loaded from
2347 file, stream of resource. }
2348 property Height: Integer read fHeight write SetHeight;
2349 {* Height of bitmap. To make code smaller, avoid changing Width or Height
2350 after bitmap is created (using NewBitmap) or after it is loaded from
2351 file, stream of resource. }
2352 property BoundsRect: TRect read GetBoundsRect;
2353 {* Returns rectangle (0,0,Width,Height). }
2354 property Empty: Boolean read GetEmpty;
2355 {* Returns True if Width or Height is 0. }
2356 procedure Clear;
2357 {* Makes bitmap empty, setting its Width and Height to 0. }
2358 procedure LoadFromFile( const Filename: String );
2359 {* Loads bitmap from file (LoadFromStream used). }
2360 function LoadFromFileEx( const Filename: String ): Boolean;
2361 {* Loads bitmap from a file. If necessary, bitmap is RLE-decoded. Code given
2362 by Vyacheslav A. Gavrik. }
2363 procedure SaveToFile( const Filename: String );
2364 {* Stores bitmap to file (SaveToStream used). }
2365 procedure LoadFromStream( Strm: PStream );
2366 {* Loads bitmap from stream. Follow loading, bitmap has DIB format (without
2367 handle allocated). It is possible to draw DIB bitmap without creating
2368 handle for it, which can economy GDI resources. }
2369 function LoadFromStreamEx( Strm: PStream ): Boolean;
2370 {* Loads bitmap from a stream. Difference is that RLE decoding supported.
2371 Code given by Vyacheslav A. Gavrik. }
2372 procedure SaveToStream( Strm: PStream );
2373 {* Saves bitmap to stream. If bitmap is not DIB, it is converted to DIB
2374 before saving. }
2375 procedure LoadFromResourceID( Inst: DWORD; ResID: Integer );
2376 {* Loads bitmap from resource using integer ID of resource. To load by name,
2377 use LoadFromResurceName. To load resource of application itself, pass
2378 hInstance as first parameter. This method also can be used to load system
2379 predefined bitmaps, if 0 is passed as Inst parameter:
2380 |<pre>
2381 OBM_BTNCORNERS OBM_REDUCE
2382 OBM_BTSIZE OBM_REDUCED
2383 OBM_CHECK OBM_RESTORE
2384 OBM_CHECKBOXES OBM_RESTORED
2385 OBM_CLOSE OBM_RGARROW
2386 OBM_COMBO OBM_RGARROWD
2387 OBM_DNARROW OBM_RGARROWI
2388 OBM_DNARROWD OBM_SIZE
2389 OBM_DNARROWI OBM_UPARROW
2390 OBM_LFARROW OBM_UPARROWD
2391 OBM_LFARROWD OBM_UPARROWI
2392 OBM_LFARROWI OBM_ZOOM
2393 OBM_MNARROW OBM_ZOOMD
2394 |</pre> }
2395 procedure LoadFromResourceName( Inst: DWORD; ResName: PChar );
2396 {* Loads bitmap from resurce (using passed name of bitmap resource. }
2397 function Assign( SrcBmp: PBitmap ): Boolean;
2398 {* Assigns bitmap from another. Returns False if not success.
2399 Note: remember, that Canvas is not assigned - only bitmap image
2400 is copied. And for DIB, handle is not allocating due this process. }
2401 property Handle: HBitmap read GetHandle write SetHandle;
2402 {* Handle of bitmap. Created whenever property accessed. To check if handle
2403 is allocated (without allocating it), use HandleAllocated property. }
2404 property HandleAllocated: Boolean read GetHandleAllocated;
2405 {* Returns True, if Handle already allocated. }
2406 function ReleaseHandle: HBitmap;
2407 {* Returns Handle and releases it, so bitmap no more know about handle.
2408 This method does not destroy bitmap image, but converts it into DIB.
2409 Returned Handle actually is a handle of copy of original bitmap. If
2410 You need not in keping it up, use Dormant method instead. }
2411 procedure Dormant;
2412 {* Releases handle from bitmap and destroys it. But image is not destroyed
2413 and its data are preserved in DIB format. Please note, that in KOL, DIB
2414 bitmaps can be drawn onto given device context without allocating of
2415 handle. So, it is very useful to call Dormant preparing it using
2416 Canvas drawing operations - to economy GDI resources. }
2417 property HandleType: TBitmapHandleType read fHandleType write SetHandleType;
2418 {* bmDIB, if DIB part of image data is filled and stored internally in
2419 TBitmap object. DIB image therefore can have Handle allocated, which
2420 require resources. Use HandleAllocated funtion to determine if handle
2421 is allocated and Dormant method to remove it, if You want to economy
2422 GDI resources. (Actually Handle needed for DIB bitmap only in case
2423 when Canvas is used to draw on bitmap surface). Please note also, that
2424 before saving bitmap to file or stream, it is converted to DIB. }
2425 property PixelFormat: TPixelFormat read GetPixelFormat write SetPixelFormat;
2426 {* Current pixel format. If format of bitmap is unknown, or bitmap is DDB,
2427 value is pfDevice. Setting PixelFormat to any other format converts
2428 bitmap to DIB, back to pfDevice converts bitmap to DDB again. Avoid
2429 such conversations for large bitmaps or for numerous bitmaps in your
2430 application to keep good performance. }
2431 function BitsPerPixel: Integer;
2432 {* Returns bits per pixel if possible. }
2433 procedure Draw( DC: HDC; X, Y: Integer );
2434 {* Draws bitmap to given device context. If bitmap is DIB, it is always
2435 drawing using SetDIBitsToDevice API call, which does not require bitmap
2436 handle (so, it is very sensible to call Dormant method to free correspondent
2437 GDI resources). }
2438 procedure StretchDraw( DC: HDC; const Rect: TRect );
2439 {* Draws bitmap onto DC, stretching it to fit given rectangle Rect. }
2440 procedure DrawTransparent( DC: HDC; X, Y: Integer; TranspColor: TColor );
2441 {* Draws bitmap onto DC transparently, using TranspColor as transparent. }
2442 procedure StretchDrawTransparent( DC: HDC; const Rect: TRect; TranspColor: TColor );
2443 {* Draws bitmap onto given rectangle of destination DC (with stretching it
2444 to fit Rect) - transparently, using TranspColor as transparent. }
2445 procedure DrawMasked( DC: HDC; X, Y: Integer; Mask: HBitmap );
2446 {* Draws bitmap to destination DC transparently by mask. It is possible
2447 to pass as a mask handle of another TBitmap, previously converted to
2448 monochrome mask using Convert2Mask method. }
2449 procedure StretchDrawMasked( DC: HDC; const Rect: TRect; Mask: HBitmap );
2450 {* Like DrawMasked, but with stretching image onto given rectangle. }
2451 procedure Convert2Mask( TranspColor: TColor );
2452 {* Converts bitmap to monochrome (mask) bitmap with TranspColor replaced
2453 to clBlack and all other ones to clWhite. Such mask bitmap can be used
2454 to draw original bitmap transparently, with given TranspColor as
2455 transparent. (To preserve original bitmap, create new instance of
2456 TBitmap and assign original bitmap to it). See also DrawTransparent and
2457 StretchDrawTransparent methods. }
2458 procedure Invert;
2459 {* Obvious. }
2460 property Canvas: PCanvas read GetCanvas;
2461 {* Canvas can be used to draw onto bitmap. Whenever it is accessed, handle
2462 is allocated for bitmap, if it is not yet (to make it possible
2463 to select bitmap to display compatible device context). }
2464 procedure RemoveCanvas;
2465 {* Call this method to destroy Canvas and free GDI resources. }
2466 property BkColor: TColor read fBkColor write SetBkColor;
2467 {* Used to fill background for Bitmap, when its width or height is increased.
2468 Although this value always synchronized with Canvas.Brush.Color, use it
2469 instead if You do not use Canvas for drawing on bitmap surface. }
2470 property Pixels[ X, Y: Integer ]: TColor read GetPixels write SetPixels;
2471 {* Allows to obtain or change certain pixels of a bitmap. This method is
2472 both for DIB and DDB bitmaps, and leads to allocate handle anyway. For
2473 DIB bitmaps, it is possible to use property DIBPixels[ ] instead,
2474 which is much faster and does not require in Handle. }
2475 property ScanLineSize: Integer read GetScanLineSize;
2476 {* Returns size of scan line in bytes. Use it to measure size of a single
2477 ScanLine. To calculate increment value from first byte of ScanLine to
2478 first byte of next ScanLine, use difference
2479 ! Integer(ScanLine[1]-ScanLine[0])
2480 (this is because bitmap can be oriented from bottom to top, so
2481 step can be negative). }
2482 property ScanLine[ Y: Integer ]: Pointer read GetScanLine;
2483 {* Use ScanLine to access DIB bitmap pixels in memory to direct access it
2484 fast. Take in attention, that for different pixel formats, different
2485 bit counts are used to represent bitmap pixels. Also do not forget, that
2486 for formats pf4bit and pf8bit, pixels actually are indices to palette
2487 entries, and for formats pf16bit, pf24bit and pf32bit are actually
2488 RGB values (for pf16bit B:5-G:6-R:5, for pf15bit B:5-G:5-R:5 (high order
2489 bit not used), for pf24bit B:8-G:8-R:8, and for pf32bit high order byte
2490 of TRGBQuad structure is not used). }
2491 property DIBPixels[ X, Y: Integer ]: TColor read GetDIBPixels write SetDIBPixels;
2492 {* Allows direct access to pixels of DIB bitmap, faster then Pixels[ ]
2493 property. Access to read is slower for pf15bit, pf16bit formats (because
2494 some conversation needed to translate packed RGB color to TColor). And
2495 for write, operation performed most slower for pf4bit, pf8bit (searching
2496 nearest color required) and fastest for pf24bit, pf32bit and pf1bit. }
2497 property DIBPalEntryCount: Integer read GetDIBPalEntryCount;
2498 {* Returns palette entries count for DIB image. Always returns 2 for pf1bit,
2499 16 for pf4bit, 256 for pf8bit and 0 for other pixel formats. }
2500 property DIBPalEntries[ Idx: Integer ]: TColor read GetDIBPalEntries write
2501 SetDIBPalEntries;
2502 {* Provides direct access to DIB palette. }
2503 function DIBPalNearestEntry( Color: TColor ): Integer;
2504 {* Returns index of entry in DIB palette with color nearest (or matching)
2505 to given one. }
2506 property DIBBits: Pointer read fDIBBits;
2507 {* This property is mainly for internal use. }
2508 property DIBSize: Integer read fDIBSize;
2509 {* Size of DIBBits array. }
2510 property DIBHeader: PBitmapInfo read fDIBHeader;
2511 {* This property is mainly for internal use. }
2512 procedure DIBDrawRect( DC: HDC; X, Y: Integer; const R: TRect );
2513 {* This procedure copies given rectangle to the target device context,
2514 but only for DIB bitmap (using SetDIBBitsToDevice API call). }
2515 procedure RotateRight;
2516 {* Rotates bitmap right (90 degree). Bitmap must be DIB. If You definitevely
2517 know format of a bitmap, use instead one of methods RotateRightMono,
2518 RotateRight4bit, RotateRight8bit, RotateRight16bit or RotateRightTrueColor
2519 - this will economy code. But if for most of formats such methods are
2520 called, this can be more economy just to call always universal method
2521 RotateRight. }
2522 procedure RotateLeft;
2523 {* Rotates bitmap left (90 degree). Bitmap must be DIB. If You definitevely
2524 know format of a bitmap, use instead one of methods RotateLeftMono,
2525 RotateLeft4bit, RotateLeft8bit, RotateLeft16bit or RotateLeftTrueColor
2526 - this will economy code. But if for most of formats such methods are
2527 called, this can be more economy just to call always universal method
2528 RotateLeft. }
2529 procedure RotateRightMono;
2530 {* Rotates bitmat right, but only if bitmap is monochrome (pf1bit). }
2531 procedure RotateLeftMono;
2532 {* Rotates bitmap left, but only if bitmap is monochrome (pf1bit). }
2533 procedure RotateRight4bit;
2534 {* Rotates bitmap right, but only if PixelFormat is pf4bit. }
2535 procedure RotateLeft4bit;
2536 {* Rotates bitmap left, but only if PixelFormat is pf4bit. }
2537 procedure RotateRight8bit;
2538 {* Rotates bitmap right, but only if PixelFormat is pf8bit. }
2539 procedure RotateLeft8bit;
2540 {* Rotates bitmap left, but only if PixelFormat is pf8bit. }
2541 procedure RotateRight16bit;
2542 {* Rotates bitmap right, but only if PixelFormat is pf16bit. }
2543 procedure RotateLeft16bit;
2544 {* Rotates bitmap left, but only if PixelFormat is pf16bit. }
2545 procedure RotateRightTrueColor;
2546 {* Rotates bitmap right, but only if PixelFormat is pf24bit or pf32bit. }
2547 procedure RotateLeftTrueColor;
2548 {* Rotates bitmap left, but only if PixelFormat is pf24bit or pf32bit. }
2549 procedure FlipVertical;
2550 {* Flips bitmap vertically }
2551 procedure FlipHorizontal;
2552 {* Flips bitmap horizontally }
2553 procedure CopyRect( const DstRect : TRect; SrcBmp : PBitmap; const SrcRect : TRect );
2554 {* It is possible to use Canvas.CopyRect for such purpose, but if You
2555 do not want use TCanvas, it is possible to copy rectangle from one
2556 bitmap to another using this function. }
2557 function CopyToClipboard: Boolean;
2558 {* Copies bitmap to clipboard. }
2559 function PasteFromClipboard: Boolean;
2560 {* Takes CF_DIB format bitmap from clipboard and assigns it to the
2561 TBitmap object. }
2562 end;
2563 //[END OF TBitmap DEFINITION]
2565 //[NewBitmap DECLARATION]
2566 function NewBitmap( W, H: Integer ): PBitmap;
2567 {* Creates bitmap object of given size. If it is possible, do not change its
2568 size (Width and Heigth) later - this can economy code a bit. See TBitmap. }
2570 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;
2571 {* Creates DIB bitmap object of given size and pixel format. If it is possible,
2572 do not change its size (Width and Heigth) later - this can economy code a bit.
2573 See TBitmap. }
2575 //[CalcScanLineSize DECLARATION]
2576 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;
2577 {* May be will be useful. }
2579 //[DefaultPixelFormat VARIABLE]
2581 //DefaultBitsPerPixel: Integer = 16;
2582 DefaultPixelFormat: TPixelFormat = pf16bit;
2584 //[Mapped bitmaps]
2586 { -- Function to load bitmap mapping some its colors. -- }
2587 function LoadMappedBitmap( hInst: THandle; BmpResID: Integer; const Map: array of TColor )
2588 : HBitmap;
2589 {* This function can be used to load bitmap and replace some it colors to
2590 desired ones. This function especially useful when loaded by the such way
2591 bitmap is used as toolbar bitmap - to replace some original colors to
2592 system default colors. To use this function properly, the bitmap shoud
2593 be prepared as 16-color bitmap, which uses only system colors. To do so,
2594 create a new 16-color bitmap with needed dimensions in Borland Image Editor
2595 and paste a bitmap image, copyed in another graphic tool, and then save it.
2596 If this is not done, bitmap will not be loaded correctly! }
2597 function LoadMappedBitmapEx( MasterObj: PObj; hInst: THandle; BmpResName: PChar; const Map: array of TColor )
2598 : HBitmap;
2599 {* Like LoadMappedBitmap, but much powerful. It uses CreateMappedBitmapEx
2600 by Alex Pravdin, so it understands any bitmap color format, including
2601 pf24bit. Also, LoadMappedBitmapEx provides auto-destroying loaded resource
2602 when MasterObj is destroyed. }
2603 function CreateMappedBitmap(Instance: THandle; Bitmap: Integer;
2604 Flags: UINT; ColorMap: PColorMap; NumMaps: Integer): HBitmap; stdcall;
2605 {* Creates mapped bitmap replacing colors correspondently to the
2606 ColorMap (each pare of colors defines color replaced and a color
2607 used for replace it in the bitmap). See also CreateMappedBitmapEx. }
2608 function CreateMappedBitmapEx(Instance: THandle; BmpRsrcName: PChar; Flags:
2609 Cardinal; ColorMap: PColorMap; NumMaps: Integer): HBitmap;
2610 {* By Alex Pravdin.
2611 Creates mapped bitmap independently from bitmap color format (works
2612 correctly with bitmaps having format deeper than 8bit per pixel). }
2625 //[ICONS]
2627 type
2628 {++}(*TIcon = class;*){--}
2629 PIcon = {-}^{+}TIcon;
2630 { ----------------------------------------------------------------------
2632 TIcon - icon image
2634 ----------------------------------------------------------------------- }
2635 //[TIcon DEFINITION]
2636 TIcon = object( TObj )
2637 {* Object type to incapsulate icon or cursor image. }
2638 protected
2639 FSize : Integer;
2640 FHandle: HIcon;
2641 FShareIcon: Boolean;
2642 procedure SetSize(const Value: Integer);
2643 procedure SetHandle(const Value: HIcon);
2644 function GetHotSpot: TPoint;
2645 function GetEmpty: Boolean;
2646 protected
2647 {++}(*public*){--}
2648 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
2649 public
2650 property Size : Integer read FSize write SetSize;
2651 {* Icon dimension (width and/or height, which are equal to each other always). }
2652 property Handle : HIcon read FHandle write SetHandle;
2653 {* Windows icon object handle. }
2654 procedure Clear;
2655 {* Clears icon, freeing image and allocated GDI resource (Handle). }
2656 property Empty: Boolean read GetEmpty;
2657 {* Returns True if icon is Empty. }
2658 property ShareIcon : Boolean read FShareIcon write FShareIcon;
2659 {* True, if icon object is shared and can not be deleted when TIcon object
2660 is destroyed (set this flag is to True, if an icon is obtained from another
2661 TIcon object, for example). }
2662 property HotSpot : TPoint read GetHotSpot;
2663 {* Hot spot point - for cursors. }
2664 procedure Draw( DC : HDC; X, Y : Integer );
2665 {* Draws icon onto given device context. Icon always is drawn transparently
2666 using its transparency mask (stored internally in icon object). }
2667 procedure StretchDraw( DC : HDC; Dest : TRect );
2668 {* Draws icon onto given device context with stretching it to fit destination
2669 rectangle. See also Draw. }
2670 procedure LoadFromStream( Strm : PStream );
2671 {* Loads icon from stream. If stream contains several icons (of
2672 different dimentions), icon with the most appropriate size is loading. }
2673 procedure LoadFromFile( const FileName : String );
2674 {* Load icon from file. If file contains several icons (of
2675 different dimensions), icon with the most appropriate size is loading. }
2676 procedure LoadFromResourceID( Inst: Integer; ResID: Integer; DesiredSize: Integer );
2677 {* Loads icon from resource. To load system default icon, pass 0 as Inst and
2678 one of followin values as ResID:
2679 |<pre>
2680 IDI_APPLICATION Default application icon.
2681 IDI_ASTERISK Asterisk (used in informative messages).
2682 IDI_EXCLAMATION Exclamation point (used in warning messages).
2683 IDI_HAND Hand-shaped icon (used in serious warning messages).
2684 IDI_QUESTION Question mark (used in prompting messages).
2685 IDI_WINLOGO Windows logo.
2686 |</pre> It is also possible to load icon from resources of another module,
2687 if pass instance handle of loaded module as Inst parameter. }
2688 procedure LoadFromResourceName( Inst: Integer; ResName: PChar; DesiredSize: Integer );
2689 {* Loads icon from resource. To load own application resource, pass
2690 hInstance as Inst parameter. It is possible to load resource from
2691 another module, if pass its instance handle as Inst. }
2692 procedure LoadFromExecutable( const FileName: String; IconIdx: Integer );
2693 {* Loads icon from executable (exe or dll file). Always default sized icon
2694 is loaded. It is possible also to get know how much icons are contained
2695 in executable using gloabl function GetFileIconCount. To obtain icon of
2696 another size, try to load given executable and use LoadFromResourceID
2697 method. }
2698 procedure SaveToStream( Strm : PStream );
2699 {* Saves single icon to stream. To save icons with several different
2700 dimensions, use global procedure SaveIcons2Stream. }
2701 procedure SaveToFile( const FileName : String );
2702 {* Saves single icon to file. To save icons with several different
2703 dimensions, use global procedure SaveIcons2File. }
2704 function Convert2Bitmap( TranColor: TColor ): HBitmap;
2705 {* Converts icon to bitmap, returning Windows GDI bitmap resource as
2706 a result. It is possible later to assign returned bitmap handle to
2707 Handle property of TBitmap object to use features of TBitmap.
2708 Pass TranColor to replace transparent area of icon with given color. }
2709 end;
2710 //[END OF TIcon DEFINITION]
2712 //[Icon save functions]
2714 procedure SaveIcons2Stream( const Icons : array of PIcon; Strm : PStream );
2715 {* Saves several icons (of different dimentions) to stream. }
2716 function SaveIcons2StreamEx( const BmpHandles: array of HBitmap; Strm: PStream ): Boolean;
2717 {* Saves icons creating it from pairs of bitmaps and their masks.
2718 BmpHandles array must contain pairs of bitmap handles, each pair
2719 of color bitmap and mask bitmap of the same size. }
2720 procedure SaveIcons2File( const Icons : array of PIcon; const FileName : String );
2721 {* Saves several icons (of different dimentions) to file. (Single file
2722 with extension .ico can contain several different sized icon images
2723 to use later one with the most appropriate size). }
2725 //[NewIcon DECLARATION]
2726 function NewIcon: PIcon;
2727 {* Creates new icon object, setting its Size to 32 by default. Created icon
2728 is Empty. }
2730 //[GetFileIconCount DECLARATION]
2731 function GetFileIconCount( const FileName: String ): Integer;
2732 {* Returns number of icon resources stored in given (executable) file. }
2734 //[ICON STRUCTURES]
2735 type
2736 TIconHeader = packed record
2737 idReserved: Word; (* Always set to 0 *)
2738 idType: Word; (* Always set to 1 *)
2739 idCount: Word; (* Number of icon images *)
2740 (* immediately followed by idCount TIconDirEntries *)
2741 end;
2743 TIconDirEntry = packed record
2744 bWidth: Byte; (* Width *)
2745 bHeight: Byte; (* Height *)
2746 bColorCount: Byte; (* Nr. of colors used, see below *)
2747 bReserved: Byte; (* not used, 0 *)
2748 wPlanes: Word; (* not used, 0 *)
2749 wBitCount: Word; (* not used, 0 *)
2750 dwBytesInRes: Longint; (* total number of bytes in images *)
2751 dwImageOffset: Longint;(* location of image from the beginning of file *)
2752 end;
2754 //[LoadImgIcon DECLARATION]
2755 function LoadImgIcon( RsrcName: PChar; Size: Integer ): HIcon;
2756 {* Loads icon of specified size from the resource. }
2782 ////////////////////////////////////////////////////////////////////////////////
2783 // UNIVERSAL CONTROL OBJECT //
2784 ////////////////////////////////////////////////////////////////////////////////
2786 //[CM_XXX CONSTANTS]
2788 const
2789 CM_EXECPROC = $8FFF;
2790 CM_BASE = $B000;
2791 CM_ACTIVATE = CM_BASE + 0;
2792 CM_DEACTIVATE = CM_BASE + 1;
2793 CM_ENTER = CM_BASE + 2;
2794 CM_RELEASE = CM_BASE + 3;
2795 CM_QUIT = CM_BASE + 4;
2796 CM_COMMAND = CM_BASE + 5;
2797 CM_MEASUREITEM = CM_BASE + 6;
2798 CM_DRAWITEM = CM_BASE + 7;
2799 CM_TRAYICON = CM_BASE + 8;
2800 CM_INVALIDATE = CM_BASE + 9;
2801 CM_UPDATE = CM_BASE + 10;
2802 CM_NCUPDATE = CM_BASE + 11;
2803 CM_SIZEPOS = CM_BASE + 12;
2804 CM_SIZE = CM_BASE + 13;
2805 CM_SETFOCUS = CM_BASE + 14;
2806 CM_CBN_SELCHANGE = 15;
2808 CM_UIACTIVATE = CM_BASE + 16;
2809 CM_UIDEACTIVATE = CM_BASE + 17;
2810 CM_PROCESS = CM_BASE + 18;
2811 CM_SHOW = CM_BASE + 19;
2813 //CM_CLOSE = CM_BASE + 20;
2814 CM_MDIClientShowEdge = CM_BASE + 21;
2816 CM_INVALIDATECHILD = CM_BASE + 22;
2817 CM_FOCUSGRAPHCTL = CM_BASE + 23;
2819 //[CN_XXX CONSTANTS]
2821 CN_BASE = $BC00;
2822 CN_CHARTOITEM = CN_BASE + WM_CHARTOITEM;
2823 CN_COMMAND = CN_BASE + WM_COMMAND;
2824 CN_COMPAREITEM = CN_BASE + WM_COMPAREITEM;
2826 CN_CTLCOLORMSGBOX = CN_BASE + WM_CTLCOLORMSGBOX;
2827 CN_CTLCOLOREDIT = CN_BASE + WM_CTLCOLOREDIT;
2828 CN_CTLCOLORLISTBOX = CN_BASE + WM_CTLCOLORLISTBOX;
2829 CN_CTLCOLORBTN = CN_BASE + WM_CTLCOLORBTN;
2830 CN_CTLCOLORDLG = CN_BASE + WM_CTLCOLORDLG;
2831 CN_CTLCOLORSCROLLBAR = CN_BASE + WM_CTLCOLORSCROLLBAR;
2832 CN_CTLCOLORSTATIC = CN_BASE + WM_CTLCOLORSTATIC;
2834 CN_DELETEITEM = CN_BASE + WM_DELETEITEM;
2835 CN_DRAWITEM = CN_BASE + WM_DRAWITEM;
2836 CN_HSCROLL = CN_BASE + WM_HSCROLL;
2837 CN_MEASUREITEM = CN_BASE + WM_MEASUREITEM;
2838 CN_PARENTNOTIFY = CN_BASE + WM_PARENTNOTIFY;
2839 CN_VKEYTOITEM = CN_BASE + WM_VKEYTOITEM;
2840 CN_VSCROLL = CN_BASE + WM_VSCROLL;
2841 CN_KEYDOWN = CN_BASE + WM_KEYDOWN;
2842 CN_KEYUP = CN_BASE + WM_KEYUP;
2843 CN_CHAR = CN_BASE + WM_CHAR;
2844 CN_SYSKEYDOWN = CN_BASE + WM_SYSKEYDOWN;
2845 CN_SYSCHAR = CN_BASE + WM_SYSCHAR;
2846 CN_NOTIFY = CN_BASE + WM_NOTIFY;
2849 //[ID_SELF DEFINED]
2850 ID_SELF: array[ 0..5 ] of Char = ( 'S','E','L','F','_',#0 );
2851 {* Identifier for window property "Self", stored directly in window, when
2852 it is created. This property is used to [fast] find TControl object,
2853 correspondent to given window handle (using API call GetProp). }
2855 //[ID_PREVPROC DEFINED]
2856 ID_PREVPROC: array[ 0..9 ] of Char = ( 'P','R','E','V','_','P','R','O','C',#0 );
2857 {* }
2859 //[MK_ALT DEFINED]
2860 MK_ALT = $20;
2862 //[RICHEDIT STRUCTURES]
2863 type
2864 TCharFormat2A = packed record
2865 cbSize: UINT;
2866 dwMask: DWORD;
2867 dwEffects: DWORD;
2868 yHeight: Longint;
2869 yOffset: Longint;
2870 crTextColor: TColorRef;
2871 bCharSet: Byte;
2872 bPitchAndFamily: Byte;
2873 szFaceName: array[0..LF_FACESIZE - 1] of AnsiChar;
2874 R2Bytes: Word;
2875 wWeight: Word; { Font weight (LOGFONT value) }
2876 sSpacing: Smallint; { Amount to space between letters }
2877 crBackColor: TColorRef; { Background color }
2878 lid: LCID; { Locale ID }
2879 dwReserved: DWORD; { Reserved. Must be 0 }
2880 sStyle: Smallint; { Style handle }
2881 wKerning: Word; { Twip size above which to kern char pair }
2882 bUnderlineType: Byte; { Underline type }
2883 bAnimation: Byte; { Animated text like marching ants }
2884 bRevAuthor: Byte; { Revision author index }
2885 bReserved1: Byte;
2886 end;
2887 TCharFormat2 = TCharFormat2A;
2889 TParaFormat2 = packed record
2890 cbSize: UINT;
2891 dwMask: DWORD;
2892 wNumbering: Word;
2893 wReserved: Word;
2894 dxStartIndent: Longint;
2895 dxRightIndent: Longint;
2896 dxOffset: Longint;
2897 wAlignment: Word;
2898 cTabCount: Smallint;
2899 rgxTabs: array [0..MAX_TAB_STOPS - 1] of Longint;
2900 dySpaceBefore: Longint; { Vertical spacing before para }
2901 dySpaceAfter: Longint; { Vertical spacing after para }
2902 dyLineSpacing: Longint; { Line spacing depending on Rule }
2903 sStyle: Smallint; { Style handle }
2904 bLineSpacingRule: Byte; { Rule for line spacing (see tom.doc) }
2905 bCRC: Byte; { Reserved for CRC for rapid searching }
2906 wShadingWeight: Word; { Shading in hundredths of a per cent }
2907 wShadingStyle: Word; { Nibble 0: style, 1: cfpat, 2: cbpat }
2908 wNumberingStart: Word; { Starting value for numbering }
2909 wNumberingStyle: Word; { Alignment, roman/arabic, (), ), ., etc. }
2910 wNumberingTab: Word; { Space bet 1st indent and 1st-line text }
2911 wBorderSpace: Word; { Space between border and text (twips) }
2912 wBorderWidth: Word; { Border pen width (twips) }
2913 wBorders: Word; { Byte 0: bits specify which borders }
2914 { Nibble 2: border style, 3: color index }
2915 end;
2917 TGetTextLengthEx = packed record
2918 flags: DWORD; { flags (see GTL_XXX defines) }
2919 codepage: UINT; { code page for translation (CP_ACP for default,
2920 1200 for Unicode }
2921 end;
2923 const
2924 PFM_SPACEBEFORE = $00000040;
2925 PFM_SPACEAFTER = $00000080;
2926 PFM_LINESPACING = $00000100;
2927 PFM_STYLE = $00000400;
2928 PFM_BORDER = $00000800; { (*) }
2929 PFM_SHADING = $00001000; { (*) }
2930 PFM_NUMBERINGSTYLE = $00002000; { (*) }
2931 PFM_NUMBERINGTAB = $00004000; { (*) }
2932 PFM_NUMBERINGSTART = $00008000; { (*) }
2934 PFM_RTLPARA = $00010000;
2935 PFM_KEEP = $00020000; { (*) }
2936 PFM_KEEPNEXT = $00040000; { (*) }
2937 PFM_PAGEBREAKBEFORE = $00080000; { (*) }
2938 PFM_NOLINENUMBER = $00100000; { (*) }
2939 PFM_NOWIDOWCONTROL = $00200000; { (*) }
2940 PFM_DONOTHYPHEN = $00400000; { (*) }
2941 PFM_SIDEBYSIDE = $00800000; { (*) }
2943 PFM_TABLE = $c0000000; { (*) }
2944 EM_REDO = WM_USER + 84;
2945 EM_AUTOURLDETECT = WM_USER + 91;
2946 EM_GETAUTOURLDETECT = WM_USER + 92;
2947 CFM_UNDERLINETYPE = $00800000; { (*) }
2948 CFM_HIDDEN = $0100; { (*) }
2949 CFM_BACKCOLOR = $04000000;
2950 CFE_AUTOBACKCOLOR = CFM_BACKCOLOR;
2951 GTL_USECRLF = 1; { compute answer using CRLFs for paragraphs }
2952 GTL_PRECISE = 2; { compute a precise answer }
2953 GTL_CLOSE = 4; { fast computation of a "close" answer }
2954 GTL_NUMCHARS = 8; { return the number of characters }
2955 GTL_NUMBYTES = 16; { return the number of _bytes_ }
2956 EM_GETTEXTLENGTHEX = WM_USER + 95;
2957 EM_SETLANGOPTIONS = WM_USER + 120;
2958 EM_GETLANGOPTIONS = WM_USER + 121;
2960 EM_SETEDITSTYLE = $400 + 204;
2961 EM_GETEDITSTYLE = $400 + 205;
2963 SES_EMULATESYSEDIT = 1;
2964 SES_BEEPONMAXTEXT = 2;
2965 SES_EXTENDBACKCOLOR = 4;
2966 SES_MAPCPS = 8;
2967 SES_EMULATE10 = 16;
2968 SES_USECRLF = 32;
2969 SES_USEAIMM = 64;
2970 SES_NOIME = 128;
2971 SES_ALLOWBEEPS = 256;
2972 SES_UPPERCASE = 512;
2973 SES_LOWERCASE = 1024;
2974 SES_NOINPUTSEQUENCECHK = 2048;
2975 SES_BIDI = 4096;
2976 SES_SCROLLONKILLFOCUS = 8192;
2977 SES_XLTCRCRLFTOCR = 16384;
2979 //[CONTROLS]
2981 type
2982 {++}(*TControl = class;*){--}
2983 PControl = {-}^{+}TControl;
2984 {* Type of pointer to TControl visual object. All
2985 |<a href="kol_pas.htm#visual_objects_constructors">
2986 constructing functions
2987 |</a>
2988 New[ControlName] are returning
2989 pointer of this type. Do not forget about some difference
2990 of using objects from using classes. Identifier Self for
2991 methods of object is not of pointer type, and to pass
2992 pointer to Self, it is necessary to pass @Self instead.
2993 At the same time, to use pointer to object in 'WITH' operator,
2994 it is necessary to apply suffix '^' to pointer to get know
2995 to compiler, what do You want. }
2997 //[TWindowFunc TYPE]
2998 TWindowFunc = function( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
2999 : Boolean;
3000 {* Event type to define custom extended message handlers (as pointers to
3001 procedure entry points). Such handlers are usually defined like add-ons,
3002 extending behaviour of certain controls and attached using AttachProc
3003 method of TControl. If the handler detects, that it is necessary to stop
3004 further message processing, it should return True. }
3007 //[Mouse TYPES]
3008 TMouseButton = ( mbNone, mbLeft, mbRight, mbMiddle );
3009 {* Available mouse buttons. mbNone is useful to get know, that
3010 there were no mouse buttons pressed. }
3012 TMouseEventData = packed Record
3013 {* Record to pass it to mouse handling routines, assigned to OnMouseXXXX
3014 events. }
3015 Button: TMouseButton;
3016 StopHandling: Boolean; // Set it to True in OnMouseXXXX event handler to
3017 // stop further processing
3018 R1, R2: Byte; // Not used
3019 Shift : DWORD; // HiWord( Shift ) = zDelta in WM_MOUSEWHEEL
3020 X, Y : SmallInt;
3021 end;
3023 TOnMouse = procedure( Sender: PControl; var Mouse: TMouseEventData ) of object;
3024 {* Common mouse handling event type. }
3026 //[Key TYPES]
3027 TOnKey = procedure( Sender: PControl; var Key: Longint; Shift: DWORD ) of object;
3028 {* Key events. Shift is a combination of flags MK_SHIFT, MK_CONTROL, MK_ALT.
3029 (See GetShiftState funtion). }
3031 TOnChar = procedure( Sender: PControl; var Key: Char; Shift: DWORD ) of object;
3032 {* Char event. Shift is a combination of flags MK_SHIFT, MK_CONTROL, MK_ALT. }
3034 TTabKey = ( tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn );
3035 {* Available tabulating key groups. }
3036 TTabKeys = Set of TTabKey;
3037 {* Set of tabulating key groups, allowed to be used in with a control
3038 (are installed by TControl.LookTabKey property). }
3040 //[Event TYPES]
3041 TOnMessage = function( var Msg: TMsg; var Rslt: Integer ): Boolean of object;
3042 {* Event type for events, which allows to extend behaviour of windowed controls
3043 descendants using add-ons. }
3045 TOnEventAccept = procedure( Sender: PObj; var Accept: Boolean ) of object;
3046 {* Event type for OnClose event. }
3047 TCloseQueryReason = ( qClose, qShutdown, qLogoff );
3048 {* Request reason type to call OnClose and OnQueryEndSession. }
3049 TWindowState = ( wsNormal, wsMinimized, wsMaximized );
3050 {* Avalable states of TControl's window object. }
3052 TOnSplit = function( Sender: PControl; NewSize1, NewSize2: Integer ): Boolean of object;
3053 {* Event type for OnSplit event handler, designed specially for splitter
3054 control. Event handler must return True to accept new size of previous
3055 (to splitter) control and new size of the rest of client area of parent. }
3057 TOnTVBeginDrag = procedure( Sender: PControl; Item: THandle ) of object;
3058 {* Event type for OnTVBeginDrag event (defined for tree view control). }
3059 TOnTVBeginEdit = function( Sender: PControl; Item: THandle ): Boolean of object;
3060 {* Event type for OnTVBeginEdit event (for tree view control). }
3061 TOnTVEndEdit = function( Sender: PControl; Item: THandle; const NewTxt: String )
3062 : Boolean of object;
3063 {* Event type for TOnTVEndEdit event. }
3064 TOnTVExpanding = function( Sender: PControl; Item: THandle; Expand: Boolean )
3065 : Boolean of object;
3066 {* Event type for TOnTVExpanding event. }
3067 TOnTVExpanded = procedure( Sender: PControl; Item: THandle; Expand: Boolean )
3068 of object;
3069 {* Event type for OnTVExpanded event. }
3070 TOnTVDelete = procedure( Sender: PControl; Item: THandle ) of object;
3071 {* Event type for OnTVDelete event. }
3073 //--------- by Sergey Shisminzev:
3074 TOnTVSelChanging = function(Sender: PControl; oldItem, newItem: THandle): Boolean //~ss
3075 of object;
3076 {* When the handler returns False, selection is not changed. }
3077 //-------------------------------
3078 TOnDrag = function( Sender: PControl; ScrX, ScrY: Integer; var CursorShape: Integer;
3079 var Stop: Boolean ): Boolean of object;
3080 {* Event, called during dragging operation (it is initiated
3081 with method Drag, where callback function of type TOnDrag is
3082 passed as a parameter). Callback function receives Stop parameter True,
3083 when operation is finishing. Otherwise, it can set it to True to force
3084 finishing the operation (in such case, returning False means cancelling
3085 drag operation, True - successful drag and in this last case callback is
3086 no more called). During the operation, when input Stop value is False,
3087 callback function can control Cursor shape, and return True, if the operation
3088 can be finished successfully at the given ScrX, ScrY position.
3089 ScrX, ScrY are screen coordinates of the mouse cursor. }
3091 //[Create Window STRUCTURES]
3092 TCreateParams = packed record
3093 {* Record to pass it through CreateSubClass method. }
3094 Caption: PChar;
3095 Style: cardinal;
3096 ExStyle: cardinal;
3097 X, Y: Integer;
3098 Width, Height: Integer;
3099 WndParent: HWnd;
3100 Param: Pointer;
3101 WindowClass: TWndClass;
3102 WinClassName: array[0..63] of Char;
3103 end;
3105 TCreateWndParams = packed Record
3106 ExStyle: DWORD;
3107 WinClassName: PChar;
3108 Caption: PChar;
3109 Style: DWORD;
3110 X, Y, Width, Height: Integer;
3111 WndParent: HWnd;
3112 Menu: HMenu;
3113 Inst: THandle;
3114 Param: Pointer;
3115 WinClsNamBuf: array[ 0..63 ] of Char;
3116 WindowClass: TWndClass;
3117 end;
3120 //[COMMAND ACTIONS TYPE FOR DIFFERENT CONTROLS]
3121 PCommandActions = ^TCommandActions;
3122 TCommandActions = packed Record
3123 aClear: procedure( Sender: PControl );
3124 aAddText: procedure( Sender: PControl; const S: String );
3125 aClick, aEnter, aLeave: WORD; aChange: SmallInt; aSelChange: SmallInt;
3126 aGetCount, aSetCount, aGetItemLength, aGetItemText, aSetItemText,
3127 aGetItemData, aSetItemData: WORD;
3128 aAddItem, aDeleteItem, aInsertItem: WORD;
3129 aFindItem, aFindPartial: WORD;
3130 aItem2Pos, aPos2Item: BYTE;
3131 aGetSelCount, aGetSelected, aGetSelRange, aExGetSelRange, aGetCurrent,
3132 aSetSelected, aSetCurrent, aSetSelRange, aExSetSelRange,
3133 aGetSelection, aReplaceSel: WORD;
3134 aTextAlignLeft, aTextAlignRight, aTextAlignCenter: WORD;
3135 aTextAlignMask: Byte;
3136 aVertAlignCenter, aVertAlignTop, aVertAlignBottom: Byte;
3137 aDir, aSetLimit: Word; aSetImgList: Word;
3138 aAutoSzX, aAutoSzY: Word;
3139 aSetBkColor: Word;
3140 aItem2XY: Word;
3141 end;
3143 //[Align TYPES]
3144 TTextAlign = ( taLeft, taRight, taCenter );
3145 {* Text alignments available. }
3146 TRichTextAlign = ( raLeft, raRight, raCenter,
3147 // all other are only set but can not be displayed:
3148 raJustify, // displayed like raLeft (though stored normally)
3149 raInterLetter, raScaled, raGlyphs, raSnapGrid );
3150 {* Text alignment styles, available for RichEdit control. }
3151 TVerticalAlign = ( vaCenter, vaTop, vaBottom );
3152 {* Vertical alignments available. }
3153 TControlAlign = ( caNone, caLeft, caTop, caRight, caBottom, caClient );
3154 {* Control alignments available. }
3156 //[BitBtn TYPES]
3157 TBitBtnOption = ( bboImageList,
3158 bboNoBorder,
3159 bboNoCaption,
3160 bboFixed );
3161 {* Options available for NewBitBtn. }
3162 TBitBtnOptions = set of TBitBtnOption;
3163 {* Set of options, available for NewBitBtn. }
3164 TGlyphLayout = ( glyphLeft, glyphTop, glyphRight, glyphBottom, glyphOver );
3165 {* Layout of glyph (for NewBitBtn). Layout glyphOver means that text is
3166 drawn over glyph. }
3167 TOnBitBtnDraw = function( Sender: PControl; BtnState: Integer ): Boolean of object;
3168 {* Event type for TControl.OnBitBtnDraw event (which is called just before
3169 drawing the BitBtn). If handler returns True, there are no drawing occure.
3170 BtnState, passed to a handler, determines current button state and can
3171 be following: 0 - not pressed, 1 - pressed, 2 - disabled, 3 - focused.
3172 Value 4 is reserved for highlight state (then mouse is over it), but
3173 highlighting is provided only if property Flat is set to True (or one
3174 of events OnMouseEnter / OnMouseLeave is assigned to something). }
3176 //[ListView TYPES]
3177 TListViewStyle = ( lvsIcon, lvsSmallIcon, lvsList, lvsDetail, lvsDetailNoHeader );
3178 {* Styles of view for ListView control (see NewListVew). }
3180 TListViewItemStates = ( lvisFocus, lvisSelect, lvisBlend, lvisHighlight );
3181 TListViewItemState = Set of TListViewItemStates;
3182 TListViewOption = (
3183 lvoIconLeft, // in lvsIcon, lvsSmallIcon plce icon left from text (rather then top)
3184 lvoAutoArrange, // keep icons auto arranged in lvsIcon and lvsSmallIcon view
3185 lvoButton, // icons look like buttons in lvsIcon view
3186 lvoEditLabel, // allows edit labels inplace (first column #0 text)
3187 lvoNoLabelWrap, // item text on a single line in lvsIcon view (by default, item text may wrap in lvsIcon view).
3188 lvoNoScroll, // obvious
3189 lvoNoSortHeader, // click on header button does not lead to sort items
3190 lvoHideSel, // hide selection when not in focus
3191 lvoMultiselect, // allow to select multiple items
3192 lvoSortAscending,
3193 lvoSortDescending,
3194 // extended styles (not documented in my Win32.hlp :( , got from VCL source:
3195 lvoGridLines,
3196 lvoSubItemImages,
3197 lvoCheckBoxes,
3198 lvoTrackSelect,
3199 lvoHeaderDragDrop,
3200 lvoRowSelect,
3201 lvoOneClickActivate,
3202 lvoTwoClickActivate,
3203 lvoFlatsb,
3204 lvoRegional,
3205 lvoInfoTip,
3206 lvoUnderlineHot,
3207 lvoMultiWorkares,
3208 // virtual list view style:
3209 lvoOwnerData,
3210 // custom draw style:
3211 lvoOwnerDrawFixed
3213 TListViewOptions = Set of TListViewOption;
3215 TOnEditLVItem = function( Sender: PControl; Idx, Col: Integer; NewText: PChar ): Boolean
3216 of object;
3217 {* Event type for OnEndEditLVItem. Return True in handler to accept new text value. }
3218 TOnDeleteLVItem = procedure( Sender: PControl; Idx: Integer ) of object;
3219 {* Event type for OnDeleteLVItem event. }
3220 TOnLVData = procedure( Sender: PControl; Idx, SubItem: Integer;
3221 var Txt: String; var ImgIdx: Integer; var State: DWORD;
3222 var Store: Boolean ) of object;
3223 {* Event type for OnLVData event. Used to provide virtual list view control
3224 (i.e. having lvoOwnerData style) with actual data on request. Use parameter
3225 Store as a flag if control should store obtained data by itself or not. }
3226 {$IFNDEF _D2}
3227 {$IFNDEF _FPC}
3228 TOnLVDataW = procedure( Sender: PControl; Idx, SubItem: Integer;
3229 var Txt: WideString; var ImgIdx: Integer; var State: DWORD;
3230 var Store: Boolean ) of object;
3231 {* Event type for OnLVDataW event (the same as OnLVData, but for unicode verion
3232 of the control OnLVDataW allows to return WideString text in the event
3233 handler). Used to provide virtual list view control
3234 (i.e. having lvoOwnerData style) with actual data on request. Use parameter
3235 Store as a flag if control should store obtained data by itself or not. }
3236 {$ENDIF _FPC}
3237 {$ENDIF _D2}
3238 TOnCompareLVItems = function( Sender: PControl; Idx1, Idx2: Integer ): Integer
3239 of object;
3240 {* Event type to compare two items of the list view (while sorting it). }
3241 TOnLVColumnClick = procedure( Sender: PControl; Idx: Integer ) of object;
3242 {* Event type for OnColumnClick event. }
3243 TOnLVStateChange = procedure( Sender: PControl; IdxFrom, IdxTo: Integer; OldState, NewState: DWORD )
3244 of object;
3245 {* Event type for OnLVStateChange event, called in responce to select/unselect
3246 a single item or items range in list view control). }
3247 TOnLVDelete = procedure( Sender: PControl; Idx: Integer ) of object;
3248 {* Event type for OnLVDelete event, called when an item is been deleting. }
3250 TDrawActions = ( odaEntire, odaFocus, odaSelect );
3251 TDrawAction = Set of TDrawActions;
3252 TDrawStates = ( odsSelected, odsGrayed, odsDisabled, odsChecked, odsFocused,
3253 odsDefault, odsHotlist, odsInactive,
3254 odsNoAccel, odsNoFocusRect,
3255 ods400reserved, ods800reserved,
3256 odsComboboxEdit,
3257 // specific for common controls:
3258 odsMarked, odsIndeterminate );
3259 {* Possible draw states.
3260 |<br>odsSelected - The menu item's status is selected.
3261 |<br>odsGrayed - The item is to be grayed. This bit is used only in a menu.
3262 |<br>odsDisabled - The item is to be drawn as disabled.
3263 |<br>odsChecked - The menu item is to be checked. This bit is used only in
3264 a menu.
3265 |<br>odsFocused - The item has the keyboard focus.
3266 |<br>odsDefault - The item is the default item.
3267 |<br>odsHotList - <b>Windows 98, Windows 2000:</b> The item is being
3268 hot-tracked, that is, the item will be highlighted when
3269 the mouse is on the item.
3270 |<br>odsInactive - <b>Windows 98, Windows 2000:</b> The item is inactive
3271 and the window associated with the menu is inactive.
3272 |<br>odsNoAccel - <b>Windows 2000:</b> The control is drawn without the
3273 keyboard accelerator cues.
3274 |<br>odsNoFocusRect - <b>Windows 2000:</b> The control is drawn without
3275 focus indicator cues.
3276 |<br>odsComboboxEdit - The drawing takes place in the selection field
3277 (edit control) of an owner-drawn combo box.
3278 |<br>odsMarked - for Common controls only. The item is marked. The meaning
3279 of this is up to the implementation.
3280 |<br>odsIndeterminate - for Common Controls only. The item is in an
3281 indeterminate state. }
3282 TDrawState = Set of TDrawStates;
3283 {* Set of possible draw states. }
3284 TOnDrawItem = function( Sender: PObj; DC: HDC; const Rect: TRect; ItemIdx: Integer;
3285 DrawAction: TDrawAction; ItemState: TDrawState ): Boolean of object;
3286 {* Event type for OnDrawItem event (applied to list box, combo box, list view). }
3287 TOnMeasureItem = function( Sender: PObj; Idx: Integer ): Integer of object;
3288 {* Event type for OnMeasureItem event. The event handler must return height of list box
3289 item as a result. }
3290 TGetLVItemPart = ( lvipBounds, lvipIcon, lvipLabel, lvupIconAndLabel );
3291 {* }
3292 TWherePosLVItem = ( lvwpOnIcon, lvwpOnLabel, lvwpOnStateIcon, lvwpOnColumn,
3293 lvwpOnItem );
3294 {* }
3296 TOnLVCustomDraw = function( Sender: PControl; DC: HDC; Stage: DWORD;
3297 ItemIdx, SubItemIdx: Integer; const Rect: TRect;
3298 ItemState: TDrawState; var TextColor, BackColor: TColor )
3299 : DWORD of object;
3300 {* Event type for OnLVCustomDraw event. }
3302 //[Paint TYPES]
3303 TOnPaint = procedure( Sender: PControl; DC: HDC ) of object;
3304 TPaintProc = procedure( DC: HDC ) of object;
3306 TGradientStyle = ( gsVertical, gsHorizontal, gsRectangle, gsElliptic, gsRombic );
3307 {* Gradient fill styles. See also TGradientLayout. }
3308 TGradientLayout = ( glTopLeft, glTop, glTopRight,
3309 glLeft, glCenter, glRight,
3310 glBottomLeft, glBottom, glBottomRight );
3311 {* Position of starting line / point for gradient filling. Depending on
3312 TGradientStyle, means either position of first line of first rectangle
3313 (ellipse) to be expanded in a loop to fit entire gradient panel area. }
3315 //[Edit TYPES]
3316 TEditOption = ( eoNoHScroll, eoNoVScroll, eoLowercase, eoMultiline,
3317 eoNoHideSel, eoOemConvert, eoPassword, eoReadonly,
3318 eoUpperCase, eoWantReturn, eoWantTab, eoNumber );
3319 {* Available edit options.
3320 |<br> Please note, that eoWantTab option just removes TAB key from a list
3321 of keys available to tabulate from the edit control. To provide insertion
3322 of tabulating key, do so in TControl.OnChar event handler. Sorry for
3323 inconvenience, but this is because such behaviour is not must in all cases.
3324 See also TControl.EditTabChar property. }
3325 TEditOptions = Set of TEditOption;
3326 {* Set of available edit options. }
3328 TRichFmtArea = ( raSelection, raWord, raAll );
3329 {* Characters formatting area for RichEdit. }
3330 TRETextFormat = ( reRTF, reText, rePlainRTF, reRTFNoObjs, rePlainRTFNoObjs,
3331 reTextized );
3332 {* Available formats for transfer RichEdit text using property
3333 TControl.RE_Text.
3334 |<pre>
3335 reRTF - normal rich text (no transformations)
3336 reText - plain text only (without OLE objects)
3337 reTextized - plain text with text representation of OLE objects
3338 rePlainRTF - reRTF without language-specific keywords
3339 reRTFNoObjs - reRTF without OLE objects
3340 rePlainRTFNoObjs - rePlainRTF without OLE objects
3341 |</pre> }
3342 TRichUnderline = ( ruSingle, ruWord, ruDouble, ruDotted,
3343 //all other - only for RichEditv3.0:
3344 ruDash, ruDashDot, ruDashDotDot, ruWave, ruThick, ruHairLine );
3345 {* Rich text exteded underline styles (available only for RichEdit v2.0,
3346 and even for RichEdit v2.0 additional styles can not displayed - but
3347 ruDotted under Windows2000 is working). }
3348 TRichTextSizes = ( rtsNoUseCRLF, rtsNoPrecise, rtsClose, rtsBytes );
3349 {* Options to calculate size of rich text. Available only for RichEdit2.0
3350 or higher. }
3351 TRichTextSize = set of TRichTextSizes;
3352 {* Set of all available optioins to calculate rich text size using
3353 property TControl.RE_TextSize[ options ]. }
3354 TRichNumbering = ( rnNone, rnBullets, rnArabic, rnLLetter, rnULetter,
3355 rnLRoman, rnURoman );
3356 {* Advanced numbering styles for paragraph (RichEdit).
3357 |<pre>
3358 rnNone - no numbering
3359 rnBullets - bullets only
3360 rnArabic - 1, 2, 3, 4, ...
3361 rnLLetter - a, b, c, d, ...
3362 rnULetter - A, B, C, D, ...
3363 rnLRoman - i, ii, iii, iv, ...
3364 rnURoman - I, II, III, IV, ...
3365 rnNoNumber - do not show any numbers (but numbering is taking place).
3366 |</pre> }
3367 TRichNumBrackets = ( rnbRight, rnbBoth, rnbPeriod, rnbPlain, rnbNoNumber );
3368 {* Brackets around number:
3369 |<pre>
3370 rnbRight - 1) 2) 3) - this is default !
3371 rnbBoth - (1) (2) (3)
3372 rnbPeriod - 1. 2. 3.
3373 rnbPlain - 1 2 3
3374 |</pre> }
3375 TBorderEdge = (beLeft, beTop, beRight, beBottom);
3376 {* Borders of rectangle. }
3378 TCharFormat = TCharFormat2;
3379 TParaFormat = TParaFormat2;
3381 TOnTestMouseOver = function( Sender: PControl ): Boolean of object;
3382 {* Event type for TControl.OnTestMouseOver event. The handler should
3383 return True, if it dectects, that mouse is over control. }
3385 TEdgeStyle = ( esRaised, esLowered, esNone );
3386 {* Edge styles (for panel - see NewPanel). }
3388 //[List TYPES]
3389 TListOption = ( loNoHideScroll, loNoExtendSel, loMultiColumn, loMultiSelect,
3390 loNoIntegralHeight, loNoSel, loSort, loTabstops,
3391 loNoStrings, loNoData, loOwnerDrawFixed, loOwnerDrawVariable );
3392 {* Options for ListBox (see NewListbox). }
3393 TListOptions = Set of TListOption;
3394 {* Set of available options for Listbox. }
3396 TComboOption = ( coReadOnly, coNoHScroll, coAlwaysVScroll, coLowerCase,
3397 coNoIntegralHeight, coOemConvert, coSort, coUpperCase,
3398 coOwnerDrawFixed, coOwnerDrawVariable, coSimple );
3399 {* Options for combobox. }
3400 TComboOptions = Set of TComboOption;
3401 {* Set of options available for combobox. }
3403 //[Progress TYPES]
3404 TProgressbarOption = ( pboVertical, pboSmooth );
3405 {* Options for progress bar. }
3406 TProgressbarOptions = set of TProgressbarOption;
3407 {* Set of options available for progress bar. }
3409 //[TreeView TYPES]
3410 TTreeViewOption = ( tvoNoLines, tvoLinesRoot, tvoNoButtons, tvoEditLabels, tvoHideSel,
3411 tvoDragDrop, tvoNoTooltips, tvoCheckBoxes, tvoTrackSelect,
3412 tvoSingleExpand, tvoInfoTip, tvoFullRowSelect, tvoNoScroll,
3413 tvoNonEvenHeight );
3414 {* Tree view options. }
3415 TTreeViewOptions = set of TTreeViewOption;
3416 {* Set of tree view options. }
3418 //[TabControl TYPES]
3419 TTabControlOption = ( tcoButtons, tcoFixedWidth, tcoFocusTabs,
3420 tcoIconLeft, tcoLabelLeft,
3421 tcoMultiline, tcoMultiselect, tcoFitRows, tcoScrollOpposite,
3422 tcoBottom, tcoVertical, tcoFlat, tcoHotTrack, tcoBorder,
3423 tcoOwnerDrawFixed );
3424 {* Options, available for TabControl. }
3425 TTabControlOptions = set of TTabControlOption;
3426 {* Set of options, available for TAbControl during its creation (by
3427 NewTabControl function). }
3429 //[Toolbar TYPES]
3430 TToolbarOption = ( tboTextRight, tboTextBottom, tboFlat, tboTransparent,
3431 tboWrapable, tboNoDivider, tbo3DBorder );
3432 {* Toolbar options. When tboFlat is set and toolbar is placed onto panel,
3433 set its property Transparent to TRUE to provide its correct view. }
3434 TToolbarOptions = Set of TToolbarOption;
3435 {* Set of toolbar options. }
3436 TOnToolbarButtonClick = procedure( Sender: PControl; BtnID: Integer ) of object;
3437 {* Special event type to handle separate toolbar buttons click events. }
3439 TDateTimePickerOption = ( dtpoTime, dtpoDateLong, dtpoUpDown, dtpoRightAlign,
3440 dtpoShowNone, dtpoParseInput );
3441 {* }
3442 TDateTimePickerOptions = set of TDateTimePickerOption;
3443 {* }
3444 TDTParseInputEvent = procedure(Sender: PControl; const UserString: string;
3445 var DateAndTime: TDateTime; var AllowChange: Boolean) of object;
3446 {* }
3447 TDateTimeRange = array[ 0..1 ] of TDateTime;
3448 {* }
3449 TDateTimePickerColor = ( dtpcBackground, dtpcMonthBk, dtpcText, dtpcTitleBk,
3450 dtpcTitleText, dtpcTrailingText );
3452 //[TOnDropFiles TYPE]
3453 TOnDropFiles = procedure( Sender: PControl; const FileList: String; const Pt: TPoint ) of object;
3454 {* An event type for OnDropFiles event. When the event is occur, FileList
3455 parameter contains a list of files dropped. File names in a list are
3456 separated with #13 character. This allows You to assign it to TStrList
3457 object using its property Text (for example):
3458 ! procedure TSomeObject.DropFiles( Sender: PControl; const FileList: String;
3459 ! const Pt: TPoint ); )
3460 ! var FList: PStrList;
3461 ! I: Integer;
3462 ! begin
3463 ! FList := NewStrList;
3464 ! FList.Text := FileList;
3465 ! for I := 0 to FList.Count-1 do
3466 ! begin
3467 ! // do something with FList.Items[ I ]
3468 ! end;
3469 ! FList.Free;
3470 ! end; }
3472 //[Scroll TYPES]
3473 TScrollerBar = ( sbHorizontal, sbVertical );
3474 TScrollerBars = set of TScrollerBar;
3476 TOnScroll = procedure( Sender: PControl; Bar: TScrollerBar; ScrollCmd: DWORD;
3477 ThumbPos: DWORD ) of object;
3479 //[TOnHelp EVENT TYPE]
3480 TOnHelp = procedure( var Sender: PControl; var Context: Integer; var Popup: Boolean )
3481 of object;
3483 //[ScrollBar TYPES]
3484 TOnSBBeforeScroll =
3485 procedure(
3486 Sender: PControl; OldPos, NewPos: Integer; Cmd: Word;
3487 var AllowChange: Boolean) of object;
3488 TOnSBScroll = procedure(Sender: PControl; Cmd: Word) of object;
3490 TOnGraphCtlMouse = procedure( var Msg: TMsg ) of object;
3491 TTriStateCheck = (tsUnchecked{=0}, tsChecked{=1}, tsIndeterminate{=2});
3494 {$IFDEF USE_MHTOOLTIP}
3495 {$DEFINE pre_interface}
3496 {$I KOLMHToolTip}
3497 {$UNDEF pre_interface}
3498 {$ENDIF}
3500 { ----------------------------------------------------------------------
3502 TControl - object to implement any visual control
3504 ----------------------------------------------------------------------- }
3505 //[TControl DEFINITION]
3506 TControl = object( TObj )
3507 protected
3508 fSBMinMax: TPoint;
3509 fSBPageSize: Integer;
3510 fSBPosition: Integer;
3511 procedure SetSBMax(Value: Longint);
3512 procedure SetSBMin(Value: Longint);
3513 procedure SetSBPageSize(Value: Integer);
3514 procedure SetSBPosition(Value: Integer);
3515 procedure SetSBMinMax(const Value: TPoint);
3517 function GetDate: TDateTime;
3518 function GetTime: TDateTime;
3519 procedure SetDate(const Value: TDateTime);
3520 procedure SetTime(const Value: TDateTime);
3521 {*! TControl is the basic visual object of KOL. And now, all visual
3522 objects have the same type PControl, differing only in "constructor",
3523 which during creating of object adjusts it so it can play role of
3524 desired control. Idea of incapsulating of all visual objects having
3525 the most common set of properties, is belonging to Vladimir Kladov,
3526 (C) 2000.
3527 |<br>&nbsp;&nbsp;&nbsp;<b> Since all visual objects are represented
3528 in KOL by this single object type, not all methods, properties and
3529 events defined in TControl, are applicable to different visual objects.
3530 See also notes about certain control kinds, located together with its
3531 |<a href="kol_pas.htm#visual_objects_constructors">
3532 |constructing functions definitions</a></b>. }
3533 protected
3534 function GetHelpPath: String;
3535 procedure SetHelpPath(const Value: String);
3536 procedure SetOnQueryEndSession(const Value: TOnEventAccept);
3537 procedure SetOnMinMaxRestore(const Index: Integer; const Value: TOnEvent);
3538 procedure SetConstraint(const Index, Value: Integer);
3539 {$IFDEF F_P}
3540 function GetOnMinMaxRestore(const Index: Integer): TOnEvent;
3541 function GetConstraint(const Index: Integer): Integer;
3542 {$ENDIF F_P}
3543 procedure SetOnScroll(const Value: TOnScroll);
3544 function GetLVColalign(Idx: Integer): TTextAlign;
3545 procedure SetLVColalign(Idx: Integer; const Value: TTextAlign);
3547 procedure SetParent( Value: PControl );
3548 function GetLeft: Integer;
3549 procedure SetLeft( Value: Integer );
3550 function GetTop: Integer;
3551 procedure SetTop( Value: Integer );
3552 function GetWidth: Integer;
3553 procedure SetWidth( Value: Integer );
3554 function GetHeight: Integer;
3555 procedure SetHeight( Value: Integer );
3557 function GetPosition: TPoint;
3558 procedure Set_Position( Value: TPoint );
3560 function GetMembers(Idx: Integer): PControl;
3561 function GetFont: PGraphicTool;
3562 procedure FontChanged( Sender: PGraphicTool );
3563 function GetBrush: PGraphicTool;
3564 procedure BrushChanged( Sender: PGraphicTool );
3565 function GetClientHeight: Integer;
3566 function GetClientWidth: Integer;
3567 procedure SetClientHeight(const Value: Integer);
3568 procedure SetClientWidth(const Value: Integer);
3569 function GetHasBorder: Boolean;
3570 procedure SetHasBorder(const Value: Boolean);
3572 function GetHasCaption: Boolean;
3573 procedure SetHasCaption(const Value: Boolean);
3575 function GetCanResize: Boolean;
3576 procedure SetCanResize( const Value: Boolean );
3578 function GetStayOnTop: Boolean;
3579 procedure SetStayOnTop(const Value: Boolean);
3580 function GetChecked: Boolean;
3581 procedure Set_Checked(const Value: Boolean);
3583 function GetCheck3: TTriStateCheck;
3584 procedure SetCheck3(value: TTriStateCheck);
3586 function GetSelStart: Integer;
3587 procedure SetSelStart(const Value: Integer);
3588 function GetSelLength: Integer;
3589 procedure SetSelLength(const Value: Integer);
3591 function GetItems(Idx: Integer): String;
3592 procedure SetItems(Idx: Integer; const Value: String);
3594 function GetItemsCount: Integer;
3595 function GetItemSelected(ItemIdx: Integer): Boolean;
3596 procedure SetItemSelected(ItemIdx: Integer; const Value: Boolean);
3598 procedure SetCtl3D(const Value: Boolean);
3599 function GetCurIndex: Integer;
3600 procedure SetCurIndex(const Value: Integer);
3601 function GetTextAlign: TTextAlign;
3602 function GetVerticalAlign: TVerticalAlign;
3603 procedure SetTextAlign(const Value: TTextAlign);
3604 procedure SetVerticalAlign(const Value: TVerticalAlign);
3606 function GetCanvas: PCanvas;
3607 function Dc2Canvas( Sender: PCanvas ): HDC;
3608 procedure SetShadowDeep(const Value: Integer);
3609 procedure SetDoubleBuffered(const Value: Boolean);
3611 procedure SetStatusText(Index: Integer; Value: PChar);
3612 function GetStatusText( Index: Integer ): PChar;
3613 function GetStatusPanelX(Idx: Integer): Integer;
3614 procedure SetStatusPanelX(Idx: Integer; const Value: Integer);
3616 procedure SetTransparent(const Value: Boolean);
3617 function GetImgListIdx(const Index: Integer): PImageList;
3619 procedure SetImgListIdx(const Index: Integer; const Value: PImageList);
3620 function GetLVColText(Idx: Integer): String;
3621 procedure SetLVColText(Idx: Integer; const Value: String);
3622 {$IFNDEF _FPC}
3623 {$IFNDEF _D2}
3624 function GetLVColTextW(Idx: Integer): WideString;
3625 procedure SetLVColTextW(Idx: Integer; const Value: WideString);
3626 {$ENDIF _D2}
3627 {$ENDIF _FPC}
3628 function LVGetItemText(Idx, Col: Integer): String;
3629 procedure LVSetItemText(Idx, Col: Integer; const Value: String);
3630 {$IFNDEF _FPC}
3631 {$IFNDEF _D2}
3632 function LVGetItemTextW(Idx, Col: Integer): WideString;
3633 procedure LVSetItemTextW(Idx, Col: Integer; const Value: WideString);
3634 {$ENDIF _D2}
3635 {$ENDIF _FPC}
3636 procedure SetLVOptions(const Value: TListViewOptions);
3637 procedure SetLVStyle(const Value: TListViewStyle);
3638 function GetLVColEx(Idx: Integer; const Index: Integer): Integer;
3639 procedure SetLVColEx(Idx: Integer; const Index: Integer;
3640 const Value: Integer);
3642 function GetChildCount: Integer;
3644 function LVGetItemPos(Idx: Integer): TPoint;
3645 procedure LVSetItemPos(Idx: Integer; const Value: TPoint);
3646 procedure LVSetColorByIdx(const Index: Integer; const Value: TColor);
3647 {$IFDEF F_P}
3648 function LVGetColorByIdx(const Index: Integer): TColor;
3649 {$ENDIF F_P}
3650 function GetIntVal(const Index: Integer): Integer;
3651 procedure SetIntVal(const Index, Value: Integer);
3652 function GetItemVal(Item: Integer; const Index: Integer): Integer;
3653 procedure SetItemVal(Item: Integer; const Index, Value: Integer);
3654 function TBGetButtonVisible(BtnID: Integer): Boolean;
3655 procedure TBSetButtonVisible(BtnID: Integer; const Value: Boolean);
3657 function TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;
3658 procedure TBSetBtnStt(BtnID: Integer; const Index: Integer; const Value: Boolean);
3659 function TBGetButtonText(BtnID: Integer): String;
3660 function TBGetButtonRect(BtnID: Integer): TRect;
3662 function TBGetRows: Integer;
3663 procedure TBSetRows(const Value: Integer);
3664 procedure SetProgressColor(const Value: TColor);
3665 function TBGetBtnImgIdx(BtnID: Integer): Integer;
3666 procedure TBSetBtnImgIdx(BtnID: Integer; const Value: Integer);
3668 procedure TBSetButtonText(BtnID: Integer; const Value: String);
3670 function TBGetBtnWidth(BtnID: Integer): Integer;
3671 procedure TBSetBtnWidth(BtnID: Integer; const Value: Integer);
3672 procedure TBSetBtMinMaxWidth(const Idx: Integer; const Value: Integer);
3673 {$IFDEF F_P}
3674 function TBGetBtMinMaxWidth(const Idx: Integer): Integer;
3675 {$ENDIF F_P}
3676 procedure TBFreeTBevents;
3677 procedure Set_Align(const Value: TControlAlign);
3678 function GetSelection: String;
3679 procedure SetSelection(const Value: String);
3680 procedure SetTabOrder(const Value: Integer);
3681 function GetFocused: Boolean;
3682 procedure SetFocused(const Value: Boolean);
3683 function REGetFont: PGraphicTool;
3684 procedure RESetFont(Value: PGraphicTool);
3685 procedure RESetFontEx(const Index: Integer);
3686 function REGetFontEffects(const Index: Integer): Boolean;
3687 function REGetFontMask(const Index: Integer): Boolean;
3688 procedure RESetFontEffect(const Index: Integer; const Value: Boolean);
3689 function REGetFontAttr(const Index: Integer): Integer;
3690 procedure RESetFontAttr(const Index, Value: Integer);
3691 procedure RESetFontAttr1(const Index, Value: Integer);
3692 function REGetFontSizeValid: Boolean;
3693 function REGetCharformat: TCharFormat;
3694 procedure RESetCharFormat(const Value: TCharFormat);
3695 function REReadText(Format: TRETextFormat;
3696 SelectionOnly: Boolean): String;
3697 procedure REWriteText(Format: TRETextFormat; SelectionOnly: Boolean;
3698 const Value: String);
3699 function REGetFontName: String;
3700 procedure RESetFontName(const Value: String);
3701 function REGetParaFmt: TParaFormat;
3702 procedure RESetParaFmt(const Value: TParaFormat);
3703 function REGetNumbering: Boolean;
3704 function REGetParaAttr( const Index: Integer ): Integer;
3705 function REGetParaAttrValid( const Index: Integer ): Boolean;
3706 function REGetTabCount: Integer;
3707 function REGetTabs(Idx: Integer): Integer;
3708 function REGetTextAlign: TRichTextAlign;
3709 procedure RESetNumbering(const Value: Boolean);
3710 procedure RESetParaAttr(const Index, Value: Integer);
3711 procedure RESetTabCount(const Value: Integer);
3712 procedure RESetTabs(Idx: Integer; const Value: Integer);
3713 procedure RESetTextAlign(const Value: TRichTextAlign);
3714 function REGetStartIndentValid: Boolean;
3715 function REGetAutoURLDetect: Boolean;
3716 procedure RESetAutoURLDetect(const Value: Boolean);
3718 function GetMaxTextSize: DWORD;
3719 procedure SetMaxTextSize(const Value: DWORD);
3720 procedure SetOnResize(const Value: TOnEvent);
3722 procedure DoSelChange;
3724 function REGetUnderlineEx: TRichUnderline;
3725 procedure RESetUnderlineEx(const Value: TRichUnderline);
3727 function GetTextSize: Integer;
3728 function REGetTextSize(Units: TRichTextSize): Integer;
3730 function REGetNumStyle: TRichNumbering;
3731 procedure RESetNumStyle(const Value: TRichNumbering);
3732 function REGetNumBrackets: TRichNumBrackets;
3733 procedure RESetNumBrackets(const Value: TRichNumBrackets);
3734 function REGetNumTab: Integer;
3735 procedure RESetNumTab(const Value: Integer);
3736 function REGetNumStart: Integer;
3737 procedure RESetNumStart(const Value: Integer);
3738 function REGetSpacing(const Index: Integer): Integer;
3739 procedure RESetSpacing(const Index, Value: Integer);
3740 function REGetSpacingRule: Integer;
3741 procedure RESetSpacingRule(const Value: Integer);
3742 function REGetLevel: Integer;
3743 function REGetBorder(Side: TBorderEdge; const Index: Integer): Integer;
3744 procedure RESetBorder(Side: TBorderEdge; const Index: Integer;
3745 const Value: Integer);
3746 function REGetParaEffect(const Index: Integer): Boolean;
3747 procedure RESetParaEffect(const Index: Integer; const Value: Boolean);
3748 function REGetOverwite: Boolean;
3749 procedure RESetOverwrite(const Value: Boolean);
3750 procedure RESetOvrDisable(const Value: Boolean);
3751 function REGetTransparent: Boolean;
3752 procedure RESetTransparent(const Value: Boolean);
3753 procedure RESetOnURL(const Index: Integer; const Value: TOnEvent);
3754 {$IFDEF F_P}
3755 function REGetOnURL(const Index: Integer): TOnEvent;
3756 {$ENDIF F_P}
3757 function REGetLangOptions(const Index: Integer): Boolean;
3758 procedure RESetLangOptions(const Index: Integer; const Value: Boolean);
3759 function LVGetItemImgIdx(Idx: Integer): Integer;
3760 procedure LVSetItemImgIdx(Idx: Integer; const Value: Integer);
3761 procedure SetFlat(const Value: Boolean);
3762 procedure SetOnMouseEnter(const Value: TOnEvent);
3763 procedure SetOnMouseLeave(const Value: TOnEvent);
3764 procedure EdSetTransparent(const Value: Boolean);
3765 procedure SetOnTestMouseOver(const Value: TOnTestMouseOver);
3766 function GetPages(Idx: Integer): PControl;
3767 function TCGetItemText(Idx: Integer): String;
3768 procedure TCSetItemText(Idx: Integer; const Value: String);
3769 function TCGetItemImgIDx(Idx: Integer): Integer;
3770 procedure TCSetItemImgIdx(Idx: Integer; const Value: Integer);
3771 function TCGetItemRect(Idx: Integer): TRect;
3772 function TVGetItemIdx(const Index: Integer): THandle;
3773 procedure TVSetItemIdx(const Index: Integer; const Value: THandle);
3774 function TVGetItemNext(Item: THandle; const Index: Integer): THandle;
3775 function TVGetItemRect(Item: THandle; TextOnly: Boolean): TRect;
3776 function TVGetItemVisible(Item: THandle): Boolean;
3777 procedure TVSetITemVisible(Item: THandle; const Value: Boolean);
3778 function TVGetItemStateFlg(Item: THandle; const Index: Integer): Boolean;
3779 procedure TVSetItemStateFlg(Item: THandle; const Index: Integer;
3780 const Value: Boolean);
3781 function TVGetItemImage(Item: THandle; const Index: Integer): Integer;
3782 procedure TVSetItemImage(Item: THandle; const Index: Integer;
3783 const Value: Integer);
3784 function TVGetItemText(Item: THandle): String;
3785 procedure TVSetItemText(Item: THandle; const Value: String);
3786 {$IFNDEF _FPC}
3787 {$IFNDEF _D2}
3788 function TVGetItemTextW(Item: THandle): WideString;
3789 procedure TVSetItemTextW(Item: THandle; const Value: WideString);
3790 {$ENDIF _D2}
3791 {$ENDIF _FPC}
3792 function TV_GetItemHasChildren(Item: THandle): Boolean;
3793 procedure TV_SetItemHasChildren(Item: THandle; const Value: Boolean);
3794 function TV_GetItemChildCount(Item: THandle): Integer;
3795 function TVGetItemData(Item: THandle): Pointer;
3796 procedure TVSetItemData(Item: THandle; const Value: Pointer);
3798 function GetToBeVisible: Boolean;
3800 procedure SetAlphaBlend(const Value: Integer);
3801 procedure SetMaxProgress(const Index, Value: Integer);
3802 procedure SetDroppedWidth(const Value: Integer);
3803 function LVGetItemState(Idx: Integer): TListViewItemState;
3804 procedure LVSetItemState(Idx: Integer; const Value: TListViewItemState);
3805 function LVGetSttImgIdx(Idx: Integer): Integer;
3806 procedure LVSetSttImgIdx(Idx: Integer; const Value: Integer);
3807 function LVGetOvlImgIdx(Idx: Integer): Integer;
3808 procedure LVSetOvlImgIdx(Idx: Integer; const Value: Integer);
3809 function LVGetItemData(Idx: Integer): DWORD;
3810 procedure LVSetItemData(Idx: Integer; const Value: DWORD);
3811 function LVGetItemIndent(Idx: Integer): Integer;
3812 procedure LVSetItemIndent(Idx: Integer; const Value: Integer);
3813 procedure SetOnDeleteAllLVItems(const Value: TOnEvent);
3814 procedure SetOnDeleteLVItem(const Value: TOnDeleteLVItem);
3815 procedure SetOnEditLVItem(const Value: TOnEditLVItem);
3816 procedure SetOnLVData(const Value: TOnLVData);
3817 {$IFNDEF _FPC}
3818 {$IFNDEF _D2}
3819 procedure SetOnLVDataW(const Value: TOnLVDataW);
3820 {$ENDIF _D2}
3821 {$ENDIF _FPC}
3822 procedure SetOnColumnClick(const Value: TOnLVColumnClick);
3823 procedure SetOnDrawItem(const Value: TOnDrawItem);
3824 procedure SetOnMeasureItem(const Value: TOnMeasureItem);
3826 procedure SetItemsCount(const Value: Integer);
3828 function GetItemData(Idx: Integer): DWORD;
3829 procedure SetItemData(Idx: Integer; const Value: DWORD);
3830 function GetLVCurItem: Integer;
3831 procedure SetLVCurItem(const Value: Integer);
3832 function GetLVFocusItem: Integer;
3833 procedure SetOnDropFiles(const Value: TOnDropFiles);
3834 procedure SetOnHide(const Value: TOnEvent);
3835 procedure SetOnShow(const Value: TOnEvent);
3836 procedure SetClientMargin(const Index, Value: Integer);
3837 {$IFDEF F_P}
3838 function GetClientMargin(const Index: Integer): Integer;
3839 {$ENDIF F_P}
3840 procedure SetOnPaint(const Value: TOnPaint);
3841 procedure SetOnEraseBkgnd(const Value: TOnPaint);
3842 procedure SetTVRightClickSelect(const Value: Boolean);
3843 procedure SetOnLVStateChange(const Value: TOnLVStateChange);
3844 procedure SetOnLVDelete(const Value: TOnLVDelete);
3845 procedure SetOnMove(const Value: TOnEvent);
3846 procedure SetColor1(const Value: TColor);
3847 procedure SetColor2(const Value: TColor);
3848 procedure SetGradientLayout(const Value: TGradientLayout);
3849 procedure SetGradientStyle(const Value: TGradientStyle);
3850 procedure SetDroppedDown(const Value: Boolean);
3851 function get_ClassName: String;
3852 procedure set_ClassName(const Value: String);
3853 procedure SetClsStyle( Value: DWord );
3855 procedure SetStyle( Value: DWord );
3856 procedure SetExStyle( Value: DWord );
3858 procedure SetCursor( Value: HCursor );
3860 procedure SetIcon( Value: HIcon );
3861 procedure SetMenu( Value: HMenu );
3862 function GetCaption: String;
3863 procedure SetCaption( const Value: String );
3865 procedure SetWindowState( Value: TWindowState );
3866 function GetWindowState: TWindowState;
3868 procedure ApplyFont2Wnd;
3869 procedure DoClick;
3871 function TBAddInsButtons( Idx: Integer; const Buttons: array of PChar; const BtnImgIdxArray: array
3872 of Integer ): Integer; stdcall;
3873 procedure SetBitBtnDrawMnemonic(const Value: Boolean);
3874 function GetBitBtnImgIdx: Integer;
3875 procedure SetBitBtnImgIdx(const Value: Integer);
3876 function GetBitBtnImageList: THandle;
3877 procedure SetBitBtnImageList(const Value: THandle);
3879 function GetModal: Boolean;
3880 {$IFDEF USE_SETMODALRESULT}
3881 procedure SetModalResult( const Value: Integer );
3882 {$ENDIF}
3884 protected
3885 fHandle: HWnd;
3886 fFocusHandle: HWnd;
3887 fClsStyle: DWord;
3888 fStyle: DWord;
3889 fExStyle: DWord;
3890 fCursor: HCursor;
3891 fCursorShared: Boolean;
3892 fIcon: HIcon;
3893 fIconShared: Boolean;
3894 fCaption: PChar; // it is now preferred to store Caption as PChar (null-
3895 // terminated string), dynamically allocated in memory.
3896 fIgnoreWndCaption: Boolean;
3898 fWindowState: TWindowState;
3899 fShowAction: Integer;
3900 fCanvas: PCanvas;
3901 fDefWndProc: Pointer;
3902 fNCDestroyed: Boolean;
3904 FParent: PControl;
3905 //FTag: Integer;
3906 fEnabled: Boolean; // Caution!!! fVisible must follow fEnabled! ___
3907 fVisible: Boolean; //____________________________________________//
3908 fTabstop: Boolean;
3909 fTabOrder: Integer;
3910 fTextAlign: TTextAlign;
3911 fVerticalAlign: TVerticalAlign;
3912 fWordWrap: Boolean;
3913 fPreventResize: Boolean;
3914 fAlphaBlend: Integer;
3915 FDroppedWidth: Integer;
3917 fChildren: PList;
3918 {* List of children. }
3919 fMDIClient: PControl;
3920 {* MDI client window control }
3921 fPass2DefProc: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
3922 {* MDI children list }
3923 fMDIChildren: PList;
3924 {* List of MDI children. It is filled for MDI client window. }
3925 fWndFunc: Pointer;
3926 {* Initially pointer to WndFunc. For MDI child window, points to DefMDIChildProc. }
3927 fExMsgProc: function( Applet: PControl; var Msg: TMsg ): Boolean;
3928 {* Additional message handler called directly from Applet.ProcessMessage.
3929 Used to call TranslateMDISysAccel API function for MDI application. }
3930 fMDIDestroying: Boolean;
3931 {* }
3933 fTmpBrush: HBrush;
3934 {* Brush handle to return in response to some color set messages.
3935 Intended for internal use instead of Brush.Color if possible
3936 to avoid using it. }
3937 fTmpBrushColorRGB: TColor;
3939 fMembersCount: Integer;
3940 {* Memebers count is first used in XCustomControl to separate
3941 some internal child controls from common XControl.Children
3942 and make it invisible among Children[]. }
3943 fDrawCtrl1st: PControl;
3944 {* Child control to draw it first, i.e. foreground of others. }
3945 FCreating: Boolean;
3946 {* True, when creating of object is in progress. }
3947 fDestroying: Boolean;
3948 {* True, when destroying of the window is started. Made protected to
3949 be accessible in descending classes. }
3950 fMenu: HMenu;
3951 {* Usually used to store handle of attached main menu, but sometimes
3952 is used to store control ID (for standard GUI controls only). }
3953 fMenuObj: PObj;
3954 {* PMenu pointer to TMenu object. Freed automatically with entire
3955 chain of menu objects attached to a control (or form). }
3956 {$IFNDEF NEW_MENU_ACCELL}
3957 fAccelTable: HAccel;
3958 {$ENDIF}
3959 {* Handle of accelerator table created by menu(s). }
3960 fImageList: PImageList;
3961 {* Pointer to first private image list. Control can own several image,
3962 lists, linked to a chain of image list objects. All these image lists
3963 are released automatically, when control is destroyed. }
3964 fCtlImageListSml: PImageList;
3965 {* ImageList object (with small icons 16x16) to use with a control (e.g.,
3966 with ListView control).
3967 If not set, but control has a list of image list objects, last added
3968 image list with small icons is used automatically. }
3969 fCtlImageListNormal: PImageList;
3970 {* ImageList object (with big icons 32x32) to use with a control.
3971 If not set, last added image list with big icons is used. }
3972 fCtlImgListState: PImageList;
3973 {* ImageList object to use as a state image list (for ListView control). }
3974 fIsApplet: Boolean;
3975 {* True, if the object represent application taskbar button. }
3976 fIsForm: Boolean;
3977 {* True, if the object is form. }
3978 fIsMDIChild: Boolean;
3979 {* TRUE, if the object is MDI child form. }
3980 fIsControl: Boolean;
3981 {* True, if it is a control on form. }
3982 fIsStaticControl: Byte;
3983 {* True, if it is static control with a caption. (To prevent flickering
3984 it in DoubleBuffered mode. }
3985 fIsCommonControl: Boolean;
3986 {* True, if it is common control. }
3987 fChangedPosSz: Byte;
3988 {* Flags of changing left (1), top (2), width (4) or height (8) }
3989 fCannotDoubleBuf: Boolean;
3990 {* True, if cannot set DoubleBuffered to True (RichEdit). }
3991 fUpdRgn: HRgn;
3992 fCollectUpdRgn: HRGN;
3993 fEraseUpdRgn: Boolean;
3994 fPaintDC: HDC;
3995 fDblBufBmp: HBitmap;
3996 {* Memory bitmap, used for DoubleBuffered painting. }
3997 fDblBufW, fDblBufH: Integer;
3998 {* Dimensions of fDblBufBmp. }
3999 fDblBufPainting: Boolean;
4000 fLookTabKeys: TTabKeys;
4001 fNotUpdate: Boolean;
4002 fDynHandlers: PList;
4003 fColumn: Integer;
4004 FSupressTab: Boolean;
4005 fUpdateCount: Integer;
4006 fPaintLater: Boolean;
4007 fOnLeave: TOnEvent;
4008 fEditing: Boolean;
4009 fAutoPopupMenu: PObj;
4010 fHelpContext: Integer;
4012 // Order of following fields is important:
4013 //_______________________________________________________________________________________________
4014 fOnDynHandlers: TWindowFunc; //
4015 fWndProcKeybd: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; //
4016 fControlClick: procedure( Sender : PObj ); //
4017 fControlClassName: PChar; //
4018 fWindowed: Boolean; //
4019 {* True, if control is windowed (or is a form). Now always True, //
4020 because KOL does not yet contain Graphic controls. } //
4021 // //
4022 fCtlClsNameChg: Boolean; //
4023 {* True, if control class name changed and memory is allocated to store it. } //
4024 fWndProcResizeFlicks: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; //
4025 fGotoControl: function( Self_: PControl; Key: DWORD; CheckOnly: Boolean ): Boolean; //
4026 fCtl3Dchild: Boolean; //
4027 fCtl3D: Boolean; //
4028 fTextColor: TColor; //
4029 {* Color of text. Used instead of fFont.Color internally to //
4030 avoid usage of Font object if user is not accessing and changing it. } //
4031 fFont: PGraphicTool; //
4032 fColor: TColor; //
4033 {* Color of control background. } //
4034 fBrush: PGraphicTool; //
4035 fMargin: Integer; //
4036 fBoundsRect: TRect; //
4037 fClientTop, fClientBottom, fClientLeft, fClientRight: Integer; //
4038 {* Store adjustment factor of ClientRect for some 'idiosincrasies' windows, //
4039 such as Groupbox or Tabcontrol. } //
4040 //_____________________________________________________________________________________________//
4041 // this is the end of fiels set, which order is important
4043 fDoubleBuffered: Boolean; //
4044 fTransparent: Boolean; //
4046 fOnMessage: TOnMessage;
4047 fOldOnMessage: TOnMessage;
4049 fOnClick: TOnEvent;
4050 fRightClick: Boolean;
4051 fCurrentControl: PControl;
4052 fCreateVisible, fCreateHidden: Boolean;
4053 fRadio1st, fRadioLast : THandle;
4054 fDropDownProc: procedure( Sender : PObj );
4055 fDropped: Boolean;
4056 fCurIdxAtDrop: Integer;
4057 fPrevWndProc: Pointer;
4058 fClickDisabled: Byte;
4059 fCurItem, fCurIndex: Integer;
4060 FOnScroll: TOnScroll;
4061 FScrollLineDist: array[ 0..1 ] of Integer;
4063 fDefaultBtn: Boolean;
4064 fCancelBtn: Boolean;
4065 fDefaultBtnCtl: PControl;
4066 fCancelBtnCtl: PControl;
4067 fAllBtnReturnClick: Boolean;
4068 fIgnoreDefault: Boolean;
4070 fOnMouseDown: TOnMouse; // CAUTION!!! Order of mouse event handlers is important. ____
4071 fOnMouseUp: TOnMouse; //
4072 fOnMouseMove: TOnMouse; //
4073 fOnMouseDblClk: TOnMouse; //
4074 fOnMouseWheel: TOnMouse; //_____________________________________________________//
4076 fOldDefWndProc: Pointer;
4078 fOnChange: TOnEvent;
4079 fOnEnter: TOnEvent;
4081 FOnLVCustomDraw: TOnLVCustomDraw;
4082 FOnSBBeforeScroll: TOnSBBeforeScroll;
4083 FOnSBScroll: TOnSBScroll;
4084 protected
4085 procedure SetOnLVCustomDraw(const Value: TOnLVCustomDraw);
4086 public
4087 fCommandActions: TCommandActions;
4088 protected
4089 fOnChar: TOnChar;
4090 fOnKeyUp: TOnKey;
4091 fOnKeyDown: TOnKey;
4093 fOnPaint: TOnPaint;
4094 fOnPaint2: TOnPaint;
4095 fPaintMsg: TMsg;
4096 fOnPrepaint: TOnPaint;
4097 fOnPostPaint: TOnPaint;
4098 fPaintProc: TPaintProc;
4100 FMaxWidth: Integer;
4101 FMinWidth: Integer;
4102 FMaxHeight: Integer;
4103 FMinHeight: Integer;
4104 fShadowDeep: Integer;
4105 fStatusCtl: PControl;
4106 fStatusWnd: HWnd;
4107 fStatusTxt: PChar;
4108 fColor1: TColor;
4109 fColor2: TColor;
4110 fLVColCount: Integer;
4111 fLVOptions: TListViewOptions;
4112 fLVStyle: TListViewStyle;
4113 fOnEditLVITem: TOnEditLVItem;
4114 fLVTextBkColor: TColor;
4115 fLVItemHeight: Integer;
4117 fOnDropDown: TOnEvent;
4118 fOnCloseUp: TOnEvent;
4120 fModalResult: Integer;
4122 fModal: Integer;
4123 fModalForm: PControl;
4125 FAlign: TControlAlign;
4126 fNotUseAlign: Boolean;
4127 fDragCallback: TOnDrag;
4128 fDragging: Boolean;
4129 fDragStartPos: TPoint;
4130 fMouseStartPos: TPoint;
4131 fSplitStartPos: TPoint;
4132 fSplitStartPos2: TPoint;
4133 fSplitStartSize: Integer;
4134 fSplitMinSize1, fSplitMinSize2: Integer;
4135 fOnSplit: TOnSplit;
4136 fSecondControl: PControl;
4137 fOnSelChange: TOnEvent;
4138 fTmpFont: PGraphicTool;
4140 fRECharFormatRec: TCharFormat2;
4141 fREError: Integer;
4142 fREStream: PStream;
4143 fREStrLoadLen: DWORD;
4144 fREParaFmtRec: TParaFormat2;
4145 FOnResize: TOnEvent;
4146 fOnProgress: TOnEvent;
4147 fCharFmtDeltaSz: Integer;
4148 fParaFmtDeltaSz: Integer;
4149 fREOvr: Boolean;
4150 fReOvrDisable: Boolean;
4151 fOnREInsModeChg: TOnEvent;
4152 fREScrolling: Boolean;
4153 fUpdCount: Integer;
4154 fOnREOverURL: TOnEvent;
4155 fOnREURLClick: TOnEvent;
4156 fRECharArea: TRichFmtArea;
4157 fBitBtnOptions : TBitBtnOptions;
4158 fGlyphLayout : TGlyphLayout;
4159 fGlyphBitmap : HBitmap;
4160 fGlyphCount : Integer;
4161 fGlyphWidth, fGlyphHeight: Integer;
4162 fOnBitBtnDraw: TOnBitBtnDraw;
4163 fFlat: Boolean;
4164 fSizeRedraw: Boolean; {YS}
4166 fOnMouseLeave: TOnEvent;
4167 fOnMouseEnter: TOnEvent;
4168 fOnTestMouseOver: TOnTestMouseOver;
4170 fMouseInControl: Boolean;
4171 fRepeatInterval: Integer;
4172 fChecked: Boolean;
4173 fPushed: Boolean;
4174 fPrevFocusWnd: HWnd;
4176 fOnTVBeginDrag: TOnTVBeginDrag;
4177 fOnTVBeginEdit: TOnTVBeginEdit;
4178 fOnTVEndEdit: TOnTVEndEdit;
4179 fOnTVExpanded: TOnTVExpanded;
4180 fOnTVExpanding: TOnTVExpanding;
4181 fOnTVDelete: TOnTVDelete;
4183 fOnDeleteLVItem: TOnDeleteLVItem;
4184 fOnDeleteAllLVItems: TOnEvent;
4185 fOnLVData: TOnLVData;
4186 {$IFNDEF _FPC}
4187 {$IFNDEF _D2}
4188 fOnLVDataW: TOnLVDataW;
4189 {$ENDIF _D2}
4190 {$ENDIF _FPC}
4191 fOnCompareLVItems: TOnCompareLVItems;
4192 fOnColumnClick: TOnLVColumnClick;
4193 fOnDrawItem: TOnDrawItem;
4194 fOnMeasureItem: TOnMeasureItem;
4195 fREUrl: String;
4196 FMinimizeWnd: PControl;
4197 FFixWidth: Integer;
4198 FFixHeight: Integer;
4199 FOnDropFiles: TOnDropFiles;
4200 FOnHide: TOnEvent;
4201 FOnShow: TOnEvent;
4202 fOnEraseBkgnd: TOnPaint;
4203 fCustomData: Pointer;
4204 fCustomObj: PObj;
4205 fOnTVSelChanging: TOnTVSelChanging;
4207 fOnClose: TOnEventAccept;
4208 fOnQueryEndSession: TOnEventAccept;
4209 fCloseQueryReason: TCloseQueryReason;
4211 //----- order of following 3 events important: //
4212 fOnMinimize: TOnEvent; //
4213 fOnMaximize: TOnEvent; //
4214 fOnRestore: TOnEvent; //
4215 //---------------------------------------------//
4217 //fCreateParamsExt: procedure( Self_: PControl; var Params: TCreateParams );
4218 fCreateWndExt: procedure( Sender: PControl );
4220 fTBttCmd: PList;
4221 fTBttTxt: PStrList;
4222 fTBevents: PList; // events for TBAssignEvents
4223 fTBBtnImgWidth: Integer; // custom toolbar bitmap width
4224 FTBBtMinWidth: Integer;
4225 FTBBtMaxWidth: Integer;
4226 fGradientStyle: TGradientStyle;
4227 fGradientLayout: TGradientLayout;
4228 fVisibleWoParent: Boolean;
4231 fTVRightClickSelect: Boolean;
4232 FOnMove: TOnEvent;
4233 FOnLVStateChange: TOnLVStateChange;
4234 FOnLVDelete: TOnLVDelete;
4235 fAutoSize: procedure( Self_: PControl );
4236 fIsButton: Boolean;
4237 fSizeGrip: Boolean;
4238 fNotAvailable: Boolean;
4239 FPressedMnemonic: DWORD;
4240 FBitBtnDrawMnemonic: Boolean;
4241 FBitBtnGetCaption: function( Self_: PControl; const S: String ): String;
4242 FBitBtnExtDraw: procedure( Self_: PControl; DC: HDC; X, Y: Integer; const R: TRect;
4243 const CapText, CapTxtOrig: String; Color: TColor );
4244 FTextShiftX, FTextShiftY: Integer;
4245 fNotifyChild: procedure( Self_, Child: PControl );
4246 fScrollChildren: procedure( Self_: PControl );
4247 fOnHelp: TOnHelp;
4249 FOnDTPUserString: TDTParseInputEvent;
4251 {$IFDEF USE_MHTOOLTIP}
4252 {$DEFINE var}
4253 {$I KOLMHToolTip}
4254 {$UNDEF var}
4256 {$DEFINE function}
4257 {$I KOLMHToolTip}
4258 {$UNDEF function}
4259 {$ENDIF}
4261 procedure Init; {-}virtual;{+}{++}(*override;*){--}
4262 {* }
4263 procedure InitParented( AParent: PControl ); virtual;
4264 {* Initialization of visual object. }
4265 procedure DestroyChildren;
4266 {* Destroys children. Is called in destructor, and can be
4267 called in descending classes as earlier as needed to
4268 prevent problems of too late destroying of visuals. }
4270 function GetParentWnd( NeedHandle: Boolean ): HWnd;
4271 {* Returns handle of parent window. }
4272 function GetParentWindow: HWnd;
4273 {* }
4274 procedure SetEnabled( Value: Boolean );
4275 {* Changes Enabled property value. Overriden here to change enabling
4276 status of a window. }
4277 function GetEnabled: Boolean;
4278 {* Returns True, if Enabled. Overriden here to obtain real window
4279 state. }
4280 procedure SetVisible( Value: Boolean );
4281 {* Sets Visible property value. Overriden here to change visibility
4282 of correspondent window. }
4283 procedure Set_Visible( Value: Boolean );
4284 {* }
4285 function GetVisible: Boolean;
4286 {* Returns True, if correspondent window is Visible. Overriden
4287 to get visibility of real window, not just value stored in object. }
4288 function Get_Visible: Boolean;
4289 {* Returns True, if correspondent window is Visible, for forms and applet,
4290 or if fVisible flag is set, for controls. }
4291 procedure SetCtlColor( Value: TColor );
4292 {* Sets TControl's Color property value. }
4293 procedure SetBoundsRect( const Value: TRect );
4294 {* Sets BoudsRect property value. }
4295 function GetBoundsRect: TRect;
4296 {* Returns bounding rectangle. }
4297 function GetIcon: HIcon;
4298 {* Returns Icon property. By default, if it is not set,
4299 returns Icon property of an Applet. }
4301 procedure CreateSubclass( var Params: TCreateParams; ControlClassName: PChar );
4302 {* Can be used in descending classes to subclass window with given
4303 standard Windows ControlClassName - must be called after
4304 creating Params but before CreateWindow. Usually it is called
4305 in overriden method CreateParams after calling of the inherited one. }
4307 function UpdateWndStyles: PControl;
4308 {* Updates fStyle, fExStyle, fClsStyle from window handle }
4309 procedure SetOnChar(const Value: TOnChar);
4310 {* }
4311 procedure SetOnKeyDown(const Value: TOnKey);
4313 {* }
4314 procedure SetOnKeyUp(const Value: TOnKey);
4315 {* }
4316 procedure SetMouseDown(const Value: TOnMouse);
4317 {* }
4318 procedure SetMouseMove(const Value: TOnMouse);
4319 {* }
4320 procedure SetMouseUp(const Value: TOnMouse);
4321 {* }
4322 procedure SetMouseWheel(const Value: TOnMouse);
4323 {* }
4324 procedure SetMouseDblClk(const Value: TOnMouse);
4325 {* }
4326 procedure SetHelpContext( Value: Integer );
4327 {* }
4328 procedure SetOnTVDelete( const Value: TOnTVDelete );
4329 {* }
4330 procedure SetDefaultBtn(const Index: Integer; const Value: Boolean);
4331 {$IFDEF F_P}
4332 function GetDefaultBtn(const Index: Integer): Boolean;
4333 {$ENDIF F_P}
4334 function DefaultBtnProc( var Msg: TMsg; var Rslt: Integer ): Boolean;
4335 {* }
4337 procedure SetDateTime( Value: TDateTime );
4338 function GetDateTime: TDateTime;
4339 procedure SetDateTimeRange( Value: TDateTimeRange );
4340 function GetDateTimeRange: TDateTimeRange;
4341 procedure SetDateTimePickerColor( Index: TDateTimePickerColor; Value: TColor );
4342 function GetDateTimePickerColor( Index: TDateTimePickerColor ): TColor;
4343 procedure SetDateTimeFormat( const Value: String );
4345 public
4346 constructor CreateParented( AParent: PControl );
4347 {* Creates new instance of TControl object, calling InitParented }
4348 //FormPointer_DoNotUseItPlease_ItIsUsedByMCK: Pointer;
4349 { ^ no more needed }
4350 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
4351 {* Destroyes object. First of all, destructors for all children
4352 are called. }
4354 function GetWindowHandle: HWnd;
4355 {* Returns window handle. If window is not yet created,
4356 method CreateWindow is called. }
4357 procedure CreateChildWindows;
4358 {* Enumerates all children recursively and calls CreateWindow for all
4359 of these. }
4360 property Parent: PControl read fParent write SetParent;
4361 {* Parent of TParent object. Also must be of TParent type or derived from TParent. }
4362 //property Tag: Integer read FTag write FTag; //--------- moved to TObj --------
4363 {* User-defined pointer, which can contain any data or reference to
4364 anywhere in memory (when used as a pointer).
4366 function ChildIndex( Child: PControl ): Integer;
4367 {* Returns index of given child. }
4368 procedure MoveChild( Child: PControl; NewIdx: Integer );
4369 {* Moves given Child into new position. }
4371 property Enabled: Boolean read GetEnabled write SetEnabled;
4372 {* Enabled usually used to decide if control can get keyboard focus
4373 or been clicked by mouse. }
4374 procedure EnableChildren( Enable, Recursive: Boolean );
4375 {* Enables (Enable = TRUE) or disables (Enable = FALSE) all the children
4376 of the control. If Recursive = TRUE then all the children of all the
4377 children are enabled or disabled recursively. }
4378 property Visible: Boolean read Get_Visible write SetVisible;
4379 {* Obvious. }
4380 property ToBeVisible: Boolean read GetToBeVisible;
4381 {* Returns True, if a control is supposed to be visible when its
4382 form is showing. Thus is, True is returned if either control
4383 is Visible or hidden, but marked with flag fCreateHidden. }
4384 property CreateVisible: Boolean read fCreateVisible write fCreateVisible;
4385 {* False by default. If You want your form to be created visible and
4386 flick due creation, set it to True. This does not affect size of
4387 executable anyway. }
4388 property Align: TControlAlign read FAlign write Set_Align;
4389 {* Align style of a control. If this property is not used in your
4390 application, there are no additional code added. Aligning of
4391 controls is made in KOL like in VCL. To align controls when
4392 initially create ones, use "transparent" function SetAlign
4393 ("transparent" means that it returns @Self as a result).
4394 |<br>
4395 Note, that it is better not to align combobox caClient, caLeft or
4396 caRight (better way is to place a panel with Border = 0 and
4397 EdgeStyle = esNone, align it as desired and to place a combobox on it
4398 aligning caTop or caBottom). Otherwise, big problems could be under
4399 Win9x/Me, and some delay could occur under any other systems.
4400 |<br> Do not attempt to align some kinds of controls (like combobox or
4401 toolbar) caLeft or caRight, this can cause infinite recursion in the
4402 application. }
4403 property BoundsRect: TRect read GetBoundsRect write SetBoundsRect;
4404 {* Bounding rectangle of the visual. Coordinates are relative
4405 to top left corner of parent's ClientRect, or to top left corner
4406 of screen (for TForm). }
4407 property Left: Integer read GetLeft write SetLeft;
4408 {* Left horizontal position. }
4409 property Top: Integer read GetTop write SetTop;
4410 {* Top vertical position. }
4411 property Width: Integer read GetWidth write SetWidth;
4412 {* Width of TVisual object. }
4413 property Height: Integer read GetHeight write SetHeight;
4414 {* Height of TVisual object. }
4416 property Position: TPoint read GetPosition write Set_Position;
4417 {* Represents top left position of the object. See also BoundsRect. }
4418 property MinWidth: Integer index 0
4419 {$IFDEF F_P} read GetConstraint
4420 {$ELSE DELPHI} read FMinWidth
4421 {$ENDIF F_P/DELPHI} write SetConstraint;
4422 {* Minimal width constraint. }
4423 property MinHeight: Integer index 1
4424 {$IFDEF F_P} read GetConstraint
4425 {$ELSE DELPHI} read FMinHeight
4426 {$ENDIF F_P/DELPHI} write SetConstraint;
4427 {* Minimal height constraint. }
4428 property MaxWidth: Integer index 2
4429 {$IFDEF F_P} read GetConstraint
4430 {$ELSE DELPHI} read FMaxWidth
4431 {$ENDIF F_P/DELPHI} write SetConstraint;
4432 {* Maximal width constraint. }
4433 property MaxHeight: Integer index 3
4434 {$IFDEF F_P} read GetConstraint
4435 {$ELSE DELPHI} read FMaxHeight
4436 {$ENDIF F_P/DELPHI} write SetConstraint;
4437 {* Maximal height constraint. }
4439 function ClientRect: TRect;
4440 {* Client rectangle of TControl. Contrary to VCL, for some
4441 classes (e.g. for graphic controls) can be relative
4442 not to itself, but to top left corner of the parent's ClientRect
4443 rectangle. }
4444 property ClientWidth: Integer read GetClientWidth write SetClientWidth;
4445 {* Obvious. Accessing this property, program forces window latent creation. }
4446 property ClientHeight: Integer read GetClientHeight write SetClientHeight;
4447 {* Obvious. Accessing this property, program forces window latent creation. }
4449 function ControlRect: TRect;
4450 {* Absolute bounding rectangle relatively to nearest
4451 Windowed parent client rectangle (at least to a form, but usually to
4452 a Parent).
4453 Useful while drawing on device context, provided by such
4454 Windowed parent. For form itself is the same as BoundsRect. }
4455 function ControlAtPos( X, Y: Integer; IgnoreDisabled: Boolean ): PControl;
4456 {* Searches TVisual at the given position (relatively to top left
4457 corner of the ClientRect). }
4459 procedure Invalidate;
4460 {* Invalidates rectangle, occupied by the visual (but only if Showing =
4461 True). }
4463 procedure InvalidateEx;
4464 {* Invalidates the window and all its children. }
4465 procedure InvalidateNC( Recursive: Boolean );
4466 {* Invalidates the window and all its children including non-client area. }
4467 procedure Update;
4468 {* Updates control's window and calls Update for all child controls. }
4469 procedure BeginUpdate;
4470 {* |<#treeview>
4471 |<#listview>
4472 |<#richedit>
4473 |<#memo>
4474 |<#listbox>
4475 Call this method to stop visual updates of the control until correspondent
4476 EndUpdate called (pairs BeginUpdate - EndUpdate can be nested). }
4477 procedure EndUpdate;
4478 {* See BeginUpdate. }
4480 property Windowed: Boolean read fWindowed;
4481 {* Constantly returns True, if object is windowed (i.e. owns
4482 correspondent window handle). Otherwise, returns False.
4483 |<br>
4484 By now, all the controls are windowed (there are no controls in KOL, which are
4485 emulating window, acually belonging to Parent - like TGraphicControl
4486 in VCL). }
4488 function HandleAllocated: Boolean;
4489 {* Returns True, if window handle is allocated. Has no sense for
4490 non-Windowed objects (but now, the KOL has no non-Windowed controls). }
4491 property MDIClient: PControl read fMDIClient;
4492 {* For MDI forms only: returns MDI client window control, containng all MDI
4493 children. Use this window to send specific messages to rule MDI children. }
4495 property ChildCount: Integer read GetChildCount;//GetChildCountWOMembers;
4496 {* Returns number of commonly accessed child objects (without
4497 MembersCount). }
4498 property Children[ Idx: Integer ]: PControl read GetMembers;
4499 {* Child items of TVisual object. Property is reintroduced here
4500 to separate access to always visible Children[] from restricted
4501 a bit Members[]. }
4502 property MembersCount: Integer read FMembersCount;
4503 {* Returns number of "internal" child objects, which are
4504 not accessible through common Children[] property. }
4505 property Members[ Idx: Integer ]: PControl read GetMembers;
4506 {* Members and children array of the object (first from 0 to
4507 MembersCount-1 are Members[], and Children[] are followed by
4508 them. Usually You do not need to use this list. Use instead
4509 Children[0..ChildCount] property, Members[] is intended for
4510 internal needs of XCL (and in KOL by now Members and Children
4511 actually are the same properties). }
4513 procedure PaintBackground( DC: HDC; Rect: PRect );
4514 {* Is called to paint background in given rectangle. This
4515 method is filling clipped area of the Rect rectangle with
4516 Color, but only if global event Global_OnPaintBkgnd is
4517 not assigned. If assigned, this one is called instead here.
4518 |<br>&nbsp;&nbsp;&nbsp;
4519 This method made public, so it can be called directly to
4520 fill some device context's rectangle. But remember, that
4521 independantly of Rect, top left corner of background piece
4522 will be located so, if drawing is occure into ControlRect
4523 rectangle. }
4524 property WindowedParent: PControl read fParent;
4525 {* Returns nearest windowed parent, the same as Parent. }
4527 function ParentForm: PControl;
4528 {* |<#form>
4529 Returns parent form for a control (of @Self for form itself. }
4530 property ActiveControl: PControl read fCurrentControl write fCurrentControl;
4531 {* }
4532 function Client2Screen( const P: TPoint ): TPoint;
4533 {* Converts the client coordinates of a specified point to screen coordinates. }
4534 function Screen2Client( const P: TPoint ): TPoint;
4535 {* Converts screen coordinates of a specified point to client coordinates. }
4536 function CreateWindow: Boolean; virtual;
4537 {* |<#form>
4538 Creates correspondent window object. Returns True if success (if
4539 window is already created, False is returned). If applied to a form,
4540 all child controls also allocates handles that time.
4541 |<br>&nbsp;&nbsp;&nbsp;
4542 Call this method to ensure, that a hanle is allocated for a form,
4543 an application button or a control. (It is not necessary to do so in
4544 the most cases, even if You plan to work with control's handle directly.
4545 But immediately after creating the object, if You want to pass its
4546 handle to API function, this can be helpful). }
4547 procedure Close;
4548 {* |<#appbutton>
4549 |<#form>
4550 Closes window. If a window is the main form, this closes application,
4551 terminating it. Also it is possible to call Close method for Applet
4552 window to stop application. }
4554 {$IFDEF USE_MHTOOLTIP}
4555 {$DEFINE public}
4556 {$I KOLMHToolTip}
4557 {$UNDEF public}
4558 {$ENDIF}
4560 property Handle: HWnd read fHandle; //GetHandle;
4561 {* Returns descriptor of system window object. If window is not yet
4562 created, 0 is returned. To allocate handle, call CreateWindow method. }
4564 property ParentWindow: HWnd read GetParentWindow;
4565 {* Returns handle of parent window (not TControl object, but system
4566 window object handle). }
4567 property ClsStyle: DWord read fClsStyle write SetClsStyle;
4568 {* Window class style. Available styles are:
4569 |<table border=0>
4570 |&L=<tr><td valign=top><font face=Fixedsys>%1</font></td><td>
4571 |&E=</td></tr>
4572 |&N=<br>&nbsp;&nbsp;&nbsp;
4573 <L CS_BYTEALIGNCLIENT> - Aligns the window's client area on the byte boundary
4574 (in the x direction) to enhance performance during
4575 drawing operations. <E>
4576 <L CS_BYTEALIGNWINDOW> - Aligns a window on a byte boundary (in the x
4577 direction). <E>
4578 <L CS_CLASSDC> - Allocates one device context to be shared by all
4579 windows in the class. <E>
4580 <L CS_DBLCLKS> - Sends double-click messages to the window
4581 procedure when the user double-clicks the mouse while the
4582 cursor is within a window belonging to the class. <E>
4583 <L CS_GLOBALCLASS> - Allows an application to create a window of
4584 the class regardless of the value of the hInstance parameter.
4585 <N> You can create a global class by creating
4586 the window class in a dynamic-link library (DLL) and listing the
4587 name of the DLL in the registry under specific keys. <E>
4588 <L CS_HREDRAW> - Redraws the entire window if a movement or
4589 size adjustment changes the width of the client area. <E>
4590 <L CS_NOCLOSE> - Disables the Close command on the System menu. <E>
4591 <L CS_OWNDC> - Allocates a unique device context for each window
4592 in the class. <E>
4593 <L CS_PARENTDC> - Sets the clipping region of the child window to
4594 that of the parent window so that the child can draw on the parent. <E>
4595 <L CS_SAVEBITS> - Saves, as a bitmap, the portion of the screen
4596 image obscured by a window. Windows uses the saved bitmap to re-create
4597 the screen image when the window is removed. <E>
4598 <L CS_VREDRAW> - Redraws the entire window if a movement or size
4599 adjustment changes the height of the client area. <E>
4600 |</table> For more info, see Win32.hlp (keyword 'WndClass');
4603 property Style: DWord read fStyle write SetStyle;
4604 {* Window styles. Available styles are:
4605 |<table border=0>
4606 <L WS_BORDER> Creates a window that has a thin-line border. <E>
4607 <L WS_CAPTION> Creates a window that has a title bar (includes the
4608 WS_BORDER style). <E>
4609 <L WS_CHILD> Creates a child window. This style cannot be used with
4610 the WS_POPUP style. <E>
4611 <L WS_CHILDWINDOW> Same as the WS_CHILD style. <E>
4612 <L WS_CLIPCHILDREN> Excludes the area occupied by child windows
4613 when drawing occurs within the parent window. This style is used
4614 when creating the parent window. <E>
4615 <L WS_CLIPSIBLINGS> Clips child windows relative to each other;
4616 that is, when a particular child window receives a WM_PAINT message,
4617 the WS_CLIPSIBLINGS style clips all other overlapping child windows
4618 out of the region of the child window to be updated. If
4619 WS_CLIPSIBLINGS is not specified and child windows overlap, it is
4620 possible, when drawing within the client area of a child window,
4621 to draw within the client area of a neighboring child window. <E>
4622 <L WS_DISABLED> Creates a window that is initially disabled. A
4623 disabled window cannot receive input from the user. <E>
4624 <L WS_DLGFRAME> Creates a window that has a border of a style
4625 typically used with dialog boxes. A window with this style cannot
4626 have a title bar. <E>
4627 <L WS_GROUP> Specifies the first control of a group of controls.
4628 The group consists of this first control and all controls defined
4629 after it, up to the next control with the WS_GROUP style.
4630 The first control in each group usually has the WS_TABSTOP
4631 style so that the user can move from group to group. The user
4632 can subsequently change the keyboard focus from one control in
4633 the group to the next control in the group by using the direction
4634 keys. <E>
4635 <L WS_HSCROLL> Creates a window that has a horizontal scroll bar. <E>
4636 <L WS_ICONIC> Creates a window that is initially minimized. Same as
4637 the WS_MINIMIZE style. <E>
4638 <L WS_MAXIMIZE> Creates a window that is initially maximized. <E>
4639 <L WS_MAXIMIZEBOX> Creates a window that has a Maximize button.
4640 Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU
4641 style must also be specified. <E>
4642 <L WS_MINIMIZE> Creates a window that is initially minimized.
4643 Same as the WS_ICONIC style. <E>
4644 <L WS_MINIMIZEBOX> Creates a window that has a Minimize button.
4645 Cannot be combined with the WS_EX_CONTEXTHELP style. The WS_SYSMENU
4646 style must also be specified. <E>
4647 <L WS_OVERLAPPED> Creates an overlapped window. An overlapped
4648 window has a title bar and a border. Same as the WS_TILED style. <E>
4649 <L WS_OVERLAPPEDWINDOW> Creates an overlapped window with the
4650 WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME, WS_MINIMIZEBOX,
4651 and WS_MAXIMIZEBOX styles. Same as the WS_TILEDWINDOW style. <E>
4652 <L WS_POPUP> Creates a pop-up window. This style cannot be used with
4653 the WS_CHILD style. <E>
4654 <L WS_POPUPWINDOW> Creates a pop-up window with WS_BORDER,
4655 WS_POPUP, and WS_SYSMENU styles. The WS_CAPTION and WS_POPUPWINDOW
4656 styles must be combined to make the window menu visible. <E>
4657 <L WS_SIZEBOX> Creates a window that has a sizing border. Same as the
4658 WS_THICKFRAME style. <E>
4659 <L WS_SYSMENU> Creates a window that has a window-menu on its title
4660 bar. The WS_CAPTION style must also be specified. <E>
4661 <L WS_TABSTOP> Specifies a control that can receive the keyboard focus
4662 when the user presses the TAB key. Pressing the TAB key changes
4663 the keyboard focus to the next control with the WS_TABSTOP style. <E>
4664 <L WS_THICKFRAME> Creates a window that has a sizing border.
4665 Same as the WS_SIZEBOX style. <E>
4666 <L WS_TILED> Creates an overlapped window. An overlapped window has
4667 a title bar and a border. Same as the WS_OVERLAPPED style. <E>
4668 <L WS_TILEDWINDOW> Creates an overlapped window with the
4669 WS_OVERLAPPED, WS_CAPTION, WS_SYSMENU, WS_THICKFRAME,
4670 WS_MINIMIZEBOX, and WS_MAXIMIZEBOX styles. Same as the
4671 WS_OVERLAPPEDWINDOW style. <E>
4672 <L WS_VISIBLE> Creates a window that is initially visible. <E>
4673 <L WS_VSCROLL> Creates a window that has a vertical scroll bar. <E>
4674 |</table>
4675 See also Win32.hlp (topic CreateWindow).
4677 property ExStyle: DWord read fExStyle write SetExStyle;
4678 {* Extra window styles. Available flags are following:
4679 |<table border=0>
4680 <L WS_EX_ACCEPTFILES> Specifies that a window created with this style
4681 accepts drag-drop files. <E>
4682 <L WS_EX_APPWINDOW> Forces a top-level window onto the taskbar
4683 when the window is minimized. <E>
4684 <L WS_EX_CLIENTEDGE> Specifies that a window has a border with a
4685 sunken edge. <E>
4686 <L WS_EX_CONTEXTHELP> Includes a question mark in the title bar of
4687 the window. When the user clicks the question mark, the cursor
4688 changes to a question mark with a pointer. If the user then clicks
4689 a child window, the child receives a WM_HELP message. The child
4690 window should pass the message to the parent window procedure,
4691 which should call the WinHelp function using the HELP_WM_HELP
4692 command. The Help application displays a pop-up window that
4693 typically contains help for the child window.WS_EX_CONTEXTHELP
4694 cannot be used with the WS_MAXIMIZEBOX or WS_MINIMIZEBOX styles. <E>
4695 <L WS_EX_CONTROLPARENT> Allows the user to navigate among the child
4696 windows of the window by using the TAB key. <E>
4697 <L WS_EX_DLGMODALFRAME> Creates a window that has a double border;
4698 the window can, optionally, be created with a title bar by
4699 specifying the WS_CAPTION style in the dwStyle parameter. <E>
4700 <L WS_EX_LEFT> Window has generic "left-aligned" properties. This
4701 is the default. <E>
4702 <L WS_EX_LEFTSCROLLBAR> If the shell language is Hebrew, Arabic, or
4703 another language that supports reading order alignment, the
4704 vertical scroll bar (if present) is to the left of the client
4705 area. For other languages, the style is ignored and not treated
4706 as an error. <E>
4707 <L WS_EX_LTRREADING> The window text is displayed using Left to
4708 Right reading-order properties. This is the default. <E>
4709 <L WS_EX_MDICHILD> Creates an MDI child window. <E>
4710 <L WS_EX_NOPARENTNOTIFY> Specifies that a child window created
4711 with this style does not send the WM_PARENTNOTIFY message to its
4712 parent window when it is created or destroyed. <E>
4713 <L WS_EX_OVERLAPPEDWINDOW> Combines the WS_EX_CLIENTEDGE and
4714 WS_EX_WINDOWEDGE styles. <E>
4715 <L WS_EX_PALETTEWINDOW> Combines the WS_EX_WINDOWEDGE,
4716 WS_EX_TOOLWINDOW, and WS_EX_TOPMOST styles. <E>
4717 <L WS_EX_RIGHT> Window has generic "right-aligned" properties.
4718 This depends on the window class. This style has an effect only
4719 if the shell language is Hebrew, Arabic, or another language that
4720 supports reading order alignment; otherwise, the style is
4721 ignored and not treated as an error. <E>
4722 <L WS_EX_RIGHTSCROLLBAR> Vertical scroll bar (if present) is to the
4723 right of the client area. This is the default. <E>
4724 <L WS_EX_RTLREADING> If the shell language is Hebrew, Arabic, or
4725 another language that supports reading order alignment, the
4726 window text is displayed using Right to Left reading-order
4727 properties. For other languages, the style is ignored and not
4728 treated as an error. <E>
4729 <L WS_EX_STATICEDGE> Creates a window with a three-dimensional
4730 border style intended to be used for items that do not accept
4731 user input. <E>
4732 <L WS_EX_TOOLWINDOW> Creates a tool window; that is, a window
4733 intended to be used as a floating toolbar. A tool window has
4734 a title bar that is shorter than a normal title bar, and the
4735 window title is drawn using a smaller font. A tool window does
4736 not appear in the taskbar or in the dialog that appears when
4737 the user presses ALT+TAB. <E>
4738 <L WS_EX_TOPMOST> Specifies that a window created with this style
4739 should be placed above all non-topmost windows and should stay
4740 above them, even when the window is deactivated. To add or remove
4741 this style, use the SetWindowPos function. <E>
4742 <L WS_EX_TRANSPARENT> Specifies that a window created with this
4743 style is to be transparent. That is, any windows that are
4744 beneath the window are not obscured by the window. A window
4745 created with this style receives WM_PAINT messages only after
4746 all sibling windows beneath it have been updated. <E>
4747 <L WS_EX_WINDOWEDGE> Specifies that a window has a border with
4748 a raised edge. <E>
4749 |</table>
4750 See also Win32.hlp (topic CreateWindowEx).
4753 property Cursor: HCursor read fCursor write SetCursor;
4754 {* Current cursor. For most of controls, sets initially to IDC_ARROW. See
4755 also ScreenCursor. }
4756 procedure CursorLoad( Inst: Integer; ResName: PChar );
4757 {* Loads Cursor from the resource. See also comments for Icon property. }
4759 property Icon: HIcon read GetIcon write SetIcon;
4760 {* |<#appbutton>
4761 |<#form>
4762 Icon. By default, icon of the Applet is used. To load icon from the
4763 resource, use IconLoad or IconLoadCursor method - this is more correct, because
4764 in such case a special flag is set to prevent attempts to destroy
4765 shared icon object in the destructor of the control. }
4767 procedure IconLoad( Inst: Integer; ResName: PChar );
4768 {* |<#appbutton>
4769 |<#form>
4770 See Icon property. }
4771 procedure IconLoadCursor( Inst: Integer; ResName: PChar );
4772 {* |<#appbutton>
4773 |<#form>
4774 Loads Icon from the cursor resource. See also Icon property. }
4777 property Menu: HMenu read fMenu write SetMenu;
4779 {* Menu (or ID of control - for standard GUI controls). }
4780 property HelpContext: Integer read fHelpContext write SetHelpContext;
4781 {* Help context. }
4782 function AssignHelpContext( Context: Integer ): PControl;
4783 {* Assigns HelpContext and returns @ Self (can be used in initialization
4784 of a control in a chain of "transparent" calls). }
4786 procedure CallHelp( Context: Integer; CtxCtl: PControl {; CtlID: Integer} );
4787 {* Method of a form or Applet. Call it to show help with the given context
4788 ID. If the Context = 0, help contents is displayed. By default,
4789 WinHelp is used. To allow using HtmlHelp, call AssignHtmlHelp global
4790 function. When WinHelp used, HelpPath variable can be assigned directly.
4791 If HelpPath variable is not assigned, application name
4792 (and path) is used, with extension replaced to '.hlp'. }
4794 property HelpPath: String read GetHelpPath write SetHelpPath;
4795 {* Property of a form or an Applet. Change it to provide custom path to
4796 WinHelp format help file. If HtmlHelp used, call global procedure
4797 AssignHtmlHelp instead. }
4799 property OnHelp: TOnHelp read fOnHelp write fOnHelp;
4800 {* An event of a form, it is called when F1 pressed or help topic requested
4801 by any other way. To prevent showing help, nullify Sender. Set Popup to
4802 TRUE to provide showing help in a pop-up window. It is also possible to
4803 change Context dynamically. }
4805 property Caption: String read GetCaption write SetCaption;
4806 {* |<#appbutton>
4807 |<#form>
4808 |<#button>
4809 |<#bitbtn>
4810 |<#label>
4811 |<#wwlabel>
4812 |<#3dlabel>
4813 Caption of a window. For standard Windows buttons, labels and so on
4814 not a caption of a window, but text of the window. }
4815 property Text: String read GetCaption write SetCaption;
4816 {* |<#edit>
4817 |<#memo>
4818 The same as Caption. To make more convenient with Edit controls. For
4819 Rich Edit control, use property RE_Text. }
4820 property SelStart: Integer read GetSelStart write SetSelStart;
4821 {* |<#edit>
4822 |<#memo>
4823 |<#richedit>
4824 |<#listbox>
4825 |<#combo>
4826 Start of selection (editbox - character position, listbox and combobox -
4827 index of [the first] selected item). }
4828 property SelLength: Integer read GetSelLength write SetSelLength;
4829 {* |<#edit>
4830 |<#memo>
4831 |<#richedit>
4832 |<#listbox>
4833 |<#listview>
4834 Length of selection (editbox - number of characters selected, multiline
4835 listbox - number of items selected). }
4837 property Selection: String read GetSelection write SetSelection;
4838 {* |<#edit>
4839 |<#memo>
4840 |<#richedit>
4841 Selected text (editbox, richedit) as string. Can be useful to replace
4842 selection. For rich edit, use RE_Text[ reText, TRUE ], if you want to
4843 read correctly characters from another locale then ANSI only. }
4844 procedure SelectAll;
4845 {* |<#edit>
4846 |<#memo>
4847 |<#richedit>
4848 Makes all the text in editbox or RichEdit, or all items in listbox
4849 selected. }
4851 procedure ReplaceSelection( const Value: String; aCanUndo: Boolean );
4852 {* |<#edit>
4853 |<#memo>
4854 |<#richedit>
4855 Replaces selection (in edit, RichEdit). Unlike assigning new value
4856 to Selection property, it is possible to specify, if operation can
4857 be undone. }
4859 procedure DeleteLines( FromLine, ToLine: Integer );
4860 {* |<#edit>
4861 |<#memo>
4862 |<#richedit>
4863 Deletes lines from FromLine to ToLine (inclusively, i.e. 0 to 0 deletes
4864 one line with index 0). Current selection is restored as possible. }
4865 property CurIndex: Integer read GetCurIndex write SetCurIndex;
4866 {* |<#listbox>
4867 |<#combo>
4868 |<#toolbar>
4869 Index of current item (for listbox, combobox) or button index pressed
4870 or dropped down (for toolbar button, and only in appropriate event
4871 handler call).
4872 |<br>
4873 You cannot use it to set or remove a selection in a multiple-selection
4874 list box, so you should set option loNoExtendSel to true.
4875 |<br>
4876 In OnClick event handler, CurIndex has not yet changed. Use OnSelChange
4877 to respond to selection changes. }
4879 property Count: Integer read GetItemsCount write SetItemsCount;
4880 {* |<#listbox>
4881 |<#combo>
4882 |<#listview>
4883 |<#treeview>
4884 |<#edit>
4885 |<#memo>
4886 |<#richedit>
4887 |<#toolbar>
4888 Number of items (listbox, combobox, listview) or lines (multiline
4889 editbox, richedit control) or buttons (toolbar). It is possible to
4890 assign a value to this property only for listbox control with loNoData
4891 style and for list view control with lvoOwnerData style (virtual list
4892 box and list view). }
4894 property Items[ Idx: Integer ]: String read GetItems write SetItems;
4895 {* |<#edit>
4896 |<#listbox>
4897 |<#combo>
4898 |<#memo>
4899 |<#richedit>
4900 Obvious. Used with editboxes, listbox, combobox. With list view, use
4901 property LVItems instead. }
4903 function Item2Pos( ItemIdx: Integer ): Integer;
4904 {* |<#edit>
4905 |<#memo>
4906 Only for edit controls: converts line index to character position. }
4907 function Pos2Item( Pos: Integer ): Integer;
4908 {* |<#edit>
4909 |<#memo>
4910 Only for edit controls: converts character position to line index. }
4912 function EditTabChar: PControl;
4913 {* |<#edit>
4914 |<#memo>
4915 Call this method (once) to provide insertion of tab character (code #9)
4916 when tab key is pressed on keyboard. }
4918 function IndexOf( const S: String ): Integer;
4919 {* |<#listbox>
4920 |<#combobox>
4921 |<#tabcontrol>
4922 Works for the most of control types, though some of those
4923 have its own methods to search given item. If a control is not
4924 list box or combobox, item is finding by enumerating all
4925 the Items one by one. See also SearchFor method. }
4926 function SearchFor( const S: String; StartAfter: Integer; Partial: Boolean ): Integer;
4927 {* |<#listbox>
4928 |<#combobox>
4929 |<#tabcontrol>
4930 Works for the most of control types, though some of those
4931 have its own methods to search given item. If a control is not
4932 list box or combobox, item is finding by enumerating all
4933 the Items one by one. See also IndexOf method. }
4936 property ItemSelected[ ItemIdx: Integer ]: Boolean read GetItemSelected write SetItemSelected;
4937 {* |<#edit>
4938 |<#memo>
4939 |<#listbox>
4940 |<#combo>
4941 Returns True, if a line (in editbox) or an item (in listbox, combobox) is
4942 selected.
4943 Can be set only for listboxes. For listboxes, which are not multiselect, and
4944 for combo lists, it is possible only to set to True, to change selection. }
4946 property ItemData[ Idx: Integer ]: DWORD read GetItemData write SetItemData;
4947 {* |<#listbox>
4948 |<#combo>
4949 Access to user-defined data, associated with the item of a list box and
4950 combo box. }
4951 property OnDropDown: TOnEvent read fOnDropDown write fOnDropDown;
4952 {* |<#combo>
4953 |<#toolbar>
4954 Is called when combobox is dropped down (or drop-down button of
4955 toolbar is pressed - see also OnTBDropDown). }
4956 property OnCloseUp: TOnEvent read fOnCloseUp write fOnCloseUp;
4957 {* |<#combo>
4958 Is called when combobox is closed up. When drop down list is closed
4959 because user pressed "Escape" key, previous selection is restored.
4960 To test if it is so, call GetKeyState( VK_ESCAPE ) and check, if
4961 negative value is returned (i.e. Escape key is pressed when event
4962 handler is calling). }
4963 property DroppedWidth: Integer read FDroppedWidth write SetDroppedWidth;
4964 {* |<#combo>
4965 Allows to change width of dropped down items list for combobox (only!)
4966 control. }
4967 property DroppedDown: Boolean read fDropped write SetDroppedDown;
4968 {* |<#combo>
4969 Dropped down state for combo box. Set it to TRUE or FALSE to change
4970 dropped down state. }
4971 procedure AddDirList( const Filemask: String; Attrs: DWORD );
4972 {* |<#listbox>
4973 |<#combo>
4974 Can be used only with listbox and combobox - to add directory list items,
4975 filtered by given Filemask (can contain wildcards) and Attrs. Following
4976 flags can be combined in Attrs:
4977 |<table border=0>
4978 |&L=<tr><td>%1</td><td>
4979 <L DDL_ARCHIVE> Include archived files. <E>
4980 <L DDL_DIRECTORY> Includes subdirectories. Subdirectory names are
4981 enclosed in square brackets ([ ]). <E>
4982 <L DDL_DRIVES> Includes drives. Drives are listed in the form [-x-],
4983 where x is the drive letter. <E>
4984 <L DDL_EXCLUSIVE> Includes only files with the specified attributes.
4985 By default, read-write files are listed even if DDL_READWRITE is
4986 not specified. Also, this flag needed to list directories only,
4987 etc. <E>
4988 <L DDL_HIDDEN> Includes hidden files. <E>
4989 <L DDL_READONLY> Includes read-only files. <E>
4990 <L DDL_READWRITE> Includes read-write files with no additional
4991 attributes. <E>
4992 <L DDL_SYSTEM> Includes system files. <E>
4993 </table>
4994 If the listbox is sorted, directory items will be sorted (alpabetically). }
4995 property OnBitBtnDraw: TOnBitBtnDraw read fOnBitBtnDraw write fOnBitBtnDraw;
4996 {* |<#bitbtn>
4997 Special event for BitBtn. Using it, it is possible to provide
4998 additional effects, such as highlighting button text (by changing
4999 its Font and other properties). If the handler returns True, it is
5000 supposed that it made all drawing and there are no further drawing
5001 occure. }
5002 property BitBtnDrawMnemonic: Boolean read FBitBtnDrawMnemonic write SetBitBtnDrawMnemonic;
5003 {* |<#bitbtn>
5004 Set this property to TRUE to provide correct drawing of bit btn control
5005 caption with '&' characters (to remove such characters, and underline
5006 follow ones). }
5007 property TextShiftX: Integer read fTextShiftX write fTextShiftX;
5008 {* |<#bitbtn>
5009 Horizontal shift for bitbtn text when the bitbtn is pressed. }
5010 property TextShiftY: Integer read fTextShiftY write fTextShiftY;
5011 {* |<#bitbtn>
5012 Vertical shift for bitbtn text when the bitbtn is pressed. }
5013 property BitBtnImgIdx: Integer read GetBitBtnImgIdx write SetBitBtnImgIdx;
5014 {* |<#bitbtn>
5015 BitBtn image index for the first image in list view, used as bitbtn
5016 image. It is used only in case when BitBtn is created with bboImageList
5017 option. }
5018 property BitBtnImgList: THandle read GetBitBtnImageList write SetBitBtnImageList;
5019 {* |<#bitbtn>
5020 BitBtn Image list. Assign image list handle to change it. }
5022 function SetButtonIcon( aIcon: HIcon ): PControl;
5023 {* |<#button>
5024 Sets up button icon image and changes its styles. Returns button itself. }
5025 function SetButtonBitmap( aBmp: HBitmap ): PControl;
5026 {* |<#button>
5027 Sets up button icon image and changes its styles. Returns button itself. }
5029 property OnMeasureItem: TOnMeasureItem read fOnMeasureItem write SetOnMeasureItem;
5030 {* |<#combo>
5031 |<#listbox>
5032 |<#listview>
5033 This event is called for owner-drawn controls, such as list box, combo box,
5034 list view with appropriate owner-drawn style. For fixed item height controls
5035 (list box with loOwnerDrawFixed style, combobox with coOwnerDrawFixed and
5036 list view with lvoOwnerDrawFixed option) this event is called once. For
5037 list box with loOwnerDrawVariable style and for combobox with coOwnerDrawVariable
5038 style this event is called for every item. }
5040 property DefaultBtn: Boolean index 13
5041 {$IFDEF F_P} read GetDefaultBtn
5042 {$ELSE DELPHI} read fDefaultBtn
5043 {$ENDIF F_P/DELPHI} write SetDefaultBtn;
5044 {* |<#button>
5045 |<#bitbtn>
5046 Set this property to true to make control clicked when ENTER key is pressed.
5047 This property uses OnMessage event of the parent form, storing it into
5048 fOldOnMessage field and calling in chain. So, assign default button
5049 after setting OnMessage event for the form. }
5050 property CancelBtn: Boolean index 27
5051 {$IFDEF F_P} read GetDefaultBtn
5052 {$ELSE DELPHI} read fCancelBtn
5053 {$ENDIF F_P/DELPHI} write SetDefaultBtn;
5054 {* |<#button>
5055 |<#bitbtn>
5056 Set this property to true to make control clicked when escape key is pressed.
5057 This property uses OnMessage event of the parent form, storing it into
5058 fOldOnMessage field and calling in chain. So, assign cancel button
5059 after setting OnMessage event for the form. }
5060 function AllBtnReturnClick: PControl;
5061 {* Call this method for a form or any its control to provide clicking
5062 a focused button when ENTER pressed. By default, a button can be clicked
5063 only by SPACE key from the keyboard, or by mouse. }
5064 property IgnoreDefault: Boolean read fIgnoreDefault write fIgnoreDefault;
5065 {* Change this property to TRUE to ignore default button reaction on
5066 press ENTER key when a focus is grabbed of the control. Default
5067 value is different for different controls. By default, DefaultBtn
5068 ignored in memo, richedit (even if read-only). }
5071 property Color: TColor read fColor write SetCtlColor;
5072 {* Property Color is one of the most common for all visual
5073 elements (like form, control etc.) Please note, that standard GUI button
5074 can not change its color and the most characteristics of the Font. Also,
5075 standard button can not become Transparent. Use bitbtn for such purposes.
5076 Also, changing Color property for some kinds of control has no effect (rich edit,
5077 list view, tree view, etc.). To solve this, use native (for such controls)
5078 color property, or call Perform method with appropriate message to set the
5079 background color. }
5080 property Font: PGraphicTool read GetFont;
5081 {* If the Font property is not accessed, correspondent TGraphicTool object
5082 is not created and its methods are not included into executable. Leaving
5083 properties Font and Brush untouched can economy executable size a lot. }
5084 property Brush: PGraphicTool read GetBrush;
5085 {* If not accessed, correspondent TGraphicTool object is not created
5086 and its methods are not referenced. See also note on Font property. }
5088 property Ctl3D: Boolean read fCtl3D write SetCtl3D;
5089 {* Inheritable from parent controls to child ones. }
5091 procedure Show;
5092 {* |<#appbutton>
5093 |<#form>
5094 Makes control visible and activates it. }
5095 function ShowModal: Integer;
5096 {* |<#form>
5097 Can be used only with a forms to show it modal. See also global function
5098 ShowMsgModal.
5099 |<br>
5100 To use a form as a modal, it is possible to make it either auto-created
5101 or dynamically created. For a first case, You (may be prefer to hide a
5102 form after showing it as a modal:
5104 ! procedure TForm1.Button1Click( Sender: PObj );
5105 ! begin
5106 ! Form2.Form.ShowModal;
5107 ! Form2.Form.Hide;
5108 ! end;
5110 Another way is to create modal form just before showing it (this economies
5111 system resources):
5113 ! procedure TForm1.Button1Click( Sender: PObj );
5114 ! begin
5115 ! NewForm2( Form2, Applet );
5116 ! Form2.Form.ShowModal;
5117 ! Form2.Form.Free; // Never call Form2.Free or Form2.Form.Close
5118 ! end; // but always Form2.Form.Free; (!)
5120 In samples above, You certainly can place any wished code before and after
5121 calling ShowModal method.
5122 |<br>
5123 Do not forget that if You have more than a single form in your project,
5124 separate Applet object should be used.
5125 |<br>
5126 See also ShowModalEx.
5128 function ShowModalParented( const AParent: PControl ): Integer;
5129 {* by Alexander Pravdin. The same as ShowModal, but with a certain
5130 form as a parent. }
5131 function ShowModalEx: Integer;
5132 {* The same as ShowModal, but all the windows of current thread are
5133 disabled while showing form modal. This is useful if KOL form from
5134 a DLL is used modally in non-KOL application. }
5135 property ModalResult: Integer read fModalResult write
5136 {$IFDEF USE_SETMODALRESULT}
5137 SetModalResult;
5138 {$ELSE}
5139 fModalResult;
5140 {$ENDIF}
5141 {* |<#form>
5142 Modal result. Set it to value<>0 to stop modal dialog. By agreement,
5143 value 1 corresponds 'OK', 2 - 'Cancel'. But it is totally by decision
5144 of yours how to interpret this value. }
5145 property Modal: Boolean read GetModal;
5146 {* |<#form>
5147 TRUE, if the form is shown modal. }
5148 property ModalForm: PControl read fModalForm write fModalForm;
5149 {* |<#form>
5150 |<#appbutton>
5151 Form currently shown modal from this form or from Applet. }
5153 procedure Hide;
5154 {* |<#appbutton>
5155 |<#form>
5156 Makes control hidden. }
5157 property OnShow: TOnEvent read FOnShow write SetOnShow;
5158 {* Is called when a control or form is to be shown. This event is not fired
5159 for a form, if its WindowState initially is set to wsMaximized or
5160 wsMinimized. This behaviour is by design (the window does not receive
5161 WM_SHOW message in such case). }
5162 property OnHide: TOnEvent read FOnHide write SetOnHide;
5163 {* Is called when a control or form becomes hidden. }
5164 property WindowState: TWindowState read GetWindowState write SetWindowState;
5165 {* |<#form>
5166 Window state. }
5168 property Canvas: PCanvas read GetCanvas;
5169 {* |<#paintbox>
5170 Placeholder for Canvas: PCanvas. But in KOL, it is possible to
5171 create applets without canvases at all. To do so, avoid using
5172 Canvas and use DC directly (which is passed in OnPaint event). }
5173 function CallDefWndProc( var Msg: TMsg ): Integer;
5174 {* Function to be called in WndProc method to redirect message handling
5175 to default window procedure. }
5176 function DoSetFocus: Boolean;
5177 {* Sets focus for Enabled window. Returns True, if success. }
5179 procedure MinimizeNormalAnimated;
5180 {* |<#form>
5181 Apply this method to a main form (not to another form or Applet,
5182 even when separate Applet control is not used and main form matches it!).
5183 This provides normal animated visual minimization for the application.
5184 It therefore has no effect, if animation during minimize/resore is
5185 turned off by user. }
5187 property OnMessage: TOnMessage read fOnMessage write fOnMessage;
5188 {* |<#appbutton>
5189 |<#form>
5190 Is called for every message processed by TControl object. And for
5191 Applet window, this event is called also for all messages, handled by
5192 all its child windows (forms). }
5194 function IsMainWindow: Boolean;
5195 {* |<#appbutton>
5196 |<#form>
5197 Returns True, if a window is the main in application (created first
5198 after the Applet, or matches the Applet). }
5199 property IsApplet: Boolean read FIsApplet;
5200 {* Returns true, if the control is created using NewApplet (or CreateApplet).
5202 property IsForm: Boolean read fIsForm;
5203 {* Returns True, if the object is form window. }
5204 property IsMDIChild: Boolean read fIsMDIChild;
5205 {* Returns TRUE, if the object is MDI child form. In such case, IsForm also
5206 returns TRUE. }
5207 property IsControl: Boolean read fIsControl;
5208 {* Returns True, is the control is control (not form or applet). }
5209 property IsButton: Boolean read fIsButton;
5210 {* Returns True, if the control is button-like or containing buttons (button,
5211 bitbtn, checkbox, radiobox, toolbar). }
5213 function ProcessMessage: Boolean;
5214 {* |<#appbutton>
5215 Processes one message. See also ProcessMessages. }
5217 procedure ProcessMessages;
5218 {* |<#appbutton>
5219 Processes pending messages during long cycle of calculation,
5220 allowing to window to be repainted if needed and to respond to other
5221 messages. But if there are no such messages, your application can be
5222 stopped until such one appear in messages queue. To prevent such
5223 situation, use method ProcessPendingMessages instead. }
5225 procedure ProcessMessagesEx;
5226 {* Version of ProcessMessages, which works always correctly, even if
5227 the application is minimized or background. }
5229 procedure ProcessPendingMessages;
5230 {* |<#appbutton>
5231 Similar to ProcessMessages, but without waiting of
5232 message in messages queue. I.e., if there are no pending
5233 messages, this method immediately returns control to your
5234 code. This method is better to call during long cycle of
5235 calculation (then ProcessMessages). }
5236 procedure ProcessPaintMessages;
5237 {* }
5238 function WndProc( var Msg: TMsg ): Integer; virtual;
5239 {* Responds to all Windows messages, posted (sended) to the
5240 window, before all other proceeding. You can override it in
5241 derived controls, but in KOL there are several other ways
5242 to control message flow of existing controls without deriving
5243 another costom controls for only such purposes. See OnMessage,
5244 AttachProc. }
5245 property HasBorder: Boolean read GetHasBorder write SetHasBorder;
5246 {* |<#form>
5247 Obvious. Form-aware. }
5249 property HasCaption: Boolean read GetHasCaption write SetHasCaption;
5250 {* |<#form>
5251 Obvious. Form-aware. }
5252 property CanResize: Boolean read GetCanResize write SetCanResize;
5253 {* |<#form>
5254 Obvious. Form-aware. }
5255 property StayOnTop: Boolean read GetStayOnTop write SetStayOnTop;
5256 {* |<#form>
5257 Obvious. Form-aware, but can be applied to controls. }
5258 property Border: Integer read fMargin write fMargin;
5259 {* |<#form>
5260 Distance between edges and child controls and between child
5261 controls by default (if methods PlaceRight, PlaceDown, PlaceUnder,
5262 ResizeParent, ResizeParentRight, ResizeParentBottom are called).
5263 |<br>
5264 Originally was named Margin, now I recommend to use the name 'Border' to
5265 avoid confusion with MarginTop, MarginBottom, MarginLeft and
5266 MarginRight properties.
5267 |<br>
5268 Initial value is always 2. Border property is used in realigning
5269 child controls (when its Align property is not caNone), and value
5270 of this property determines size of borders between edges of children
5271 and its parent and between aligned controls too.
5272 |<br>
5273 See also properties MarginLeft, MarginRight, MarginTop, MarginBottom. }
5274 function SetBorder( Value: Integer ): PControl;
5275 {* Assigns new Border value, and returns @ Self. }
5277 property Margin: Integer read fMargin write fMargin;
5278 {* |<#form>
5279 Old name for property Border. }
5281 property MarginTop: Integer index 1
5282 {$IFDEF F_P} read GetClientMargin
5283 {$ELSE DELPHI} read fClientTop
5284 {$ENDIF F_P/DELPHI} write SetClientMargin;
5285 {* Additional distance between true window client top and logical top of
5286 client rectangle. This value is added to Top of rectangle, returning
5287 by property ClientRect. Together with other margins and property Border,
5288 this property allows to change view of form for case, that Align property
5289 is used to align controls on parent (it is possible to provide some
5290 distance from child controls to its parent, and between child controls.
5291 |<br>
5292 Originally this property was introduced to compensate incorrect
5293 ClientRect property, calculated for some types of controls.
5294 |<br>
5295 See also properties Border, MarginBottom, MarginLeft, MarginRight. }
5296 property MarginBottom: Integer index 2
5297 {$IFDEF F_P} read GetClientMargin
5298 {$ELSE DELPHI} read fClientBottom
5299 {$ENDIF F_P/DELPHI} write SetClientMargin;
5300 {* The same as MarginTop, but a distance between true window Bottom of
5301 client rectangle and logical bottom one. Take in attention, that this value
5302 should be POSITIVE to make logical bottom edge located above true edge.
5303 |<br>
5304 See also properties Border, MarginTop, MarginLeft, MarginRight. }
5305 property MarginLeft: Integer index 3
5306 {$IFDEF F_P} read GetClientMargin
5307 {$ELSE DELPHI} read fClientLeft
5308 {$ENDIF F_P/DELPHI} write SetClientMargin;
5309 {* The same as MarginTop, but a distance between true window Left of
5310 client rectangle and logical left edge.
5311 |<br>
5312 See also properties Border, MarginTop, MarginRight, MarginBottom. }
5313 property MarginRight: Integer index 4
5314 {$IFDEF F_P} read GetClientMargin
5315 {$ELSE DELPHI} read fClientRight
5316 {$ENDIF F_P/DELPHI} write SetClientMargin;
5317 {* The same as MarginLeft, but a distance between true window Right of
5318 client rectangle and logical bottom one. Take in attention, that this value
5319 should be POSITIVE to make logical right edge located left of true edge.
5320 |<br>
5321 See also properties Border, MarginTop, MarginLeft, MarginBottom. }
5323 property Tabstop: Boolean read fTabstop write fTabstop;
5324 {* True, if control can be focused using tabulating between controls.
5325 Set it to False to make control unavailable for keyboard, but only
5326 for mouse. }
5328 property TabOrder: Integer read fTabOrder write SetTabOrder;
5329 {* Order of tabulating of controls. Initially, TabOrder is equal to
5330 creation order of controls. If TabOrder changed, TabOrder of
5331 all controls with not less value of one is shifted up. To place
5332 control before another, assign TabOrder of one to another.
5333 For example:
5334 ! Button1.TabOrder := EditBox1.TabOrder;
5335 In code above, Button1 is placed just before EditBox1 in tabulating
5336 order (value of TabOrder of EditBox1 is incremented, as well as
5337 for all follow controls). }
5339 property Focused: Boolean read GetFocused write SetFocused;
5340 {* True, if the control is current on form (but check also, what form
5341 itself is focused). For form it is True, if the form is active (i.e.
5342 it is foreground and capture keyboard). Set this value to True to make
5343 control current and focused (if applicable). }
5345 function BringToFront: PControl;
5346 {* Changes z-order of the control, bringing it to the topmost level. }
5347 function SendToBack: PControl;
5348 {* Changes z-order of the control, sending it to the back of siblings. }
5349 property TextAlign: TTextAlign read GetTextAlign write SetTextAlign;
5350 {* |<#label>
5351 |<#panel>
5352 |<#button>
5353 |<#bitbtn>
5354 |<#edit>
5355 |<#memo>
5356 Text horizontal alignment. Applicable to labels, buttons,
5357 multi-line edit boxes, panels. }
5358 property VerticalAlign: TVerticalAlign read GetVerticalAlign write SetVerticalAlign;
5359 {* |<#button>
5360 |<#label>
5361 |<#panel>
5362 Text vertical alignment. Applicable to buttons, labels and panels. }
5363 property WordWrap: Boolean read fWordWrap write fWordWrap;
5364 {* TRUE, if this is a label, created using NewWordWrapLabel. }
5365 property ShadowDeep: Integer read FShadowDeep write SetShadowDeep;
5366 {* |<#3dlabel>
5367 Deep of a shadow (for label effect only, created calling NewLabelEffect). }
5369 property CannotDoubleBuf: Boolean read fCannotDoubleBuf write fCannotDoubleBuf;
5370 {* }
5371 property DoubleBuffered: Boolean read fDoubleBuffered write SetDoubleBuffered;
5372 {* Set it to true for some controls, which are flickering in repainting
5373 (like label effect). Slow, and requires additional code. This property
5374 is inherited by all child controls.
5375 |<br>&nbsp;&nbsp;&nbsp;
5376 Note: RichEdit control can not become DoubleBuffered. }
5377 //function IsSelfOrParentDblBuf: Boolean;
5378 {* Returns true, if DoubleBuffered or one of parents is DoubleBuffered. }
5379 function DblBufTopParent: PControl;
5380 {* Returns the topmost DoubleBuffered Parent control. }
5381 property Transparent: Boolean read fTransparent write SetTransparent;
5382 {* Set it to true to get special effects. Transparency also uses
5383 DoubleBuffered and inherited by child controls.
5384 |<br>&nbsp;&nbsp;&nbsp;
5385 Please note, that some controls can not be shown properly, when
5386 Transparent is set to True for it. If You want to make edit control
5387 transparent (e.g., over gradient filled panel), handle its OnChanged
5388 property and call there Invalidate to provide repainting of edit
5389 control content. Note also, that for RichEdit control property
5390 Transparent has no effect (as well as DoubleBuffered). But special
5391 property RE_Transparent is designed especially for RichEdit control
5392 (it works fine, but with great number of flicks while resizing
5393 of a control). Another note is about Edit control. To allow editing
5394 of transparent edit box, it is necessary to invalidate it for
5395 every pressed character. Or, use Ed_Transparent property instead. }
5397 property Ed_Transparent: Boolean read fTransparent write EdSetTransparent;
5398 {* |<#edit>
5399 |<#memo>
5400 Use this property for editbox to make it really Transparent. Remember,
5401 that though Transparent property is inherited by child controls from
5402 its parent, this is not so for Ed_Transparent. So, it is necessary to
5403 set Ed_Transparent to True for every edit control explicitly. }
5404 property AlphaBlend: Integer read fAlphaBlend write SetAlphaBlend;
5405 {* |<#form>
5406 If assigned to 0..254, makes window (form or control) semi-transparent
5407 (Win2K only).
5408 |<br>
5409 Depending on value assigned, it is possible to adjust transparency
5410 level ( 0 - totally transparent, 255 - totally opaque). }
5412 property LookTabKeys: TTabKeys read fLookTabKeys write fLookTabKeys;
5413 {* Set of keys which can be used as tabulation keys in a control. }
5414 procedure GotoControl( Key: DWORD );
5415 {* |<#form>
5416 Emulates tabulation key press w/o sending message to current control.
5417 Can be applied to a form or to any its control. If VK_TAB is used,
5418 state of shift kay is checked in: if it is pressed, tabulate is in
5419 backward direction. }
5420 property SubClassName: String read get_ClassName write set_ClassName;
5421 {* Name of window class - unique for every window class
5422 in every run session of a program. }
5424 property OnClose: TOnEventAccept read fOnClose write fOnClose;
5425 {* |<#form>
5426 |<#applet>
5427 Called before closing the window. It is possible to set Accept
5428 parameter to False to prevent closing the window. This event events
5429 is not called when windows session is finishing (to handle this
5430 event, handle WM_QUERYENDSESSION message, or assign OnQueryEndSession
5431 event to another or the same event handler). }
5433 property OnQueryEndSession: TOnEventAccept read fOnQueryEndSession write SetOnQueryEndSession;
5434 {* |<#form>
5435 |<#applet>
5436 Called when WM_QUERYENDSESSION message come in. It is possible to set Accept
5437 parameter to False to prevent closing the window (in such case session ending
5438 is halted). It is possible to check CloseQueryReason property to find out,
5439 why event occur. }
5440 property CloseQueryReason: TCloseQueryReason read fCloseQueryReason;
5441 {* Reason why OnClose or OnQueryEndSession called. }
5442 property OnMinimize: TOnEvent index 0
5443 {$IFDEF F_P} read GetOnMinMaxRestore
5444 {$ELSE DELPHI} read fOnMinimize
5445 {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;
5446 {* |<#form>
5447 Called when window is minimized. }
5448 property OnMaximize: TOnEvent index 8
5449 {$IFDEF F_P} read GetOnMinMaxRestore
5450 {$ELSE DELPHI} read fOnMaximize
5451 {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;
5452 {* |<#form>
5453 Called when window is maximized. }
5454 property OnRestore: TOnEvent index 16
5455 {$IFDEF F_P} read GetOnMinMaxRestore
5456 {$ELSE DELPHI} read fOnRestore
5457 {$ENDIF F_P/DELPHI} write SetOnMinMaxRestore;
5458 {* |<#form>
5459 Called when window is restored from minimized or maximized state. }
5461 property UpdateRgn: HRgn read fUpdRgn;
5462 {* A handle of update region. Valid only in OnPaint method. You
5463 can use it to improve painting (for speed), if necessary. When
5464 UpdateRgn is obtained in response to WM_PAINT message, value
5465 of the property EraseBackground is used to pass it to the API
5466 function GetUpdateRgn. If UpdateRgn = 0, this means that entire
5467 window should be repainted. Otherwise, You (e.g.) can check
5468 if the rectangle is in clipping region using API function
5469 RectInRegion. }
5471 property EraseBackground: Boolean read fEraseUpdRgn write fEraseUpdRgn;
5472 {* This value is used to pass it to the API function GetUpdateRgn,
5473 when UpadateRgn property is obtained first in responce to WM_PAINT
5474 message. If EraseBackground is set to True, system is responsible
5475 for erasing background of update region before painting. If not
5476 (default), the entire region invalidated should be painted by your
5477 event handler. }
5479 property OnPaint: TOnPaint read fOnPaint write SetOnPaint;
5480 {* Event to set to override standard control painting. Can be applied
5481 to any control (though originally was designed only for paintbox
5482 control). When an event handler is called, it is possible to use
5483 UpdateRgn to examine what parts of window require painting to
5484 improve performance of the painting operation. }
5485 property OnPrePaint: TOnPaint read fOnPrePaint write fOnPrePaint;
5486 {* Only for graphic controls. If you assign it, call Invalidate also. }
5487 property OnPostPaint: TOnPaint read fOnPostPaint write fOnPostPaint;
5488 {* Only for graphic controls. If you assign it, call Invalidate also. }
5490 property OnEraseBkgnd: TOnPaint read fOnEraseBkgnd write SetOnEraseBkgnd;
5491 {* This event allows to override erasing window background in response
5492 to WM_ERASEBKGND message. This allows to add some decorations to
5493 standard controls without overriding its painting in total.
5494 Note: When erase background, remember, that property ClientRect can
5495 return not true client rectangle of the window - use GetClientRect
5496 API function instead. For example:
5498 !var BkBmp: HBitmap;
5500 !procedure TForm1.KOLForm1FormCreate(Sender: PObj);
5501 !begin
5502 ! Toolbar1.OnEraseBkgnd := DecorateToolbar;
5503 ! BkBmp := LoadBitmap( hInstance, 'BK1' );
5504 !end;
5506 !procedure TForm1.DecorateToolbar(Sender: PControl; DC: HDC);
5507 !var CR: TRect;
5508 !begin
5509 ! GetClientRect( Sender.Handle, CR );
5510 ! Sender.Canvas.Brush.BrushBitmap := BkBmp;
5511 ! Sender.Canvas.FillRect( CR );
5512 !end;
5517 property OnClick: TOnEvent read fOnClick write fOnClick;
5518 {* |<#button>
5519 |<#checkbox>
5520 |<#radiobox>
5521 |<#toolbar>
5522 Called on click at control. For buttons, checkboxes and radioboxes
5523 is called regadless if control clicked by mouse or keyboard. For toolbar,
5524 the same event is used for all toolbar buttons and toolbar itself.
5525 To determine which toolbar button is clicked, check CurIndex property.
5526 And note, that all the buttons including separator buttons are enumerated
5527 starting from 0. Though images are stored (and prepared) only for
5528 non-separator buttons. And to determine, if toolbar button was clicked
5529 with right mouse button, check RightClick property. }
5530 property RightClick: Boolean read fRightClick;
5531 {* |<#toolbar>
5532 |<#listview>
5533 Use this property to determine which mouse button was clicked
5534 (applicable to toolbar in the OnClick event handler). }
5535 property OnEnter: TOnEvent read fOnEnter write fOnEnter;
5536 {* Called when control receives focus. }
5537 property OnLeave: TOnEvent read fOnLeave write fOnLeave;
5538 {* Called when control looses focus. }
5539 property OnChange: TOnEvent read fOnChange write fOnChange;
5540 {* |<#edit>
5541 |<#memo>
5542 |<#listbox>
5543 |<#combo>
5544 |<#tabcontrol>
5545 Called when edit control is changed, or selection in listbox or
5546 current index in combobox is changed (but if OnSelChanged assigned,
5547 the last is called for change selection). To respond to check/uncheck
5548 checkbox or radiobox events, use OnClick instead. }
5549 property OnSelChange: TOnEvent read fOnSelChange write fOnSelChange;
5550 {* |<#richedit>
5551 |<#listbox>
5552 |<#combo>
5553 |<#treeview>
5554 Called for rich edit control, listbox, combobox or treeview when current selection
5555 (range, or current item) is changed. If not assigned, but OnChange is
5556 assigned, OnChange is called instead. }
5557 property OnResize: TOnEvent read FOnResize write SetOnResize;
5558 {* Called whenever control receives message WM_SIZE (thus is, if
5559 control is resized. }
5560 property OnMove: TOnEvent read FOnMove write SetOnMove;
5561 {* Called whenever control receives message WM_MOVE (i.e. when control is
5562 moved over its parent). }
5564 property MinSizePrev: Integer read fSplitMinSize1 write fSplitMinSize1;
5565 {* |<#splitter>
5566 Minimal allowed (while dragging splitter) size of previous control
5567 for splitter (see NewSplitter). }
5568 property SplitMinSize1: Integer read fSplitMinSize1 write fSplitMinSize1;
5569 {* The same as MinSizePrev. }
5570 property MinSizeNext: Integer read fSplitMinSize2 write fSplitMinSize2;
5571 {* |<#splitter>
5572 Minimal allowed (while dragging splitter) size of the rest of parent
5573 of splitter or of SecondControl (see NewSplitter). }
5574 property SplitMinSize2: Integer read fSplitMinSize2 write fSplitMinSize2;
5575 {* The same as MinSizeNext. }
5576 property SecondControl: PControl read fSecondControl write fSecondControl;
5577 {* |<#splitter>
5578 Second control to check (while dragging splitter) if its size not less
5579 than SplitMinSize2 (see NewSplitter). By default, second control is
5580 not necessary, and needed only in rare case when SecondControl can not
5581 be determined automatically to restrict splitter right (bottom) position. }
5582 property OnSplit: TOnSplit read fOnSplit write fOnSplit;
5583 {* |<#splitter>
5584 Called when splitter control is dragging - to allow for
5585 your event handler to decide if to accept new size of
5586 left (top) control, and new size of the rest area of parent. }
5587 property Dragging: Boolean read FDragging;
5588 {* |<#splitter>
5589 True, if splitter control is dragging now by user with left
5590 mouse button. Also, this property can be used to detect if the control
5591 is dragging with mouse (after calling DragStartEx method). }
5592 procedure DragStart;
5593 {* Call this method for a form or control to drag it with left mouse button,
5594 when mouse left button is already down. Dragging is stopped when left mouse
5595 button is released. See also DragStartEx, DragStopEx. }
5596 procedure DragStartEx;
5597 {* Call this method to start dragging the form by mouse. To stop
5598 dragging, call DragStopEx method. (Tip: to detect mouse up event,
5599 use OnMouseUp event of the dragging control). This method can be used
5600 to move any control with the mouse, not only entire form. State of
5601 mouse button is not significant. Determine dragging state of the control
5602 checking its Dragging property. }
5603 procedure DragStopEx;
5604 {* Call this method to stop dragging the form (started by DragStopEx). }
5605 procedure DragItem( OnDrag: TOnDrag );
5606 {* Starts dragging something with mouse. During the process,
5607 callback function OnDrag is called, which allows to control
5608 drop target, change cursor shape, etc. }
5610 property OnKeyDown: TOnKey read fOnKeyDown write SetOnKeyDown;
5611 {* Obvious. }
5612 property OnKeyUp: TOnKey read fOnKeyUp write SetOnKeyUp;
5613 {* Obvious. }
5614 property OnChar: TOnChar read fOnChar write SetOnChar;
5615 {* Obvious. }
5617 property OnMouseDown: TOnMouse read fOnMouseDown write SetMouseDown;
5618 {* Obvious. }
5619 property OnMouseUp: TOnMouse read fOnMouseUp write SetMouseUp;
5620 {* Obvious. }
5621 property OnMouseMove: TOnMouse read fOnMouseMove write SetMouseMove;
5622 {* Obvious. }
5623 property OnMouseDblClk: TOnMouse read fOnMouseDblClk write SetMouseDblClk;
5624 {* Obvious. }
5625 property OnMouseWheel: TOnMouse read fOnMouseWheel write SetMouseWheel;
5626 {* Obvious. }
5628 property OnMouseEnter: TOnEvent read fOnMouseEnter write SetOnMouseEnter;
5629 {* Is called when mouse is entered into control. See also OnMouseLeave. }
5630 property OnMouseLeave: TOnEvent read fOnMouseLeave write SetOnMouseLeave;
5631 {* Is called when mouse is leaved control. If this event is assigned,
5632 then mouse is captured on mouse enter event to handle all other
5633 mouse events until mouse cursor leaves the control. }
5634 property OnTestMouseOver: TOnTestMouseOver read fOnTestMouseOver write SetOnTestMouseOver;
5635 {* |<#bitbtn>
5636 Special event, which allows to extend OnMouseEnter / OnMouseLeave
5637 (and also Flat property for BitBtn control). If a handler is assigned
5638 to this event, actual testing whether mouse is in control or not,
5639 is occuring in the handler. So, it is possible to simulate more
5640 careful hot tracking for controls with non-rectangular shape (such
5641 as glyphed BitBtn control). }
5643 property MouseInControl: Boolean read fMouseInControl;
5644 {* |<#bitbtn>
5645 This property can return True only if OnMouseEnter / OnMouseLeave
5646 event handlers are set for a control (or, for BitBtn, property Flat
5647 is set to True. Otherwise, False is returned always. }
5649 property Flat: Boolean read fFlat write SetFlat;
5650 {* |<#bitbtn>
5651 Set it to True for BitBtn, to provide either flat border for a button
5652 or availability of "highlighting" (correspondent to glyph index 4).
5653 |<br>
5654 Note: this can work incorrectly a bit under win95 without comctl32.dll
5655 updated. Therefore, application will launch. To enforce correct working
5656 even under Win95, use your own timer, which event handler checks for
5657 mouse over bitbtn control, e.g.:
5658 ! procedure TForm1.Timer1Timer(Sender: PObj);
5659 ! var P: TPoint;
5660 ! begin
5661 ! if not BitBtn1.MouseInControl then Exit;
5662 ! GetCursorPos( P );
5663 ! P := BitBtn1.Screen2Client( P );
5664 ! if not PtInRect( BitBtn1.ClientRect, P ) then
5665 ! begin
5666 ! BitBtn1.Flat := FALSE;
5667 ! BitBtn1.Flat := TRUE;
5668 ! end;
5669 ! end;
5671 property RepeatInterval: Integer read fRepeatInterval write fRepeatInterval;
5672 {* |<#bitbtn>
5673 If this property is set to non-zero, it is interpreted (for BitBtn
5674 only) as an interval in milliseconds between repeat button down events,
5675 which are generated after first mouse or button click and until
5676 button is released. Though, if the button is pressed with keyboard (with
5677 space key), RepeatInterval value is ignored and frequency of repeatitive
5678 clicking is determined by user keyboard settings only. }
5679 function LikeSpeedButton: PControl;
5680 {* |<#button>
5681 |<#bitbtn>
5682 Transparent method (returns control itself). Makes button not focusable. }
5684 function Add( const S: String ): Integer;
5685 {* |<#listbox>
5686 |<#combo>
5687 Only for listbox and combobox. }
5689 function Insert( Idx: Integer; const S: String ): Integer;
5690 {* |<#listbox>
5691 |<#combo>
5692 Only for listbox and combobox. }
5693 procedure Delete( Idx: Integer );
5694 {* |<#listbox>
5695 |<#combo>
5696 Only for listbox and combobox. }
5697 procedure Clear;
5698 {* Clears object content. Has different sense for different controls.
5699 E.g., for label, editbox, button and other simple controls it
5700 assigns empty string to Caption property. For listbox, combobox,
5701 listview it deletes all items. For toolbar, it deletes all buttons.
5702 Et so on. }
5704 property Progress: Integer index ((PBM_SETPOS or $8000) shl 16) or PBM_GETPOS
5705 read GetIntVal write SetIntVal;
5706 {* |<#progressbar>
5707 Only for ProgressBar. }
5708 property MaxProgress: Integer index ((PBM_SETRANGE32 or $8000) shl 16) or PBM_GETRANGE
5709 read GetIntVal write SetMaxProgress;
5710 {* |<#progressbar>
5711 Only for ProgressBar. 100 is the default value. }
5712 property ProgressColor: TColor read fTextColor write SetProgressColor;
5713 {* |<#progressbar>
5714 Only for ProgressBar. }
5715 property ProgressBkColor: TColor read fColor write SetCtlColor; //SetProgressBkColor;
5716 {* |<#progressbar>
5717 Obsolete. Now the same as Color. }
5719 property StatusText[ Idx: Integer ]: PChar read GetStatusText write SetStatusText;
5720 {* |<#form>
5721 Only for forms to set/retrieve status text to/from given status panel.
5722 Panels are enumerated from 0 to 254, 255 is to indicate simple
5723 status bar. Size grip in right bottom corner of status window is
5724 displayed only if form still CanResize.
5725 |<br>
5726 When a status text is set first time, status bar window is created
5727 (always aligned to bottom), and form is resizing to preset client height.
5728 While status bar is showing, client height value is returned without
5729 height of status bar. To remove status bar, call RemoveStatus method for
5730 a form.
5731 |<br>
5732 By default, text is left-aligned within the specified part of a status
5733 window. You can embed tab characters (#9) in the text to center or
5734 right-align it. Text to the right of a single tab character is centered,
5735 and text to the right of a second tab character is right-aligned.
5736 |<br>
5737 If You use separate status bar onto several panels, these automatically
5738 align its widths to the same value (width divided to number of panels).
5739 To adjust status panel widths for every panel, use property StatusPanelRightX.
5741 property SimpleStatusText: PChar index 255 read GetStatusText write SetStatusText;
5742 {* |<#form>
5743 Only for forms to set/retrive status text to/from simple status bar.
5744 Size grip in right bottom corner of status window is displayed only
5745 if form CanResize.
5746 |<br>
5747 When status text set first time, (simple) status bar window is created
5748 (always aligned to bottom), and form is resizing to preset client height.
5749 While status bar is showing, client height value is returned without
5750 height of status bar. To remove status bar, call RemoveStatus method for
5751 a form.
5752 |<br>
5753 By default, text is left-aligned within the specified part of a status
5754 window. You can embed tab characters (#9) in the text to center or
5755 right-align it. Text to the right of a single tab character is centered,
5756 and text to the right of a second tab character is right-aligned.
5758 property StatusCtl: PControl read fStatusCtl;
5759 {* Pointer to Status bar control. To "create" child controls on
5760 the status bar, first create it as a child of form, for instance, and
5761 then change its property Parent, e.g.:
5762 ! var Progress1: PControl;
5763 ! ...
5764 ! Progress1 := NewProgressBar( Form1 );
5765 ! Progress1.Parent := Form1.StatusCtl;
5766 (If you use MCK, code should be another a bit, and in this case it is
5767 possible to create and adjust the control at design-time, and at run-time
5768 change its parent control. E.g. (Progress1 is created at run-time here too):
5769 ! Progress1 := NewProgressBar( Form );
5770 ! Progress1.Parent := Form.StatusCtl;
5772 Do not forget to provide StatusCtl to be existing first (e.g. assign
5773 one-space string to SimpleStatusText property of the form, for MCK do
5774 so using Object Inspector).
5776 property SizeGrip: Boolean read fSizeGrip write fSizeGrip;
5777 {* Size grip for status bar. Has effect only before creating window. }
5779 procedure RemoveStatus;
5780 {* |<#form>
5781 Call it to remove status bar from a form (created in result of assigning
5782 value(s) to StatusText[], SimpleStatusText properties). When status bar is
5783 removed, form is resized to preset client height. }
5784 function StatusPanelCount: Integer;
5785 {* |<#form>
5786 Returns number of status panels defined in status bar. }
5787 property StatusPanelRightX[ Idx: Integer ]: Integer read GetStatusPanelX write SetStatusPanelX;
5788 {* |<#form>
5789 Use this property to adjust status panel right edges (if the status bar is
5790 divided onto several subpanels). If the right edge for the last panel is
5791 set to -1 (by default) it is expanded to the right edge of a form window.
5792 Otherwise, status bar can be shorter then form width. }
5793 property StatusWindow: HWND read fStatusWnd;
5794 {* |<#form>
5795 Provided for case if You want to use API direct message sending to
5796 status bar. }
5798 property Color1: TColor read fColor1 write SetColor1;
5799 {* |<#gradient>
5800 Top line color for GradientPanel. }
5801 property Color2: TColor read fColor2 write SetColor2;
5802 {* |<#gradient>
5803 |<#3Dlabel>
5804 Bottom line color for GradientPanel, or shadow color for LabelEffect.
5805 (If clNone, shadow color for LabelEffect is calculated as a mix bitween
5806 TextColor and clBlack). }
5807 property GradientStyle: TGradientStyle read FGradientStyle write SetGradientStyle;
5808 {* |<#gradient>
5809 Styles other then gsVertical and gsHorizontal has effect only for
5810 gradient panel, created by NewGradientPanelEx. }
5811 property GradientLayout: TGradientLayout read FGradientLayout write SetGradientLayout;
5812 {* |<#gradient>
5813 Has only effect for gradient panel, created by NewGradientPanelEx.
5814 Ignored for styles gsVertical and gsHorizontal. }
5816 //======== Image lists (for ListView, TreeView, ToolBar and TabControl):
5817 property ImageListSmall: PImageList index 16 read GetImgListIdx write SetImgListIdx;
5818 {* |<#listview>
5819 Image list with small icons used with List View control. If not set,
5820 last added (i.e. created with a control as an owner) image list with
5821 small icons is used. }
5822 property ImageListNormal: PImageList index 32 read GetImgListIdx write SetImgListIdx;
5823 {* |<#listview>
5824 |<#treeview>
5825 |<#tabcontrol>
5826 |<#bitbtn>
5827 Image list with normal size icons used with List View control (or with
5828 icons for BitBtn, TreeView, ToolBar or TabControl). If not set,
5829 last added (i.e. created with a control as an owner) image list is used.
5831 property ImageListState: PImageList index 0 read GetImgListIdx write SetImgListIdx;
5832 {* |<#listview>
5833 |<#treeview>
5834 Image list used as a state images list for ListView or TreeView control. }
5836 //========
5837 function SetUnicode( Unicode: Boolean ): PControl;
5838 {* |<#listview>
5839 |<#treeview>
5840 |<#tabcontrol>
5841 Sets control as Unicode or not. The control itself is returned as for
5842 other "transparent" functions. A conditional define UNICODE_CTRLS must
5843 be added to a project to provide handling unicode messages. }
5845 //======== TabControl-specific properties and methods:
5846 property Pages[ Idx: Integer ]: PControl read GetPages;
5847 {* |<#tabcontrol>
5848 Returns controls, which can be used as parent for controls, placed on
5849 different pages of a tab control. Use it like in follows example:
5850 | Label1 := NewLabel( TabControl1.Pages[ 0 ], 'Label1' );
5851 To find number of pages available, check out Count property of the tab
5852 control. Pages are enumerated from 0 to Count - 1, as usual. }
5853 property TC_Pages[ Idx: Integer ]: PControl read GetPages;
5854 {* |<#tabcontrol>
5855 The same as above. }
5856 function TC_Insert( Idx: Integer; const TabText: String; TabImgIdx: Integer ): PControl;
5857 {* |<#tabcontrol>
5858 Inserts new tab before given, returns correspondent page control
5859 (which can be used as a parent for controls to place on the page). }
5860 procedure TC_Delete( Idx: Integer );
5861 {* |<#tabcontrol>
5862 Removes tab from tab control, destroying all its child controls. }
5863 property TC_Items[ Idx: Integer ]: String read TCGetItemText write TCSetItemText;
5864 {* |<#tabcontrol>
5865 Text, displayed on tab control tabs. }
5866 property TC_Images[ Idx: Integer ]: Integer read TCGetItemImgIDx write TCSetItemImgIdx;
5867 {* |<#tabcontrol>
5868 Image index for a tab in tab control. }
5869 property TC_ItemRect[ Idx: Integer ]: TRect read TCGetItemRect;
5870 {* |<#tabcontrol>
5871 Item rectangle for a tab in tab control. }
5872 procedure TC_SetPadding( cx, cy: Integer );
5873 {* |<#tabcontrol>
5874 Sets space padding around tab text in a tab of tab control. }
5875 function TC_TabAtPos( x, y: Integer ): Integer;
5876 {* |<#tabcontrol>
5877 Returns index of tab, found at the given position (relative to
5878 a client rectangle of tab control). If no tabs found at the
5879 position, -1 is returned. }
5880 function TC_DisplayRect: TRect;
5881 {* |<#tabcontrol>
5882 Returns rectangle, occupied by a page rather then tab. }
5883 function TC_IndexOf(const S: String): Integer;
5884 {* |<#tabcontrol>
5885 By Mr Brdo. Index of page by its Caption. }
5886 function TC_SearchFor(const S: String; StartAfter: Integer; Partial: Boolean): Integer;
5887 {* |<#tabcontrol>
5888 By Mr Brdo. Index of page by its Caption. }
5890 //======== ListView style and options:
5891 property LVStyle: TListViewStyle read fLVStyle write SetLVStyle;
5892 {* |<#listview>
5893 ListView style of view. Can be changed at run time. }
5895 property LVOptions: TListViewOptions read fLVOptions write SetLVOptions;
5896 {* |<#listview>
5897 ListView options. Can be changed at run time. }
5899 property LVTextColor: TColor index LVM_GETTEXTCOLOR
5900 {$IFDEF F_P} read LVGetColorByIdx
5901 {$ELSE DELPHI} read fTextColor
5902 {$ENDIF F_P/DELPHI} write LVSetColorByIdx;
5903 {* |<#listview>
5904 ListView text color. Use it instead of TextColor. }
5905 property LVTextBkColor: TColor index LVM_GETTEXTBKCOLOR
5906 {$IFDEF F_P} read LVGetColorByIdx
5907 {$ELSE DELPHI} read fLVTextBkColor
5908 {$ENDIF F_P/DELPHI} write LVSetColorByIdx;
5909 {* |<#listview>
5910 ListView background color for text. }
5911 property LVBkColor: TColor read fColor write SetCtlColor; //LVSetBkColor;
5912 {* |<#listview>
5913 ListView background color. Use it instead of Color. }
5915 //======== List View columns handling:
5916 property LVColCount: Integer read fLVColCount;
5917 {* |<#listview>
5918 ListView (additional) column count. Value 0 means that there are
5919 no columns (single item text / icon is used). If You want
5920 to provide several columns, first call LVColAdd to "insert" column 0,
5921 i.e. to provide header text for first column (with index 0).
5922 If there are no column, nothing will be shown in lvsDetail /
5923 lvsDetailNoHeader view style. }
5924 procedure LVColAdd( const aText: String; aalign: TTextAlign; aWidth: Integer );
5925 {* |<#listview>
5926 Adds new column. Pass 'width' <= 0 to provide default column width.
5927 'text' is a column header text. }
5928 {$IFNDEF _FPC}
5929 {$IFNDEF _D2}
5930 procedure LVColAddW( const aText: WideString; aalign: TTextAlign; aWidth: Integer );
5931 {* |<#listview>
5932 Adds new column (unicode version). }
5933 {$ENDIF _D2}
5934 {$ENDIF _FPC}
5935 procedure LVColInsert( ColIdx: Integer; const aText: String; aAlign: TTextAlign; aWidth: Integer );
5936 {* |<#listview>
5937 Inserts new column at the Idx position (1-based column index). }
5938 {$IFNDEF _FPC}
5939 {$IFNDEF _D2}
5940 procedure LVColInsertW( ColIdx: Integer; const aText: WideString; aAlign: TTextAlign; aWidth: Integer );
5941 {* |<#listview>
5942 Inserts new column at the Idx position (1-based column index). }
5943 {$ENDIF _D2}
5944 {$ENDIF _FPC}
5945 procedure LVColDelete( ColIdx: Integer );
5946 {* |<#listview>
5947 Deletes column from List View }
5948 property LVColWidth[ Item: Integer ]: Integer index LVM_GETCOLUMNWIDTH
5949 read GetItemVal write SetItemVal;
5950 {* |<#listview>
5951 Retrieves or changes column width. For lvsList view style, the same width
5952 is returned for all columns (ColIdx is ignored). It is possible to use
5953 special values to assign to a property:
5954 |<br> LVSCW_AUTOSIZE - Automatically sizes the column
5955 |<br> LVSCW_AUTOSIZE_USEHEADER - Automatically sizes the column to fit
5956 the header text
5957 |<br>
5958 To set coumn width in lvsList view mode, column index must be -1
5959 (and Width to set must be in range 0..32767 always). }
5960 property LVColText[ Idx: Integer ]: String read GetLVColText write SetLVColText;
5961 {* |<#listview>
5962 Allows to get/change column header text at run time. }
5963 {$IFNDEF _FPC}
5964 {$IFNDEF _D2}
5965 property LVColTextW[ Idx: Integer ]: WideString read GetLVColTextW write SetLVColTextW;
5966 {* |<#listview>
5967 Allows to get/change column header text at run time. }
5968 {$ENDIF _D2}
5969 {$ENDIF _FPC}
5970 property LVColAlign[ Idx: Integer ]: TTextAlign read GetLVColalign write SetLVColalign;
5971 {* |<#listview>
5972 Column text aligning. }
5973 property LVColImage[ Idx: Integer ]: Integer index LVCF_IMAGE or (24 shl 16) read GetLVColEx write SetLVColEx;
5974 {* |<#listview>
5975 Only starting from comctrl32.dll of version 4.70 (IE4+). Allows to
5976 set an image for list view column itself from the ImageListSmall.
5978 property LVColOrder[ Idx: Integer ]: Integer index LVCF_ORDER or (28 shl 16) read GetLVColEx write SetLVColEx;
5979 {* |<#listview>
5980 Only starting from comctrl32.dll of version 4.70 (IE4+). Allows to
5981 set visual order of the list view column from the ImageListSmall.
5982 This value does not affect the index, by which the column is still
5983 accessible in the column array.
5986 //======== List View items handling:
5987 property LVCount: Integer read GetItemsCount write SetItemsCount;
5988 {* |<#listview>
5989 Returns item count for ListView control. It is possible to use Count
5990 property instead when obtaining of item count is needed only. But this this
5991 property allows also to set actual count of list view items when a list
5992 view is virtual. }
5994 property LVCurItem: Integer read GetLVCurItem write SetLVCurItem;
5995 {* |<#listview>
5996 Returns first selected item index in a list view. See also LVNextSelected,
5997 LVNextItem and LVFocusItem functions. }
5999 property LVFocusItem: Integer read GetLVFocusItem;
6000 {* |<#listview>
6001 Returns focused item index in a list view. See also LVCurItem. }
6003 function LVNextItem( IdxPrev: Integer; Attrs: DWORD ): Integer;
6004 {* |<#listview>
6005 Returns an index of the next after IdxPrev item with given attributes in
6006 the list view. }
6007 function LVNextSelected( IdxPrev: Integer ): Integer;
6008 {* |<#listview>
6009 Returns an index of next (after IdxPrev) selected item in a list view. }
6011 function LVAdd( const aText: String; ImgIdx: Integer; State: TListViewItemState;
6012 StateImgIdx, OverlayImgIdx: Integer; Data: DWORD ): Integer;
6013 {* |<#listview>
6014 Adds new line to the end of ListView control. Only content of item itself
6015 is set (aText, ImgIdx). To change other column text and attributes of
6016 item added, use appropriate properties / methods ().
6017 |<br>
6018 Returns an index of added item.
6019 |<br>
6020 There is no Unicode version defined, use LVItemAddW instead. }
6021 function LVItemAdd( const aText: String ): Integer;
6022 {* |<#listview>
6023 Adds an item to the end of list view. Returns an index of the item added. }
6024 {$IFNDEF _FPC}
6025 {$IFNDEF _D2}
6026 function LVItemAddW( const aText: WideString ): Integer;
6027 {* |<#listview>
6028 Adds an item to the end of list view. Returns an index of the item added. }
6029 {$ENDIF _D2}
6030 {$ENDIF _FPC}
6031 function LVInsert( Idx: Integer; const aText: String; ImgIdx: Integer;
6032 State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer; Data: DWORD ): Integer;
6033 {* |<#listview>
6034 Inserts new line before line with index Idx in ListView control. Only
6035 content of item itself is set (aText, ImgIdx). To change other column
6036 text and attributes of item added, use appropriate properties / methods ().
6037 if ImgIdx = I_IMAGECALLBACK, event handler OnGetLVItemImgIdx is responsible
6038 for returning image index for an item ( /// not implemented yet /// )
6039 Pass StateImgIdx and OverlayImgIdx = 0 (ignored in that case) or 1..15 to
6040 use correspondent icon from ImageListState image list.
6041 |<br> Returns an index of item inserted.
6042 |<br> There is no unicode version of this method, use LVItemInsertW. }
6043 function LVItemInsert( Idx: Integer; const aText: String ): Integer;
6044 {* |<#listview>
6045 Inserts an item to Idx position. }
6046 {$IFNDEF _FPC}
6047 {$IFNDEF _D2}
6048 function LVItemInsertW( Idx: Integer; const aText: WideString ): Integer;
6049 {* |<#listview>
6050 Inserts an item to Idx position. }
6051 {$ENDIF _D2}
6052 {$ENDIF _FPC}
6054 procedure LVDelete( Idx: Integer );
6055 {* |<#listview>
6056 Deletes item of ListView with subitems (full row - in lvsDetail view style. }
6057 procedure LVSetItem( Idx, Col: Integer; const aText: String; ImgIdx: Integer;
6058 State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer; Data: DWORD );
6059 {* |<#listview>
6060 Use this method to set item data and item columns data for ListView control.
6061 It is possible to pass I_SKIP as ImgIdx, StateImgIdx, OverlayImgIdx values to
6062 skip setting this fields. But all other are set always. Like in LVInsert /
6063 LVAdd, ImgIdx can be I_IMAGECALLBACK to determine that image will be
6064 retrieved in OnGetItemImgIdx event handler when needed.
6065 |<br>
6066 If this method is called to set data for column > 0, parameters ImgIdx and
6067 Data are ignored anyway.
6068 |<br> There is no unicode version of this method, use other methods
6069 to set up listed properties separately using correspondent W-functions. }
6071 property LVItemState[ Idx: Integer ]: TListViewItemState read LVGetItemState write LVSetItemState;
6072 {* |<#listview>
6073 Access to list view item states set [lvisBlend, lvisHighlight, lvisFocus,
6074 lvisSelect]. When assign new value to the property, it is possible to use
6075 special index value -1 to change state for all items for a list view
6076 (but only when lvoMultiselect style is applied to the list view, otherwise
6077 index -1 is referring to the last item of the list view). }
6079 property LVItemIndent[ Idx: Integer ]: Integer read LVGetItemIndent write LVSetItemIndent;
6080 {* Item indentation. Indentation is calculated as this value multiplied to
6081 image list ImgWidth value (Image list must be applied to list view).
6082 Note: indentation supported only if IE3.0 or higher installed. }
6083 property LVItemStateImgIdx[ Idx: Integer ]: Integer read LVGetSttImgIdx write LVSetSttImgIdx;
6084 {* |<#listview>
6085 Access to state image of the item. Use index -1 to assign the same state
6086 image index to all items of the list view at once (fast).
6087 Option lvoCheckBoxes just means, that control itself creates special inner
6088 image list for two state images. Later it is possible to examine checked
6089 state for items or set checked state programmatically by changing
6090 LVItemStateImgIdx[ ] property. Value 1 corresponds to unchecked state,
6091 2 to checked. Value 0 allows to remove checkbox at all. So, to check all
6092 added items by default (e.g.), do following:
6093 ! ListView1.LVItemStateImgIdx[ -1 ] := 2;
6094 |<br>Use 1-based index of the image
6095 in image list ImageListState. Value 0 reserved to use as "no state image".
6096 Values 1..15 can be used only - this is the Windows restriction on
6097 state images. }
6098 property LVItemOverlayImgIdx[ Idx: Integer ]: Integer read LVGetOvlImgIdx write LVSetOvlImgIdx;
6099 {* |<#listview>
6100 Access to overlay image of the item. Use index -1 to assign the same
6101 overlay image to all items of the list view at once (fast). }
6102 property LVItemData[ Idx: Integer ]: DWORD read LVGetItemData write LVSetItemData;
6103 {* |<#listview>
6104 Access to user defined data, assiciated with the item of the list view. }
6105 procedure LVSelectAll;
6106 {* |<#listview>
6107 Call this method to select all the items of the list view control. }
6108 property LVSelCount: Integer read GetSelLength write SetSelLength;
6109 {* |<#listview>
6110 Returns number of items selected in listview. }
6111 property LVItemImageIndex[ Idx: Integer ]: Integer read LVGetItemImgIdx write LVSetItemImgIdx;
6112 {* |<#listview>
6113 Image index of items in listview. When an item is created (using LVItemAdd
6114 or LVItemInsert), image index 0 is set by default (not -1 like in VCL!). }
6115 property LVItems[ Idx, Col: Integer ]: String read LVGetItemText write LVSetItemText;
6116 {* |<#listview>
6117 Access to List View item text. }
6118 {$IFNDEF _FPC}
6119 {$IFNDEF _D2}
6120 property LVItemsW[ Idx, Col: Integer ]: WideString read LVGetItemTextW write LVSetItemTextW;
6121 {* |<#listview>
6122 Access to List View item text. }
6123 {$ENDIF _D2}
6124 {$ENDIF _FPC}
6125 function LVItemRect( Idx: Integer; Part: TGetLVItemPart ): TRect;
6126 {* |<#listview>
6127 Returns rectangle occupied by given item part(s) in ListView window.
6128 Empty rectangle is returned, if the item is not viewing currently. }
6129 function LVSubItemRect( Idx, ColIdx: Integer ): TRect;
6130 {* |<#listview>
6131 Returns rectangle occupied by given item's subitem in ListView window,
6132 in lvsDetail or lvsDetailNoHeader style. Empty rectangle (0,0,0,0) is
6133 returned if the item is not viewing currently. Left or/and right bounds
6134 of the rectangle returned can be outbound item rectangle if only a part
6135 of the subitem is visible or the subitem is not visible in the item,
6136 which is visible itself. }
6137 property LVItemPos[ Idx: Integer ]: TPoint read LVGetItemPos write LVSetItemPos;
6138 {* |<#listview>
6139 Position of List View item (can be changed in icon or small icon view). }
6140 function LVItemAtPos( X, Y: Integer ): Integer;
6141 {* |<#listview>
6142 Return index of item at the given position. }
6143 function LVItemAtPosEx( X, Y: Integer; var Where: TWherePosLVItem ): Integer;
6144 {* |<#listview>
6145 Retrieves index of item and sets in Where, what part of item is under
6146 given coordinates. If there are no items at the specified position,
6147 -1 is returned. }
6148 procedure LVMakeVisible( Item: Integer; PartiallyOK: Boolean );
6149 {* |<#listview>
6150 Makes listview item visible. Ignred when Item passed < 0. }
6151 procedure LVEditItemLabel( Idx: Integer );
6152 {* |<#listview>
6153 Begins in-place editing of item label (first column text). }
6154 procedure LVSort;
6155 {* |<#listview>
6156 Initiates sorting of list view items. This sorting procedure is available only
6157 for Win2K, WinNT4 with IE5, Win98 or Win95 with IE5. See also LVSortData. }
6158 procedure LVSortData;
6159 {* |<#listview>
6160 Initiates sorting of list view items. This sorting procedure is always available
6161 in Windows95/98, NT/2000. But OnCompareLVItems procedure receives not indexes of
6162 items compared but its Data field associated instead. }
6163 procedure LVSortColumn( Idx: Integer );
6164 {* |<#listview>
6165 This is a method to simplify sort by column. Just call it in your OnColumnClick
6166 event passing column index and enjoy with your list view sorted automatically
6167 when column header is clicked. Requieres Windows2000 or Winows98, not supported
6168 under WinNT 4.0 and below and under Windows95.
6169 |<br>
6170 Either lvoSortAscending or lvoSortDescending option must be set in
6171 LVOptions, otherwise no sorting is performed. }
6172 function LVIndexOf( const S: String ): Integer;
6173 {* Returns first list view item index with caption matching S.
6174 The same as LVSearchFor( S, -1, FALSE ). }
6175 {$IFNDEF _FPC}
6176 {$IFNDEF _D2}
6177 function LVIndexOfW( const S: WideString ): Integer;
6178 {* Returns first list view item index with caption matching S.
6179 The same as LVSearchForW( S, -1, FALSE ). }
6180 {$ENDIF _D2}
6181 {$ENDIF _FPC}
6182 function LVSearchFor( const S: String; StartAfter: Integer; Partial: Boolean ): Integer;
6183 {* Searches an item with Caption equal to S (or starting from S, if Partial = TRUE).
6184 Searching is started after an item specified by StartAfter parameter. }
6185 {$IFNDEF _FPC}
6186 {$IFNDEF _D2}
6187 function LVSearchForW( const S: WideString; StartAfter: Integer; Partial: Boolean ): Integer;
6188 {* Searches an item with Caption equal to S (or starting from S, if Partial = TRUE).
6189 Searching is started after an item specified by StartAfter parameter. }
6190 {$ENDIF _D2}
6191 {$ENDIF _FPC}
6193 //======== List view page:
6194 property LVTopItem: Integer index LVM_GETTOPINDEX read GetIntVal; //LVGetTopItem;
6195 {* |<#listview>
6196 Returns index of topmost visible item of ListView in lvsList view style. }
6197 property LVPerPage: Integer index LVM_GETCOUNTPERPAGE read GetIntVal; //LVGetPerPage;
6198 {* |<#listview>
6199 Returns the number of fully-visible items if successful. If the current
6200 view is icon or small icon view, the return value is the total number
6201 of items in the list view control. }
6203 //======== List View specific events:
6204 property OnEndEditLVItem: TOnEditLVItem read fOnEditLVITem write SetOnEditLVItem;
6205 {* |<#listview>
6206 Called when edit of an item label in ListView control finished. Return
6207 True to accept new label text, or false - to not accept it (item label
6208 will not be changed). If handler not set to an event, all changes are
6209 accepted. }
6211 property OnDeleteLVItem: TOnDeleteLVItem read fOnDeleteLVItem write SetOnDeleteLVItem;
6212 {* |<#listview>
6213 Called for every deleted list view item. }
6214 property OnDeleteAllLVItems: TOnEvent read fOnDeleteAllLVItems write SetOnDeleteAllLVItems;
6215 {* |<#listview>
6216 Called when all the items of the list view control are to be deleted. If after
6217 returning from this event handler event OnDeleteLVItem is yet assigned,
6218 an event OnDeleteLVItem will be called for every deleted item. }
6219 property OnLVData: TOnLVData read fOnLVData write SetOnLVData;
6220 {* |<#listview>
6221 Called to provide virtual list view with actual data. To use list view as
6222 virtaul list view, define also lvsOwnerData style and set Count property
6223 to actual row count of the list view. This manner of working with list view
6224 control can greatly improve performance of an application when working with
6225 huge data sets represented in listview control. }
6226 {$IFNDEF _FPC}
6227 {$IFNDEF _D2}
6228 property OnLVDataW: TOnLVDataW read fOnLVDataW write SetOnLVDataW;
6229 {* |<#listview>
6230 The same as OnLVData, but for unicode version of the list view allows
6231 to return WideString text in the event handler. Though for unicode list
6232 view it is still possible to use ordinary event OnLVData, it is
6233 very recommended to use this event istead. }
6234 {$ENDIF _D2}
6235 {$ENDIF _FPC}
6237 property OnCompareLVItems: TOnCompareLVItems read fOnCompareLVItems write fOnCompareLVItems;
6238 {* |<#listview>
6239 Event to compare two list view items during sort operation (initiated by
6240 LVSort method call). Do not send any messages to the list view control
6241 while it is sorting - results can be unpredictable! }
6242 property OnColumnClick: TOnLVColumnClick read fOnColumnClick write SetOnColumnClick;
6243 {* |<#listview>
6244 This event handler is called when column of the list view control is clicked.
6245 You can use this event to initiate sorting of list view items by this column. }
6246 property OnLVStateChange: TOnLVStateChange read FOnLVStateChange write SetOnLVStateChange;
6247 {* |<#listview>
6248 This event occure when an item or items range in list view control are
6249 changing its state (e.g. selected or unselected). }
6250 property OnLVDelete: TOnLVDelete read FOnLVDelete write SetOnLVDelete;
6251 {* |<#listview>
6252 This event is called when an item is deleted in the listview.
6253 Do not add, delete, or rearrange items in the list view while processing
6254 this notification. }
6255 property OnDrawItem: TOnDrawItem read fOnDrawItem write SetOnDrawItem;
6256 {* |<#listview>
6257 |<#listbox>
6258 |<#combo>
6259 This event can be used to implement custom drawing for list view, list box, dropped
6260 list of a combobox. For a list view, custom drawing using this event is possible
6261 only in lvsDetail and lvsDetailNoHeader styles, and OnDrawItem is called to draw
6262 entire row at once only. See also OnLVCustomDraw event. }
6264 property OnLVCustomDraw: TOnLVCustomDraw read FOnLVCustomDraw write SetOnLVCustomDraw;
6265 {* |<#listview>
6266 Custom draw event for listview. For every item to be drawn, this event
6267 can be called several times during a single drawing cycle - depending on
6268 a result, returned by an event handler. Stage can have one of following
6269 values:
6270 |<pre>
6271 CDDS_PREERASE
6272 CDDS_POSTERASE
6273 CDDS_ITEMPREERASE
6274 CDDS_PREPAINT
6275 CDDS_ITEMPREPAINT
6276 CDDS_ITEM
6277 CDDS_SUBITEM + CDDS_ITEMPREPAINT
6278 CDDS_SUBITEM + CDDS_ITEMPOSTPAINT
6279 CDDS_ITEMPOSTPAINT
6280 CDDS_POSTPAINT
6281 </pre>
6282 When called, see on Stage to get know, on what stage the event is
6283 activated. And depend on the stage and on what you want to paint,
6284 return a value as a result, which instructs the system, if to use
6285 default drawing on this (and follows) stage(s) for the item, and if
6286 to notify further about different stages of drawing the item during
6287 this drawing cycle. Possible values to return are:
6288 |<pre>
6289 CDRF_DODEFAULT - perform default drawing. Do not notify further for this
6290 item (subitem) (or for entire listview, if called with
6291 flag CDDS_ITEM reset - ?);
6292 CDRF_NOTIFYITEMDRAW - return this value, when the event is called the
6293 first time in a cycle of drawing, with ItemIdx = -1 and
6294 flag CDDS_ITEM reset in Stage parameter;
6295 CDRF_NOTIFYPOSTERASE - usually can be used to provide default erasing,
6296 if you want to perform drawing immediately after that;
6297 CDRF_NOTIFYPOSTPAINT - return this value to provide calling the event
6298 after performing default drawing. Useful when you wish
6299 redraw only a part of the (sub)item;
6300 CDRF_SKIPDEFAULT - return this value to inform the system that all
6301 drawing is done and system should not peform any more
6302 drawing for the (sub)item during this drawing cycle.
6303 CDRF_NEWFONT - informs the system, that font is changed and default
6304 drawing should be performed with changed font;
6305 |</pre>
6306 If you want to get notifications for each subitem, do not use option
6307 lvoOwnerDrawFixed, because such style prevents system from notifying
6308 the application for each subitem to be drawn in the listview and only
6309 notifications will be sent about entire items.
6310 |<br>
6311 See also NM_CUSTOMDRAW in API Help.
6314 procedure Set_LVItemHeight(Value: Integer);
6315 function SetLVItemHeight(Value: Integer): PControl;
6316 property LVItemHeight: Integer read fLVItemHeight write Set_LVItemHeight;
6319 //======== TreeView specific properties and methods:
6320 function TVInsert( nParent, nAfter: THandle; const Txt: String ): THandle;
6321 {* |<#treeview>
6322 Inserts item to a tree view. If nParent is 0 or TVI_ROOT, the item is
6323 inserted at the root of tree view. It is possible to pass following special
6324 values as nAfter parameter:
6325 |<pre>
6326 TVI_FIRST Inserts the item at the beginning of the list.
6327 TVI_LAST Inserts the item at the end of the list.
6328 TVI_SORT Inserts the item into the list in alphabetical order.
6329 |</pre> }
6330 {$IFNDEF _FPC}
6331 {$IFNDEF _D2}
6332 function TVInsertW( nParent, nAfter: THandle; const Txt: WideString ): THandle;
6333 {* |<#treeview>
6334 Inserts item to a tree view. If nParent is 0 or TVI_ROOT, the item is
6335 inserted at the root of tree view. It is possible to pass following special
6336 values as nAfter parameter:
6337 |<pre>
6338 TVI_FIRST Inserts the item at the beginning of the list.
6339 TVI_LAST Inserts the item at the end of the list.
6340 TVI_SORT Inserts the item into the list in alphabetical order.
6341 |</pre><br>
6342 This version of the method is Unicode. The tree view control should be
6343 set up as unicode control calling Perform( TVM_SETUNICODEFORMAT, 1, 0 ),
6344 and conditional symbol UNICODE_CTRLS must be defined to provide event
6345 handling for such kind of tree view (and other Unicode) controls. }
6346 {$ENDIF _D2}
6347 {$ENDIF _FPC}
6348 procedure TVDelete( Item: THandle );
6349 {* |<#treeview>
6350 Removes an item from the tree view. If value TVI_ROOT is passed, all items
6351 are removed. }
6353 property TVSelected: THandle index TVGN_CARET read TVGetItemIdx write TVSetItemIdx;
6354 {* |<#treeview>
6355 Returns or sets currently selected item handle in tree view. }
6357 property TVDropHilighted: THandle index TVGN_DROPHILITE read TVGetItemIdx write TVSetItemIdx;
6358 {* |<#treeview>
6359 Returns or sets item, which is currently highlighted as a drop target. }
6360 property TVDropHilited: THandle index TVGN_DROPHILITE read TVGetItemIdx write TVSetItemIdx;
6361 {* The same as TVDropHilighted. }
6362 property TVFirstVisible: THandle index TVGN_FIRSTVISIBLE read TVGetItemIdx write TVSetItemIdx;
6363 {* |<#treeview>
6364 Returns or sets given item to top of tree view. }
6366 property TVIndent: Integer index TVM_GETINDENT read GetIntVal write SetIntVal;
6367 {* |<#treeview>
6368 The amount, in pixels, that child items are indented relative to their
6369 parent items. }
6370 property TVVisibleCount: Integer index TVM_GETVISIBLECOUNT read GetIntVal;
6371 {* |<#treeview>
6372 Returns number of fully (not partially) visible items in tree view. }
6374 property TVRoot: THandle index TVGN_ROOT read TVGetItemIdx;
6375 {* |<#treeview>
6376 Returns handle of root item in tree view (or 0, if tree is empty). }
6377 property TVItemChild[ Item: THandle ]: THandle index TVGN_CHILD read TVGetItemNext;
6378 {* |<#treeview>
6379 Returns first child item for given one. }
6380 property TVItemHasChildren[ Item: THandle ]: Boolean read TV_GetItemHasChildren write TV_SetItemHasChildren;
6381 {* |<#treeview>
6382 TRUE, if an Item has children. Set this value to true if you want to
6383 force [+] sign appearing left from the node, even if there are no
6384 subnodes added to the node yet. }
6385 property TVItemChildCount[ Item: THandle ]: Integer read TV_GetItemChildCount;
6386 {* |<#treeview>
6387 Returns number of node child items in tree view.
6389 property TVItemNext[ Item: THandle ]: THandle index TVGN_NEXT read TVGetItemNext;
6390 {* |<#treeview>
6391 Returns next sibling item handle for given one (or 0, if passed item is
6392 the last child for its parent node). }
6393 property TVItemPrevious[ Item: THandle ]: THandle index TVGN_PREVIOUS read TVGetItemNext;
6394 {* |<#treeview>
6395 Returns previous sibling item (or 0, if the is no such item). }
6396 property TVItemNextVisible[ Item: THandle ]: THandle index TVGN_NEXTVISIBLE read TVGetItemNext;
6397 {* |<#treeview>
6398 Returns next visible item (passed item must be visible too, to determine,
6399 if it is really visible, use property TVItemRect or TVItemVisible. }
6400 property TVItemPreviousVisible[ Item: THandle ]: THandle index TVGN_PREVIOUSVISIBLE read TVGetItemNext;
6401 {* |<#treeview>
6402 Returns previous visible item. }
6403 property TVItemParent[ Item: THandle ]: THandle index TVGN_PARENT read TVGetItemNext;
6404 {* |<#treeview>
6405 Returns parent item for given one (or 0 for root item). }
6407 property TVItemText[ Item: THandle ]: String read TVGetItemText write TVSetItemText;
6408 {* |<#treeview>
6409 Text of tree view item. }
6410 {$IFNDEF _FPC}
6411 {$IFNDEF _D2}
6412 property TVItemTextW[ Item: THandle ]: WideString read TVGetItemTextW write TVSetItemTextW;
6413 {* |<#treeview>
6414 Text of tree view item. }
6415 {$ENDIF _D2}
6416 {$ENDIF _FPC}
6417 function TVItemPath( Item: THandle; Delimiter: Char ): String;
6418 {* |<#treeview>
6419 Returns full path from the root item to given item. Path is calculated
6420 as a concatenation of all parent nodes text strings, separated by
6421 given delimiter character.
6422 |<br>Please note, that returned path has no trailing delimiter, this
6423 character is only separating different parts of the path.
6424 |<br>If Item is not specified ( =0 ), path is returned
6425 for Selected item. }
6426 {$IFNDEF _FPC}
6427 {$IFNDEF _D2}
6428 function TVItemPathW( Item: THandle; Delimiter: WideChar ): WideString;
6429 {* |<#treeview>
6430 Returns full path from the root item to given item. Path is calculated
6431 as a concatenation of all parent nodes text strings, separated by
6432 given delimiter character. If Item is not specified ( =0 ), path is returned
6433 for Selected item. }
6434 {$ENDIF _D2}
6435 {$ENDIF _FPC}
6437 property TVItemRect[ Item: THandle; TextOnly: Boolean ]: TRect read TVGetItemRect;
6438 {* |<#treeview>
6439 Returns rectangle, occupied by an item in tree view. }
6441 property TVItemVisible[ Item: THandle ]: Boolean read TVGetItemVisible write TVSetITemVisible;
6442 {* |<#treeview>
6443 Returs True, if item is visible in tree view. It is also possible to
6444 assign True to this property to ensure that a tree view item is visible
6445 (if False is assigned, this does nothing). }
6446 function TVItemAtPos( x, y: Integer; var Where: DWORD ): THandle;
6447 {* |<#treeview>
6448 Returns handle of item found at specified position (relative to upper left
6449 corener of client area of the tree view). If no item found, 0 is returned.
6450 Variable Where receives additional flags combination, describing more
6451 detailed, on which part of item or tree view given point is located,
6452 such as:
6453 |<pre>
6454 TVHT_ABOVE Above the client area
6455 TVHT_BELOW Below the client area
6456 TVHT_NOWHERE In the client area, but below the last item
6457 TVHT_ONITEM On the bitmap or label associated with an item
6458 TVHT_ONITEMBUTTON On the button associated with an item
6459 TVHT_ONITEMICON On the bitmap associated with an item
6460 TVHT_ONITEMINDENT In the indentation associated with an item
6461 TVHT_ONITEMLABEL On the label (string) associated with an item
6462 TVHT_ONITEMRIGHT In the area to the right of an item
6463 TVHT_ONITEMSTATEICON On the state icon for a tree-view item that is in a user-defined state
6464 TVHT_TOLEFT To the right of the client area
6465 TVHT_TORIGHT To the left of the client area
6466 |</pre> }
6468 property TVRightClickSelect: Boolean read fTVRightClickSelect write SetTVRightClickSelect;
6469 {* |<#treeview>
6470 Set this property to True to allow change selection to an item, clicked with right mouse button. }
6471 property TVEditing: Boolean read fEditing;
6472 {* |<#treeview>
6473 Returns True, if tree view control is editing its item label. }
6475 property TVItemBold[ Item: THandle ]: Boolean index TVIS_BOLD read TVGetItemStateFlg write TVSetItemStateFlg;
6476 {* |<#treeview>
6477 True, if item is bold. }
6478 property TVItemCut[ Item: THandle ]: Boolean index TVIS_CUT read TVGetITemStateFlg write TVSetItemStateFlg;
6479 {* |<#treeview>
6480 True, if item is selected as part of "cut and paste" operation. }
6481 property TVItemDropHighlighted[ Item: THandle ]: Boolean index TVIS_DROPHILITED read TVGetITemStateFlg write TVSetItemStateFlg;
6482 {* |<#treeview>
6483 True, if item is selected as drop target. }
6484 property TVItemDropHilited[ Item: THandle ]: Boolean index TVIS_DROPHILITED read TVGetITemStateFlg write TVSetItemStateFlg;
6485 {* The same as TVItemDropHighlighted. }
6486 property TVItemExpanded[ Item: THandle ]: Boolean index TVIS_EXPANDED read TVGetITemStateFlg; // write TVSetItemStateFlg;
6487 {* |<#treeview>
6488 True, if item's list of child items is currently expanded. To change
6489 expanded state, use method TVExpand. }
6490 property TVItemExpandedOnce[ Item: THandle ]: Boolean index TVIS_EXPANDEDONCE read TVGetITemStateFlg; // write TVSetItemStateFlg;
6491 {* |<#treeview>
6492 True, if item's list of child items has been expanded at least once. }
6493 property TVItemSelected[ Item: THandle ]: Boolean index TVIS_SELECTED read TVGetITemStateFlg write TVSetItemStateFlg;
6494 {* |<#treeview>
6495 True, if item is selected. }
6497 procedure TVExpand( Item: THandle; Flags: DWORD );
6498 {* |<#treeview>
6499 Call it to expand/collapse item's child nodes. Possible values for Flags
6500 parameter are:
6501 <pre>
6502 TVE_COLLAPSE Collapses the list.
6503 TVE_COLLAPSERESET Collapses the list and removes the child items. Note
6504 that TVE_COLLAPSE must also be specified.
6505 TVE_EXPAND Expands the list.
6506 TVE_TOGGLE Collapses the list if it is currently expanded or
6507 expands it if it is currently collapsed.
6508 </pre>
6510 procedure TVSort( N: THandle );
6511 {* |<#treeview>
6512 By Alex Mokrov. Sorts treeview. If N = 0, entire treeview is sorted.
6513 Otherwise, children of the given node only.
6516 property TVItemImage[ Item: THandle ]: Integer index TVIF_IMAGE read TVGetItemImage write TVSetItemImage;
6517 {* |<#treeview>
6518 Image index for an item of tree view. To tell that there are no image
6519 set, use index -2 (value -1 is reserved for callback image). }
6520 property TVItemSelImg[ Item: THandle ]: Integer index TVIF_SELECTEDIMAGE read TVGetItemImage write TVSetItemImage;
6521 {* |<#treeview>
6522 Image index for an item of tree view in selected state. Use value -2 to
6523 provide no image, -1 used for callback image. }
6524 property TVItemOverlay[ Item: THandle ]: Integer index TVIS_OVERLAYMASK or $80000
6525 read TVGetItemImage write TVSetItemImage;
6526 {* |<#treeview>
6527 Overlay image index for an item in tree view. }
6528 property TVItemStateImg[ Item: THandle ]: Integer index TVIS_STATEIMAGEMASK or $C0000
6529 read TVGetItemImage write TVSetItemImage;
6530 {* |<#treeview>
6531 State image index for an item in tree view. Use 1-based index of the image
6532 in image list ImageListState. Value 0 reserved to use as "no state image".
6533 Values 1..15 can be used only - this is the Windows restriction on
6534 state images. }
6536 property TVItemData[ Item: THandle ]: Pointer read TVGetItemData write TVSetItemData;
6537 {* |<#treeview>
6538 Stores any program-defined pointer with the item. }
6539 procedure TVEditItem( Item: THandle );
6540 {* |<#treeview>
6541 Begins editing given item label in tree view. }
6542 procedure TVStopEdit( Cancel: Boolean );
6543 {* |<#treeview>
6544 Ends editing item label, started by user or explicitly by TVEditItem method. }
6546 property OnTVBeginDrag: TOnTVBeginDrag read fOnTVBeginDrag write fOnTVBeginDrag;
6547 {* |<#treeview>
6548 Is called for tree view, when its item is to be dragging. }
6549 property OnTVBeginEdit: TOnTVBeginEdit read fOnTVBeginEdit write fOnTVBeginEdit;
6550 {* |<#treeview>
6551 Is called for tree view, when its item label is to be editing. }
6552 property OnTVEndEdit: TOnTVEndEdit read fOnTVEndEdit write fOnTVEndEdit;
6553 {* |<#treeview>
6554 Is called when item label is edited. It is possible to cancel
6555 edit, returning False as a result. }
6556 property OnTVExpanding: TOnTVExpanding read fOnTVExpanding write fOnTVExpanding;
6557 {* |<#treeview>
6558 Is called just before expanding/collapsing item. It is possible to
6559 return False to prevent expanding item. }
6560 property OnTVExpanded: TOnTVExpanded read fOnTVExpanded write fOnTVExpanded;
6561 {* |<#treeview>
6562 Is called after expanding/collapsing item children. }
6563 property OnTVDelete: TOnTVDelete read fOnTVDelete write SetOnTVDelete;
6564 {* |<#treeview>
6565 Is called just before deleting item. You may use this event to free
6566 resources, associated with an item (see TVItemData property). }
6567 //----------------- by Sergey Shisminzev:
6568 property OnTVSelChanging: TOnTVSelChanging read fOnTVSelChanging write fOnTVSelChanging;
6569 {* |<#treeview>
6570 Is called before changing the selection. The handler can return FALSE
6571 to prevent changing the selection. }
6572 //--------------------------------------
6574 //======== Toolbar specific methods:
6575 procedure TBAddBitmap( Bitmap: HBitmap );
6576 {* |<#toolbar>
6577 Adds bitmaps to a toolbar. You can pass special values as Bitmap to
6578 add one of predefined system button images bitmaps:
6579 |<br> THandle(-1) to add standard small icons,
6580 |<br> THandle(-2) to add standard large icons,
6581 |<br> THandle(-5) to add standard small view icons,
6582 |<br> THandle(-6) to add standard large view icons,
6583 |<br> THandle(-9) to add standard small view icons,
6584 |<br> THandle(-10) to add standard large view icons,
6585 (in that case use following values as indexes to the standard and view
6586 bitmaps:
6587 |<br>
6588 STD_COPY, STD_CUT, STD_DELETE, STD_FILENEW, STD_FILEOPEN, STD_FILESAVE,
6589 STD_FIND, STD_HELP, STD_PASTE, STD_PRINT, STD_PRINTPRE, STD_PROPERTIES,
6590 STD_REDO, STD_REPLACE, STD_UNDO,
6591 |<br>
6592 VIEW_LARGEICONS, VIEW_SMALLICONS,
6593 VIEW_LIST, VIEW_DETAILS, VIEW_SORTNAME, VIEW_SORTSIZE, VIEW_SORTDATE,
6594 VIEW_SORTTYPE (use it as parameters BtnImgIdxArray in TBAddButtons or
6595 TBInsertButtons methods, and in assigning value to TBButtonImage[ ]
6596 property).
6597 Added bitmaps have indeces starting from previous count of images
6598 (as these are appended to existing - if any).
6599 |<br>
6600 Note, that if You add your own (custom) bitmap, it is not transparent.
6601 Do not assume that clSilver is always equal to clBtnFace. Use API
6602 function CreateMappedBitmap to load bitmap from resource and map
6603 desired colors as you wish (e.g., convert clTeal to clBtnFace). Or,
6604 call defined in KOL function LoadMappedBitmap to do the same more easy.
6605 Unfortunately, resource identifier for bitmap to pass it to LoadMappedBitmap
6606 or to CreateMappedBitmap seems must be integer, so it is necessary to
6607 create rc-file manually and compile using Borland Resource Compiler to
6608 figure it out. }
6611 function TBAddButtons( const Buttons: array of PChar; const BtnImgIdxArray: array
6612 of Integer ): Integer;
6613 {* |<#toolbar>
6614 Adds buttons to toolbar. Last string in Buttons array *must* be empty
6615 ('' or nil), so to add buttons without text, pass ' ' string (one space
6616 char). It is not necessary to provide image indexes for all
6617 buttons (it is sufficient to assign index for first button only).
6618 But in place, correspondent to separator button (defined by string '-'),
6619 any integer must be passed to assign follow image indexes correctly.
6620 See example.
6621 |*Toolbar adding buttons sample.
6622 Code below shows how to call TBAddButtons method to add two buttons with
6623 a separator between these buttons. idxNew and idxOld are integer
6624 expressions assigning image indexes to buttons 'New' and 'Old'. This
6625 indexes are zero-based and refer to bitmap images, added earlier (either
6626 in creating toolbar by call of NewToolbar or later in call of TBAddBitmap).
6628 ! TBAddButtons( [ '&New', '-', '&Old', '' ], [ idxNew, 0, idxOld ] );
6631 To add check buttons, use prefix '+' or '-' in button definition
6632 string. If next character is '!', such buttons are grouped to a
6633 radio-group. Also, it is possible to use '^' prefix (must be first) to
6634 define button with small drop-down section (use also OnTBDropDown event
6635 to respond to clicking drop down section of such buttons).
6636 |<br>
6637 This function returns command id for first added button (other
6638 id's can be calculated incrementing the result by one for each
6639 button, except separators, which have no command id).
6640 |<br>
6641 Note: for static toolbar (single in application and created
6642 once) ids are started from value 100. }
6644 function TBInsertButtons( BeforeIdx: Integer; Buttons: array of PChar;
6645 BtnImgIdxArray: array of Integer ): Integer;
6646 {* |<#toolbar>
6647 Inserts buttons before button with given index on toolbar. Returns
6648 command identifier for first button inserted (other can be calculated
6649 incrementing returned value needed times. See also TBAddButtons. }
6651 procedure TBDeleteButton( BtnID: Integer );
6652 {* |<#toolbar>
6653 Deletes single button given by its command id. To delete separator,
6654 use TBDeleteBtnByIdx instead. }
6656 procedure TBDeleteBtnByIdx( Idx: Integer );
6657 {* |<#toolbar>
6658 Deletes single button given by its index in toolbar (not by command ID). }
6660 procedure TBAssignEvents( BtnID: Integer; Events: array of TOnToolbarButtonClick );
6661 {* |<#toolbar>
6662 Allows to assign separate OnClick events for every toolbar button.
6663 BtnID should be toolbar button ID or index of the first button to
6664 assign event. If it is an ID, events are assigned to buttons in
6665 creation order. Otherwise, events are assigned in placement order.
6666 Anyway, separator buttons are not skipped, so pass at least nil for such
6667 button as an event.
6668 |<br>
6669 Please note, that though not all buttons should exist before
6670 assigning events to it, therefore at least the first button
6671 (specified by BtnID) must be already added before calling TBAssignEvents. }
6673 procedure TBResetImgIdx( BtnID, BtnCount: Integer );
6674 {* |<#toolbar>
6675 Resets image index for BtnCount buttons starting from BtnID. }
6677 property CurItem: Integer read fCurItem;
6678 {* |<#toolbar>
6679 For toolbar, in OnClick event this property can be used to determine
6680 which button was clicked (100-based button id in toolbar). It is also
6681 possible to use CurIndex property (zero-based) for this purpose as
6682 well, but do not assume, that CurItem always equal to CurIndex+100.
6683 At least, it is possible to call TBItem2Index function to convert
6684 button ID to its index in toolbar.
6685 |<br>
6686 In case, when button (or toolbar itself) is clicked using right
6687 mouse button, CurItem and CurIndex are always set to -1. To further
6688 determine which button was clicked, get mouse coordinates on screen,
6689 apply Screen2Client method of toolbar control to it and then use
6690 TBButtonAtPos function to determine which button was under cursor.
6693 property TBButtonCount: Integer read GetItemsCount; //TBGetButtonCount;
6694 {* |<#toolbar>
6695 Returns count of buttons on toolbar. The same as Count. }
6697 property TBBtnImgWidth: Integer read fTBBtnImgWidth write fTBBtnImgWidth;
6698 {* |<#toolbar>
6699 Custom toolbar buttons width. Set it before assigning buttons bitmap.
6700 Changing this property after assigning the bitmap has no effect. }
6702 function TBItem2Index( BtnID: Integer ): Integer;
6703 {* |<#toolbar>
6704 Converts button command id to button index for tool bar. }
6706 function TBIndex2Item( Idx: Integer ): Integer;
6707 {* |<#toolbar>
6708 Converts toolbar button index to its command ID. }
6710 procedure TBConvertIdxArray2ID( const IdxVars: array of PDWORD );
6711 {* |<#toolbar>
6712 Converts toolbar button indexes to its command IDs for an array
6713 of indexes (each item in the array passed is a pointer to
6714 Integer, containing button index when the procedure is callled,
6715 then all these indexes are relaced with a correspondent button ID).}
6717 property TBButtonEnabled[ BtnID: Integer ]: Boolean index TB_ENABLEBUTTON
6718 read TBGetBtnStt write TBSetBtnStt;
6719 {* |<#toolbar>
6720 Obvious. }
6722 property TBButtonVisible[ BtnID: Integer ]: Boolean read TBGetButtonVisible
6723 write TBSetButtonVisible;
6724 {* |<#toolbar>
6725 Allows to hide/show some of toolbar buttons. }
6727 property TBButtonChecked[ BtnID: Integer ]: Boolean index TB_CHECKBUTTON
6728 read TBGetBtnStt write TBSetBtnStt;
6729 {* |<#toolbar>
6730 Allows to determine 'checked' state of a button (e.g., radio-button),
6731 and to check it programmatically. }
6733 property TBButtonMarked[ BtnID: Integer ]: Boolean index TB_MARKBUTTON
6734 read TBGetBtnStt write TBSetBtnStt;
6735 {* |<#toolbar>
6736 Returns True if toolbar button is marked (highlighted). Allows to
6737 highlight buttons assigning True to this value. }
6739 property TBButtonPressed[ BtnID: Integer ]: Boolean index TB_PRESSBUTTON
6740 read TBGetBtnStt write TBSetBtnStt;
6741 {* |<#toolbar>
6742 Allows to detrmine if toolbar button (given by its command ID) pressed,
6743 and press/unpress it programmatically. }
6745 property TBButtonText[ BtnID: Integer ]: String read TBGetButtonText write TBSetButtonText;
6746 {* |<#toolbar>
6747 Obtains toolbar button text and allows to change it. Be sure that text
6748 is not empty for all buttons, if You want for it to be shown (if at least
6749 one button has empty text, no text labels will be shown at all). At
6750 least set it to ' ' for buttons, which You do not want to show labels,
6751 if You want from other ones to have it. }
6753 property TBButtonImage[ BtnID: Integer ]: Integer read TBGetBtnImgIdx write TBSetBtnImgIdx;
6754 {* |<#toolbar>
6755 Allows to access/change button image. Do not read this property for
6756 separator buttons, returning value is not proper. If you do not know,
6757 is the button a separator, using function below. }
6759 function TBButtonSeparator( BtnID: Integer ): Boolean;
6760 {* |<#toolbar>
6761 Returns TRUE, if a toolbar button is separator. }
6763 property TBButtonRect[ BtnID: Integer ]: TRect read TBGetButtonRect;
6764 {* |<#toolbar>
6765 Obtains rectangle occupied by toolbar button in toolbar window.
6766 (It is not possible to obtain rectangle for buttons, currently
6767 not visible). }
6769 property TBButtonWidth[ BtnID: Integer ]: Integer read TBGetBtnWidth write TBSetBtnWidth;
6770 {* |<#toolbar>
6771 Allows to obtain / change toolbar button width. }
6773 property TBButtonsMinWidth: Integer index 0
6774 {$IFDEF F_P} read TBGetBtMinMaxWidth
6775 {$ELSE DELPHI} read FTBBtMinWidth
6776 {$ENDIF F_P/DELPHI} write TBSetBtMinMaxWidth;
6777 {* |<#toolbar>
6778 Allows to set minimal width for all toolbar buttons. }
6779 property TBButtonsMaxWidth: Integer index 1
6780 {$IFDEF F_P} read TBGetBtMinMaxWidth
6781 {$ELSE DELPHI} read FTBBtMaxWidth
6782 {$ENDIF F_P/DELPHI} write TBSetBtMinMaxWidth;
6783 {* |<#toolbar>
6784 Allows to set maximal width for all toolbar buttons. }
6786 function TBButtonAtPos( X, Y: Integer ): Integer;
6787 {* |<#toolbar>
6788 Returns command ID of button at the given position on toolbar,
6789 or -1, if there are no button at the position. Value 0 is returned
6790 for separators. }
6792 function TBBtnIdxAtPos( X, Y: Integer ): Integer;
6793 {* |<#toolbar>
6794 Returns index of button at the given position on toolbar.
6795 This also can be index of separator button. -1 is returned if
6796 there are no buttons found at the position. }
6798 function TBMoveBtn( FromIdx, ToIdx: Integer ): Boolean;
6799 {* |<#toolbar>
6800 By TR"]F. Moves button from one position to another. }
6802 property TBRows: Integer read TBGetRows write TBSetRows;
6803 {* |<#toolbar>
6804 Returns number of rows for toolbar and allows to try to set
6805 desired number of rows (but system can set another number of
6806 rows in some cases). This property has no effect if tboWrapable
6807 style not present in Options when toolbar is created. }
6809 procedure TBSetTooltips( BtnID1st: Integer; Tooltips: array of PChar );
6810 {* |<#toolbar>
6811 Allows to assign tooltips to several buttons. Until this procedure
6812 is not called, tooltips list is not created and no code is added
6813 to executable. This method of tooltips maintainance for toolbar buttons
6814 is useful both for static and dynamic toolbars (meaning "dynamic" -
6815 toolbars with buttons, deleted and inserted at run-time). }
6817 property OnTBDropDown: TOnEvent read fOnDropDown write fOnDropDown;
6818 {* |<#toolbar>
6819 This event is called for drop down buttons, when user click drop part
6820 of drop down button. To determine for which button event is called,
6821 look at CurItem or CurIndex property. It is also possible to use
6822 common (with combobox) property OnDropDown. }
6824 property OnTBClick: TOnEvent read fOnClick write fOnClick;
6825 {* |<#toolbar>
6826 The same as OnClick. }
6828 //================== RichEdit specific: ==================
6830 property MaxTextSize: DWORD read GetMaxTextSize write SetMaxTextSize;
6831 {* |<#richedit>
6832 This property valid also for simple edit control, not only for RichEdit.
6833 But for usual edit control, maximum text size available is 32K. For
6834 RichEdit, limit is 4Gb. By default, RichEdit is limited to
6835 32767 bytes (to set maximum size available to 2Gb, assign MaxInt value
6836 to a property). Also, to get current text size of RichEdit, use property
6837 TextSize or RE_TextSize[ ]. }
6838 property TextSize: Integer read GetTextSize;
6839 {* |<#richedit>
6840 Common for edit and rich edit controls property, which returns size of
6841 text in edit control. Also, for any other control (or form, or applet
6842 window) returns size (in characters) of Caption or Text (what is, the
6843 same property actually). }
6844 property RE_TextSize[ Units: TRichTextSize ]: Integer read REGetTextSize;
6845 {* |<#richedit>
6846 For RichEdit control, it returns text size, measured in desired units
6847 (rtsChars - characters, including OLE objects, counted as a single
6848 character; rtsBytes - presize length of text image (if it would be stored
6849 in file or stream). Please note, that for RichEdit1.0, only size in
6850 characters can be obtained. }
6851 function RE_TextSizePrecise: Integer;
6852 {* |<#richedit>
6853 By Savva. Returns length of rich edit text. }
6855 property RE_CharFmtArea: TRichFmtArea read fRECharArea write fRECharArea;
6856 {* |<#richedit>
6857 By default, this property is raSelection. Changing it, You determine in
6858 for which area characters format is applyed, when changing
6859 character formatting properties below (not paragraph formatting).
6860 |&A=<a href=#RE_CharFmtArea target=main>%0</a>
6862 property RE_CharFormat: TCharFormat read REGetCharformat write RESetCharFormat;
6863 {* |<#richedit>
6864 In differ to follow properties, which allow to control certain formatting
6865 attributes, this property provides low level access for formatting current
6866 character area (see RE_CharFmtArea). It returns TCharFormat structure,
6867 filled in with formatting attributes, and by assigning another value to
6868 this property You can change desired attributes as You wish. Even if
6869 RichEdit1.0 is used, TCharFormat2 is returned (but extended fields are
6870 ignored for RichEdit1.0). }
6871 property RE_Font: PGraphicTool read REGetFont write RESetFont;
6872 {* |<#richedit>
6873 Font of the first character in current selection (when retrieve).
6874 When set (or subproperties of RE_Font are set), all font attributes are
6875 applied to entire <A area>. To apply only needed attributes, use another
6876 properties: RE_FmtBold, RE_FmtItalic, RE_FmtStrikeout, RE_FmtUnderline,
6877 RE_FmtName, etc.
6878 |<br>
6879 Note, that font size is measured in twips, which is about 1/10 of pixel. }
6880 property RE_FmtBold: Boolean index CFM_BOLD read REGetFontEffects write RESetFontEffect;
6881 {* |<#richedit>
6882 Formatting flag. When retrieve, returns True, if fsBold style RE_Font.FontStyle
6883 is valid for a first character in the selection. When set, changes fsBold
6884 style (True - set, False - reset) for all characters in <A area>. }
6885 property RE_FmtBoldValid: Boolean index CFM_BOLD read REGetFontMask;
6886 {* }
6887 property RE_FmtItalic: Boolean index CFM_ITALIC read REGetFontEffects write RESetFontEffect;
6888 {* |<#richedit>
6889 Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsItalic
6890 style valid for the first character of the selection, and when set, changes
6891 only fsItalic style for an <A area>. }
6892 property RE_FmtItalicValid: Boolean index CFM_ITALIC read REGetFontMask;
6893 {* }
6894 property RE_FmtStrikeout: Boolean index CFM_STRIKEOUT read REGetFontEffects write RESetFontEffect;
6895 {* |<#richedit>
6896 Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsStrikeout
6897 style valid for the first selected character, and when set, changes only
6898 fsStrikeout style for an <A area>. }
6899 property RE_FmtStrikeoutValid: Boolean index CFM_STRIKEOUT read REGetFontMask;
6900 {* }
6901 property RE_FmtUnderline: Boolean index CFM_UNDERLINE read REGetFontEffects write RESetFontEffect;
6902 {* |<#richedit>
6903 Formatting flag. Like RE_FmtBold, when retrieving, shows, is fsUnderline
6904 style valid for the first selected character, and when set, changes
6905 fsUnderline style for an <A area>. }
6906 property RE_FmtUnderlineValid: Boolean index CFM_UNDERLINE read REGetFontMask;
6907 {* }
6908 property RE_FmtUnderlineStyle: TRichUnderline
6909 read REGetUnderlineEx write RESetUnderlineEx;
6910 {* |<#richedit>
6911 Extended underline style. To check, if this property is valid for
6912 entire selection, examine RE_FmtUnderlineValid value. }
6913 property RE_FmtProtected: Boolean index CFM_PROTECTED read REGetFontEffects write RESetFontEffect;
6914 {* |<#richedit>
6915 Formatting flag. When retrieving, shows, is the first character of the selection
6916 is protected from changing it by user (True) or not (False). To get know,
6917 if retrived value is valid for entire selection, check the property
6918 RE_FmtProtectedValid. When set, makes all characters in <A area> protected (
6919 True) or not (False). }
6920 property RE_FmtProtectedValid: Boolean index CFM_PROTECTED read REGetFontMask;
6921 {* |<#richedit>
6922 True, if property RE_FmtProtected is valid for entire selection, when
6923 retrieving it. }
6924 property RE_FmtHidden: Boolean index CFM_HIDDEN read REGetFontEffects write RESetFontEffect;
6925 {* |<#richedit>
6926 For RichEdit3.0, makes text hidden (not displayed). }
6927 property RE_FmtHiddenValid: Boolean index CFM_HIDDEN read REGetFontMask;
6928 {* |<#richedit>
6929 Returns True, if RE_FmtHidden style is valid for entire selection. }
6931 property RE_FmtLink: Boolean index $20 {CFM_LINK} read REGetFontEffects write RESetFontEffect;
6932 {* |<#richedit>
6933 Returns True, if the first selected character is a part of link (URL). }
6934 // by Sergey Shisminzev
6936 property RE_FmtLinkValid: Boolean index $20 {CFM_LINK} read REGetFontMask;
6937 {* }
6938 property RE_FmtFontSize: Integer index (12 shl 16) or CFM_SIZE read REGetFontAttr write RESetFontAttr;
6939 {* |<#richedit>
6940 Formatting value: font size, in twips (1/1440 of an inch, or 1/20 of a
6941 printer's point, or about 1/10 of pixel). When retrieving, returns
6942 RE_Font.FontHeight.
6943 When set, changes font size for entire <A area> (but does not change
6944 other font attributes). }
6945 property RE_FmtFontSizeValid: Boolean read REGetFontSizeValid;
6946 {* |<#richedit>
6947 Returns True, if property RE_FmtFontSize is valid for entire selection,
6948 when retrieving it. }
6949 //property RE_FmtBackColor: Integer index (62 shl 16) or CFM_BACKCOLOR read REGetFontAttr write RESetFontAttr1;
6950 {* |<#richedit>
6951 Background color for an <A area>. }
6952 //property RE_FmtBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontEffect;
6953 {* |<#richedit>
6954 True, if RE_FmtBackColor valid for entire <A area>. }
6955 property RE_FmtAutoBackColor: Boolean index CFM_BACKCOLOR read REGetFontEffects write RESetFontEffect;
6956 {* |<#richedit>
6957 True, when automatic back color is used. }
6958 property RE_FmtAutoBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontMask;
6959 {* }
6960 property RE_FmtFontColor: Integer index (20 shl 16) or CFM_COLOR read REGetFontAttr write RESetFontAttr1;
6961 {* |<#richedit>
6962 Formatting value (font color). When retrieving, returns RE_Font.Color.
6963 When set, changes font color for entire <A area> (but does not change
6964 other font attributes). }
6965 property RE_FmtFontColorValid: Boolean index CFM_COLOR read REGetFontMask;
6966 {* |<#richedit>
6967 Returns True, if property RE_FmtFontColor valid for entire selection,
6968 when retrieving it. }
6969 property RE_FmtAutoColor: Boolean index CFM_COLOR read REGetFontEffects write RESetFontEffect;
6970 {* |<#richedit>
6971 True, when automatic text color is used (in such case, RE_FmtFontColor
6972 assignment is ignored for current area). }
6973 property RE_FmtAutoColorValid: Boolean index CFM_COLOR read REGetFontMask;
6974 {* }
6975 property RE_FmtBackColor: Integer index (64 shl 16) or CFM_BACKCOLOR read REGetFontAttr write RESetFontAttr1;
6976 {* |<#richedit>
6977 Formatting value (back color). Only available for Rich Edit 2.0 and higher.
6978 When set, changes background color for entire <A area> (but does not change
6979 other font attributes). }
6980 property RE_FmtBackColorValid: Boolean index CFM_BACKCOLOR read REGetFontMask;
6981 {* }
6982 property RE_FmtFontOffset: Integer index (16 shl 16) or CFM_OFFSET read REGetFontAttr write RESetFontAttr;
6983 {* |<#richedit>
6984 Formatting value (font vertical offset from baseline, positive values
6985 correspond to subscript). When retrieving, returns offset for first
6986 character in the selection. When set, changes font offset for entire
6987 <A area>. To get know, is retrieved value valid for entire selction,
6988 check RE_FmtFontOffsetValid property. }
6989 property RE_FmtFontOffsetValid: Boolean index CFM_OFFSET read REGetFontMask;
6990 {* |<#richedit>
6991 Returns True, if property RE_FmtFontOffset is valid for entire selection,
6992 when retrieving it. }
6993 property RE_FmtFontCharset: Integer index (25 shl 16) or CFM_CHARSET read REGetFontAttr write RESetFontAttr;
6994 {* |<#richedit>
6995 Returns charset for first character in current selection, when retrieved
6996 (and to get know, if this value is valid for entire selection, check
6997 property RE_FmtFontCharsetValid). When set, changes charset for all
6998 characters in <A area>, but does not alter other formatting attributes. }
6999 property RE_FmtFontCharsetValid: Boolean index CFM_CHARSET read REGetFontMask;
7000 {* |<#richedit>
7001 Returns True, only if rerieved property RE_FmtFontCharset is valid for
7002 entire selection. }
7003 property RE_FmtFontName: String read REGetFontName write RESetFontName;
7004 {* |<#richedit>
7005 Returns font face name for first character in the selection, when retrieved,
7006 and sets font name for entire <A area>, wnen assigned to (without
7007 changing of other formatting attributes). To get know, if retrived
7008 font name valid for entire selection, examine property RE_FmtFontNameValid. }
7009 property RE_FmtFontNameValid: Boolean index CFM_FACE read REGetFontMask;
7010 {* |<#richedit>
7011 Returns True, only if the font name is the same for entire selection,
7012 thus is, if rerieved property value RE_FmtFontName is valid for entire
7013 selection. }
7015 property RE_ParaFmt: TParaFormat read REGetParaFmt write RESetParaFmt;
7016 {* |<#richedit>
7017 Allows to retrieve or set paragraph formatting attributes for currently
7018 selected paragraph(s) in RichEdit control. See also following properties,
7019 which allow to do the same for certain paragraph format attributes
7020 separately. }
7021 property RE_TextAlign: TRichTextAlign read REGetTextAlign write RESetTextAlign;
7022 {* |<#richedit>
7023 Returns text alignment for current selection and allows to change it
7024 (without changing other formatting attributes). }
7025 property RE_TextAlignValid: Boolean index PFM_ALIGNMENT read REGetParaAttrValid;
7026 {* |<#richedit>
7027 Returns True, if property RE_TextAlign is valid for entire selection. If
7028 False, it is concerning only start of selection. }
7029 property RE_Numbering: Boolean read REGetNumbering write RESetNumbering;
7030 {* |<#richedit>
7031 Returns True, if selected text is numbered (or has style of list with
7032 bullets). To get / change numbering style, see properties
7033 RE_NumStyle and RE_NumBrackets. }
7034 property RE_NumStyle: TRichNumbering read REGetNumStyle write RESetNumStyle;
7035 {* |<#richedit>
7036 Advanced numbering style, such as rnArabic etc. If You use it, do not
7037 change RE_Numbering property simultaneously - this can cause changing
7038 style to rnBullets only. }
7039 property RE_NumStart: Integer read REGetNumStart write RESetNumStart;
7040 {* |<#richedit>
7041 Starting number for advanced numbering style. If this property is not
7042 set, numbering is starting by default from 0. For rnLRoman and rnURoman
7043 this cause, that first item has no number to be shown (ancient Roman
7044 people did not invent '0'). }
7045 property RE_NumBrackets: TRichNumBrackets read REGetNumBrackets write RESetNumBrackets;
7046 {* |<#richedit>
7047 Brackets style for advanced numbering. rnbPlain is default
7048 brackets style, and every time, when RE_NumStyle is changed,
7049 RE_NumBrackets is reset to rnbPlain. }
7050 property RE_NumTab: Integer read REGetNumTab write RESetNumTab;
7051 {* |<#richedit>
7052 Tab between start of number and start of paragraph text. If too small too
7053 view number, number is not displayed. (Default value seems to be sufficient
7054 though). }
7055 property RE_NumberingValid: Boolean index PFM_NUMBERING read REGetParaAttrValid;
7056 {* |<#richedit>
7057 Returns True, if RE_Numbering, RE_NumStyle, RE_NumBrackets, RE_NumTab,
7058 RE_NumStart properties are valid for entire selection. }
7059 property RE_Level: Integer read REGetLevel;
7060 {* |<#richedit>
7061 Outline level (for numbering paragraphs?). Read only. }
7062 property RE_SpaceBefore: Integer index 0 or PFM_SPACEBEFORE read REGetSpacing write RESetSpacing;
7063 {* |<#richedit>
7064 Spacing before paragraph. }
7065 property RE_SpaceBeforeValid: Boolean index PFM_SPACEBEFORE read REGetParaAttrValid;
7066 {* |<#richedit>
7067 True, if RE_SpaceBefore value is valid for all selected paragraph (if
7068 False, this value is valid only for first paragraph. }
7069 property RE_SpaceAfter: Integer index 4 or PFM_SPACEAFTER read REGetSpacing write RESetSpacing;
7070 {* |<#richedit>
7071 Spacing after paragraph. }
7072 property RE_SpaceAfterValid: Boolean index PFM_SPACEAFTER read REGetParaAttrValid;
7073 {* |<#richedit>
7074 True, only if RE_SpaceAfter value is valid for all selected paragraphs. }
7075 property RE_LineSpacing: Integer index 8 or PFM_LINESPACING read REGetSpacing write RESetSpacing;
7076 {* |<#richedit>
7077 Linespacing in paragraph (this value is based on RE_SpacingRule property). }
7078 property RE_SpacingRule: Integer read REGetSpacingRule write RESetSpacingRule;
7079 {* |<#richedit>
7080 Linespacing rule. Do not know what is it. }
7081 property RE_LineSpacingValid: Boolean index PFM_LINESPACING read REGetParaAttrValid;
7082 {* |<#richedit>
7083 True, only if RE_LineSpacing and RE_SpacingRule values are valid for
7084 entire selection. }
7085 property RE_Indent: Integer index (20 shl 16) or PFM_OFFSET read REGetParaAttr write RESetParaAttr;
7086 {* |<#richedit>
7087 Returns left indentation for paragraph in current selection and allows
7088 to change it (without changing other formatting attributes). }
7089 property RE_IndentValid: Boolean index PFM_OFFSET read REGetParaAttrValid;
7090 {* |<#richedit>
7091 Returns True, if RE_Indent property is valid for entire selection. }
7092 property RE_StartIndent: Integer index (12 shl 16) or PFM_OFFSETINDENT read REGetParaAttr write RESetParaAttr;
7093 {* |<#richedit>
7094 Returns left indentation for first line in paragraph for current
7095 selection, and allows to change it (without changing other formatting
7096 attributes). }
7097 property RE_StartIndentValid: Boolean read REGetStartIndentValid;
7098 {* |<#richedit>
7099 Returns True, if property RE_StartIndent is valid for entire selection. }
7100 property RE_RightIndent: Integer index (16 shl 16) or PFM_RIGHTINDENT read REGetParaAttr write RESetParaAttr;
7101 {* |<#richedit>
7102 Returns right indent for paragraph in current selection, and allow to
7103 change it (without changing other formatting attributes). }
7104 property RE_RightIndentValid: Boolean index PFM_RIGHTINDENT read REGetParaAttrValid;
7105 {* |<#richedit>
7106 Returns True, if property RE_RightIndent is valid for entire selection only. }
7107 property RE_TabCount: Integer read REGetTabCount write RESetTabCount;
7108 {* |<#richedit>
7109 Number of tab stops in current selection. This value can not be set greater
7110 then MAX_TAB_COUNT (32). }
7111 property RE_Tabs[ Idx: Integer ]: Integer read REGetTabs write RESetTabs;
7112 {* |<#richedit>
7113 Tab stops for RichEdit control. }
7114 property RE_TabsValid: Boolean index PFM_TABSTOPS read REGetParaAttrValid;
7115 {* |<#richedit>
7116 Returns True, if properties RE_Tabs[ ] and RE_TabCount are valid for
7117 entire selection. }
7120 // following does not work now :
7121 property RE_BorderWidth[ Side: TBorderEdge ]: Integer index 2 read REGetBorder write RESetBorder;
7122 { * |<#richedit>
7123 Border width. }
7124 property RE_BorderSpace[ Side: TBorderEdge ]: Integer index 0 read REGetBorder write RESetBorder;
7125 { * |<#richedit>
7126 Border space. }
7127 property RE_BorderStyle[ Side: TBorderEdge ]: Integer index 4 read REGetBorder write RESetBorder;
7128 { * |<#richedit>
7129 Border style. }
7130 property RE_BorderValid: Boolean index PFM_BORDER read REGetParaAttrValid;
7131 { * |<#richedit>
7132 Returns True, if border style, space and width are the same for all
7133 paragraphs in selection. }
7134 property RE_Table: Boolean index $C000 read REGetParaEffect write RESetParaEffect;
7135 { * |<#richedit>
7136 True, if current paragraph is a part of table (row, cell or cell end).
7137 seems working as read only property. }
7138 // end of experiment section
7140 function RE_FmtStandard: PControl;
7141 {* |<#richedit>
7142 "Transparent" method (returns @Self as a result), which (when called)
7143 provides "standard" keyboard interface for formatting Rich text (just
7144 call this method, for example:
7145 ! RichEd1 := NewRichEdit( Panel1, [ ] ).SetAlign( caClient ).RE_FmtStandard;
7146 Following keys will be maintained additionally:
7147 |<pre>
7148 CTRL+I - switch "Italic",
7149 CTRL+B - switch "Bold",
7150 CTRL+U - switch "Underline",
7151 CTRL+SHIFT+U - swith underline type
7152 and turn underline on (note, that some of underline styles
7153 can not be shown properly in RichEdit v2.0 and lower,
7154 though RichEdit2.0 stores data successfully).
7155 CTRL+O - switch "StrikeOut",
7156 CTRL+'gray+' - increase font size,
7157 CTRL+'gray-' - decrease font size,
7158 CTRL+SHIFT+'gray+' - superscript,
7159 CTRL+SHIFT+'gray-' - subscript.
7160 CTRL+SHIFT+Z - ReDo
7161 |</pre>
7162 And, though following standard formatting keys are provided by RichEdit
7163 control itself in Windows2000, some of these are not functioning
7164 automatically in earlier Windows versions, even for RichEdit2.0. So,
7165 functionality of some of these (marked with (*) ) are added here too:
7166 |<pre>
7167 CTRL+L - align paragraph left, (*)
7168 CTRL+R - align paragraph right, (*)
7169 CTRL+E - align paragraph center, (*)
7170 CTRL+A - select all, (*)
7171 double-click on word - select word,
7172 CTRL+Right - to next word,
7173 CTRL+Left - to previous word,
7174 CTRL+Home - to the beginning of text,
7175 CTRL+End - to the end of text.
7176 CTRL+Z - UnDo
7177 |</pre>
7178 If You originally assign some (plain) text to Text property, switching "underline"
7179 can also change other font attributes, e.g., "bold" - if fsBold style is
7180 in default Font. To prevent such behavior, select entire text first (see
7181 SelectAll) and make assignment to RE_Font property, e.g.:
7182 ! RichEd1.SelectAll;
7183 ! RichEd1.RE_Font := RichEd1.RE_Font;
7184 ! RichEd1.SelLength := 0;
7185 |<br>
7186 And, some other notices about formatting. Please remember, that only True
7187 Type fonts can be succefully scaled and transformed to get desired effects
7188 (e.g., bold). By default, RichEdit uses System font face name, which can
7189 even have problems with fsBold style. Please remember also, that assigning
7190 RE_Font to RE_Font just initializying formatting attributes, making all
7191 those valid in entire text, but does not change font attributes. To use
7192 True Type font, directly assign face name You wish, e.g.:
7193 ! RichEd1.SelectAll;
7194 ! RichEd1.RE_Font := RichEd1.RE_Font;
7195 ! RichEd1.RE_Font.FontName := 'Arial';
7196 ! RichEd1.SelLength := 0;
7198 property RE_AutoKeyboard: Boolean index 1 read REGetLangOptions write RESetLangOptions;
7199 {* |<#richedit>
7200 True if autokeyboard on (lovely "feature" of automatic switching keyboard
7201 language when caret is over another language text). For older RichEdit,
7202 is 'on' always, for newest - 'off' by default. }
7204 property RE_OverwriteMode: Boolean read REGetOverwite write RESetOverwrite;
7205 {* |<#richedit>
7206 This property allows to control insert/overwrite mode. First, to examine, if
7207 insert or overwrite mode is current (but it is necessary either to
7208 access this property, at least once, immediately after creating RichEdit
7209 control, or to assign event OnRE_InsOvrMode_Change to your handler).
7210 Second, to set desired mode programmatically - by assigning value to
7211 this property (You also have to initialize monitoring procedure by either
7212 reading RE_OverwriteMode property or assigning handler to event
7213 OnRE_InsOvrMode_Change immediately following RichEdit control creation). }
7214 property OnRE_InsOvrMode_Change: TOnEvent read fOnREInsModeChg write fOnREInsModeChg;
7215 {* |<#richedit>
7216 This event is called, whenever key INSERT is pressed in control (and for
7217 RichEdit, this means, that insert mode is changed). }
7218 property RE_DisableOverwriteChange: Boolean read fReOvrDisable write RESetOvrDisable;
7219 {* |<#richedit>
7220 It is possible to disable switching between "insert" and "overwrite" mode
7221 by user (therefore, event OnRE_InsOvrMode_Change continue works, but it
7222 just called when key INSERT is pressed, though RE_OverwriteMode property
7223 is not actually changed if switching is disabled). }
7225 function RE_LoadFromStream( Stream: PStream; Length: Integer;
7226 Format: TRETextFormat; SelectionOnly: Boolean ): Boolean;
7227 {* |<#richedit>
7228 Use this method rather then assignment to RE_Text property, if
7229 source is stored in file or stream (to minimize resources during
7230 loading of RichEdit content). Data is loading starting from current
7231 position in stream and no more then Length bytes are loaded (use -1
7232 value to load to the end of stream). Loaded data replaces entire
7233 content of RichEdit control, or selection only, depending on SelectionOnly
7234 flag.
7235 |<br>&nbsp;&nbsp;&nbsp;
7236 If You want to provide progress (e.g. in form of progress bar), assign
7237 OnProgress event to your handler - and to examine current position of
7238 loading, read TSream.Position property of soiurce stream). }
7239 function RE_SaveToStream( Stream: PStream; Format: TRETextFormat; SelectionOnly: Boolean ): Boolean;
7240 {* |<#richedit>
7241 Use this method rather then RE_TextProperty to store data to file
7242 or stream (to minimize resources during saving of RichEdit content).
7243 Data is saving starting from current position in a stream (until
7244 end of RichEdit data). If SelectionOnly flag is True, only selected
7245 part of RichEdit text is saved.
7246 |<br>&nbsp;&nbsp;&nbsp;
7247 Like for RE_LoadFromStream, it is possible to assign your method to
7248 OnProgress event (but to calculate progress of save-to-stream operation,
7249 compare current stream position with RE_Size[ rsBytes ] property
7250 value). }
7252 property OnProgress: TOnEvent read fOnProgress write fOnProgress;
7253 {* |<#richedit>
7254 This event is called during RE_SaveToStream, RE_LoadFromStream (and also
7255 during RE_SaveToFile, RE_LoadFromFile and while accessing or changing
7256 RE_Text property). To calculate relative progress, it is possible to
7257 examine current position in stream/file with its total size while reading,
7258 or with rich edit text size, while writing (property RE_TextSize[ rsBytes ]).
7260 function RE_LoadFromFile( const Filename: String; Format: TRETextFormat;
7261 SelectionOnly: Boolean ): Boolean;
7262 {* |<#richedit>
7263 Use this method rather then other assignments to RE_Text property,
7264 if a source for RichEdit is the file. See also RE_LoadFromStream. }
7265 function RE_SaveToFile( const Filename: String; Format: TRETextFormat;
7266 SelectionOnly: Boolean ): Boolean;
7267 {* |<#richedit>
7268 Use this method rather then other similar, if You want to store
7269 entire content of RichEdit or selection only of RichEdit to a file. }
7271 property RE_Text[ Format: TRETextFormat; SelectionOnly: Boolean ]: String read REReadText write REWriteText;
7272 {* |<#richedit>
7273 This property allows to get / replace content of RichEdit control
7274 (entire text or selection only). Using different formats, it is
7275 possible to exclude or replace undesired formatting information
7276 (see TRETextFormat specification). To get or replace entire text
7277 in reText mode (plain text only), it is possible to use habitual
7278 for edit controls Text property.
7279 |<br>&nbsp;&nbsp;&nbsp;
7280 Note: it is possible to append text to the end of RichEdit control
7281 using method Add, but only if property RE_Text is accessed at least
7282 once:
7283 ! RichEdit1.RE_Text[ reText, True ];
7284 (This line can be written immediatelly after creating RichEdit control). }
7286 procedure RE_Append( const S: String; ACanUndo: Boolean );
7287 {* }
7288 procedure RE_InsertRTF( const S: String );
7289 {* }
7290 property RE_Error: Integer read fREError;
7291 {* |<#richedit>
7292 Contains error code, if access to RE_Text failed. }
7294 procedure RE_HideSelection( aHide: Boolean );
7295 {* |<#richedit>
7296 Allows to hide / show selection in RichEdit. }
7298 function RE_SearchText( const Value: String; MatchCase, WholeWord, ScanForward: Boolean;
7299 SearchFrom, SearchTo: Integer ): Integer;
7300 {* |<#richedit>
7301 Searches given string starting from SearchFrom position up to SearchTo
7302 position (to the end of text, if SearchTo is -1). Returns zero-based
7303 character position of the next match, or -1 if there are no more matches.
7304 To search in bacward direction, set ScanForward to False, and pass
7305 SearchFrom > SearchTo (or even SearchFrom = -1 and SearchTo = 0). }
7307 property RE_AutoURLDetect: Boolean read REGetAutoURLDetect write RESetAutoURLDetect;
7308 {* |<#richedit>
7309 If set to True, automatically detects URLs (and highlights it with
7310 blue color, applying fsItalic and fsUnderline font styles (while
7311 typing and loading). Default value is False. Note: if event OnRE_URLClick
7312 or event OnRE_OverURL are set, property RE_AutoURLDetect is set to True
7313 automatically. }
7315 property RE_URL: String read fREUrl;
7316 {* |<#richedit>
7317 Detected URL (valid in OnRE_OverURL and OnRE_URLClick event handlers). }
7318 property OnRE_OverURL: TOnEvent index 0
7319 {$IFDEF F_P} read REGetOnURL
7320 {$ELSE DELPHI} read fOnREOverURL
7321 {$ENDIF F_P/DELPHI} write RESetOnURL;
7322 {* |<#richedit>
7323 Is called when mouse is moving over URL. This can be used to set
7324 cursor, for example, depending on type of URL (to determine URL type
7325 read property RE_URL). }
7326 property OnRE_URLClick: TOnEvent index 8
7327 {$IFDEF F_P} read REGetOnURL
7328 {$ELSE DELPHI} read fOnREURLClick
7329 {$ENDIF F_P/DELPHI} write RESetOnURL;
7330 {* |<#richedit>
7331 Is called when click on URL detected. }
7333 //property RE_SelectionBar: Boolean read REGetSelectionBar write RESetSelectionBar;
7334 //{* ??? - don't know that is this... }
7335 function RE_NoOLEDragDrop: PControl;
7336 {* |<#richedit>
7337 Just prevents drop OLE objects to the rich edit control. Seems not
7338 working for some cases. }
7340 //function RE_Wyswig: PControl;
7342 function RE_Bottomless: PControl;
7343 // not finished
7345 property RE_Transparent: Boolean read REGetTransparent write RESetTransparent;
7346 {* |<#richedit>
7347 Use this property to make richedit control transparent, instead of
7348 Ed_Transparent or Transparent. But do not place such transparent
7349 richedit control directly on form - it can be draw incorrectly when
7350 form is activated and rich editr control is not current active control.
7351 Use at least panel as a parent instead.
7354 //========== both for Edit and RichEdit: =====================
7355 function CanUndo: Boolean;
7356 {* |<#richedit>
7357 |<#edit>
7358 |<#memo>
7359 Returns True, if the edit (or RichEdit) control can correctly process
7360 the EM_UNDO message. }
7361 procedure EmptyUndoBuffer;
7362 {* |<#richedit>
7363 |<#edit>
7364 |<#memo>
7365 Reset the undo flag of an edit control, preventing undoing all previous
7366 changes. }
7367 function Undo: Boolean;
7368 {* |<#richedit>
7369 |<#edit>
7370 |<#memo>
7371 For a single-line edit control, the return value is always TRUE. For a
7372 multiline edit control and RichEdit control, the return value is TRUE if
7373 the undo operation is successful, or FALSE if the undo operation fails. }
7375 function RE_Redo: Boolean;
7376 {* |<#richedit>
7377 Only for RichEdit control: Returns True if successful. }
7379 //----------------------------------------------------------------------
7380 // DateTimePicker
7381 property OnDTPUserString: TDTParseInputEvent read FOnDTPUserString
7382 write FOnDTPUserString;
7383 {* Special event to parse input from the application. Option dtpoParseInput
7384 must be set when control is created. }
7385 property DateTime: TDateTime read GetDateTime write SetDateTime;
7386 {* DateTime for DateTimePicker control only. }
7387 property Date: TDateTime read GetDate write SetDate;
7388 {* Date only for DateTimePicker control only. }
7389 property Time: TDateTime read GetTime write SetTime;
7390 {* Time only for DateTimePicker control only. }
7391 property DateTimeRange: TDateTimeRange read GetDateTimeRange
7392 write SetDateTimeRange;
7393 {* DateTimePicker range. If first date in the agrument assigned is NAN,
7394 minimum system allowed value is used as the left bound, and if the second is
7395 NAN, maximum system allowed is used as the right one. }
7396 property DateTimePickerColors[ Index: TDateTimePickerColor ]: TColor
7397 read GetDateTimePickerColor write SetDateTimePickerColor;
7398 property DateTimeFormat: String write SetDateTimeFormat;
7401 //----------------------------------------------------------------------
7403 //----------------------------------------------------------------------
7404 // ScrollBar
7405 property SBMin: Longint read fSBMinMax.X write SetSBMin;
7406 property SBMax: Longint read fSBMinMax.Y write SetSBMax;
7407 property SBMinMax: TPoint read fSBMinMax write SetSBMinMax;
7408 property SBPosition: Integer read fSBPosition write SetSBPosition;
7409 property SBPageSize: Integer read fSBPageSize write SetSBPageSize;
7411 property OnSBBeforeScroll: TOnSBBeforeScroll read FOnSBBeforeScroll write FOnSBBeforeScroll;
7412 property OnSBScroll: TOnSBScroll read FOnSBScroll write FOnSBScroll;
7414 function SBSetScrollInfo(const SI: TScrollInfo): Integer;
7415 function SBGetScrollInfo(var SI: TScrollInfo): Boolean;
7416 function GetSBMinMax: TPoint;
7417 function GetSBPageSize: Integer;
7418 function GetSBPosition: Integer;
7419 //----------------------------------------------------------------------
7422 // "Through", or "transparent" methods to simplify initial
7423 // adjustment of controls and make non-visual designing of
7424 // forms more easy. All these functions return @Self as a
7425 // result, so, it is possible to use such methods immediately
7426 // in constructing statement, concatenating it with dots, e.g.:
7428 // NewButton( MyForm, 'Click here' ).PlaceUnder.ResizeParentBottom;
7430 function PlaceRight: PControl;
7431 {* Places control right (to previously created on the same parent). }
7432 function PlaceDown: PControl;
7433 {* Places control below (to previously created on the same parent).
7434 Left position is not changed (thus is, kept equal to Parent.Margin). }
7435 function PlaceUnder: PControl;
7436 {* Places control below (to previously created one, aligning its
7437 Left position to Left position of previous control). }
7438 function SetSize( W, H: Integer ): PControl;
7440 {* Changes size of a control. If W or H less or equal to 0,
7441 correspondent size is not changed. }
7442 function Size( W, H: Integer ): PControl;
7443 {* Like SetSize, but provides automatic resizing of parent control
7444 (recursively). Especially useful for aligned controls. }
7445 function SetClientSize( W, H: Integer ): PControl;
7446 {* Like SetSize, but works setting W = ClientWidth, H = ClientHeight.
7447 Use this method for forms, which can not be resized (dialogs). }
7449 function AutoSize( AutoSzOn: Boolean ): PControl;
7450 function MakeWordWrap: PControl;
7452 {* Determines if to autosize control (like label, button, etc.) }
7453 function IsAutoSize: Boolean;
7454 {* TRUE, if a control is autosizing. }
7455 function AlignLeft( P: PControl ): PControl;
7456 {* assigns Left := P.Left }
7457 function AlignTop( P: PControl ): PControl;
7458 {* assigns Top := P.Top }
7459 function ResizeParent: PControl;
7460 {* Resizes parent, calling ResizeParentRight and ResizeParentBottom. }
7461 function ResizeParentRight: PControl;
7462 {* Resizes parent right edge (Margin of parent is added to right
7463 coordinate of a control). If called second time (for the same
7464 parent), resizes only for increasing of right edge of parent. }
7466 function ResizeParentBottom: PControl;
7467 {* Resizes parent bottom edge (Margin of parent is added to
7468 bottom coordinate of a control). }
7469 function CenterOnParent: PControl;
7470 {* Centers control on parent, or if applied to a form, centers
7471 form on screen. }
7473 function Shift( dX, dY : Integer ): PControl;
7474 {* Moves control respectively to current position (Left := Left + dX,
7475 Top := Top + dY). }
7476 function SetPosition( X, Y: Integer ): PControl;
7477 {* Moves control directly to the specified position. }
7479 function Tabulate: PControl;
7480 {* Call it once for form/applet to provide tabulation between controls on
7481 form/on all forms using TAB / SHIFT+TAB and arrow keys. }
7482 function TabulateEx: PControl;
7483 {* Call it once for form/applet to provide tabulation between controls on
7484 form/on all forms using TAB / SHIFT+TAB and arrow keys. Arrow keys are
7485 used more smart, allowing go to nearest control in certain direction. }
7487 function SetAlign( AAlign: TControlAlign ): PControl;
7488 {* Assigns passed value to property Align, aligning control on parent,
7489 and returns @Self (so it is "transparent" function, which can be
7490 used to adjust control at the creation, e.g.:
7491 ! MyLabel := NewLabel( MyForm, 'Label1' ).SetAlign( caBottom );
7492 See also property Align. }
7493 function PreventResizeFlicks: PControl;
7494 {* If called, prevents resizing flicks for child controls, aligned to
7495 right and bottom (but with a lot of code added to executable - about 3,5K).
7496 There is sensible to set DoubleBuffered to True also to eliminate the
7497 most of flicks.
7498 |<br>&nbsp;&nbsp;&nbsp;
7499 This method been applied to a form, prevents, resizing flicks for
7500 form and all controls on the form. If it is called for applet window,
7501 all forms are affected. And if You want, You can apply it for certain
7502 control only - in such case only given control and its children will
7503 be resizing without flicks (e.g., using splitter control). }
7505 property Checked: Boolean read GetChecked write Set_Checked;
7506 {* |<#checkbox>
7507 |<#radiobox>
7508 For checkbox and radiobox - if it is checked. Do not assign
7509 value for radiobox - use SetRadioChecked instead. }
7510 function SetChecked(const Value: Boolean): PControl;
7511 {* |<#checkbox>
7512 Use it to check/uncheck check box control or push button.
7513 Do not apply it to check radio buttons - use SetRadioChecked
7514 method below. }
7515 function SetRadioChecked : PControl;
7516 {* |<#radiobox>
7517 Use it to check radio button item correctly (unchecking all
7518 alternative ones). Actually, method Click is called, and control
7519 itself is returned. }
7520 function SetRadioCheckedOld: PControl;
7521 {* |<#radiobox>
7522 Old version of SetRadioChecked (implemented using recommended API
7523 call. It does not work properly, if control is not visible
7524 (together with its form). }
7525 property Check3: TTriStateCheck read GetCheck3 write SetCheck3;
7526 {* |<#checkbox>
7527 State of checkbox with BS_AUTO3STATE style. }
7528 procedure Click;
7529 {* |<#button>
7530 |<#checkbox>
7531 |<#radiobox>
7532 Emulates click on control programmatically, sending WM_COMMAND
7533 message with BN_CLICKED code. This method is sensible only for
7534 buttons, checkboxes and radioboxes. }
7536 function Perform( msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;
7537 {* Sends message to control's window (created if needed). }
7538 function Postmsg( msgcode: DWORD; wParam, lParam: Integer): Boolean; stdcall;
7539 {* Sends message to control's window (created if needed). }
7540 procedure AttachProc( Proc: TWindowFunc );
7541 {* It is possible to attach dynamically any message handler to window
7542 procedure using this method. Last attached procedure is called first.
7543 If procedure returns True, further processing of a message is stopped.
7544 Attached procedure can be detached using DetachProc (but do not
7545 attach/detach procedures during handling of attached procedure -
7546 this can hang application). }
7547 procedure AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );
7548 {* The same as AttachProc, but a handler is executed even after terminating
7549 the main message loop processing (i.e. after assigning true to
7550 AppletTerminated global variable. }
7551 function IsProcAttached( Proc: TWindowFunc ): Boolean;
7552 {* Returns True, if given procedure is already in chain of attached
7553 ones for given control window proc. }
7554 procedure DetachProc( Proc: TWindowFunc );
7555 {* Detaches procedure attached earlier using AttachProc. }
7557 property OnDropFiles: TOnDropFiles read FOnDropFiles write SetOnDropFiles;
7558 {* Assign this event to your handler, if You want to accept drag and drop
7559 files from other applications such as explorer onto your control. When
7560 this event is assigned to a control or form, this has effect also for
7561 all its child controls too. }
7563 property CustomData: Pointer read fCustomData write fCustomData;
7564 {* Can be used to exend the object when new type of control added. Memory,
7565 pointed by this pointer, released automatically in the destructor. }
7566 property CustomObj: PObj read fCustomObj write fCustomObj;
7567 {* Can be used to exend the object when new type of control added. Object,
7568 pointed by this pointer, released automatically in the destructor. }
7569 procedure SetAutoPopupMenu( PopupMenu: PObj );
7570 {* To assign a popup menu to the control, call SetAutoPopupMenu method of
7571 the control with popup menu object as a parameter. }
7573 function SupportMnemonics: PControl;
7574 {* This method provides supporting mnemonic keys in menus, buttons, checkboxes,
7575 toolbar buttons. }
7576 property OnScroll: TOnScroll read FOnScroll write SetOnScroll;
7577 {* }
7578 protected
7579 {$IFDEF USE_DROPDOWNCOUNT}
7580 fDropDownCount: Cardinal;
7581 {$ENDIF}
7582 fGraphCtlMouseEvent: TOnGraphCtlMouse;
7583 public
7584 {$IFDEF USE_DROPDOWNCOUNT}
7585 property DropDownCount: Cardinal read fDropDownCount write fDropDownCount;
7586 {$ENDIF}
7587 protected
7588 fPushedBtn: PControl;
7589 fFocused: Boolean;
7590 fEditOptions: TEditOptions;
7591 fEditCtl: PControl;
7592 fSetFocus: procedure of object;
7593 fSaveCursor: HCursor;
7594 fLeave: TOnEvent;
7595 fKeyboardProcess: TOnMessage;
7596 fHot: Boolean;
7597 fHotCtl: PControl;
7598 fMouseLeaveProc: TOnEvent;
7599 fIsGroupBox: Boolean;
7600 fErasingBkgnd: Boolean;
7601 fButtonIcon: HIcon;
7602 procedure GraphicLabelPaint( DC: HDC );
7603 procedure GraphicCheckBoxPaint( DC: HDC );
7604 procedure GraphicCheckBoxMouse( var Msg: TMsg );
7605 procedure GraphicRadioBoxPaint( DC: HDC );
7606 procedure GraphicButtonPaint( DC: HDC );
7607 procedure GraphicButtonMouse( var Msg: TMsg );
7608 procedure GraphButtonSetFocus;
7609 function GraphButtonKeyboardProcess( var Msg: TMsg; var Rslt: Integer ): Boolean;
7610 procedure LeaveGraphButton( Sender: PObj );
7611 procedure GraphicEditPaint( DC: HDC );
7612 procedure GraphicEditMouse( var Msg: TMsg );
7613 function EditGraphEdit: PControl;
7614 procedure DestroyGraphEdit( Sender: PObj );
7615 procedure LeaveGraphEdit( Sender: PObj );
7616 procedure ChangeGraphEdit( Sender: PObj );
7617 procedure GraphEditboxSetFocus;
7618 procedure GraphCtlDrawFocusRect( DC: HDC; const R: TRect );
7619 {$IFDEF GRAPHCTL_HOTTRACK}
7620 procedure MouseLeaveFromParentOfGraphCtl( Sender: PObj );
7621 {$ENDIF GRAPHCTL_HOTTRACK}
7622 procedure GroupBoxPaint( DC: HDC );
7623 {$IFDEF KEY_PREVIEW}
7624 protected
7625 fKeyPreview: Boolean;
7626 public
7627 property KeyPreview: Boolean read fKeyPreview write fKeyPreview;
7628 {$ENDIF KEY_PREVIEW}
7629 public
7630 {$IFDEF USE_CONSTRUCTORS}
7631 //------------------------------------------------------------
7632 // constructors here:
7633 constructor CreateWindowed( AParent: PControl; AClassName: PChar; ACtl3D: Boolean );
7634 constructor CreateApplet( const ACaption: String );
7635 constructor CreateForm( AParent: PControl; const ACaption: String );
7636 constructor CreateControl( AParent: PControl; AClassName: PChar; AStyle: DWORD;
7637 ACtl3D: Boolean; Actions: PCommandActions );
7638 constructor CreateButton( AParent: PControl; const ACaption: String );
7639 constructor CreateBitBtn( AParent: PControl; const ACaption: String;
7640 AOptions: TBitBtnOptions; ALayout: TGlyphLayout; AGlyphBitmap: HBitmap;
7641 AGlyphCount: Integer);
7642 constructor CreateLabel( AParent: PControl; const ACaption: String );
7643 constructor CreateWordWrapLabel( AParent: PControl; const ACaption: String );
7644 constructor CreateLabelEffect( AParent: PControl; ACaption: String; AShadowDeep: Integer );
7645 constructor CreatePaintBox( AParent: PControl );
7646 constructor CreateGradientPanel( AParent: PControl; AColor1, AColor2: TColor );
7647 constructor CreateGradientPanelEx( AParent: PControl; AColor1, AColor2: TColor;
7648 AStyle: TGradientStyle; ALayout: TGradientLayout );
7649 constructor CreateGroupbox( AParent: PControl; const ACaption: String );
7650 constructor CreateCheckbox( AParent: PControl; const ACaption: String );
7651 constructor CreateRadiobox( AParent: PControl; const ACaption: String );
7652 constructor CreateEditbox( AParent: PControl; AOptions: TEditOptions );
7653 constructor CreatePanel( AParent: PControl; AStyle: TEdgeStyle );
7654 constructor CreateSplitter( AParent: PControl; AMinSizePrev, AMinSizeNext: Integer;
7655 EdgeStyle: TEdgeStyle );
7656 constructor CreateListbox( AParent: PControl; AOptions: TListOptions );
7657 constructor CreateCombobox( AParent: PControl; AOptions: TComboOptions );
7658 constructor CreateCommonControl( AParent: PControl; AClassName: PChar; AStyle: DWORD;
7659 ACtl3D: Boolean; Actions: PCommandActions );
7660 constructor CreateRichEdit( AParent: PControl; AOptions: TEditOptions );
7661 constructor CreateRichEdit1( AParent: PControl; AOptions: TEditOptions );
7662 constructor CreateProgressbar( AParent: PControl );
7663 constructor CreateProgressbarEx( AParent: PControl; AOptions: TProgressbarOptions );
7664 constructor CreateListView( AParent: PControl; AStyle: TListViewStyle; AOptions: TListViewOptions;
7665 AImageListSmall, AImageListNormal, AImageListState: PImageList );
7666 constructor CreateTreeView( AParent: PControl; AOptions: TTreeViewOptions;
7667 AImgListNormal, AImgListState: PImageList );
7668 constructor CreateTabControl( AParent: PControl; ATabs: array of String;
7669 AOptions: TTabControlOptions; AImgList: PImageList; AImgList1stIdx: Integer );
7670 constructor CreateToolbar( AParent: PControl; AAlign: TControlAlign; AOptions: TToolbarOptions;
7671 ABitmap: HBitmap; AButtons: array of PChar;
7672 ABtnImgIdxArray: array of Integer );
7673 {$ENDIF USE_CONSTRUCTORS}
7675 {$IFDEF USE_CUSTOMEXTENSIONS}
7676 {$I CUSTOM_TCONTROL_EXTENSION.inc}
7677 {$ENDIF}
7678 // If an option USE_CUSTOMEXTENSIONS is enabled (at the beginning of this
7679 // unit), You can freely extend TControl definition by your own fields,
7680 // methods and properties. This provides You with capability to extend
7681 // TControl implementing another kinds of visual controls without deriving
7682 // new descendant objects from TControl. This way is provided to avoid too
7683 // large grow of executable size. You also can derive your own controls
7684 // from TControl using standard OOP capabilities. In such case an option
7685 // USE_CONSTRUCTORS should be turned on (see it at the start of this unit).
7686 // If You choose this "flat" model of extending the TControl with your
7687 // own properties, fieds, methods, events, etc. You should provide three
7688 // inc-files: CUSTOM_TCONTROL_EXTENSION.inc, containing such definitions
7689 // for TControl, CUSTOM_KOL_EXTENSION.inc, containing needed global
7690 // declarations, and CUSTOM_CODE_EXTENSION.inc, the implementation of those
7691 // two.
7692 // Because KOL is always grow and constantly is extending by me, I also can
7693 // add my own complements for TControl. To avoid naming conflicts, I suggest
7694 // to use the same naming rule for all of You. Name your fields, properies, etc.
7695 // using a form idx_SomeName, where idx is a prefix, containing several
7696 // (at least one) letters and digits. E.g. ZK65_OnSomething.
7698 end;
7699 //[END OF TControl DEFINITION]
7701 {$IFDEF USE_MHTOOLTIP}
7702 {$DEFINE interface}
7703 {$I KOLMHToolTip}
7704 {$UNDEF interface}
7705 {$ENDIF}
7707 //[Paint Background PROCEDURE]
7708 type
7709 TOnPaintBkgnd = procedure( Sender: PControl; DC: HDC; Rect: PRect );
7710 {* Global event definition. Used to define Global_OnPaintBackground
7711 event placeholder. }
7713 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );
7716 Global_OnPaintBkgnd: TOnPaintBkgnd = DefaultPaintBackground;
7717 {* Global event. It is assigned in XBackgounds.pas add-on to replace
7718 PaintBackground method for all TVisual objects, allowing great
7719 visualization effect: transparent controls over [animated] bitmap
7720 background. Idea:
7721 | <a href=mailto:"bw@sunv.com">Wei&nbsp;Bao</a>. Implementation:
7722 | <a href=mailto:"bonanzas@xcl.cjb.net">Kladov&nbsp;Vladimir</a>. }
7724 procedure DummyPaintProc( Sender: PControl; DC: HDC );
7726 //[GetShiftState DECLARATION]
7727 function GetShiftState: DWORD;
7729 //[WndProcXXX DECLARATIONS]
7730 function WndProcMouse( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7731 function WndProcKeybd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7732 function WndProcDummy( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7733 function WndProcBufferedDraw( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7734 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
7735 function WndProcBtnReturnClick( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
7736 {$ENDIF}
7737 function AutoMinimizeApplet(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
7738 {* By Sergey Shishmintzev.
7739 Attach this handler to your modal dialog form handle to provide automatic
7740 minimization of all other forms in the application together with the dialog. }
7742 //[InitCommonXXXX DECLARATIONS]
7743 procedure InitCommonControlSizeNotify( Ctrl: PControl );
7744 procedure InitCommonControlCommonNotify( Ctrl: PControl );
7746 //[Buffered Draw DECLARATIONS]
7748 Global_OnBufferedDraw: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean
7749 = WndProcDummy;
7750 Global_DblBufCreateWnd: procedure( Sender: PObj ) = DummyObjProc;
7751 Global_Invalidate: procedure( Sender: PObj ) = DummyObjProc;
7752 {* Is called in TControl.Invalidate to extend it in case when DoubleBuffered
7753 painting used. }
7755 Global_TranspDrawBkgnd: procedure( DC: HDC; Sender: PControl );
7757 //Global_OnCreateWindow: procedure( Sender: PObj ) = DummyObjProc;
7758 //{* Is called when TControl object is created. }
7759 //Global_OnDestroyWindow: procedure( Sender: PObj ) = DummyObjProc;
7760 //{* Is called before destroying TControl object (after accepting it,
7761 // if event OnClose is defined). }
7762 Global_OnBeginPaint: procedure( Sender: PControl; DC: HDC ) = DummyPaintProc;
7763 {* Is called before painting a window. }
7764 Global_OnEndPaint: procedure( Sender: PControl; DC: HDC ) = DummyPaintProc;
7765 {* Is called after painting a window. }
7766 HelpFilePath: PChar;
7767 {* Path to application help file. If not assigned, application path with
7768 extension replaced to '.hlp' used. To use '.chm' file (HtmlHelp),
7769 call AssignHtmlHelp with a path to a html help file (or a name). }
7771 //[Html Help DECLARATIONS]
7772 procedure AssignHtmlHelp( const HtmlHelpPath: String );
7773 procedure HtmlHelpCommand( Wnd: HWnd; const HelpFilePath: String; Cmd, Data: Integer );
7774 {* Use this wrapper procedure to call HtmlHelp API function. }
7775 //+++++++++++ HTML HELP DEFINITIONS SECTION:
7776 // this section is from
7777 // HTML Help API Interface Unit
7778 // Copyright (c) 1999 The Helpware Group
7779 // provided for KOL by Alexey Babenko
7780 const
7781 HH_DISPLAY_TOPIC = $0000; {**}
7782 HH_HELP_FINDER = $0000; // WinHelp equivalent
7783 HH_DISPLAY_TOC = $0001; // not currently implemented
7784 HH_DISPLAY_INDEX = $0002; // not currently implemented
7785 HH_DISPLAY_SEARCH = $0003; // not currently implemented
7786 HH_SET_WIN_TYPE = $0004;
7787 HH_GET_WIN_TYPE = $0005;
7788 HH_GET_WIN_HANDLE = $0006;
7789 HH_ENUM_INFO_TYPE = $0007; // Get Info type name, call repeatedly to enumerate, -1 at end
7790 HH_SET_INFO_TYPE = $0008; // Add Info type to filter.
7791 HH_SYNC = $0009;
7792 HH_RESERVED1 = $000A;
7793 HH_RESERVED2 = $000B;
7794 HH_RESERVED3 = $000C;
7795 HH_KEYWORD_LOOKUP = $000D;
7796 HH_DISPLAY_TEXT_POPUP = $000E; // display string resource id or text in a popup window
7797 HH_HELP_CONTEXT = $000F; {**}// display mapped numeric value in dwData
7798 HH_TP_HELP_CONTEXTMENU = $0010; // text popup help, same as WinHelp HELP_CONTEXTMENU
7799 HH_TP_HELP_WM_HELP = $0011; // text popup help, same as WinHelp HELP_WM_HELP
7800 HH_CLOSE_ALL = $0012; // close all windows opened directly or indirectly by the caller
7801 HH_ALINK_LOOKUP = $0013; // ALink version of HH_KEYWORD_LOOKUP
7802 HH_GET_LAST_ERROR = $0014; // not currently implemented // See HHERROR.h
7803 HH_ENUM_CATEGORY = $0015; // Get category name, call repeatedly to enumerate, -1 at end
7804 HH_ENUM_CATEGORY_IT = $0016; // Get category info type members, call repeatedly to enumerate, -1 at end
7805 HH_RESET_IT_FILTER = $0017; // Clear the info type filter of all info types.
7806 HH_SET_INCLUSIVE_FILTER = $0018; // set inclusive filtering method for untyped topics to be included in display
7807 HH_SET_EXCLUSIVE_FILTER = $0019; // set exclusive filtering method for untyped topics to be excluded from display
7808 HH_INITIALIZE = $001C; // Initializes the help system.
7809 HH_UNINITIALIZE = $001D; // Uninitializes the help system.
7810 HH_PRETRANSLATEMESSAGE = $00fd; // Pumps messages. (NULL, NULL, MSG*).
7811 HH_SET_GLOBAL_PROPERTY = $00fc; // Set a global property. (NULL, NULL, HH_GPROP)
7813 { window properties }
7815 const
7816 HHWIN_PROP_TAB_AUTOHIDESHOW = $00000001; // (1 << 0) Automatically hide/show tri-pane window
7817 HHWIN_PROP_ONTOP = $00000002; // (1 << 1) Top-most window
7818 HHWIN_PROP_NOTITLEBAR = $00000004; // (1 << 2) no title bar
7819 HHWIN_PROP_NODEF_STYLES = $00000008; // (1 << 3) no default window styles (only HH_WINTYPE.dwStyles)
7820 HHWIN_PROP_NODEF_EXSTYLES = $00000010; // (1 << 4) no default extended window styles (only HH_WINTYPE.dwExStyles)
7821 HHWIN_PROP_TRI_PANE = $00000020; // (1 << 5) use a tri-pane window
7822 HHWIN_PROP_NOTB_TEXT = $00000040; // (1 << 6) no text on toolbar buttons
7823 HHWIN_PROP_POST_QUIT = $00000080; // (1 << 7) post WM_QUIT message when window closes
7824 HHWIN_PROP_AUTO_SYNC = $00000100; // (1 << 8) automatically ssync contents and index
7825 HHWIN_PROP_TRACKING = $00000200; // (1 << 9) send tracking notification messages
7826 HHWIN_PROP_TAB_SEARCH = $00000400; // (1 << 10) include search tab in navigation pane
7827 HHWIN_PROP_TAB_HISTORY = $00000800; // (1 << 11) include history tab in navigation pane
7828 HHWIN_PROP_TAB_FAVORITES = $00001000; // (1 << 12) include favorites tab in navigation pane
7829 HHWIN_PROP_CHANGE_TITLE = $00002000; // (1 << 13) Put current HTML title in title bar
7830 HHWIN_PROP_NAV_ONLY_WIN = $00004000; // (1 << 14) Only display the navigation window
7831 HHWIN_PROP_NO_TOOLBAR = $00008000; // (1 << 15) Don't display a toolbar
7832 HHWIN_PROP_MENU = $00010000; // (1 << 16) Menu
7833 HHWIN_PROP_TAB_ADVSEARCH = $00020000; // (1 << 17) Advanced FTS UI.
7834 HHWIN_PROP_USER_POS = $00040000; // (1 << 18) After initial creation, user controls window size/position
7835 HHWIN_PROP_TAB_CUSTOM1 = $00080000; // (1 << 19) Use custom tab #1
7836 HHWIN_PROP_TAB_CUSTOM2 = $00100000; // (1 << 20) Use custom tab #2
7837 HHWIN_PROP_TAB_CUSTOM3 = $00200000; // (1 << 21) Use custom tab #3
7838 HHWIN_PROP_TAB_CUSTOM4 = $00400000; // (1 << 22) Use custom tab #4
7839 HHWIN_PROP_TAB_CUSTOM5 = $00800000; // (1 << 23) Use custom tab #5
7840 HHWIN_PROP_TAB_CUSTOM6 = $01000000; // (1 << 24) Use custom tab #6
7841 HHWIN_PROP_TAB_CUSTOM7 = $02000000; // (1 << 25) Use custom tab #7
7842 HHWIN_PROP_TAB_CUSTOM8 = $04000000; // (1 << 26) Use custom tab #8
7843 HHWIN_PROP_TAB_CUSTOM9 = $08000000; // (1 << 27) Use custom tab #9
7844 HHWIN_TB_MARGIN = $10000000; // (1 << 28) the window type has a margin
7846 { window parameters }
7848 const
7849 HHWIN_PARAM_PROPERTIES = $00000002; // (1 << 1) valid fsWinProperties
7850 HHWIN_PARAM_STYLES = $00000004; // (1 << 2) valid dwStyles
7851 HHWIN_PARAM_EXSTYLES = $00000008; // (1 << 3) valid dwExStyles
7852 HHWIN_PARAM_RECT = $00000010; // (1 << 4) valid rcWindowPos
7853 HHWIN_PARAM_NAV_WIDTH = $00000020; // (1 << 5) valid iNavWidth
7854 HHWIN_PARAM_SHOWSTATE = $00000040; // (1 << 6) valid nShowState
7855 HHWIN_PARAM_INFOTYPES = $00000080; // (1 << 7) valid apInfoTypes
7856 HHWIN_PARAM_TB_FLAGS = $00000100; // (1 << 8) valid fsToolBarFlags
7857 HHWIN_PARAM_EXPANSION = $00000200; // (1 << 9) valid fNotExpanded
7858 HHWIN_PARAM_TABPOS = $00000400; // (1 << 10) valid tabpos
7859 HHWIN_PARAM_TABORDER = $00000800; // (1 << 11) valid taborder
7860 HHWIN_PARAM_HISTORY_COUNT = $00001000; // (1 << 12) valid cHistory
7861 HHWIN_PARAM_CUR_TAB = $00002000; // (1 << 13) valid curNavType
7863 { button constants }
7865 const
7866 HHWIN_BUTTON_EXPAND = $00000002; // (1 << 1) Expand/contract button
7867 HHWIN_BUTTON_BACK = $00000004; // (1 << 2) Back button
7868 HHWIN_BUTTON_FORWARD = $00000008; // (1 << 3) Forward button
7869 HHWIN_BUTTON_STOP = $00000010; // (1 << 4) Stop button
7870 HHWIN_BUTTON_REFRESH = $00000020; // (1 << 5) Refresh button
7871 HHWIN_BUTTON_HOME = $00000040; // (1 << 6) Home button
7872 HHWIN_BUTTON_BROWSE_FWD = $00000080; // (1 << 7) not implemented
7873 HHWIN_BUTTON_BROWSE_BCK = $00000100; // (1 << 8) not implemented
7874 HHWIN_BUTTON_NOTES = $00000200; // (1 << 9) not implemented
7875 HHWIN_BUTTON_CONTENTS = $00000400; // (1 << 10) not implemented
7876 HHWIN_BUTTON_SYNC = $00000800; // (1 << 11) Sync button
7877 HHWIN_BUTTON_OPTIONS = $00001000; // (1 << 12) Options button
7878 HHWIN_BUTTON_PRINT = $00002000; // (1 << 13) Print button
7879 HHWIN_BUTTON_INDEX = $00004000; // (1 << 14) not implemented
7880 HHWIN_BUTTON_SEARCH = $00008000; // (1 << 15) not implemented
7881 HHWIN_BUTTON_HISTORY = $00010000; // (1 << 16) not implemented
7882 HHWIN_BUTTON_FAVORITES = $00020000; // (1 << 17) not implemented
7883 HHWIN_BUTTON_JUMP1 = $00040000; // (1 << 18)
7884 HHWIN_BUTTON_JUMP2 = $00080000; // (1 << 19)
7885 HHWIN_BUTTON_ZOOM = $00100000; // (1 << 20)
7886 HHWIN_BUTTON_TOC_NEXT = $00200000; // (1 << 21)
7887 HHWIN_BUTTON_TOC_PREV = $00400000; // (1 << 22)
7889 HHWIN_DEF_BUTTONS = (HHWIN_BUTTON_EXPAND
7890 OR HHWIN_BUTTON_BACK
7891 OR HHWIN_BUTTON_OPTIONS
7892 OR HHWIN_BUTTON_PRINT);
7895 { Button IDs }
7897 const
7898 IDTB_EXPAND = 200;
7899 IDTB_CONTRACT = 201;
7900 IDTB_STOP = 202;
7901 IDTB_REFRESH = 203;
7902 IDTB_BACK = 204;
7903 IDTB_HOME = 205;
7904 IDTB_SYNC = 206;
7905 IDTB_PRINT = 207;
7906 IDTB_OPTIONS = 208;
7907 IDTB_FORWARD = 209;
7908 IDTB_NOTES = 210; // not implemented
7909 IDTB_BROWSE_FWD = 211;
7910 IDTB_BROWSE_BACK = 212;
7911 IDTB_CONTENTS = 213; // not implemented
7912 IDTB_INDEX = 214; // not implemented
7913 IDTB_SEARCH = 215; // not implemented
7914 IDTB_HISTORY = 216; // not implemented
7915 IDTB_FAVORITES = 217; // not implemented
7916 IDTB_JUMP1 = 218;
7917 IDTB_JUMP2 = 219;
7918 IDTB_CUSTOMIZE = 221;
7919 IDTB_ZOOM = 222;
7920 IDTB_TOC_NEXT = 223;
7921 IDTB_TOC_PREV = 224;
7924 { Notification codes }
7926 const
7927 HHN_FIRST = (0-860);
7928 HHN_LAST = (0-879);
7930 HHN_NAVCOMPLETE = (HHN_FIRST-0);
7931 HHN_TRACK = (HHN_FIRST-1);
7932 HHN_WINDOW_CREATE = (HHN_FIRST-2);
7935 type
7936 {*** Used by command HH_GET_LAST_ERROR
7937 NOTE: Not part of the htmlhelp.h but documented in HH Workshop help
7938 You must call SysFreeString(xx.description) to free BSTR
7940 tagHH_LAST_ERROR = packed record
7941 cbStruct: Integer; // sizeof this structure
7942 hr: Integer; // Specifies the last error code.
7943 description: PWideChar; // (BSTR) Specifies a Unicode string containing a description of the error.
7944 end;
7945 HH_LAST_ERROR = tagHH_LAST_ERROR;
7946 THHLastError = tagHH_LAST_ERROR;
7949 type
7950 {*** Notify event info for HHN_NAVCOMPLETE, HHN_WINDOW_CREATE }
7951 PHHNNotify = ^THHNNotify;
7952 tagHHN_NOTIFY = packed record
7953 hdr: TNMHdr;
7954 pszUrl: PChar; //PCSTR: Multi-byte, null-terminated string
7955 end;
7956 HHN_NOTIFY = tagHHN_NOTIFY;
7957 THHNNotify = tagHHN_NOTIFY;
7959 {** Use by command HH_DISPLAY_TEXT_POPUP}
7960 PHHPopup = ^THHPopup;
7961 tagHH_POPUP = packed record
7962 cbStruct: Integer; // sizeof this structure
7963 hinst: HINST; // instance handle for string resource
7964 idString: cardinal; // string resource id, or text id if pszFile is specified in HtmlHelp call
7965 pszText: PChar; // used if idString is zero
7966 pt: TPOINT; // top center of popup window
7967 clrForeground: COLORREF; // use -1 for default
7968 clrBackground: COLORREF; // use -1 for default
7969 rcMargins: TRect; // amount of space between edges of window and text, -1 for each member to ignore
7970 pszFont: PChar; // facename, point size, char set, BOLD ITALIC UNDERLINE
7971 end;
7972 HH_POPUP = tagHH_POPUP;
7973 THHPopup = tagHH_POPUP;
7975 {** Use by commands - HH_ALINK_LOOKUP, HH_KEYWORD_LOOKUP}
7976 PHHAKLink = ^THHAKLink;
7977 tagHH_AKLINK = packed record
7978 cbStruct: integer; // sizeof this structure
7979 fReserved: BOOL; // must be FALSE (really!)
7980 pszKeywords: PChar; // semi-colon separated keywords
7981 pszUrl: PChar; // URL to jump to if no keywords found (may be NULL)
7982 pszMsgText: PChar; // Message text to display in MessageBox if pszUrl is NULL and no keyword match
7983 pszMsgTitle: PChar; // Message text to display in MessageBox if pszUrl is NULL and no keyword match
7984 pszWindow: PChar; // Window to display URL in
7985 fIndexOnFail: BOOL; // Displays index if keyword lookup fails.
7986 end;
7987 HH_AKLINK = tagHH_AKLINK;
7988 THHAKLink = tagHH_AKLINK;
7991 const
7992 HHWIN_NAVTYPE_TOC = 0;
7993 HHWIN_NAVTYPE_INDEX = 1;
7994 HHWIN_NAVTYPE_SEARCH = 2;
7995 HHWIN_NAVTYPE_FAVORITES = 3;
7996 HHWIN_NAVTYPE_HISTORY = 4; // not implemented
7997 HHWIN_NAVTYPE_AUTHOR = 5;
7998 HHWIN_NAVTYPE_CUSTOM_FIRST = 11;
8001 const
8002 IT_INCLUSIVE = 0;
8003 IT_EXCLUSIVE = 1;
8004 IT_HIDDEN = 2;
8006 type
8007 PHHEnumIT = ^THHEnumIT;
8008 tagHH_ENUM_IT = packed record //tagHH_ENUM_IT, HH_ENUM_IT, *PHH_ENUM_IT
8009 cbStruct: Integer; // size of this structure
8010 iType: Integer; // the type of the information type ie. Inclusive, Exclusive, or Hidden
8011 pszCatName: PAnsiChar; // Set to the name of the Category to enumerate the info types in a category; else NULL
8012 pszITName: PAnsiChar; // volitile pointer to the name of the infotype. Allocated by call. Caller responsible for freeing
8013 pszITDescription: PAnsiChar; // volitile pointer to the description of the infotype.
8014 end;
8015 THHEnumIT = tagHH_ENUM_IT;
8018 type
8019 PHHEnumCat = ^THHEnumCat;
8020 tagHH_ENUM_CAT = packed record //tagHH_ENUM_CAT, HH_ENUM_CAT, *PHH_ENUM_CAT
8021 cbStruct: Integer; // size of this structure
8022 pszCatName: PAnsiChar; // volitile pointer to the category name
8023 pszCatDescription: PAnsiChar; // volitile pointer to the category description
8024 end;
8025 THHEnumCat = tagHH_ENUM_CAT;
8028 type
8029 PHHSetInfoType = ^THHSetInfoType;
8030 tagHH_SET_INFOTYPE = packed record //tagHH_SET_INFOTYPE, HH_SET_INFOTYPE, *PHH_SET_INFOTYPE
8031 cbStruct: Integer; // the size of this structure
8032 pszCatName: PAnsiChar; // the name of the category, if any, the InfoType is a member of.
8033 pszInfoTypeName: PAnsiChar; // the name of the info type to add to the filter
8034 end;
8035 THHSetInfoType = tagHH_SET_INFOTYPE;
8038 type
8039 HH_INFOTYPE = DWORD;
8040 THHInfoType = HH_INFOTYPE;
8041 PHHInfoType = ^THHInfoType; //PHH_INFOTYPE
8044 const
8045 HHWIN_NAVTAB_TOP = 0;
8046 HHWIN_NAVTAB_LEFT = 1;
8047 HHWIN_NAVTAB_BOTTOM = 2;
8049 const
8050 HH_MAX_TABS = 19; // maximum number of tabs
8051 const
8052 HH_TAB_CONTENTS = 0;
8053 HH_TAB_INDEX = 1;
8054 HH_TAB_SEARCH = 2;
8055 HH_TAB_FAVORITES = 3;
8056 HH_TAB_HISTORY = 4;
8057 HH_TAB_AUTHOR = 5;
8058 HH_TAB_CUSTOM_FIRST = 11;
8059 HH_TAB_CUSTOM_LAST = HH_MAX_TABS;
8061 HH_MAX_TABS_CUSTOM = (HH_TAB_CUSTOM_LAST - HH_TAB_CUSTOM_FIRST + 1);
8065 { HH_DISPLAY_SEARCH Command Related Structures and Constants }
8067 const
8068 HH_FTS_DEFAULT_PROXIMITY = (-1);
8070 type
8071 {** Used by command HH_DISPLAY_SEARCH}
8072 PHHFtsQuery = ^THHFtsQuery;
8073 tagHH_FTS_QUERY = packed record //tagHH_FTS_QUERY, HH_FTS_QUERY
8074 cbStruct: integer; // Sizeof structure in bytes.
8075 fUniCodeStrings: BOOL; // TRUE if all strings are unicode.
8076 pszSearchQuery: PChar; // String containing the search query.
8077 iProximity: LongInt; // Word proximity.
8078 fStemmedSearch: Bool; // TRUE for StemmedSearch only.
8079 fTitleOnly: Bool; // TRUE for Title search only.
8080 fExecute: Bool; // TRUE to initiate the search.
8081 pszWindow: PChar; // Window to display in
8082 end;
8083 THHFtsQuery = tagHH_FTS_QUERY;
8086 { HH_WINTYPE Structure }
8088 type
8089 {** Used by commands HH_GET_WIN_TYPE, HH_SET_WIN_TYPE}
8090 PHHWinType = ^THHWinType;
8091 tagHH_WINTYPE = packed record //tagHH_WINTYPE, HH_WINTYPE, *PHH_WINTYPE;
8092 cbStruct: Integer; // IN: size of this structure including all Information Types
8093 fUniCodeStrings: BOOL; // IN/OUT: TRUE if all strings are in UNICODE
8094 pszType: PChar; // IN/OUT: Name of a type of window
8095 fsValidMembers: DWORD; // IN: Bit flag of valid members (HHWIN_PARAM_)
8096 fsWinProperties: DWORD; // IN/OUT: Properties/attributes of the window (HHWIN_)
8098 pszCaption: PChar; // IN/OUT: Window title
8099 dwStyles: DWORD; // IN/OUT: Window styles
8100 dwExStyles: DWORD; // IN/OUT: Extended Window styles
8101 rcWindowPos: TRect; // IN: Starting position, OUT: current position
8102 nShowState: Integer; // IN: show state (e.g., SW_SHOW)
8104 hwndHelp: HWND; // OUT: window handle
8105 hwndCaller: HWND; // OUT: who called this window
8107 paInfoTypes: PHHInfoType; // IN: Pointer to an array of Information Types
8109 { The following members are only valid if HHWIN_PROP_TRI_PANE is set }
8111 hwndToolBar: HWND; // OUT: toolbar window in tri-pane window
8112 hwndNavigation: HWND; // OUT: navigation window in tri-pane window
8113 hwndHTML: HWND; // OUT: window displaying HTML in tri-pane window
8114 iNavWidth: Integer; // IN/OUT: width of navigation window
8115 rcHTML: TRect; // OUT: HTML window coordinates
8117 pszToc: PChar; // IN: Location of the table of contents file
8118 pszIndex: PChar; // IN: Location of the index file
8119 pszFile: PChar; // IN: Default location of the html file
8120 pszHome: PChar; // IN/OUT: html file to display when Home button is clicked
8121 fsToolBarFlags: DWORD; // IN: flags controling the appearance of the toolbar (HHWIN_BUTTON_)
8122 fNotExpanded: BOOL; // IN: TRUE/FALSE to contract or expand, OUT: current state
8123 curNavType: Integer; // IN/OUT: UI to display in the navigational pane
8124 tabpos: Integer; // IN/OUT: HHWIN_NAVTAB_TOP, HHWIN_NAVTAB_LEFT, or HHWIN_NAVTAB_BOTTOM
8125 idNotify: Integer; // IN: ID to use for WM_NOTIFY messages
8126 tabOrder: packed array[0..HH_MAX_TABS] of Byte; // IN/OUT: tab order: Contents, Index, Search, History, Favorites, Reserved 1-5, Custom tabs
8127 cHistory: Integer; // IN/OUT: number of history items to keep (default is 30)
8128 pszJump1: PChar; // Text for HHWIN_BUTTON_JUMP1
8129 pszJump2: PChar; // Text for HHWIN_BUTTON_JUMP2
8130 pszUrlJump1: PChar; // URL for HHWIN_BUTTON_JUMP1
8131 pszUrlJump2: PChar; // URL for HHWIN_BUTTON_JUMP2
8132 rcMinSize: TRect; // Minimum size for window (ignored in version 1)
8134 cbInfoTypes: Integer; // size of paInfoTypes;
8135 pszCustomTabs: PChar; // multiple zero-terminated strings
8136 end;
8137 HH_WINTYPE = tagHH_WINTYPE;
8138 THHWinType = tagHH_WINTYPE;
8140 const
8141 HHACT_TAB_CONTENTS = 0;
8142 HHACT_TAB_INDEX = 1;
8143 HHACT_TAB_SEARCH = 2;
8144 HHACT_TAB_HISTORY = 3;
8145 HHACT_TAB_FAVORITES = 4;
8147 HHACT_EXPAND = 5;
8148 HHACT_CONTRACT = 6;
8149 HHACT_BACK = 7;
8150 HHACT_FORWARD = 8;
8151 HHACT_STOP = 9;
8152 HHACT_REFRESH = 10;
8153 HHACT_HOME = 11;
8154 HHACT_SYNC = 12;
8155 HHACT_OPTIONS = 13;
8156 HHACT_PRINT = 14;
8157 HHACT_HIGHLIGHT = 15;
8158 HHACT_CUSTOMIZE = 16;
8159 HHACT_JUMP1 = 17;
8160 HHACT_JUMP2 = 18;
8161 HHACT_ZOOM = 19;
8162 HHACT_TOC_NEXT = 20;
8163 HHACT_TOC_PREV = 21;
8164 HHACT_NOTES = 22;
8166 HHACT_LAST_ENUM = 23;
8169 type
8170 {*** Notify event info for HHN_TRACK }
8171 PHHNTrack = ^THHNTrack;
8172 tagHHNTRACK = packed record //tagHHNTRACK, HHNTRACK;
8173 hdr: TNMHdr;
8174 pszCurUrl: PChar; // Multi-byte, null-terminated string
8175 idAction: Integer; // HHACT_ value
8176 phhWinType: PHHWinType; // Current window type structure
8177 end;
8178 HHNTRACK = tagHHNTRACK;
8179 THHNTrack = tagHHNTRACK;
8182 ///////////////////////////////////////////////////////////////////////////////
8184 // Global Control Properties.
8186 const
8187 HH_GPROPID_SINGLETHREAD = 1; // VARIANT_BOOL: True for single thread
8188 HH_GPROPID_TOOLBAR_MARGIN = 2; // long: Provides a left/right margin around the toolbar.
8189 HH_GPROPID_UI_LANGUAGE = 3; // long: LangId of the UI.
8190 HH_GPROPID_CURRENT_SUBSET = 4; // BSTR: Current subset.
8191 HH_GPROPID_CONTENT_LANGUAGE = 5; // long: LandId for desired content.
8193 type
8194 tagHH_GPROPID = HH_GPROPID_SINGLETHREAD..HH_GPROPID_CONTENT_LANGUAGE; //tagHH_GPROPID, HH_GPROPID
8195 HH_GPROPID = tagHH_GPROPID;
8196 THHGPropID = HH_GPROPID;
8198 ///////////////////////////////////////////////////////////////////////////////
8200 // Global Property structure
8202 {type
8203 PHHGlobalProperty = ^THHGlobalProperty;
8204 tagHH_GLOBAL_PROPERTY = record //tagHH_GLOBAL_PROPERTY, HH_GLOBAL_PROPERTY
8205 id: THHGPropID;
8206 Dummy: Integer; // Added to enforce 8-byte packing
8207 var_: VARIANT;
8208 end;
8209 HH_GLOBAL_PROPERTY = tagHH_GLOBAL_PROPERTY;
8210 THHGlobalProperty = tagHH_GLOBAL_PROPERTY;}
8211 //[END OF HTMLHELP DECLARATIONS]
8213 //[GetCtlBrush DECLARATIONS]
8214 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush; //forward;
8217 Global_GetCtlBrushHandle: function( Sender: PControl ): HBrush = SimpleGetCtlBrushHandle;
8218 {* Is called to obtain brush handle. }
8220 Global_Align: procedure( Sender: PObj ) = DummyObjProc;
8221 {* Is set to perform aligning of control, and only if property Align
8222 is changed for TControl, or SetAlign method is called for it. }
8224 //[WndFunc DECLARATION]
8225 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
8226 : Integer; stdcall;
8227 {* Global message handler for window. Redirects all messages to
8228 destination windows, obtaining target TControl object address from
8229 window itself, using GetProp API call. }
8231 //[Applet VARIABLES]
8232 var AppletRunning: Boolean;
8233 {* Is set to True while message loop is processing (in Run procedure). }
8234 AppletTerminated: Boolean;
8235 {* Is set to True when message loop is terminated. }
8236 Applet: PControl;
8237 {* Applet window object. Actually, can be set to main form if program
8238 not needed in special applet button window (useful to make applet
8239 button invisible on taskbar, or to have several forms with single
8240 applet button - crete it in that case using NewApplet). }
8241 AppButtonUsed: Boolean;
8242 {* True if special window to represent applet button (may be invisible)
8243 is used. If no, every form is represented with its own taskbar button
8244 (always visible). }
8246 //[Screen DECLARATIONS]
8247 ScreenCursor: HCursor;
8248 {* Set this global variable to override any cursor settings of current
8249 form or control. }
8251 function ScreenWidth: Integer;
8252 {* Returns screen width in pixels. }
8253 function ScreenHeight: Integer;
8254 {* Returns screen height in pixels. }
8256 //[Status DECLARATIONS]
8257 type
8258 TStatusOption = ( soNoSizeGrip, soTop );
8259 {* Options available for status bars. }
8260 TStatusOptions = Set of TStatusOption;
8261 {* Status bar options. }
8264 procedure DrawFormattedText( Ctl: PControl; DC: HDC; var R: TRect; Flags: DWORD {EditCtl: Boolean} );
8265 {* This procedure can be useful to draw control's text in custom-defined controls. }
8267 {$IFDEF GRAPHCTL_XPSTYLES}
8268 var DoNotDrawGraphCtlsUsingXPStyles: Boolean;
8269 procedure DrawFormattedTextXP( Theme: THandle; Ctl: PControl; DC: HDC;
8270 var R: TRect; CtlType, CtlStates, Flags1, Flags2: Integer );
8271 {* This procedure can be useful to draw control's text in custom-defined controls. }
8272 {$ENDIF}
8274 function _NewGraphCtl( AParent: PControl; ATabStop: Boolean ): PControl;
8275 {* Creates graphic control basics. }
8277 function NewGraphLabel( AParent: PControl; const ACaption: String ): PControl;
8278 {* Creates graphic label, which does not require a window handle. }
8280 function NewWordWrapGraphLabel( AParent: PControl; const ACaption: String ): PControl;
8281 {* Creates graphic label, which does not require a window handle. }
8283 function NewGraphPaintBox( AParent: PControl ): PControl;
8284 {* Creates graphic paint box (just the same as graphic label, but with empty Caption). }
8286 function NewGraphCheckBox( AParent: PControl; const ACaption: String ): PControl;
8287 {* Creates graphic checkbox. }
8289 function NewGraphRadioBox( AParent: PControl; const ACaption: String ): PControl;
8290 {* Creates graphic radiobox. }
8292 function NewGraphButton( AParent: PControl; const ACaption: String ): PControl;
8293 {* Creates graphic button. }
8295 function NewGraphEditbox( AParent: PControl; Options: TEditOptions ): PControl;
8296 {* Creates graphic edit box. To do editing, this box should be replaced with
8297 real edit box with a handle (actually, it is enough to place an edit box
8298 on the same Parent having the same BoundsRect). }
8300 //[Run DECLARATION]
8301 procedure Run( var AppletWnd: PControl );
8302 {* |<#appbutton>
8303 Call this procedure to process messages loop of your program.
8304 Pass here pointer to applet button object (if You have created it
8305 - see NewApplet) or your main form object of type PControl (created
8306 using NewForm).
8307 |<br><br>
8308 |<h1 align=center><font color=#FF8040><a name="visual_objects_constructors"></a>
8309 Visual objects constructing functions
8310 |</font></h1>
8311 Following constructing functions for visual controls are available:
8312 |#control
8315 procedure TerminateExecution( var AppletWnd: PControl );
8317 //[Applet FUNCTIONS DECLARATIONS]
8318 procedure AppletMinimize;
8319 {* Minimizes the application (Applet should be assigned to have effect). }
8320 procedure AppletHide;
8321 {* Minimizes and hides application. }
8322 procedure AppletRestore;
8323 {* Restores Applet when minimized. }
8325 //[Idle handler DECALRATIONS]
8326 {YS+}
8327 procedure RegisterIdleHandler( const OnIdle: TOnEvent );
8328 {* Registers new Idle handler. Idle handler is called each time when
8329 message queue becomes empty. }
8330 procedure UnRegisterIdleHandler( const OnIdle: TOnEvent );
8331 {* Unregisters Idle handler. }
8332 {YS-}
8336 //[InitCommonXXXX ANOTHER DECLARATIONS]
8338 {* ComCtrl32 controls initialization. }
8339 procedure InitCommonControls; stdcall;
8340 procedure DoInitCommonControls( dwICC: DWORD );
8341 {* Calls extended initialization for Common Controls (from ComCtrl32).
8342 Pass one of following constants:
8343 |<pre>
8344 ICC_LISTVIEW_CLASSES = $00000001; // listview, header
8345 ICC_TREEVIEW_CLASSES = $00000002; // treeview, tooltips
8346 ICC_BAR_CLASSES = $00000004; // toolbar, statusbar, trackbar, tooltips
8347 ICC_TAB_CLASSES = $00000008; // tab, tooltips
8348 ICC_UPDOWN_CLASS = $00000010; // updown
8349 ICC_PROGRESS_CLASS = $00000020; // progress
8350 ICC_HOTKEY_CLASS = $00000040; // hotkey
8351 ICC_ANIMATE_CLASS = $00000080; // animate
8352 ICC_WIN95_CLASSES = $000000FF;
8353 ICC_DATE_CLASSES = $00000100; // month picker, date picker, time picker, updown
8354 ICC_USEREX_CLASSES = $00000200; // comboex
8355 ICC_COOL_CLASSES = $00000400; // rebar (coolbar) control
8356 ICC_INTERNET_CLASSES = $00000800;
8357 ICC_PAGESCROLLER_CLASS = $00001000; // page scroller
8358 ICC_NATIVEFNTCTL_CLASS = $00002000; // native font control
8359 |</pre>
8362 const
8363 ICC_LISTVIEW_CLASSES = $00000001; // listview, header
8364 ICC_TREEVIEW_CLASSES = $00000002; // treeview, tooltips
8365 ICC_BAR_CLASSES = $00000004; // toolbar, statusbar, trackbar, tooltips
8366 ICC_TAB_CLASSES = $00000008; // tab, tooltips
8367 ICC_UPDOWN_CLASS = $00000010; // updown
8368 ICC_PROGRESS_CLASS = $00000020; // progress
8369 ICC_HOTKEY_CLASS = $00000040; // hotkey
8370 ICC_ANIMATE_CLASS = $00000080; // animate
8371 ICC_WIN95_CLASSES = $000000FF;
8372 ICC_DATE_CLASSES = $00000100; // month picker, date picker, time picker, updown
8373 ICC_USEREX_CLASSES = $00000200; // comboex
8374 ICC_COOL_CLASSES = $00000400; // rebar (coolbar) control
8375 ICC_INTERNET_CLASSES = $00000800;
8376 ICC_PAGESCROLLER_CLASS = $00001000; // page scroller
8377 ICC_NATIVEFNTCTL_CLASS = $00002000; // native font control
8379 //[Ole DECLARATIONS]
8380 function OleInit: Boolean;
8381 {* Calls OleInitialize (once - all other calls are simulated by incrementing
8382 call counter. Every OleInit shoud be complemented with correspondent OleUninit.
8383 (Though, it is possible to call API function OleUnInitialize once to
8384 cancel all OleInit calls). }
8385 procedure OleUnInit;
8386 {* Decrements counter and calls OleUnInitialize when it is zeroed. }
8387 var OleInitCount: Integer;
8390 function StringToOleStr(const Source: string): PWideChar;
8391 {* }
8394 function SysAllocStringLen(psz: PWideChar; len: Integer): PWideChar; stdcall;
8395 procedure SysFreeString( psz: PWideChar ); stdcall;
8406 { -- Contructors for visual controls -- }
8407 //[NewXXXX DECLARATIONS]
8409 //[_NewWindowed DECLARATION]
8410 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;
8412 //[NewApplet DECLARATION]
8413 function NewApplet( const Caption: String ): PControl;
8414 {* |<#control>
8415 Creates applet button window, which has to be parent of all other forms
8416 in your project (but this is *not must*). See also comments about NewForm.
8417 |<br>
8418 Following methods, properties and events are useful to work with applet
8419 control:
8420 |#appbutton }
8422 //[NewForm DECLARATION]
8423 function NewForm( AParent: PControl; const Caption: String ): PControl;
8424 {* |<#control>
8425 Creates form window object and returns pointer to it. If You use only one form,
8426 and You are not going to do applet button on task bar invisible, it is not
8427 necessary to create also special applet button window - just pass
8428 your (main) form object to Run procedure. In that case, it is a good
8429 idea to assign pointer to your main form object to Applet variable
8430 immediately following creating it - because some objects (e.g. TTimer)
8431 want to have Applet assigned to something.
8432 |<br>
8433 |&D=<a href="tcontrol.htm#%1" target=_top> %0 </a>
8434 Following methods, properties and events are useful to work with forms
8435 (ones common for all visual objects, such as <D Left>, <D Top>, <D Width>,
8436 <D Height>, etc. are not listed here - look TControl for it):
8437 |#form }
8439 //[_NewControl DECLARATION]
8440 function _NewControl( AParent: PControl; ControlClassName: PChar;
8441 Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;
8443 //[NewButton DECLARATION]
8444 function NewButton( AParent: PControl; const Caption: String ): PControl;
8445 {* |<#control>
8446 Creates button on given parent control or form.
8447 Please note, that in Windows, buttons can not change its <D Font> color
8448 and to be <D Transparent>.
8449 |<br> Following methods, properies and events are (especially) useful with
8450 a button:
8451 |#button }
8453 //[NewBitBtn DECLARATION]
8454 function NewBitBtn( AParent: PControl; const Caption: String;
8455 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap; GlyphCount: Integer ): PControl;
8456 {* |<#control>
8457 Creates image button (actually implemented as owner-drawn). In Options,
8458 it is possible to determine, whether bitmap or image list used to contain
8459 one or more (up to 5) images, correspondent to certain BitBtn state.
8460 |<br>&nbsp;&nbsp;&nbsp;
8461 For case of imagelist (option bboImageList), it is possible to use a
8462 number of glyphs from the image list, starting from image index given
8463 by GlyphCount parameter. Number of used glyphs is passed in that case
8464 in high word of GlyphCount parameter (if 0, one image is used therefore).
8465 For bboImageList, BitBtn can be Transparent (and in that case bboNoBorder
8466 style can be useful to draw custom buttons of non-rectangular shape).
8467 |<br>&nbsp;&nbsp;&nbsp;
8468 For case of bitmap BitBtn, image is stretched down (if too big), but can
8469 not be transparent. It is not necessary for bitmap BitBtn to pass correct
8470 GlyphCount - it is calculated on base of bitmap size, if 0 is passed.
8471 |<br>&nbsp;&nbsp;&nbsp;
8472 And, certainly, BitBtn can be without glyph image (text only). For that
8473 case, it is therefore is more flexible and power than usual Button (but
8474 requires more code). E.g., BitBtn can change its <D Font>, <D Color>,
8475 and to be totally <D Transparent>.
8476 Moreover, BitBtn can be <D Flat>, bboFixed, <D SpeedButton> and
8477 have property <D RepeatInterval>.
8478 |<br>&nbsp;&nbsp;&nbsp;
8479 Note: if You use bboFixed Style, use OnChange event instead of OnClick,
8480 because <D Checked> state is changed immediately however OnClick occure
8481 only when mouse or space key released (and can be not called at all if
8482 mouse button is released out of BitBtn bounds). Also, bboFixed defines
8483 only which glyph to show (the border if it is not turned off behaves as
8484 usual for a button, i.e. it becomes lowered and then raised again at any click).
8485 Here You can find references to other properties, events and methods
8486 applicable to BitBtn:
8487 |#bitbtn }
8489 //[NewLabel DECLARATION]
8490 function NewLabel( AParent: PControl; const Caption: String ): PControl;
8491 {* |<#control>
8492 Creates static text control (native Windows STATIC control).
8493 Use property <D Caption> at run time to change label text. Also
8494 it is possible to adjust label <D Font>, <D Brush> or <D Color>.
8495 Label can be <D Transparent>. If You want to have rotated text
8496 label, call NewLabelEffect instead and change its <D Font>.FontOrientation.
8497 Other references certain for a label:
8498 |#label }
8500 //[NewWordWrapLabel DECLARATION]
8501 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
8502 {* |<#control>
8503 Creates multiline static text control (native Windows STATIC control),
8504 which can wrap long text onto several lines. See also NewLabel.
8505 See also:
8506 |#wwlabel
8507 |#label }
8509 //[NewLabelEffect DECLARATION]
8510 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
8511 {* |<#control>
8512 Creates 3D-label with capability to rotate its text <D Caption>, which
8513 is controlled by changing <D Font>.FontOrientation property. If You want
8514 to get flat effect label (e.g. to rotate it only), pass <D ShadowDeep> = 0.
8515 Please note, that drawing procedure uses <D Canvas> property, so using of
8516 LabelEffect leads to increase size of executable.
8517 See also:
8518 |#3dlabel
8519 |#label }
8521 //[NewPaintbox DECLARATION]
8522 function NewPaintbox( AParent: PControl ): PControl;
8523 {* |<#control>
8524 Creates owner-drawn STATIC control. Set its <D OnPaint> event to
8525 perform custom painting.
8526 |#paintbox }
8528 //[NewImageShow DECLARATION]
8529 function NewImageShow( AParent: PControl; AImgList: PImageList; ImgIdx: Integer ): PControl;
8530 {* |<#control>
8531 Creates an image show control, implemented as a paintbox which is used to
8532 draw an image from the imagelist. At run-time, use property CurIndex to
8533 select another image from the imagelist, and a property ImageListNormal to
8534 use another image list. When the control is created, its size becomes
8535 equal to dimensions of imagelist (if any). }
8537 //[NewScrollBar DECLARATION]
8538 function NewScrollBar( AParent: PControl; BarSide: TScrollerBar ): PControl;
8539 { * not yet finished... }
8541 //[NewScrollBox DECLARATION]
8542 function NewScrollBox( AParent: PControl; EdgeStyle: TEdgeStyle;
8543 Bars: TScrollerBars ): PControl;
8544 {* |<#control>
8545 Creates simple scrolling box, which can be used any way you wish, e.g. to scroll
8546 certain large image. To provide automatic scrolling of a set of child controls,
8547 use advanced scroll box, created with NewScrollBoxEx. }
8549 procedure NotifyScrollBox( Self_, Child: PControl );
8552 function NewScrollBoxEx( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
8553 {* |<#control>
8554 Creates extended scrolling box control, which automatically scrolls child
8555 controls (if any). }
8557 //[NewGradientPanel DECLARATION]
8558 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
8559 {* |<#control>
8560 Creates gradient-filled STATIC control. To adjust colors at the
8561 run time, change <D Color1> and <D Color2> properties (which initially are
8562 assigned from Color1, Color2 parameters), and call <D Invalidate> method
8563 to repaint control. }
8565 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
8566 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
8567 {* |<#control>
8568 Creates gradient-filled STATIC control. To adjust colors at the
8569 run time, change <D Color1> and <D Color2> properties (which initially are
8570 assigned from Color1, Color2 parameters), and call <D Invalidate> method
8571 to repaint control. Depending on style and first line/point layout, can
8572 looking different. Idea: Vladimir Stojiljkovic. }
8574 //[NewPanel DECLARATION]
8575 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
8576 {* |<#control>
8577 Creates panel, which can be parent for other controls (though, any
8578 control can be used as a parent for other ones, but panel is specially
8579 designed for such purpose). }
8581 //[NewMDIxxx DECLARATIONS]
8582 function NewMDIClient( AParent: PControl; WindowMenu: THandle ): PControl;
8583 {* |<#control>
8584 Creates MDI client window, which is a special type of child window,
8585 containing all MDI child windows, created calling NewMDIChild function.
8586 On a form, MDI client behaves like a panel, so it can be placed and sized
8587 (or aligned) like any other controls. To minimize flick during resizing
8588 main form having another aligned controls, place MDI client window on
8589 a panel and align it caClient in the panel.
8590 |<br>Note:
8591 MDI client must be a single on the form. }
8593 function NewMDIChild( AParent: PControl; const ACaption: String ): PControl;
8594 {* |<#control>
8595 Creates MDI client window. AParent should be a MDI client window,
8596 created with NewMDIClient function. }
8598 //[NewSplitter DECLARATIONS]
8599 function NewSplitter( AParent: PControl; MinSizePrev, MinSizeNext: Integer ): PControl;
8600 {* |<#control>
8601 Creates splitter control, which will separate previous one (i.e. last
8602 created one before splitter on the same parent) from created
8603 next, allowing to user to adjust size of separated controls by dragging
8604 the splitter in desired direction. Created splitter becomes vertical
8605 or horizontal depending on Align style of previous control on the same
8606 parent (if caLeft/caRight then vertical, if caTop/caBottom then horizontal).
8607 |<br>&nbsp;&nbsp;&nbsp;
8608 Please note, what if previous control has no Align equal to caLeft/caRight
8609 or caTop/caBottom, splitter will not be able to function normally. If
8610 previous control does not exist, it is yet possible to use splitter as
8611 a resizeable panel (but set its initial Align value first - otherwise it
8612 is not set by default. Also, change Cursor property as You wish in that
8613 case, since it is not set too in case, when previous control does not
8614 exist).
8615 |<br>&nbsp;&nbsp;&nbsp;
8616 Additional parameters determine, which minimal size (width or height -
8617 correspondently to split direction) is allowed for left (top) control
8618 and to rest of client area of parent, correspondently. (It is possible
8619 later to set second control for checking its size with MinSizeNext
8620 value - using TControl.SecondControl property). If -1 passed,
8621 correspondent control size is not checked during dragging of splitter.
8622 Usually 0 is more suitable value (with this value, it is garantee, that
8623 splitter will be always available even if mouse was released far from the
8624 edge of form).
8625 |<br>&nbsp;&nbsp;&nbsp;
8626 It is possible for user to press Escape any time while dragging splitter
8627 to abort all adjustments made starting from left mouse button push and
8628 begin of drag the splitter. But remember please, that such event is
8629 controlled using timer, and therefore correspondent keyboard events
8630 are received by currently focused control. Be sure, that pressing Escape
8631 will not affect to any control on form, which could be focused, otherwise
8632 filter keyboard messages (by yourself) to prevent undesired handling of
8633 Escape key by certain controls while splitting. (Use Dragging property
8634 to check if splitter is dragging by user with mouse).
8635 |<br>&nbsp;&nbsp;&nbsp;
8636 See also:
8637 NewSplitterEx
8638 |#splitter }
8640 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
8641 EdgeStyle: TEdgeStyle ): PControl;
8642 {* |<#control>
8643 Creates splitter control. Difference from NewSplitter is what it is possible
8644 to determine if a splitter will be beveled or not. See also NewSplitter. }
8646 //[NewGroupbox DECLARATION]
8647 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
8648 {* |<#control>
8649 Creates group box control. Note, that to group radio items, group
8650 box is not necessary - any parent can play role of group for radio items.
8651 See also NewPanel. }
8653 //[NewCheckbox DECLARATION]
8654 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
8655 {* |<#control>
8656 Creates check box control. Special properties, methods, events:
8657 |#checkbox }
8659 function NewCheckBox3State( AParent: PControl; const Caption: String ): PControl;
8660 {* |<#control>
8661 Creates check box control with 3 states. Special properties, methods,
8662 events:
8663 |#checkbox }
8665 //[NewRadiobox DECLARATION]
8666 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
8667 {* |<#control>
8668 Creates radio box control. Alternative radio items must have the
8669 same parent window (regardless of its kind, either groupbox (NewGroupbox),
8670 panel (NewPanel) or form itself). Following properties, methods and events
8671 are specially for radiobox controls:
8672 |#radiobox }
8674 //[NewEditbox DECLARATION]
8675 function NewEditbox( AParent: PControl; Options: TEditOptions ): PControl;
8676 {* |<#control>
8677 Creates edit box control. To create multiline edit box, similar to
8678 TMemo in VCL, apply eoMultiline in Options. Following properties, methods,
8679 events are special for edit controls:
8680 |#edit }
8682 //[NewRichEdit DECLARATION]
8683 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
8684 {* |<#control>
8685 Creates rich text edit control. A rich edit control is a window in which
8686 the user can enter and edit text. The text can be assigned character and
8687 paragraph formatting, and can include embedded OLE objects. Rich edit
8688 controls provide a programming interface for formatting text. However, an
8689 application must implement any user interface components necessary to make
8690 formatting operations available to the user.
8691 |<br>&nbsp;&nbsp;&nbsp;
8692 Note: eoPassword, eoMultiline options have no effect for RichEdit control.
8693 Some operations are supersided with special versions of those, created
8694 especially for RichEdit, but in some cases it is necessary to use
8695 another properties and methods, specially designed for RichEdit (see
8696 methods and properties, which names are starting from RE_...).
8697 |<br>&nbsp;&nbsp;&nbsp;
8698 Following properties, methods, events are special for edit controls:
8699 |#richedit
8702 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
8703 {* |<#control>
8704 Like NewRichEdit, but to work with older RichEdit control version 1.0
8705 (window class 'RichEdit' forced to use instead of 'RichEdit20A', even
8706 if library RICHED20.DLL found and loaded successfully). One more
8707 difference - OleInit is not called, so the most of OLE capabilities
8708 of RichEdit could not working. }
8710 //[NewListbox DECLARATION]
8711 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
8712 {* |<#control>
8713 Creates list box control. Following properties, methods and events are
8714 special for Listbox:
8715 |#listbox }
8717 //[NewCombobox DECLARATION]
8718 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
8719 {* |<#control>
8720 Creates new combo box control. Note, that it is not possible to align
8721 combobox caLeft or caRight: this can cause infinit recursion in the
8722 application.
8723 |<br>Following properties, methods and events are
8724 special for Combobox:
8725 |#combo }
8727 //[_NewCommonControl DECLARATION]
8728 function _NewCommonControl( AParent: PControl; ClassName: PChar; Style: DWORD;
8729 Ctl3D: Boolean; Actions: PCommandActions ): PControl;
8731 //[NewProgressbar DECLARATION]
8732 function NewProgressbar( AParent: PControl ): PControl;
8733 {* |<#control>
8734 Creates progress bar control. Following properties are special for
8735 progress bar:
8736 |#progressbar
8737 See also NewProgressEx. }
8739 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
8740 {* |<#control>
8741 Can create progress bar with smooth style (progress is not segmented
8742 onto bricks) or/and vertical progress bar - using additional parameter.
8743 For list of properties, suitable for progress bars, see NewProgressbar. }
8745 //[NewListVew DECLARATION]
8746 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
8747 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
8748 {* |<#control>
8749 Creates list view control. It is very powerful control, which can partially
8750 compensate absence of grid controls (in lvsDetail view mode). Properties,
8751 methods and events, special for list view control are:
8752 |#listview }
8754 //[NewTreeView DECLARATION]
8755 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
8756 ImgListNormal, ImgListState: PImageList ): PControl;
8757 {* |<#control>
8758 Creates tree view control. See tree view methods and properties:
8759 |#treeview }
8761 //[NewTabControl DECLARATION]
8762 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
8763 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
8764 {* |<#control>
8765 Creates new tab control (like notebook). To place child control on a certain
8766 page of TabControl, use property Pages[ Idx ], for example:
8767 ! Label1 := NewLabel( TabControl1.Pages[ 0 ], 'Label1' );
8768 | &nbsp;&nbsp;&nbsp;
8769 To determine number of pages at run time, use property <D Count>;
8770 |<br> to determine which page is currently selected (or to change
8771 selection), use property <D CurrentIndex>;
8772 |<br> to feedback to switch between tabs assign your handler to OnSelChange
8773 event;
8774 |<br>Note, that by default, tab control is created with a border lowered to
8775 tab control's parent. To remove it, you can apply WS_EX_TRANSPARENT extended
8776 style (see TControl.ExStyle property), but painting of some child controls
8777 can be strange a bit in this case (no border drawing for edit controls was
8778 found, but not always...). You can also apply style WS_THICKFRAME (TControl.Style
8779 property) to make the border raised.
8780 |<br> Other methods and properties, suitable for tab control, are:
8781 |#tabcontrol }
8783 //[NewToolbar DECLARATION]
8784 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
8785 Bitmap: HBitmap; Buttons: array of PChar;
8786 BtnImgIdxArray: array of Integer ) : PControl;
8787 {* |<#control>
8788 Creates toolbar control. Bitmap must contain images for all buttons
8789 excluding separators (defined by string '-' in Buttons array), otherwise
8790 last buttons will no have images at all. Image width for every button
8791 is assumed to be equal to Bitmap height (if last of "squares" has
8792 insufficient width, it will not be used). To define fixed buttons, use
8793 characters '+' or '-' as a prefix for button string (even empty). To
8794 create groups of (radio-)buttons, use also '!' follow '+' or '-'. (These rules
8795 are similar used in menu creation). To define drop down button, use (as
8796 first) prefix '^'. (Do not forget to set <D OnTBDropDown> event for this
8797 case). If You want to assign images to buttons not in the same order
8798 how these are placed in Bitmap (or You use system bitmap), define for every
8799 button (in BtnImgIdxArray array) indexes for every button (excluding
8800 separator buttons). Otherwise, it is possible to define index only for first
8801 button (e.g., [0]). It is also possible to change TBImages[ ] property
8802 for such purpose, or do the same in method TBSetBtnImgIdx).
8803 |<br>
8804 Following properties, methods and event are specially designed to work with
8805 toolbar control:
8806 |#toolbar
8807 |<br>&nbsp;&nbsp;&nbsp;
8808 If your project uses Align property to align controls, this can conflict with
8809 toolbar native aligning. To solve such problem, place toolbar to parent panel,
8810 which has its own Align property assigned to desired value.
8811 |<br>
8812 To create toolbar with buttons, drawn from top to bottom, instead from left
8813 to right, combine caLeft / caRight in Align parameter and style tboWrapable
8814 when create toolbar. To adjust width of vertically aligned toolbar, it is
8815 possible to call ResizeParentLeft for it. E.g.:
8817 ! P0 := NewPanel( W, esRaised ) .SetSize( 30, 0 ) .SetAlign( caLeft );
8818 ! // ^^^^^^^^^^^^^^^^^ //////
8819 !TB := NewToolbar( P0, caLeft, [ tboNoDivider, tboWrapable ], DWORD(-1),
8820 ! // ////// ///////////
8821 ! [ ' ', ' ', ' ', '-', ' ', ' ' ],
8822 ! [ STD_FILEOPEN ] ).ResizeParentRight;
8823 !//Note, that caLeft is *must*, and tboWrapable style too. SetSize for
8824 !//parent panel is not necessary, but only if ResizeParentRight is called
8825 !//than for Toolbar.
8826 |<br><br>
8827 One more note: if You create toolbar without text labels (passing ' ' for
8828 each button You add), include also option tboTextRight to fix incorrect
8829 sizing of buttons under Windows9x.
8832 //[NewDateTimePicker DECLARATION]
8833 function NewDateTimePicker( AParent: PControl; Options: TDateTimePickerOptions )
8834 : PControl;
8835 {* |<#control>
8836 Creates date and time picker common control.
8841 { -- Constructor for Image List objet -- }
8843 //[NewImageList DECLARATION]
8844 function NewImageList( AOwner: PControl ): PImageList;
8845 {* Constructor of TImageList object. Unlike other non-visual objects, image list
8846 can be parented by TControl object (but this does not *must*), and in that
8847 case it is destroyed automatically when its parent control is destroyed.
8848 Every control can have several TImageList objects, linked to a simple list.
8849 But if any TImageList object is destroyed, all following ones are destroyed
8850 too (at least, now I implemented it so). }
8883 //[TIMER]
8884 type
8885 {++}(*TTimer = class;*){--}
8886 PTimer = {-}^{+}TTimer;
8887 { ----------------------------------------------------------------------
8889 TTimer object
8891 ----------------------------------------------------------------------- }
8892 //[TTimer DEFINITION]
8893 TTimer = object( TObj )
8894 {* Easy timer incapsulation object. Uses applet window to
8895 receive timer events. So, either assign your main form
8896 to Applet variable or create applet button object (and
8897 assign it to Applet) before enabling timer. }
8898 protected
8899 fHandle : Integer;
8900 fEnabled: Boolean;
8901 fInterval: Integer;
8902 fOnTimer: TOnEvent;
8903 procedure SetEnabled(const Value: Boolean); virtual;
8904 procedure SetInterval(const Value: Integer);
8905 protected
8906 {++}(*public*){--}
8907 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
8908 {* Destructor. }
8909 public
8910 property Handle : Integer read fHandle;
8911 {* Windows timer object handle. }
8912 property Enabled : Boolean read fEnabled write SetEnabled;
8913 {* True, is timer is on. Initially, always False. Before assigning True,
8914 make sure, that Applet global variable is assigned to applet object
8915 (NewApplet) or to form (NewForm). }
8916 property Interval : Integer read fInterval write SetInterval;
8917 {* Interval in milliseconds (1000 is default and means 1 second). }
8918 property OnTimer : TOnEvent read fOnTimer write fOnTimer;
8919 {* Event, which is called when time interval is over. }
8920 end;
8921 //[END OF TTimer DEFINITION]
8923 //[NewTimer DECLARATION]
8924 function NewTimer( Interval: Integer ): PTimer;
8925 {* Constructs initially disabled timer with interval 1000 (1 second). }
8928 //[MULTIMEDIA TIMER]
8929 type
8930 {++}(*TMMTimer = class;*){--}
8931 PMMTimer = {-}^{+}TMMTimer;
8933 //[TMMTimer DEFINITION]
8934 TMMTimer = object( TTimer )
8935 {* Multimedia timer incapsulation object. Does not require Applet or special
8936 window to handle it. System creates a thread for each high resolution
8937 timer, so using many such objects can degrade total PC performance. }
8938 protected
8939 FResolution: Integer;
8940 FPeriodic: Boolean;
8941 procedure SetEnabled(const Value: Boolean); {-}virtual;{+}{++}(*override;*){--}
8942 public
8943 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
8944 {* }
8945 property Resolution: Integer read FResolution write FResolution;
8946 {* Minimum timer resolution. The less the more accuracy (0 is exactly
8947 Interval milliseconds between timer shots). It is recommended to set
8948 this property greater to prevent entire system from reducing overhead.
8949 If you change this value, reset and then set Enabled again to apply
8950 changes. }
8951 property Periodic: Boolean read FPeriodic write FPeriodic;
8952 {* TRUE, if timer is periodic (default). Otherwise, timer is one-shot
8953 (set it Enabled every time in such case for each shot). If you change
8954 this property, reset and set Enabled property again to get effect. }
8955 end;
8956 //[END OF TMMTimer DEFINITION]
8958 //[NewMMTimer DECLARATION]
8959 function NewMMTimer( Interval: Integer ): PMMTimer;
8960 {* Creates multimedia timer object. Initially, it has Resolution = 0,
8961 Periodic = TRUE and Enabled = FALSE. Do not forget also to assign your
8962 event handler to OnTimer to do something on timer shot. }
8982 { -- TTrayIcon object -- }
8983 //[TRAYICON]
8985 type
8986 TOnTrayIconMouse = procedure( Sender: PObj; Message : Word ) of object;
8987 {* Event type to be called when Applet receives a message from an icon,
8988 added to the taskbar tray. }
8990 {++}(*TTrayIcon = class;*){--}
8991 PTrayIcon = {-}^{+}TTrayIcon;
8992 { ----------------------------------------------------------------------
8994 TTrayIcon - icon in tray area of taskbar
8996 ----------------------------------------------------------------------- }
8997 //[TTrayIcon DEFINITION]
8998 TTrayIcon = object(TObj)
8999 {* Object to place (and change) a single icon onto taskbar tray. }
9000 protected
9001 FIcon: HIcon;
9002 FActive: Boolean;
9003 FTooltip: String;
9004 FOnMouse: TOnTrayIconMouse;
9005 FControl: PControl;
9006 fAutoRecreate: Boolean;
9007 FNoAutoDeactivate: Boolean;
9008 FWnd: HWnd;
9009 procedure SetIcon(const Value: HIcon);
9010 procedure SetActive(const Value: Boolean);
9011 procedure SetTrayIcon( const Value : DWORD );
9012 procedure SetTooltip(const Value: String);
9013 procedure SetAutoRecreate(const Value: Boolean);
9014 protected
9015 {++}(*public*){--}
9016 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
9017 {* Destructor. Use Free method instead (as usual). }
9018 public
9019 property Icon : HIcon read FIcon write SetIcon;
9020 {* Icon to be shown on taskbar tray. If not set, value of Active
9021 property has no effect. It is also possible to assign a value
9022 to Icon property after assigning True to Active to install
9023 icon first time or to replace icon with another one (e.g. to
9024 get animation effect).
9025 |<br>&nbsp;&nbsp;&nbsp;
9026 Previously allocated icon (if any) is not deleted using
9027 DeleteObject. This is normal for icons, loaded from resource
9028 (e.g., by LoadIcon API call). But if icon was created (e.g.) by
9029 CreateIconIndirect, your code is responsible for destroying
9030 of it). }
9031 property Active : Boolean read FActive write SetActive;
9032 {* Set it to True to show assigned Icon on taskbar tray. Default
9033 is False. Has no effect if Icon property is not assigned.
9034 TrayIcon is deactivated automatically when Applet is finishing
9035 (but only if Applet window is used as a "parent" for tray
9036 icon object). }
9037 property Tooltip : String read FTooltip write SetTooltip;
9038 {* Tooltip string, showing automatically when mouse is moving
9039 over installed icon. Though "huge string" type is used, only
9040 first 63 characters are considered. Also note, that only in
9041 most recent versions of Windows multiline tooltips are supported. }
9042 property OnMouse : TOnTrayIconMouse read FOnMouse write FOnMouse;
9043 {* Is called then mouse message is taking place concerning installed
9044 icon. Only type of message can be obtained (e.g. WM_MOUSEMOVE,
9045 WM_LBUTTONDOWN etc.) }
9046 property AutoRecreate: Boolean read fAutoRecreate write SetAutoRecreate;
9047 {* If set to TRUE, auto-recreating of tray icon is proveded in case,
9048 when Explorer is restarted for some (unpredictable) reasons. Otherwise,
9049 your tray icon is disappeared forever, and if this is the single way
9050 to communicate with your application, the user nomore can achieve it. }
9051 property NoAutoDeactivate: Boolean read FNoAutoDeactivate write FNoAutoDeactivate;
9052 {* If set to true, tray icon is not removed from tray automatically on
9053 WM_CLOSE message receive by owner control. Set Active := FALSE in
9054 your code for such case before accepting closing the form. }
9055 property Wnd: HWnd read FWnd write FWnd;
9056 {* A window to use as a base window for tray icon messages. Overrides
9057 parent Control handle is assigned. Note, that if Wnd property used,
9058 message handling is not done automatically, and you should do this in
9059 your code, or at least for one tray icon object, call AttachProc2Wnd. }
9060 procedure AttachProc2Wnd;
9061 {* Call this method for a tray icon object in case if Wnd used rather then
9062 control. It is enough to call this method once for each Wnd used, even
9063 if several other tray icons are also based on the same Wnd. See also
9064 DetachProc2Wnd method. }
9065 procedure DetachProc2Wnd;
9066 {* Call this method to detach window procedure attached via AttachProc2Wnd.
9067 Do it once for a Wnd, used as a base to handle tray icon messages.
9068 Caution! If you do not call this method before destroying Wnd, the
9069 application will not functioning normally. }
9070 end;
9071 {* When You create invisible application, which should be represented by
9072 only the tray icon, prepare a handle for the window, resposible for
9073 messages handling. Remember, that window handle is created automatically
9074 only when a window is showing first time. If window's property Visible is
9075 set to False, You should to call CreateWindow manually.
9076 <br>
9077 There is a known bug exist with similar invisible tray-iconized applications.
9078 When a menu is activated in response to tray mouse event, if there was
9079 not active window, belonging to the application, the menu is not disappeared
9080 when mouse is clicked anywhere else. This bug is occure in Windows9x/ME.
9081 To avoid it, activate first your form window. This last window shoud have
9082 status visible (but, certainly, there are no needs to place it on visible
9083 part of screen - change its position, so it will not be visible for user,
9084 if You wish).
9085 <br>
9086 Also, to make your application "invisible" but until special event is occure,
9087 use Applet separate from the main form, and make for both Visible := False.
9088 This allows for You to make your form visible any time You wish, and without
9089 making application button visible if You do not wish.
9091 {= Êîãäà Âû äåëàåòå íåâèäèìîå ïðèëîæåíèå, êîòîðîå äîëæíî áûòü ïðåäñòàâëåíî
9092 òîëüêî èêîíêîé â òðåå, îáåñïå÷üòå íåíóëåâîé Handle äëÿ îêíà, îòâå÷àþùåãî
9093 çà îáðàáîòêó ñîîáùåíèé. Ïîìíèòå, ÷òî Handle îêíà ñîçäàåòñÿ àâòîìàòè÷åñêè
9094 òîëüêî â òîò ìîìåíò, êîãäà îíî äîëæíî ïîÿâèòüñÿ â ïåðâûé ðàç. Åñëè ñâîéñòâî
9095 îêíà Visible óñòàíîâëåíî â FALSE, íåîáõîäèìî âûçâàòü CreateWindow ñàìîñòîÿòåëüíî.
9096 <br>
9097 Ñóùåñòâóåò èçâåñòíûé BUG ñ ïîäîáíûìè íåâèäèìûìè ìèíèìèçèðîâàííûìè â òðåé
9098 ïðèëîæåíèÿìè. Êîãäà â îòâåò íà ñîáûòèå ìûøè àêòèâèçèðâàíî âûïàäàþùåå ìåíþ,
9099 îíî íå èñ÷åçàåò ïî ùåë÷êó ìûøè âíå ýòîãî ìåíþ. Ïðîèñõîäèò ýòî â Windows9x/ME.
9100 ÷òîáû ðåøèòü ýòó ïðîáëåìó, ñíà÷àëà àêòèâèçèðóéòå ñâîå îêíî (ôîðìó). Ýòî îêíî
9101 äîëæíî áûòü âèäèìûì (íî, êîíå÷íî, åãî ìîæíî ðàçìåñòèòü âíå ïðåäåëîâ âèäèìîé
9102 ÷àñòè ýêðàíà, òàê ÷òî ïîëüçîâàòåëþ åãî âèäíî íå áóäåò).
9103 <br>
9104 Òàê æå, ÷òîáû ñäåëàòü ïðèëîæåíèå íåâèäèìûì, ïî êðàéíåé ìåðå, ïîêà ýòî íå
9105 ïîòðåáóåòñÿ, èñïîëüçóéòå îòäåëüíûé ïðåäñòàâèòåëü êëàññà TControl - ãëîáàëüíóþ
9106 ïåðåìåííóþ Applet, è ïðèñâîéòå FALSE åå ñâîéñòâó Visible.
9108 //[END OF TTrayIcon DEFINITION]
9110 //[NewTrayIcon DECLARATION]
9111 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;
9112 {* Constructor of TTrayIcon object. Pass main form or applet as Wnd
9113 parameter. }
9126 //[JUST ONE]
9127 { -- JustOne -- }
9129 type
9130 TOnAnotherInstance = procedure( const CmdLine: String ) of object;
9131 {* Event type to use in JustOneNotify function. }
9133 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;
9134 {* Returns True, if this is a first instance. For all other instances
9135 (application is already running), False is returned. }
9137 function JustOneNotify( Wnd: PControl; const Identifier : String;
9138 const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;
9139 {* Returns True, if this is a first instance. For all other instances
9140 (application is already running), False is returned. If handler
9141 aOnAnotherInstance passed, it is called (in first instance) every time
9142 when another instance of an application is started, receiving command
9143 line used to run it. }
9161 { -- string (mainly) utility procedures and functions. -- }
9163 //[Message Box DECLARATIONS]
9164 function MsgBox( const S: String; Flags: DWORD ): DWORD;
9165 {* Displays message box with the same title as Applet.Caption. If applet
9166 is not running, and Applet global variable is not assigned, caption
9167 'Error' is displayed (but actually this is not an error - the system
9168 does so, if nil is passed as a title).
9169 |<br>&nbsp;&nbsp;&nbsp;
9170 Returns ID_... result (correspondently to flags passed (MB_OK, MBYESNO,
9171 etc. -> ID_OK, ID_YES, ID_NO, etc.) }
9172 procedure MsgOK( const S: String );
9173 {* Displays message box with the same title as Applet.Caption (or 'Error',
9174 if Applet is not running). }
9175 function ShowMsg( const S: String; Flags: DWORD ): DWORD;
9176 {* Displays message box like MsgBox, but uses Applet.Handle as a parent
9177 (so the message has no button on a task bar). }
9178 procedure ShowMessage( const S: String );
9179 {* Like ShowMsg, but has only styles MB_OK and MB_SETFOREGROUND. }
9180 procedure ShowMsgModal( const S: String );
9181 {* This message function can be used out of a message loop (e.g., after
9182 finishing the application). It is always modal.
9183 Actually, a form with word-wrap label (decorated as borderless edit
9184 box with btnFace color) and with OK button is created and shown modal.
9185 When a dialog is called from outside message loop, caption 'Information'
9186 is always displayed.
9187 Dialog form is automatically resized vertically to fit message text
9188 (but until screen height is achieved) and shown always centered on
9189 screen. The width is fixed (400 pixels).
9190 |<br>
9191 Do not use this function outside the message loop for case, when the
9192 Applet variable is not used in an application. }
9193 function ShowQuestion( const S: String; Answers: String ): Integer;
9194 {* Modal dialog like ShowMsgModal. It is based on KOL form, so it can
9195 be called also out of message loop, e.g. after finishing the
9196 application. Also, this function *must* be used in MDI applications
9197 in place of any dialog functions, based on MessageBox.
9198 |<br>
9199 The second parameter should be empty string or several possible
9200 answers separated by '/', e.g.: 'Yes/No/Cancel'. Result is
9201 a number answered, starting from 1. For example, if 'Cancel'
9202 was pressed, 3 will be returned.
9203 |<br>
9204 User can also press ESCAPE key, or close modal dialog. In such case
9205 -1 is returned. }
9206 function ShowQuestionEx( const S: String; Answers: String; CallBack: TOnEvent ): Integer;
9207 {* Like ShowQuestion, but with CallBack function, called just before showing
9208 the dialog. }
9209 procedure SpeakerBeep( Freq: Word; Duration: DWORD );
9210 {* On Windows NT, calls Windows.Beep. On Windows 9x, produces beep on speaker
9211 of desired frequency during given duration time (in milliseconds). }
9213 {++}(*
9214 function FormatMessage(dwFlags: DWORD; lpSource: Pointer; dwMessageId: DWORD; dwLanguageId: DWORD;
9215 lpBuffer: PChar; nSize: DWORD; Arguments: Pointer): DWORD; stdcall;
9216 *){--}
9217 function SysErrorMessage(ErrorCode: Integer): string;
9218 {* Creates and returns a string containing formatted system error message.
9219 It is possible then to display this message or write it to a log
9220 file, e.g.:
9221 ! ShowMsg( SysErrorMessage( GetLastError ) );
9225 |&R=<a name="%0"></a><font color=#FF8040><h1>%0</h1></font>
9226 <R 64-bit integer numbers>
9228 //[I64 TYPE]
9229 type
9230 I64 = record
9231 {* 64 bit integer record. Use it and correspondent functions below in KOL
9232 projects to avoid dependancy from Delphi version (earlier versions of
9233 Delphi had no Int64 type). }
9234 Lo, Hi: DWORD;
9235 end;
9236 PI64 = ^I64;
9237 {* }
9241 {$IFNDEF _D4orHigher}
9242 Int64 = I64;
9243 PInt64 = PI64;
9244 {$ENDIF}
9246 function MakeInt64( Lo, Hi: DWORD ): I64;
9247 {* }
9248 function Int2Int64( X: Integer ): I64;
9249 {* }
9250 procedure IncInt64( var I64: I64; Delta: Integer );
9251 {* I64 := I64 + Delta; }
9252 procedure DecInt64( var I64: I64; Delta: Integer );
9253 {* I64 := I64 - Delta; }
9254 function Add64( const X, Y: I64 ): I64;
9255 {* Result := X + Y; }
9256 function Sub64( const X, Y: I64 ): I64;
9257 {* Result := X - Y; }
9258 function Neg64( const X: I64 ): I64;
9259 {* Result := -X; }
9260 function Mul64i( const X: I64; Mul: Integer ): I64;
9261 {* Result := X * Mul; }
9262 function Div64i( const X: I64; D: Integer ): I64;
9263 {* Result := X div D; }
9264 function Mod64i( const X: I64; D: Integer ): Integer;
9265 {* Result := X mod D; }
9266 function Sgn64( const X: I64 ): Integer;
9267 {* Result := sign( X ); i.e.:
9268 |<br>
9269 if X < 0 then -1
9270 |<br>
9271 if X = 0 then 0
9272 |<br>
9273 if X > 0 then 1 }
9274 function Cmp64( const X, Y: I64 ): Integer;
9275 {* Result := sign( X - Y ); i.e.
9276 |<br>
9277 if X < Y then -1
9278 |<br>
9279 if X = Y then 0
9280 |<br>
9281 if X > Y then 1 }
9282 function Int64_2Str( X: I64 ): String;
9283 {* }
9284 function Str2Int64( const S: String ): I64;
9285 {* }
9286 function Int64_2Double( const X: I64 ): Double;
9287 {* }
9288 function Double2Int64( D: Double ): I64;
9293 <R Floating point numbers>
9296 const
9297 NAN = 0.0 / 0.0;
9299 {++}(*const NAN = 1e-100;*){--}
9302 function IsNan(const AValue: Double): Boolean;
9303 {* Checks is an argument passed is NAN. }
9305 function IntPower(Base: Extended; Exponent: Integer): Extended;
9306 {* Result := Base ^ Exponent; }
9308 //[String<->Double DECLARATIONS]
9309 function Str2Double( const S: String ): Double;
9310 {* }
9312 function Double2Str( D: Double ): String;
9313 {* }
9314 function Extended2Str( E: Extended ): String;
9315 {* }
9317 function Double2StrEx( D: Double ): String;
9318 {* experimental, do not use }
9320 function TruncD( D: Double ): Double;
9321 {* Result := trunc( D ) as Double;
9322 |<hr>
9338 <R Small bit arrays (max 32 bits in array)>
9339 See also TBits object.
9342 //[SMALL BIT ARRAYS DECLARATIONS]
9343 function GetBits( N: DWORD; first, last: Byte ): DWord;
9344 {* Retuns bits straing from <first> and to <last> inclusively. }
9345 function GetBitsL( N: DWORD; from, len: Byte ): DWord;
9346 {* Retuns len bits starting from index <from>.
9347 |<hr>
9359 <R Arithmetics, geometry and other utility functions>
9361 See also units KolMath.pas, CplxMath.pas and Err.pas.
9363 //[MulDiv DECLARATION]
9364 {$IFNDEF FPC}
9365 function MulDiv( A, B, C: Integer ): Integer;
9366 {* Returns A * B div C. Small and fast. }
9367 {$ENDIF}
9369 //[TMethod TYPE]
9370 type
9371 ///////////////////////////////////////////
9372 {$ifndef _D6orHigher} //
9373 ///////////////////////////////////////////
9374 TMethod = packed record
9375 {* Is defined here because using of VCL classes.pas unit is
9376 not recommended in XCL. This record type is used often
9377 to set/access event handlers, referring to a procedure
9378 of object (usually to set such event to an ordinal
9379 procedure setting Data field to nil. }
9380 Code: Pointer; // Pointer to method code.
9381 {* If used to fake assigning to event handler of type 'procedure
9382 of object' with ordinal procedure pointer, use symbol '@'
9383 before method:
9384 |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font face="Courier"><b>
9385 | Method.Code := @MyProcedure;
9386 |</b></font> }
9387 Data: Pointer; // Pointer to object, owning the method.
9388 {* To fake event of type 'procedure of object' with setting it to
9389 ordinal procedure assign here NIL; }
9390 end;
9391 {* When assigning TMethod record to event handler, typecast it with
9392 desired event type, e.g.:
9393 |<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font face="Courier"><b>
9394 | SomeObject.OnSomeEvent := TOnSomeEvent( Method );
9395 |</b></font><br> }
9396 ///////////////////////////////////////////
9397 {$endif} //
9398 ///////////////////////////////////////////
9399 PMethod = ^TMethod;
9400 {* }
9402 function MakeMethod( Data, Code: Pointer ): TMethod;
9403 {* Help function to construct TMethod record. Can be useful to
9404 assign regular type procedure/function as event handler for
9405 event, defined as object method (do not forget, that in that
9406 case it must have first dummy parameter to replace @Self,
9407 passed in EAX to methods of object). }
9409 //[Rectangles&Points DECLARATIONS]
9410 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;
9411 {* Use it instead of VCL Rect function }
9412 function RectsEqual( const R1, R2: TRect ): Boolean;
9413 {* Returns True if rectangles R1 and R2 have the same bounds }
9414 function RectsIntersected( const R1, R2: TRect ): Boolean;
9415 {* Returns TRUE if rectangles R1 and R2 have at least one common point.
9416 Note, that right and bottom bounds of rectangles are not their part,
9417 so, if such points are lying on that bounds, FALSE is returned. }
9418 function PointInRect( const P: TPoint; const R: TRect ): Boolean;
9419 {* Returns True if point P is located in rectangle R (including
9420 left and top bounds but without right and bottom bounds of the
9421 rectangle). }
9422 function MakePoint( X, Y: Integer ): TPoint;
9423 {* Use instead of VCL function Point }
9424 //[MakeFlags DECLARATION]
9425 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;
9426 {* }
9428 function MakeDateTimeRange( D1, D2: TDateTime ): TDateTimeRange;
9429 {* Returns TDateTimeRange from two TDateTime bounds. }
9431 //[Integer FUNCTIONS DECLARATIONS]
9432 procedure Swap( var X, Y: Integer );
9433 {* exchanging values }
9434 function Min( X, Y: Integer ): Integer;
9435 {* minimum of two integers }
9436 function Max( X, Y: Integer ): Integer;
9437 {* maximum of two integers }
9438 {$IFDEF REDEFINE_ABS}
9439 function Abs( X: Integer ): Integer;
9440 {* absolute value }
9441 {$ENDIF}
9442 function Sgn( X: Integer ): Integer;
9443 {* sign of X: if X < 0, -1 is returned, if > 0, then +1, otherwise 0. }
9444 function iSqrt( X: Integer ): Integer;
9445 {* square root
9446 |<hr>
9451 <R String to number and number to string conversions>
9453 //[Integer<->String DECLARATIONS]
9454 function Int2Hex( Value : DWord; Digits : Integer ) : String;
9455 {* Converts integer Value into string with hex number. Digits parameter
9456 determines minimal number of digits (will be completed by adding
9457 necessary number of leading zeroes). }
9458 function Int2Str( Value : Integer ) : String;
9459 {* Obvious. }
9460 function UInt2Str( Value: DWORD ): String;
9461 {* The same as Int2Str, but for unsigned integer value. }
9462 function Int2StrEx( Value, MinWidth: Integer ): String;
9463 {* Like Int2Str, but resulting string filled with leading spaces to provide
9464 at least MinWidth characters. }
9465 function Int2Rome( Value: Integer ): String;
9466 {* Represents number 1..8999 to Rome numer. }
9467 function Int2Ths( I : Integer ) : String;
9468 {* Converts integer into string, separating every three digits from each
9469 other by character ThsSeparator. (Convert to thousands). You }
9470 function Int2Digs( Value, Digits : Integer ) : String;
9471 {* Converts integer to string, inserting necessary number of leading zeroes
9472 to provide desired length of string, given by Digits parameter. If
9473 resulting string is greater then Digits, string is not truncated anyway. }
9474 function Num2Bytes( Value : Double ) : String;
9475 {* Converts double float to string, considering it as a bytes count.
9476 If Value is sufficiently large, number is represented in kilobytes (with
9477 following letter K), or in megabytes (M), gigabytes (G) or terabytes (T).
9478 Resulting string number is truncated to two decimals (.XX) or to one (.X),
9479 if the second is 0. }
9480 function S2Int( S: PChar ): Integer;
9481 {* Converts null-terminated string to Integer. Scanning stopped when any
9482 non-digit character found. Even empty string or string not containing
9483 valid integer number silently converted to 0. }
9484 function Str2Int(const Value : String) : Integer;
9485 {* Converts string to integer. First character, which can not be
9486 recognized as a part of number, regards as a separator. Even
9487 empty string or string without number silently converted to 0. }
9488 function Hex2Int( const Value : String) : Integer;
9489 {* Converts hexadecimal number to integer. Scanning is stopped
9490 when first non-hexadicimal character is found. Leading dollar ('$')
9491 character is skept (if present). Minus ('-') is not concerning as
9492 a sign of number and also stops scanning.}
9493 function cHex2Int( const Value : String) : Integer;
9494 {* As Hex2Int, but also checks for leading '0x' and skips it. }
9495 function Octal2Int( const Value: String ) : Integer;
9496 {* Converts octal number to integer. Scanning is stopped on first
9497 non-octal digit (any char except 0..7). There are no checking if
9498 there octal numer in the parameter. If the first char is not octal
9499 digit, 0 is returned. }
9500 function Binary2Int( const Value: String ) : Integer;
9501 {* Converts binary number to integer. Like Octal2Int, but only digits
9502 0 and 1 are allowed. }
9503 {$IFNDEF _FPC}
9504 function Format( const fmt: string; params: array of const ): String;
9505 {* Uses API call to wvsprintf, so does not understand extra formats,
9506 such as floating point, date/time, currency conversions. See list of
9507 available formats in win32.hlp (topic wsprintf).
9508 |<hr>
9512 <R Working with null-terminated and ansi strings>
9514 {$ENDIF _FPC}
9515 //[String FUNCTIONS DECLARATIONS]
9516 function StrComp(const Str1, Str2: PChar): Integer;
9517 {* Compares two strings fast. -1: Str1<Str2; 0: Str1=Str2; +1: Str1>Str2 }
9518 function StrComp_NoCase(const Str1, Str2: PChar): Integer;
9519 {* Compares two strings fast without case sensitivity.
9520 Returns: -1 when Str1<Str2; 0 when Str1=Str2; +1 when Str1>Str2 }
9521 function StrLComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
9522 {* Compare two strings (fast). Terminating 0 is not considered, so if
9523 strings are equal, comparing is continued up to MaxLen bytes.
9524 Since this, pass minimum of lengths as MaxLen. }
9525 function StrLComp_NoCase(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
9526 {* Compare two strings fast without case sensitivity.
9527 Terminating 0 is not considered, so if strings are equal,
9528 comparing is continued up to MaxLen bytes.
9529 Since this, pass minimum of lengths as MaxLen. }
9530 function StrCopy( Dest, Source: PChar ): PChar;
9531 {* Copy source string to destination (fast). Pointer to Dest is returned. }
9532 function StrCat( Dest, Source: PChar ): PChar;
9533 {* Append source string to destination (fast). Pointer to Dest is returned. }
9534 function StrLen(const Str: PChar): Cardinal;
9535 {* StrLen returns the number of characters in Str, not counting the null
9536 terminator. }
9537 function StrScanLen(Str: PChar; Chr: Char; Len: Integer): PChar;
9538 {* Fast scans string Str of length Len searching character Chr.
9539 Pointer to a character next to found or to Str[Len] (if no one found)
9540 is returned. }
9541 function StrScan(Str: PChar; Chr: Char): PChar;
9542 {* Fast search of given character in a string. Pointer to found character
9543 (or nil) is returned. }
9544 function StrRScan(const Str: PChar; Chr: Char): PChar;
9545 {* StrRScan returns a pointer to the last occurrence of Chr in Str. If Chr
9546 does not occur in Str, StrRScan returns NIL. The null terminator is
9547 considered to be part of the string. }
9548 function StrIsStartingFrom( Str, Pattern: PChar ): Boolean;
9549 {* Returns True, if string Str is starting from Pattern, i.e. if
9550 Copy( Str, 1, StrLen( Pattern ) ) = Pattern. Str must not be nil! }
9551 function StrIsStartingFromNoCase( Str, Pattern: PChar ): Boolean;
9552 {* Like StrIsStartingFrom above, but without case sensitivity. }
9553 function TrimLeft(const S: string): string;
9554 {* Removes spaces, tabulations and control characters from the starting
9555 of string S. }
9556 function TrimRight(const S: string): string;
9557 {* Removes spaces, tabulates and other control characters from the
9558 end of string S. }
9559 function Trim( const S : string): string;
9560 {* Makes TrimLeft and TrimRight for given string. }
9561 function RemoveSpaces( const S: String ): String;
9562 {* Removes all characters less or equal to ' ' in S and returns it. }
9563 procedure Str2LowerCase( S: PChar );
9564 {* Converts null-terminated string to lowercase (inplace). }
9565 function LowerCase(const S: string): string;
9566 {* Obvious. }
9567 function UpperCase(const S: string): string;
9568 {* Obvious. }
9569 function AnsiUpperCase(const S: string): string;
9570 {* Obvious. }
9571 function AnsiLowerCase(const S: string): string;
9572 {* Obvious. }
9573 {$IFNDEF _D2}
9574 {$IFNDEF _FPC}
9575 function WAnsiUpperCase(const S: WideString): WideString;
9576 {* Obvious. }
9577 function WAnsiLowerCase(const S: WideString): WideString;
9578 {* Obvious. }
9579 {$ENDIF _FPC}
9580 {$ENDIF _D2}
9581 function AnsiCompareStr(const S1, S2: string): Integer;
9582 {* AnsiCompareStr compares S1 to S2, with case-sensitivity. The compare
9583 operation is controlled by the current Windows locale. The return value
9584 is the same as for CompareStr. }
9585 function _AnsiCompareStr(S1, S2: PChar): Integer;
9586 {* The same, but for PChar ANSI strings }
9587 function AnsiCompareStrNoCase(const S1, S2: string): Integer;
9588 {* AnsiCompareStr compares S1 to S2, with case-sensitivity. The compare
9589 operation is controlled by the current Windows locale. The return value
9590 is the same as for CompareStr. }
9591 function _AnsiCompareStrNoCase(S1, S2: PChar): Integer;
9592 {* The same, but for PChar ANSI strings }
9593 function AnsiCompareText( const S1, S2: String ): Integer;
9594 {* }
9596 {$IFNDEF _FPC}
9597 function LStrFromPWCharLen(Source: PWideChar; Length: Integer): String;
9598 {* from Delphi5 - because D2 does not contain it. }
9599 function LStrFromPWChar(Source: PWideChar): String;
9600 {* from Delphi5 - because D2 does not contain it. }
9601 {$ENDIF _FPC}
9603 function CopyEnd( const S : String; Idx : Integer ) : String;
9604 {* Returns copy of source string S starting from Idx up to the end of
9605 string S. Works correctly for case, when Idx > Length( S ) (returns
9606 empty string for such case). }
9607 function CopyTail( const S : String; Len : Integer ) : String;
9608 {* Returns last Len characters of the source string. If Len > Length( S ),
9609 entire string S is returned. }
9610 procedure DeleteTail( var S : String; Len : Integer );
9611 {* Deletes last Len characters from string. }
9612 function IndexOfChar( const S : String; Chr : Char ) : Integer;
9613 {* Returns index of given character (1..Length(S)), or
9614 -1 if a character not found. }
9615 function IndexOfCharsMin( const S, Chars : String ) : Integer;
9616 {* Returns index (in string S) of those character, what is taking place
9617 in Chars string and located nearest to start of S. If no such
9618 characters in string S found, -1 is returned. }
9619 {$IFNDEF _D2}
9620 {$IFNDEF _FPC}
9621 function IndexOfWideCharsMin( const S, Chars : WideString ) : Integer;
9622 {* Returns index (in wide string S) of those wide character, what
9623 is taking place in Chars wide string and located nearest to start of S.
9624 If no such characters in string S found, -1 is returned. }
9625 {$ENDIF _FPC}
9626 {$ENDIF _D2}
9628 function IndexOfStr( const S, Sub : String ) : Integer;
9629 {* Returns index of given substring in source string S. If found,
9630 1..Length(S)-Length(Sub), if not found, -1. }
9631 function Parse( var S : String; const Separators : String ) : String;
9632 {* Returns first characters of string S, separated from others by
9633 one of characters, taking place in Separators string, assigning
9634 a tail of string (after found separator) to source string. If
9635 no separator characters found, source string S is returned, and
9636 source string itself becomes empty. }
9637 {$IFNDEF _FPC}
9638 {$IFNDEF _D2}
9639 function WParse( var S : WideString; const Separators : WideString ) : WideString;
9640 {* Returns first wide characters of wide string S, separated from others
9641 by one of wide characters, taking place in Separators wide string,
9642 assigning a tail of wide string (following found separator) to the
9643 source one. If there are no separator characters found, source wide
9644 string S is returned, and source wide string itself becomes empty. }
9645 {$ENDIF _D2}
9646 {$ENDIF _FPC}
9647 function ParsePascalString( var S : String; const Separators : String ) : String;
9648 {* Returns first characters of string S, separated from others by
9649 one of characters, taking place in Separators string, assigning
9650 a tail of string (after the found separator) to source string. If
9651 there are no separator characters found, the source string S is returned,
9652 and the source string itself becomes empty. Additionally: if the first (after
9653 a blank space) is the quote "'" or '#', pascal string is assumung first
9654 and is converted to usual string (without quotas) before analizing
9655 of other separators. }
9656 function String2PascalStrExpr( const S : String ) : String;
9657 {* Converts string to Pascal-like string expression (concatenation of
9658 strings with quotas and characters with leading '#'). }
9659 function StrEq( const S1, S2 : String ) : Boolean;
9660 {* Returns True, if LowerCase(S1) = LowerCase(S2). I.e., if strings
9661 are equal to each other without caring of characters case sensitivity
9662 (ASCII only). }
9663 function AnsiEq( const S1, S2 : String ) : Boolean;
9664 {* Returns True, if AnsiLowerCase(S1) = AnsiLowerCase(S2). I.e., if ANSI
9665 stringsare equal to each other without caring of characters case
9666 sensitivity. }
9667 {$IFNDEF _D2}
9668 {$IFNDEF _FPC}
9669 function WAnsiEq( const S1, S2 : WideString ) : Boolean;
9670 {* Returns True, if AnsiLowerCase(S1) = AnsiLowerCase(S2). I.e., if ANSI
9671 stringsare equal to each other without caring of characters case
9672 sensitivity. }
9673 {$ENDIF _FPC}
9674 {$ENDIF _D2}
9676 function StrIn( const S : String; const A : array of String ) : Boolean;
9677 {* Returns True, if S is "equal" to one of strings, taking place
9678 in A array. To check equality, StrEq function is used, i.e.
9679 comaprison is taking place without case sensitivity. }
9680 {$IFNDEF _FPC}
9681 {$IFNDEF _D2}
9682 function WStrIn( const S : WideString; const A : array of WideString ) : Boolean;
9683 {* Returns True, if S is "equal" to one of strings, taking place
9684 in A array. To check equality, WAnsiEq function is used, i.e.
9685 comaprison is taking place without case sensitivity. }
9686 {$ENDIF _D2}
9687 {$ENDIF _FPC}
9688 function StrIs( const S : String; const A : array of String; var Idx: Integer ) : Boolean;
9689 {* Returns True, if S is "equal" to one of strings, taking place
9690 in A array, and in such Case Idx also is assigned to an index of A element
9691 equal to S. To check equality, StrEq function is used, i.e.
9692 comaprison is taking place without case sensitivity. }
9693 function IntIn( Value: Integer; const List: array of Integer ): Boolean;
9694 {* Returns TRUE, if Value is found in a List. }
9695 function _StrSatisfy( S, Mask : PChar ) : Boolean;
9696 {* }
9697 function _2StrSatisfy( S, Mask: PChar ): Boolean;
9698 {* }
9699 function StrSatisfy( const S, Mask : String ) : Boolean;
9700 {* Returns True, if S is satisfying to a given Mask (which can contain
9701 wildcard symbols '*' and '?' interpeted correspondently as 'any
9702 set of characters' and 'single any character'. If there are no
9703 such wildcard symbols in a Mask, result is True only if S is maching
9704 to Mask string.) }
9705 function StrReplace( var S: String; const From, ReplTo: String ): Boolean;
9706 {* Replaces first occurance of From to ReplTo in S, returns True,
9707 if pattern From was found and replaced. }
9708 {$IFNDEF _FPC}
9709 {$IFNDEF _D2}
9710 function WStrReplace( var S: WideString; const From, ReplTo: WideString ): Boolean;
9711 {* Replaces first occurance of From to ReplTo in S, returns True,
9712 if pattern From was found and replaced. See also function StrReplace.
9713 This function is not available in Delphi2 (this version of Delphi
9714 does not support WideString type). }
9715 {$ENDIF _D2}
9716 {$ENDIF _FPC}
9718 function StrRepeat( const S: String; Count: Integer ): String;
9719 {* Repeats given string Count times. E.g., StrRepeat( 'A', 5 ) gives 'AAAAA'. }
9720 {$IFNDEF _FPC}
9721 {$IFNDEF _D2}
9722 function WStrRepeat( const S: WideString; Count: Integer ): WideString;
9723 {* Repeats given wide string Count times. E.g., StrRepeat( 'A', 5 ) gives 'AAAAA'. }
9724 {$ENDIF _D2}
9725 {$ENDIF _FPC}
9727 procedure NormalizeUnixText( var S: String );
9728 {* In the string S, replaces all occurances of character #10 (without leading #13)
9729 to the character #13. }
9731 function StrPCopy(Dest: PChar; const Source: string): PChar;
9732 {* Copyes Pascal-style string into null-terminaed one. }
9733 function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar;
9734 {* Copyes first MaxLen characters of Pascal-style string into
9735 null-terminated one. }
9737 function DelimiterLast( const Str, Delimiters: String ): Integer;
9738 {* Returns index of the last of delimiters given by same named parameter
9739 among characters of Str. If there are no delimiters found, length of
9740 Str is returned. This function is intended mainly to use in filename
9741 parsing functions. }
9742 function __DelimiterLast( Str, Delimiters: PChar ): PChar;
9743 {* Returns address of the last of delimiters given by Delimiters parameter
9744 among characters of Str. If there are no delimeters found, position of
9745 the null terminator in Str is returned. This function is intended
9746 mainly to use in filename parsing functions. }
9747 function SkipSpaces( P: PChar ): PChar;
9748 {* Skips all characters #1..' ' in a string.
9750 {$IFDEF F_P}
9751 function DummyStrFun( const S: String ): String;
9752 {$ENDIF}
9755 //[Memory FUNCTIONS DECLARATIONS]
9756 function CompareMem(P1, P2: Pointer; Length: Integer): Boolean;
9757 {* Fast compare of two memory blocks. }
9758 function AllocMem( Size : Integer ) : Pointer;
9759 {* Allocates global memory and unlocks it. }
9760 procedure DisposeMem( var Addr : Pointer );
9761 {* Locks global memory block given by pointer, and frees it.
9762 Does nothing, if the pointer is nil.
9763 |<hr>
9765 <R Text in clipboard operations>
9768 //[clipboard FUNCTIONS DECLARATIONS]
9769 function Clipboard2Text: String;
9770 {* If clipboard contains text, this function returns it for You. }
9771 {$IFNDEF _FPC}
9772 {$IFNDEF _D2}
9773 function Clipboard2WText: WideString;
9774 {* If clipboard contains text, this function returns it for You (as Unicode string). }
9775 {$ENDIF _D2}
9776 {$ENDIF _FPC}
9777 function Text2Clipboard( const S: String ): Boolean;
9778 {* Puts given string to a clipboard. }
9779 {$IFNDEF _FPC}
9780 {$IFNDEF _D2}
9781 function WText2Clipboard( const WS: WideString ): Boolean;
9782 {* Puts given Unicode string to a clipboard.
9783 |<hr>
9785 {$ENDIF _D2}
9786 {$ENDIF _FPC}
9790 //[Mnemonics FUNCTIONS DECLARATIONS]
9791 var SearchMnemonics: function ( const S: String ): String
9792 = {$IFDEF F_P} DummyStrFun {$ELSE} UpperCase {$ENDIF};
9793 MnemonicsLocale: Integer;
9795 procedure SupportAnsiMnemonics( LocaleID: Integer );
9796 {* Provides encoding to work with given locale. Call this global function to
9797 extend TControl.SupportMnemonics capability (also should be called for a form
9798 or for Applet variable).
9804 <R Date and time handling>
9806 //[TDateTime TYPE DEFINITION]
9807 type
9808 //TDateTime = Double; // well, it is already defined so in System.pas
9809 {* Basic date and time type. Integer part represents year and days (as is,
9810 i.e. 1-Jan-2000 is representing by value 730141, which is a number of
9811 days from 1-Jan-0001 to 1-Jan-2000 inclusively). Fractional part is
9812 representing hours, minutes, seconds and milliseconds of a day
9813 proportionally (like in VCL TDateTime type, e.g. 0.5 = 12:00, 0.25 = 6:00,
9814 etc.). }
9816 PDayTable = ^TDayTable;
9817 TDayTable = array[1..12] of Word;
9819 TDateFormat = ( dfShortDate, dfLongDate );
9820 {* Date formats available to use in formatting date/time to string. }
9821 TTimeFormatFlag = ( tffNoMinutes, tffNoSeconds, tffNoMarker, tffForce24 );
9822 {* Additional flags, used for formatting time. }
9823 TTimeFormatFlags = Set of TTimeFormatFlag;
9824 {* Set of flags, used for formatting time. }
9826 const
9827 MonthDays: array [Boolean] of TDayTable =
9828 ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
9829 (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));
9830 {* The MonthDays array can be used to quickly find the number of
9831 days in a month: MonthDays[IsLeapYear(Y), M]. }
9833 SecsPerDay = 24 * 60 * 60;
9834 {* Seconds per day. }
9835 MSecsPerDay = SecsPerDay * 1000;
9836 {* Milliseconds per day. }
9838 VCLDate0 = 693594;
9839 {* Value to convert VCL "date 0" to KOL "date 0" and back.
9840 This value corresponds to 30-Dec-1899, 0:00:00. So,
9841 to convert VCL date to KOL date, just subtract this
9842 value from VCL date. And to convert back from KOL date
9843 to VCL date, add this value to KOL date.}
9845 {++}(*
9846 procedure GetLocalTime(var lpSystemTime: TSystemTime); stdcall;
9847 procedure GetSystemTime(var lpSystemTime: TSystemTime); stdcall;
9848 *){--}
9850 //[Date&Time FUNCTIONS DECLARATIONS]
9851 function Now : TDateTime;
9852 {* Returns local date and time on running PC. }
9853 function Date: TDateTime;
9854 {* Returns todaylocal date. }
9855 procedure DecodeDateFully( DateTime: TDateTime; var Year, Month, Day, DayOfWeek: WORD );
9856 {* Decodes date. }
9857 procedure DecodeDate( DateTime: TDateTime; var Year, Month, Day: WORD );
9858 {* Decodes date. }
9859 function EncodeDate( Year, Month, Day: WORD; var DateTime: TDateTime ): Boolean;
9860 {* Encodes date. }
9861 function CompareSystemTime(const D1, D2 : TSystemTime) : Integer;
9862 {* Compares to TSystemTime records. Returns -1, 0, or 1 if, correspondantly,
9863 D1 < D2, D1 = D2 and D1 > D2. }
9864 procedure IncDays( var SystemTime : TSystemTime; DaysNum : Integer );
9865 {* Increases/decreases day in TSystemTime record onto given days count
9866 (can be negative). }
9867 procedure IncMonths( var SystemTime : TSystemTime; MonthsNum : Integer );
9868 {* Increases/decreases month number in TSystemTime record onto given
9869 months count (can be negative). Correct result is not garantee if
9870 day number is incorrect for newly obtained month. }
9871 function IsLeapYear(Year: Word): Boolean;
9872 {* Returns True, if given year is "leap" (i.e. has 29 days in the February). }
9873 function DayOfWeek(Date: TDateTime): Integer;
9874 {* Returns day of week (0..6) for given date. }
9875 function SystemTime2DateTime(const SystemTime : TSystemTime; var DateTime : TDateTime ) : Boolean;
9876 {* Converts TSystemTime record to XDateTime variable. }
9877 function DateTime2SystemTime(const DateTime : TDateTime; var SystemTime : TSystemTime ) : Boolean;
9878 {* Converts TDateTime variable to TSystemTime record. }
9879 function DateTime_System2Local( DTSys: TDateTime ): TDateTime;
9880 {* Converts DTSys representing system time (+0 Grinvich) to local time. }
9881 function DateTime_Local2System( DTLoc: TDateTime ): TDateTime;
9882 {* Converts DTLoc representing local time to system time (+0 Grinvich) }
9883 function CatholicEaster( nYear: Integer ): TDateTime;
9884 {* Returns date of catholic easter for given year. }
9886 procedure DivMod(Dividend: Integer; Divisor: Word; var Result, Remainder: Word);
9887 {* Dividing of integer onto divisor with obtaining both result of division
9888 and remainder. }
9890 function SystemDate2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
9891 const DfltDateFormat : TDateFormat; const DateFormat : PChar ) : String;
9892 {* Formats date, stored in TSystemTime record into string, using given locale
9893 and date/time formatting flags. (E.g.: GetUserDefaultLangID). }
9894 function SystemTime2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
9895 const Flags : TTimeFormatFlags; const TimeFormat : PChar ) : String;
9896 {* Formats time, stored in TSystemTime record into string, using given locale
9897 and date/time formatting flags. }
9899 function Date2StrFmt( const Fmt: String; D: TDateTime ): String;
9900 {* Represents date as a string correspondently to Fmt formatting string.
9901 See possible pictures in definition of the function Str2DateTimeFmt
9902 (the first part). If Fmt string is empty, default system date format
9903 for short date string used. }
9904 function Time2StrFmt( const Fmt: String; D: TDateTime ): String;
9905 {* Represents time as a string correspondently to Fmt formatting string.
9906 See possible pictures in definition of the function Str2DateTimeFmt
9907 (the second part). If Fmt string is empty, default system time format
9908 for short date string used. }
9909 function DateTime2StrShort( D: TDateTime ): String;
9910 {* Formats date and time to string in short date format using current user
9911 locale. }
9912 function Str2DateTimeFmt( const sFmtStr, sS: String ): TDateTime;
9913 {* Restores date or/and time from string correspondently to a format string.
9914 Date and time formatting string can contain following pictures (case
9915 sensitive):
9916 |<pre>
9917 DATE PICTURES
9918 d Day of the month as digits without leading zeros for single digit days.
9919 dd Day of the month as digits with leading zeros for single digit days
9920 ddd Day of the week as a 3-letter abbreviation as specified by a
9921 LOCALE_SABBREVDAYNAME value.
9922 dddd Day of the week as specified by a LOCALE_SDAYNAME value.
9923 M Month as digits without leading zeros for single digit months.
9924 MM Month as digits with leading zeros for single digit months
9925 MMM Month as a three letter abbreviation as specified by a LOCALE_SABBREVMONTHNAME value.
9926 MMMM Month as specified by a LOCALE_SMONTHNAME value.
9927 y Year represented only be the last digit.
9928 yy Year represented only be the last two digits.
9929 yyyy Year represented by the full 4 digits.
9930 gg Period/era string as specified by the CAL_SERASTRING value. The gg
9931 format picture in a date string is ignored if there is no associated era
9932 string. In Enlish locales, usual values are BC or AD.
9934 TIME PICTURES
9935 h Hours without leading zeros for single-digit hours (12-hour clock).
9936 hh Hours with leading zeros for single-digit hours (12-hour clock).
9937 H Hours without leading zeros for single-digit hours (24-hour clock).
9938 HH Hours with leading zeros for single-digit hours (24-hour clock).
9939 m Minutes without leading zeros for single-digit minutes.
9940 mm Minutes with leading zeros for single-digit minutes.
9941 s Seconds without leading zeros for single-digit seconds.
9942 ss Seconds with leading zeros for single-digit seconds.
9943 t One character–time marker string (usually P or A, in English locales).
9944 tt Multicharacter–time marker string (usually PM or AM, in English locales).
9945 |</pre>
9946 E.g., 'D, yyyy/MM/dd h:mm:ss'.
9947 See also Str2DateTimeShort function.
9949 function Str2DateTimeShort( const S: String ): TDateTime;
9950 {* Restores date and time from string correspondently to current user locale. }
9951 function Str2DateTimeShortEx( const S: String ): TDateTime;
9952 {* Like Str2DateTimeShort above, but uses locale defined date and time
9953 separators to avoid recognizing time as a date in some cases.
9954 |<hr>
9957 <R File and directory routines>
9960 //[OpenFile CONSTANTS]
9961 const
9962 ofOpenRead = $80000000;
9963 {* Use this flag (in combination with others) to open file for "read" only. }
9964 ofOpenWrite = $40000000;
9965 {* Use this flag (in combination with others) to open file for "write" only. }
9966 ofOpenReadWrite = $C0000000;
9967 {* Use this flag (in combination with others) to open file for "read" and "write". }
9968 ofShareExclusive = $00;
9969 {* Use this flag (in combination with others) to open file for exclusive use. }
9970 ofShareDenyWrite = $01;
9971 {* Use this flag (in combination with others) to open file in share mode, when
9972 only attempts to open it in other process for "write" will be impossible.
9973 I.e., other processes could open this file simultaneously for read only
9974 access. }
9975 ofShareDenyRead = $02;
9976 {* Use this flag (in combination with others) to open file in share mode, when
9977 only attempts to open it for "read" in other processes will be disabled.
9978 I.e., other processes could open it for "write" only access. }
9979 ofShareDenyNone = $03;
9980 {* Use this flag (in combination with others) to open file in full sharing mode.
9981 I.e. any process will be able open this file using the same share flag. }
9982 ofCreateNew = $100;
9983 {* Default creation disposition. Use this flag for creating new file (usually
9984 for write access. }
9985 ofCreateAlways = $200;
9986 {* Use this flag (in combination with others) to open existing or creating new
9987 file. If existing file is opened, it is truncated to size 0. }
9988 ofOpenExisting = $300;
9989 {* Use this flag (in combination with others) to open existing file only. }
9990 ofOpenAlways = $400;
9991 {* Use this flag (in combination with others) to open existing or create new
9992 (if such file is not yet exists). }
9993 ofTruncateExisting = $500;
9994 {* Use this flag (in combination with others) to open existing file and truncate
9995 it to size 0. }
9997 ofAttrReadOnly = $10000;
9998 {* Use this flag to create Read-Only file (?). }
9999 ofAttrHidden = $20000;
10000 {* Use this flag to create hidden file. }
10001 ofAttrSystem = $40000;
10002 {* Use this flag to create system file. }
10003 ofAttrTemp = $1000000;
10004 {* Use this flag to create temp file. }
10005 ofAttrArchive = $200000;
10006 {* Use this flag to create archive file. }
10007 ofAttrCompressed = $8000000;
10008 {* Use this flag to create compressed file. Has effect only on NTFS, and
10009 only if ofAttrCompressed is not specified also. }
10010 ofAttrOffline = $10000000;
10011 {* Use this flag to create offline file. }
10012 //[END OF OpenFileConstants]
10014 //[File FUNCTIONS DECLARATIONS]
10015 function FileCreate(const FileName: string; OpenFlags: DWord): THandle;
10016 {* Call this function to open existing or create new file. OpenFlags
10017 parameter can be a combination of up to three flags (by one from
10018 each group:
10019 |<table border=0>
10020 |&L=<tr><td valign=top>%0</td><td valign=top>
10021 |&E=</td></tr>
10022 <L ofOpenRead, ofOpenWrite, ofOpenReadWrite> - 1st group. Here You decide
10023 wish You open file for read, write or read-and-write operations; <E>
10024 <L ofShareExclusive, ofShareDenyWrite, ofShareDenyRead, ofShareDenyNone> -2nd
10025 group - sharing. Here You can mark out sharing mode, which is used to
10026 open file. <E>
10027 <L ofCreateNew, ofCreateAlways, ofOpenExisting, ofOpenAlways, ofTruncateExisting>
10028 - 3rd group - creation disposition. Here You determine, either to create new
10029 or open existing file and if to truncate existing or not.
10030 |</table> }
10031 function FileClose(Handle: THandle): Boolean;
10032 {* Call it to close opened earlier file. }
10033 function FileExists( const FileName: String ) : Boolean;
10034 {* Returns True, if given file exists.
10035 |<br>Note (by Dod):
10036 It is not documented in a help for GetFileAttributes, but it seems that
10037 under NT-based Windows systems, FALSE is always returned for files
10038 opened for excluseve use like pagefile.sys. }
10039 function FileRead(Handle: THandle; var Buffer; Count: DWord): DWord;
10040 {* Reads bytes from current position in file to buffer. Returns number of
10041 read bytes. }
10042 function File2Str(Handle: THandle): String;
10043 {* Reads file from current position to the end and returns result as ansi string. }
10045 function FileSeek(Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
10046 {* Changes current position in file. }
10047 function FileWrite(Handle: THandle; const Buffer; Count: DWord): DWord;
10048 {* Writes bytes from buffer to file from current position, extending its
10049 size if needed. }
10050 function FileEOF( Handle: THandle ) : Boolean;
10051 {* Returns True, if EOF is achieved during read operations or last byte is
10052 overwritten or append made to extend file during last write operation. }
10053 function FileFullPath( const FileName : String ) : String;
10054 {* Returns full path name for given file. Validness of source FileName path
10055 is not checked at all. }
10056 function FileShortPath( const FileName: String ): String;
10057 {* Returns short path to the file or directory. }
10058 function FileIconSystemIdx( const Path: String ): Integer;
10059 {* Returns index of the index of the system icon correspondent to the file or
10060 directory in system icon image list. }
10061 function FileIconSysIdxOffline( const Path: String ): Integer;
10062 {* The same as FileIconSystemIdx, but an icon is calculated for the file
10063 as it were offline (it is possible to get an icon for file even if
10064 it is not existing, on base of its extension only). }
10065 procedure LogFileOutput( const filepath, str: String );
10066 {* Debug function. Use it to append given string to the end of the given file. }
10068 function StrSaveToFile( const Filename, Str: String ): Boolean;
10069 {* Saves a string to a file without any changes. If file does not exists, it is
10070 created. If it exists, it is overriden. If operation failed, FALSE is returned. }
10071 function StrLoadFromFile( const Filename: String ): String;
10072 {* Reads entire file and returns its content as a string. If operation failed,
10073 an empty strinng is returned.
10074 |<br>by Sergey Shishmintzev: it is possible to pass Filename = 'CON' to
10075 read input from redirected console output. }
10077 function Mem2File( Filename: PChar; Mem: Pointer; Len: Integer ): Integer;
10078 {* Saves memory block to a file (if file exists it is overriden, created new if
10079 not exists). }
10080 function File2Mem( Filename: PChar; Mem: Pointer; MaxLen: Integer ): Integer;
10081 {* Loads file content to memory. }
10083 function FileSize( const Path: String ) : Integer;
10084 {* Returns file size in bytes without opening it. If file too large
10085 to represent its size as Integer, -1 is returned. }
10086 function GetUniqueFilename( PathName: string ) : String;
10087 {* If file given by PathName exists, modifies it to create unique
10088 filename in target folder and returns it. Modification is performed
10089 by incrementing last number in name (if name part of file does not
10090 represent a number, such number is generated and concatenated to
10091 it). E.g., if file aaa.aaa is already exist, the function checks
10092 names aaa1.aaa, aaa2.aaa, ..., aaa10.aaa, etc. For name abc123.ext,
10093 names abc124.ext, abc125.ext, etc. will be checked. }
10095 function FileTimeCompare( const FT1, FT2 : TFileTime ) : Integer;
10096 {* Compares time of file (createing, writing, accessing. Returns
10097 -1, 0, 1 if correspondantly FT1<FT2, FT1=FT2, FT1>FT2. }
10099 //[Directory FUNCTIONS DECLARATIONS]
10100 function GetStartDir: String;
10101 {* Returns path to directory where executable is located (regardless
10102 of current directory). }
10103 function DirectoryExists(const Name: string): Boolean;
10104 {* Returns True if given directory (folder) exists. }
10105 function DirectoryEmpty(const Name: String): Boolean;
10106 {* Returns True if given directory is not exists or empty. }
10108 function DirectorySize( const Path: String ): I64;
10109 -- moved after PDirList
10111 function DirectoryHasSubdirs( const Path: String ): Boolean;
10112 {* Returns TRUE if given directory exists and has subdirectories. }
10113 function CheckDirectoryContent( const Name: String; SubDirsOnly: Boolean; const Mask: String ): Boolean;
10114 {* Returns TRUE if directory does not contain files (or directories only)
10115 satisfying given mask. }
10117 //---------------------------------------------------------
10118 // Following functions/procedures are created by Edward Aretino:
10119 // IncludeTrailingPathDelimiter, ExcludeTrailingPathDelimiter,
10120 // ForceDirectories, CreateDir, ChangeFileExt
10121 //---------------------------------------------------------
10122 function IncludeTrailingPathDelimiter(const S: string): string;
10123 {* by Edward Aretino. Adds '\' to the end if it is not present. }
10124 function ExcludeTrailingPathDelimiter(const S: string): string;
10125 {* by Edward Aretino. Removes '\' at the end if it is present. }
10126 function ForceDirectories(Dir: String): Boolean;
10127 {* by Edward Aretino. Creates given directory if not present. All needed
10128 subdirectories are created if necessary. }
10129 function CreateDir(const Dir: string): Boolean;
10130 {* by Edward Aretino. Creates given directory. }
10131 function ChangeFileExt(FileName: String; const Extension: string): string;
10132 {* by Edward Aretino. Changes file extention. }
10134 function ExcludeTrailingChar( const S: String; C: Char ): String;
10135 {* If S is finished with character C, it is excluded. }
10136 function IncludeTrailingChar( const S: String; C: Char ): String;
10137 {* If S is not finished with character C, it is added. }
10139 function ExtractFilePath( const Path: String ) : String;
10140 {* Returns only path part from exact path to file. }
10141 function ExtractFileName( const Path: String ) : String;
10142 {* Extracts file name from exact path to file. }
10143 function ExtractFileNameWOext( const Path: String ) : String;
10144 {* Extracts file name from path to file or from filename. }
10145 function ExtractFileExt( const Path: String ) : String;
10146 {* Extracts extention from file name (returns it with dot '.' first) }
10147 function ReplaceFileExt( const Path, NewExt: String ): String;
10148 {* Returns a path with extension replaced to a given one. }
10149 function ExtractShortPathName( const Path: String ): String;
10150 {* }
10151 function FilePathShortened( const Path: String; MaxLen: Integer ): String;
10152 {* Returns shortened file path to fit MaxLen characters. }
10153 function FilePathShortenPixels( const Path: String; DC: HDC; MaxPixels: Integer ): String;
10154 {* Returns shortened file path to fit MaxPixels for a given DC. If you pass
10155 Canvas.Handle of any control or bitmap object, ensure that font is valid
10156 for it (or call TCanvas.RequiredState( FontValid ) method before. If DC passed
10157 = 0, call is equivalent to call FilePathShortened, and MaxPixels means in such
10158 case maximum number of characters. }
10159 function MinimizeName( const Path: String; DC: HDC; MaxPixels: Integer ): String;
10160 {* Exactly the same as MinimizeName in FileCtrl.pas (VCL). }
10162 function GetSystemDir: String;
10163 {* Returns path to windows system directory. }
10164 function GetWindowsDir : string;
10165 {* Returns path to Windows directory. }
10166 function GetWorkDir : string;
10167 {* Returns path to application's working directory. }
10168 function GetTempDir : string;
10169 {* Returns path to default temp folder (directory to place temporary files). }
10170 function CreateTempFile( const DirPath, Prefix: String ): String;
10171 {* Returns path to just created temporary file. }
10172 function GetFileListStr(FPath{e.g.'c:\tmp\'}, FMask{e.g.'*.*'}: string): string;
10173 {* List of files in string, separating each path from others with semicolon (';').
10174 E.g.: 'c:\tmp\unit1.dcu;c:\tmp\unit1.~pa' (for use with DeleteFile2Recycle())}
10175 function DeleteFiles( const DirPath: String ): Boolean;
10176 {* Deletes files by file mask (given with wildcards '*' and '?'). }
10177 function DeleteFile2Recycle( const Filename : String ) : Boolean;
10178 {* Deletes file to recycle bin. This operation can be very slow, when
10179 called for a single file. To delete group of files at once (fast),
10180 pass a list of paths to files to be deleted, separating each path
10181 from others with semicolon (';'). E.g.: 'unit1.dcu;unit1.~pa'
10182 |<br>
10183 FALSE is returned only in case when at least one file was not deleted
10184 successfully.
10185 |<br>
10186 Note, that files are deleted not to recycle bin, if wildcards are
10187 used or not fully qualified paths to files. }
10188 function CopyMoveFiles( const FromList, ToList: String; Move: Boolean ): Boolean;
10189 {* }
10191 function DiskFreeSpace( const Path: String ): I64; {+}
10192 {* Returns disk free space in bytes. Pass a path to root directory,
10193 e.g. 'C:\'.
10194 |<hr>
10205 <R Wrappers to registry API functions>
10207 These functions can be used independently to simplify access to Windows
10208 registry. }
10210 //[Registry FUNCTIONS DECLARATIONS]
10211 {++}(*
10212 function RegSetValueEx(hKey: HKEY; lpValueName: PChar;
10213 Reserved: DWORD; dwType: DWORD; lpData: Pointer; cbData: DWORD): Longint; stdcall;
10214 *){--}
10215 function RegKeyOpenRead( Key: HKey; const SubKey: String ): HKey;
10216 {* Opens registry key for read operations (including enumerating of subkeys).
10217 Pass either handle of opened earlier key or one of constans
10218 HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS
10219 as a first parameter. If not successful, 0 is returned. }
10220 function RegKeyOpenWrite( Key: HKey; const SubKey: String ): HKey;
10221 {* Opens registry key for write operations (including adding new values or
10222 subkeys), as well as for read operations too. See also RegKeyOpenRead. }
10223 function RegKeyOpenCreate( Key: HKey; const SubKey: String ): HKey;
10224 {* Creates and opens key. }
10225 function RegKeyGetStr( Key: HKey; const ValueName: String ): String;
10226 {* Reads key, which must have type REG_SZ (null-terminated string). If
10227 not successful, empty string is returned. This function as well as all
10228 other registry manipulation functions, does nothing, if Key passed is 0
10229 (without producing any error). }
10230 function RegKeyGetStrEx( Key: HKey; const ValueName: String ): String;
10231 {* Like RegKeyGetStr, but accepts REG_EXPAND_SZ type, expanding all
10232 environment variables in resulting string.
10233 |<br>
10234 Code provided by neuron, e-mailto:neuron@hollowtube.mine.nu }
10235 function RegKeyGetDw( Key: HKey; const ValueName: String ): DWORD;
10236 {* Reads key value, which must have type REG_DWORD. If ValueName passed
10237 is '' (empty string), unnamed (default) value is reading. If not
10238 successful, 0 is returned. }
10239 function RegKeySetStr(Key: HKey; const ValueName: String; const Value: String ): Boolean;
10240 {* Writes new key value as null-terminated string (type REG_SZ). If not
10241 successful, returns False. }
10242 function RegKeySetStrEx( Key: HKey; const ValueName: string; const Value: string;
10243 expand: boolean): Boolean;
10244 {* Writes new key value as REG_SZ or REG_EXPAND_SZ. - by neuron, e-mailto:neuron@hollowtube.mine.nu }
10245 function RegKeySetDw( Key: HKey; const ValueName: String; Value: DWORD ): Boolean;
10246 {* Writes new key value as dword (with type REG_DWORD). Returns False,
10247 if not successful. }
10248 procedure RegKeyClose( Key: HKey );
10249 {* Closes key, opened using RegKeyOpenRead or RegKeyOpenWrite. (But does
10250 nothing, if Key passed is 0). }
10251 function RegKeyDelete( Key: HKey; const SubKey: String ): Boolean;
10252 {* Deletes key. Does nothing if key passed is 0 (returns FALSE). }
10253 function RegKeyDeleteValue( Key: HKey; const SubKey: String ): Boolean;
10254 {* Deletes value. - by neuron, e-mailto:neuron@hollowtube.mine.nu }
10255 function RegKeyExists( Key: HKey; const SubKey: String ): Boolean;
10256 {* Returns TRUE, if given subkey exists under given Key. }
10257 function RegKeyValExists( Key: HKey; const ValueName: String ): Boolean;
10258 {* Returns TRUE, if given value exists under the Key.
10260 function RegKeyValueSize( Key: HKey; const ValueName: String ): Integer;
10261 {* Returns a size of value. This is a size of buffer needed to store
10262 registry key value. For string value, size returned is equal to a
10263 length of string plus 1 for terminated null character. }
10264 function RegKeyGetBinary( Key: HKey; const ValueName: String; var Buffer; Count: Integer ): Integer;
10265 {* Reads binary data from a registry, writing it to the Buffer.
10266 It is supposed that size of Buffer provided is at least Count bytes.
10267 Returned value is actul count of bytes read from the registry and written
10268 to the Buffer.
10269 |<br>
10270 This function can be used to get data of any type from the registry, not
10271 only REG_BINARY. }
10272 function RegKeySetBinary( Key: HKey; const ValueName: String; const Buffer; Count: Integer ): Boolean;
10273 {* Stores binary data in the registry. }
10274 function RegKeyGetDateTime(Key: HKey; const ValueName: String): TDateTime;
10275 {* Returns datetime variable stored in registry in binary format. }
10276 function RegKeySetDateTime(Key: HKey; const ValueName: String; DateTime: TDateTime): Boolean;
10277 {* Stores DateTime variable in the registry. }
10280 //-------------------------------------------------------
10281 // registry functions by Valerian Luft <luft@valerian.de>
10282 //-------------------------------------------------------
10283 function RegKeyGetSubKeys( const Key: HKEY; List: PStrList): Boolean;
10284 {* The function enumerates subkeys of the specified open registry key.
10285 True is returned, if successful.
10287 function RegKeyGetValueNames(const Key: HKEY; List: PStrList): Boolean;
10288 {* The function enumerates value names of the specified open registry key.
10289 True is returned, if successful.
10291 function RegKeyGetValueTyp (const Key:HKEY; const ValueName: String) : DWORD;
10292 {* The function receives the type of data stored in the specified value.
10293 |<br>
10294 If the function fails, the return value is the Key value.
10295 |<br>
10296 If the function succeeds, the return value return will be one of the following:
10297 |<br>
10298 REG_BINARY , REG_DWORD, REG_DWORD_LITTLE_ENDIAN,
10299 REG_DWORD_BIG_ENDIAN, REG_EXPAND_SZ, REG_LINK , REG_MULTI_SZ,
10300 REG_NONE, REG_RESOURCE_LIST, REG_SZ
10303 |<hr>
10323 <R Data sorting (quicksort implementation)>
10324 This part contains implementation of 'quick sort' algorithm,
10325 based on following code:
10327 |<pre>
10328 | TQSort by Mike Junkin 10/19/95.
10329 | DoQSort routine adapted from Peter Szymiczek's QSort procedure which
10330 | was presented in issue#8 of The Unofficial Delphi Newsletter.
10332 | TQSort changed by Vladimir Kladov (Mr.Bonanzas) to allow 32-bit
10333 | sorting (of big arrays with more than 64K elements).
10334 |</pre>
10336 Finally, this sort procedure is adapted to XCL (and then to KOL)
10337 requirements (no references to SysUtils, Classes etc. TQSort object
10338 is transferred to a single procedure call and DoQSort method is
10339 renamed to SortData - which is a regular procedure now). }
10341 //[Sorting TYPES]
10342 type
10343 TCompareEvent = function (const Data: Pointer; const e1,e2 : Dword) : Integer;
10344 {* Event type to define comparison function between two elements of an array.
10345 This event handler must return -1 or +1 (correspondently for cases e1<e2
10346 and e2>e2). Items are enumerated from 0 to uNElem. }
10347 TSwapEvent = procedure (const Data : Pointer; const e1,e2 : Dword);
10348 {* Event type to define swap procedure which is swapping two elements of an
10349 array. }
10351 //[SortData FUNCTIONS DECLARATIONS]
10352 procedure SortData( const Data: Pointer; const uNElem: Dword;
10353 const CompareFun: TCompareEvent;
10354 const SwapProc: TSwapEvent );
10355 {* Call it to sort any array of data of any kind, passing total
10356 number of items in an array and two defined (regular) function
10357 and procedure to perform custom compare and swap operations.
10358 First procedure parameter is to pass it to callback function
10359 CompareFun and procedure SwapProc. Items are enumerated from
10360 0 to uNElem-1. }
10362 procedure SortIntegerArray( var A : array of Integer );
10363 {* procedure to sort array of integers. }
10365 procedure SortDwordArray( var A : array of DWORD );
10366 {* Procedure to sort array of unsigned 32-bit integers.
10367 |<hr>
10382 { -- directory list object -- }
10383 //[DirList Object]
10385 type
10386 TDirItemAction = ( diSkip, diAccept, diCancel );
10387 TOnDirItem = procedure( Sender: PObj; var DirItem: TWin32FindData; var Accept: TDirItemAction )
10388 of object;
10389 TSortDirRules = ( sdrNone, sdrFoldersFirst, sdrCaseSensitive, sdrByName, sdrByExt,
10390 sdrBySize, sdrBySizeDescending, sdrByDateCreate, sdrByDateChanged,
10391 sdrByDateAccessed );
10392 {* List of rules (options) to sort directories. Rules are passed to Sort
10393 method in an array, and first placed rules are applied first. }
10395 {++}(*TDirList = class;*){--}
10396 PDirList = {-}^{+}TDirList;
10397 { ----------------------------------------------------------------------
10399 TDirList - Directory scanning
10401 ----------------------------------------------------------------------- }
10402 //[TDirList DEFINITION]
10403 TDirList = object( TObj )
10404 {* Allows easy directory scanning. This is not visual object, but
10405 storage to simplify working with directory content. }
10406 protected
10407 FList : PList;
10408 FPath: string;
10409 fFilters: PStrList;
10410 fOnItem: TOnDirItem;
10411 function Get(Idx: Integer): PWin32FindData;
10412 function GetCount: Integer;
10413 function GetNames(Idx: Integer): string;
10414 function GetIsDirectory(Idx: Integer): Boolean;
10415 protected
10416 function SatisfyFilter( FileName : PChar; FileAttr, FindAttr : DWord ) : Boolean;
10417 {++}(*public*){--}
10418 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10419 {* Destructor. As usual, call Free method to destroy an object. }
10420 public
10421 property Items[ Idx : Integer ] : PWin32FindData read Get; default;
10422 {* Full access to scanned items (files and subdirectories). }
10423 property IsDirectory[ Idx: Integer ]: Boolean read GetIsDirectory;
10424 {* Returns TRUE, if specified item represents a directory, not a file. }
10425 property Count : Integer read GetCount;
10426 {* Number of items. }
10427 property Names[ Idx : Integer ] : string read GetNames;
10428 {* Full long names of directory items. }
10429 property Path : string read FPath;
10430 {* Path of scanned directory. }
10431 procedure Clear;
10432 {* Call it to clear list of files. }
10433 procedure ScanDirectory( const DirPath, Filter : String; Attr : DWord );
10434 {* Call it to rescan directory or to scan another directory content
10435 (method Clear is called first). Pass path to directory, file filter
10436 and attributes to scan directory immediately.
10437 |<br>&nbsp;&nbsp;&nbsp;
10438 Note: Pass FILE_ATTRIBUTE_... constants or-combination as Attr
10439 parameter. If 0 passed, both files and directories are listed. }
10440 procedure ScanDirectoryEx( const DirPath, Filters : String; Attr : DWord );
10441 {* Call it to rescan directory or to scan another directory content
10442 (method Clear is called first). Pass path to directory, file filter
10443 and attributes to scan directory immediately.
10444 |<br>&nbsp;&nbsp;&nbsp;
10445 Note: Pass FILE_ATTRIBUTE_... constants or-combination as Attr
10446 parameter. }
10447 procedure Sort( Rules : array of TSortDirRules );
10448 {* Sorts directory entries. If empty rules array passed, default rules
10449 array DefSortDirRules is used. }
10450 function FileList( const Separator {e.g.: ';', or #13}: String;
10451 Dirs, FullPaths: Boolean ): String;
10452 {* Returns a string containing all names separated with Separator.
10453 If Dirs=FALSE, only files are returned. }
10454 property OnItem: TOnDirItem read fOnItem write fOnItem;
10455 {* This event is called on reading each item while scanning directory.
10456 To use it, first create PDirList object with empty path to scan, then
10457 assign OnItem event and call ScanDirectory with correct path. }
10458 end;
10459 //[END OF TDirList DEFINITION]
10461 //[NewDirList DECLARATIONS]
10462 function NewDirList( const DirPath, Filter: String; Attr: DWORD ): PDirList;
10463 {* Creates directory list object using easy one-string filter. If Attr = FILE_ATTRIBUTE_NORMAL,
10464 only files are scanned without directories. If Attr = 0, both files and
10465 directories are listed. }
10467 function NewDirListEx( const DirPath, Filters: String; Attr: DWORD ): PDirList;
10468 {* Creates directory list object using several filters, separated by ';'.
10469 Filters starting from '^' consider to be anti-filters, i.e. files,
10470 satisfying to those masks, are skept during scanning. }
10472 const DefSortDirRules : array[ 0..3 ] of TSortDirRules = ( sdrFoldersFirst,
10473 sdrByName, sdrBySize, sdrByDateCreate );
10474 {* Default rules to sort directory entries. }
10476 //[DirectorySize DECLARATION]
10478 function DirectorySize( const Path: String ): I64;
10479 {* Returns directory size in bytes as large 64 bit integer. }
10483 //[OpenSaveDialog OPTIONS]
10484 type
10485 TOpenSaveOption = ( OSCreatePrompt,
10486 OSExtensionDiffent,
10487 OSFileMustExist,
10488 OSHideReadonly,
10489 OSNoChangedir,
10490 OSNoReferenceLinks,
10491 OSAllowMultiSelect,
10492 OSNoNetworkButton,
10493 OSNoReadonlyReturn,
10494 OSOverwritePrompt,
10495 OSPathMustExist,
10496 OSReadonly,
10497 OSNoValidate
10498 //{$IFDEF OpenSaveDialog_Extended}
10500 OSTemplate,
10501 OSHook
10502 //{$ENDIF}
10504 TOpenSaveOptions = set of TOpenSaveOption;
10505 {* Options available for TOpenSaveDialog. }
10507 {++}(*TOpenSaveDialog = class;*){--}
10508 POpenSaveDialog = {-}^{+}TOpenSaveDialog;
10509 { ----------------------------------------------------------------------
10511 TOpenSaveDialog
10513 ----------------------------------------------------------------------- }
10514 //[TOpenSaveDialog DEFINITION]
10515 TOpenSaveDialog = object( TObj )
10516 {* Object to show standard Open/Save dialog. Initially provided
10517 for XCL by Carlo Kok. }
10518 protected
10519 FFilter : String;
10520 fFilterIndex : Integer;
10521 fOpenDialog : Boolean;
10522 FInitialDir : String;
10523 FDefExtension : String;
10524 FFilename : string;
10525 FTitle : string;
10526 FOptions : TOpenSaveOptions;
10527 fWnd: THandle;
10528 public
10529 {$IFDEF OpenSaveDialog_Extended}
10530 TemplateName: String;
10531 HookProc: Pointer;
10532 {$ENDIF}
10533 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10534 {* destructor }
10535 Function Execute : Boolean;
10536 {* Call it after creating to perform selecting of file by user. }
10537 property Filename : String read FFilename write FFileName;
10539 Filename is seperated by #13 when multiselect is true and the first
10540 file, is the path of the files selected.
10541 |<pre>
10542 | C:\Projects
10543 | Test1.Dpr
10544 | Test2.Dpr
10545 |</pre>
10546 If only one file is selected, it is provided as (e.g.)
10547 C:\Projects\Test1.dpr
10548 |<br> For case when OSAllowMultiselect option used, after each
10549 call initial value for a Filename containing several files prevents
10550 system from opening the dialog. To fix this, assign another initial
10551 value to Filename property in your code, when you use multiselect.
10553 property InitialDir : string read FInitialDir write FInitialDir;
10554 {* Initial directory path. If not set, current directory (usually
10555 directory when program is started) is used. }
10556 property Filter : String read FFilter write FFilter;
10557 {* A list of pairs of filter names and filter masks, separated with '|'.
10558 If a mask contains more than one mask, it should be separated with ';'.
10559 E.g.:
10560 ! 'All files|*.*|Text files|*.txt;*.1st;*.diz' }
10561 property FilterIndex : Integer read FFilterIndex write FFilterIndex;
10562 {* Index of default filter mask (0 by default, which means "first"). }
10563 property OpenDialog : Boolean read FOpenDialog write FOpenDialog;
10564 {* True, if "Open" dialog. False, if "Save" dialog. True is default. }
10565 property Title : String read Ftitle write Ftitle;
10566 {* Title for dialog. }
10567 property Options : TOpenSaveOptions read FOptions write FOptions;
10568 {* Options. }
10569 property DefExtension : String read FDefExtension write FDefExtension;
10570 {* Default extention. Set it to desired extension without leading period,
10571 e.g. 'txt', but not '.txt'. }
10572 property WndOwner: THandle read fWnd write fWnd;
10573 {* Owner window handle. If not assigned, Applet.Handle is used (whenever
10574 possible). Assign it, if your application has stay-on-top forms, and
10575 a separate Applet object is used. }
10576 end;
10577 //[END OF TOpenSaveDialog DEFINITION]
10579 //[Default OpenSaveDialog OPTIONS]
10580 const DefOpenSaveDlgOptions: TOpenSaveOptions = [ OSHideReadonly,
10581 OSOverwritePrompt, OSFileMustExist, OSPathMustExist ];
10583 //[NewOpenSaveDialog DECLARATION]
10584 function NewOpenSaveDialog( const Title, StrtDir: String;
10585 Options: TOpenSaveOptions ): POpenSaveDialog;
10586 {* Creates object, which can be used (several times) to open file(s)
10587 selecting dialog. }
10591 //[OpenDirectory Object]
10592 type
10593 {++}(*TOpenDirDialog = class;*){--}
10594 POpenDirDialog = {-}^{+}TOpenDirDialog;
10596 TOpenDirOption = ( odBrowseForComputer, odBrowseForPrinter, odDontGoBelowDomain,
10597 odOnlyFileSystemAncestors, odOnlySystemDirs, odStatusText,
10598 odBrowseIncludeFiles, odEditBox, odNewDialogStyle );
10599 {* Flags available for TOpenDirDialog object. }
10600 // odfStatusText - do not support status callback
10601 TOpenDirOptions = set of TOpenDirOption;
10602 {* Set of all flags used to control ZOpenDirDialog class. }
10604 TOnODSelChange = procedure( Sender: POpenDirDialog; NewSelDir: PChar;
10605 var EnableOK: Integer; var StatusText: String )
10606 of object;
10607 {* Event type to be called when user select another directory in OpenDirDialog.
10608 Set EnableOK to -1 to disable OK button, or to +1 to enable it.
10609 It is also possible to set new StatusText string. }
10611 { ----------------------------------------------------------------------
10613 TOpenDirDialog
10615 ----------------------------------------------------------------------- }
10616 //[TOpenDirDialog DEFINITION]
10617 TOpenDirDialog = object( TObj )
10618 {* Dialog for open directories, uses SHBrowseForFolder. }
10619 protected
10620 FTitle: String;
10621 FOptions: TOpenDirOptions;
10622 FCallBack: Pointer;
10623 FCenterProc: procedure( Wnd: HWnd );
10624 FBuf : array[ 0..MAX_PATH ] of Char;
10625 FInitialPath: String;
10626 FCenterOnScreen: Boolean;
10627 FDoSelChanged: procedure( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ); stdcall;
10628 FOnSelChanged: TOnODSelChange;
10629 FStatusText: String;
10630 FWnd: HWnd;
10631 function GetPath: String;
10632 procedure SetInitialPath(const Value: String);
10633 procedure SetCenterOnScreen(const Value: Boolean);
10634 procedure SetOnSelChanged(const Value: TOnODSelChange);
10635 function GetInitialPath: String;
10636 public
10637 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10638 {* destructor }
10639 function Execute : Boolean;
10640 {* Call it to select directory by user. Returns True, if operation was
10641 not cancelled by user. }
10642 property Title : String read FTitle write FTitle;
10643 {* Title for a dialog. }
10644 property Options : TOpenDirOptions read FOptions write FOptions;
10645 {* Option flags. }
10646 property Path : String read GetPath;
10647 {* Resulting (selected by user) path. }
10648 property InitialPath: String read GetInitialPath write SetInitialPath;
10649 {* Set this property to a path of directory to be selected initially
10650 in a dialog. }
10651 property CenterOnScreen: Boolean read FCenterOnScreen write SetCenterOnScreen;
10652 {* Set it to True to center dialog on screen. }
10653 property OnSelChanged: TOnODSelChange read FOnSelChanged write SetOnSelChanged;
10654 {* This event is called every time, when user selects another directory.
10655 It is possible to eneble/disable OK button in dialog and/or change
10656 dialog status text in responce to event. }
10657 property WndOwner: HWnd read FWnd write FWnd;
10658 {* Owner window. If you want to provide your dialog visible over stay-on-top
10659 form, fire it as a child of the form, assigning the handle of form window
10660 to this property first. }
10661 end;
10662 //[END OF TOpenDirDialog DEFINITION]
10664 //[NewOpenSaveDialog DECLARATION]
10665 function NewOpenDirDialog( const Title: String; Options: TOpenDirOptions ):
10666 POpenDirDialog;
10667 {* Creates object, which can be used (several times) to open directory
10668 selecting dialog (using SHBrowseForFolder API call). }
10678 //[Color Dialog Object]
10679 type
10680 TColorCustomOption = ( ccoFullOpen, ccoShortOpen, ccoPreventFullOpen );
10682 {++}(*TColorDialog = class;*){--}
10683 PColorDialog = {-}^{+}TColorDialog;
10684 { ----------------------------------------------------------------------
10686 TColorDialog
10688 ----------------------------------------------------------------------- }
10689 //[TColorDialog DEFINITION]
10690 TColorDialog = object( TObj )
10691 {* Color choosing dialog. }
10692 protected
10693 public
10694 OwnerWindow: HWnd;
10695 {* Owner window (can be 0). }
10696 CustomColors: array[ 1..16 ] of TColor;
10697 {* Array of stored custom colors. }
10698 ColorCustomOption: TColorCustomOption;
10699 {* Options (how to open a dialog). }
10700 Color: TColor;
10701 {* Returned color (if the result of Execute is True). }
10702 function Execute: Boolean;
10703 {* Call this method to open a dialog and wait its result. }
10704 end;
10705 //[END OF TColorDialog DEFINITION]
10707 //[NewColorDialog DECLARATION]
10708 function NewColorDialog( FullOpen: TColorCustomOption ): PColorDialog;
10709 {* Creates color choosing dialog object. }
10719 //[Ini files]
10720 type
10721 TIniFileMode = ( ifmRead, ifmWrite );
10722 {* ifmRead is default mode (means "read" data from ini-file.
10723 Set mode to ifmWrite to write data to ini-file, correspondent to
10724 TIniFile. }
10726 {++}(*TIniFile = class;*){--}
10727 PIniFile = {-}^{+}TIniFile;
10728 { ----------------------------------------------------------------------
10730 TIniFile - store/load data to ini-files
10732 ----------------------------------------------------------------------- }
10733 //[TIniFile DEFINITION]
10734 TIniFile = object( TObj )
10735 {* Ini file incapsulation. The main feature is what the same block of
10736 read-write operations could be defined (difference must be only in
10737 Mode value).
10738 |*Ini file sample.
10739 This sample shows how the same Pascal operators can be used both
10740 for read and write for the same variables, when working with TIniFile:
10741 ! procedure ReadWriteIni( Write: Boolean );
10742 ! var Ini: PIniFile;
10743 ! begin
10744 ! Ini := OpenIniFile( 'MyIniFile.ini' );
10745 ! Ini.Section := 'Main';
10746 ! if Write then // if Write, the same operators will save
10747 ! Ini.Mode := ifmWrite; // data rather then load.
10748 ! MyForm.Left := Ini.ValueInteger( 'Left', MyForm.Left );
10749 ! MyForm.Top := Ini.ValueInteger( 'Top', MyForm.Top );
10750 ! Ini.Free;
10751 ! end;
10753 |* }
10754 protected
10755 fMode: TIniFileMode;
10756 fFileName: String;
10757 fSection: String;
10758 protected
10759 public
10760 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10761 {* destructor }
10762 property Mode: TIniFileMode read fMode write fMode;
10763 {* ifmWrite, if write data to ini-file rather than read it. }
10764 property FileName: String read fFileName;
10765 {* Ini file name. }
10766 property Section: String read fSection write fSection;
10767 {* Current ini section. }
10768 function ValueInteger( const Key: String; Value: Integer ): Integer;
10769 {* Reads or writes integer data value. }
10770 function ValueString( const Key: String; const Value: String ): String;
10771 {* Reads or writes string data value. }
10772 function ValueBoolean( const Key: String; Value: Boolean ): Boolean;
10773 {* Reads or writes boolean data value. }
10774 function ValueData( const Key: String; Value: Pointer; Count: Integer ): Boolean;
10775 {* Reads or writes data from/to buffer. Returns True, if success. }
10776 procedure ClearAll;
10777 {* Clears all sections of ini-file. }
10778 procedure ClearSection;
10779 {* Clears current Section of ini-file. }
10780 procedure ClearKey( const Key: String );
10781 {* Clears given key in current section. }
10783 /////////////// + by Vyacheslav A. Gavrik:
10784 procedure GetSectionNames(Names:PStrList);
10785 {* Retrieves section names, storing it in string list passed as a parameter.
10786 String list does not cleared before processing. Section names are added
10787 to the end of the string list. }
10788 procedure SectionData(Names:PStrList);
10789 {* Read/write current section content to/from string list. (Depending on
10790 current Mode value). }
10791 ///////////////
10793 end;
10794 //[END OF TIniFile DEFINITION]
10796 //[OpenIniFile DECLARATION]
10797 function OpenIniFile( const FileName: String ): PIniFile;
10798 {* Opens ini file, creating TIniFile object instance to work with it. }
10807 //[MENU OBJECT]
10809 type
10810 TMenuitemInfo = packed record
10811 cbSize: UINT;
10812 fMask: UINT;
10813 fType: UINT; { used if MIIM_TYPE}
10814 fState: UINT; { used if MIIM_STATE}
10815 wID: UINT; { used if MIIM_ID}
10816 hSubMenu: HMENU; { used if MIIM_SUBMENU}
10817 hbmpChecked: HBITMAP; { used if MIIM_CHECKMARKS}
10818 hbmpUnchecked: HBITMAP; { used if MIIM_CHECKMARKS}
10819 dwItemData: DWORD; { used if MIIM_DATA}
10820 dwTypeData: PAnsiChar; { used if MIIM_TYPE}
10821 cch: UINT; { used if MIIM_TYPE}
10822 hbmpItem: HBITMAP; { used if MIIM_BITMAP - not exists under Windows95 }
10823 end;
10825 type
10826 {++}(*TMenu = class;*){--}
10827 PMenu = {-}^{+}TMenu;
10829 TOnMenuItem = procedure( Sender : PMenu; Item : Integer ) of object;
10830 {* Event type to define OnMenuItem event. }
10832 TMenuAccelerator = packed Record
10833 {* Menu accelerator record. Use MakeAccelerator function to combine desired
10834 attributes into a record, describing the accelerator. }
10835 fVirt: Byte; // or-combination of FSHIFT, FCONTROL, FALT, FVIRTKEY, FNOINVERT
10836 Key: Word; // character or virtual key code (FVIRTKEY flag is present above)
10837 NotUsed: Byte; // not used
10838 end;
10840 // by Sergey Shisminzev:
10841 TMenuOption = (moDefault, moDisabled, moChecked,
10842 moCheckMark, moRadioMark, moSeparator, moBitmap, moSubMenu,
10843 moBreak, moBarBreak);
10844 {* Options to add menu items dynamically. }
10845 TMenuOptions = set of TMenuOption;
10846 {* Set of options for menu item to use it in TMenu.AddItem method. }
10848 TMenuBreak = ( mbrNone, mbrBreak, mbrBarBreak );
10849 {* Possible menu item break types. }
10851 { ----------------------------------------------------------------------
10853 TMenu - main, popup menu and menu item
10855 ----------------------------------------------------------------------- }
10856 //[TMenu DEFINITION]
10857 TMenu = object( TObj )
10858 {* Dynamic menu incapsulation object. Can play role of form main menu or popup
10859 menu, depending on kind of parent window (form or control) and order of
10860 creation (created first (for a form) become main menu). Does not allow
10861 merging menus, but items can be hidden. Additionally checkmark bitmaps,
10862 shortcut key accelerators and other features are available. }
10863 protected
10864 FHandle: HMenu;
10865 FId: Integer;
10866 FParent: PMenu;
10867 FControl: PControl;
10868 fNextMenu : PMenu;
10869 FRadioGroup: Integer;
10870 FIsCheckItem: Boolean;
10871 FIsSeparator: Boolean;
10872 FMenuBreak: TMenuBreak;
10873 FItems: PList;
10874 FOnMenuItem : TOnMenuItem;
10875 FOnRadioOff : TOnMenuItem;
10876 fOnPopup: TOnEvent;
10877 fByAccel: Boolean;
10878 FPopupFlags: DWORD;
10879 //fAutoPopup: Boolean;
10880 FVisible: Boolean;
10881 FSavedState: DWORD;
10882 FData: Pointer;
10883 FOwnerDraw: Boolean;
10884 FCaption: String;
10885 FBitmap: HBitmap;
10886 FBmpChecked: HBitmap;
10887 FBmpItem: HBitmap;
10888 ClearBitmapsProc: procedure( Sender: PMenu );
10889 FClearBitmaps: Boolean;
10890 FNotPopup: Boolean;
10891 FAccelerator: TMenuAccelerator;
10892 FHelpContext: Integer;
10893 FOnMeasureItem: TOnMeasureItem;
10894 FOnDrawItem: TOnDrawItem;
10895 {$IFDEF USE_MENU_CURCTL}
10896 fCurCtl: PControl;
10897 {$ENDIF USE_MENU_CURCTL}
10898 function GetItems( Id: HMenu ): PMenu;
10899 function GetCount: Integer;
10900 function GetTopParent: PMenu;
10901 function GetState( const Index: Integer ): Boolean;
10902 procedure SetState( const Index: Integer; Value: Boolean );
10903 procedure SetVisible( Value: Boolean );
10904 procedure SetData( Value: Pointer );
10905 procedure SetMenuItemCaption( const Value: String );
10906 function FillMenuItems(AHandle: HMenu; StartIdx: Integer;
10907 const Template: array of PChar): Integer;
10908 procedure SetMenuBreak( Value: TMenuBreak );
10909 function GetControl: PControl;
10910 function GetInfo( var MII: TMenuItemInfo ): Boolean;
10911 function SetInfo( var MII: TMenuItemInfo ): Boolean;
10912 function SetTypeInfo( var MII: TMenuItemInfo ): Boolean;
10913 procedure SetBitmap( Value: HBitmap );
10914 procedure SetBmpChecked( Value: HBitmap );
10915 procedure SetBmpItem( Value: HBitmap );
10916 procedure ClearBitmaps;
10917 procedure SetAccelerator( const Value: TMenuAccelerator );
10918 procedure SetHelpContext( Value: Integer );
10919 procedure SetSubmenu( Value: HMenu );
10920 procedure SetOnMeasureItem( const Value: TOnMeasureItem );
10921 procedure SetOnDrawItem( const Value: TOnDrawItem );
10922 procedure SetOwnerDraw( Value: Boolean );
10923 protected
10924 function GetItemChecked( Item : Integer ) : Boolean;
10925 procedure SetItemChecked( Item : Integer; Value : Boolean );
10926 function GetItemBitmap(Idx: Integer): HBitmap;
10927 procedure SetItemBitmap(Idx: Integer; const Value: HBitmap);
10928 function GetItemText(Idx: Integer): String;
10929 procedure SetItemText(Idx: Integer; const Value: String);
10930 function GetItemEnabled(Idx: Integer): Boolean;
10931 procedure SetItemEnabled(Idx: Integer; const Value: Boolean);
10932 function GetItemVisible(Idx: Integer): Boolean;
10933 procedure SetItemVisible(Idx: Integer; const Value: Boolean);
10934 function GetItemAccelerator(Idx: Integer): TMenuAccelerator;
10935 procedure SetItemAccelerator(Idx: Integer; const Value: TMenuAccelerator);
10936 function GetItemSubMenu( Idx: Integer ): HMenu;
10937 public
10938 destructor Destroy; {-}virtual;{+}{++}(*override;*){--}
10939 {* To release menu dynamically, call Free method instead. All (popup)
10940 menus created after this (for the same control) are destroyed in
10941 that case too.
10942 |<br>
10943 It is not necessary to release menu object manually: all menus,
10944 created with given form (or control), are automatically released,
10945 when owner form (or control) is destroyed.
10947 property Handle : HMenu read FHandle;
10948 {* Handle of Windows menu object. }
10949 property MenuId: Integer read FId;
10950 {* Id of the menu item object. If menu item has subitems, it has
10951 also submenu Handle. Top parent menu object itself has no Id.
10952 Id-s areassigned automatically starting from 4096. Do not
10953 (re)create menu items instantly, because such values are not
10954 reused, and maximum possible Id value must not exceed 65535. }
10955 property Parent: PMenu read FParent;
10956 {* Parent menu item (or parent menu). }
10957 property TopParent: PMenu read GetTopParent;
10958 {* Top parent menu, owning all nested subitems. }
10959 property Owner: PControl read GetControl;
10960 {* Parent control or form. }
10961 property Caption: String read FCaption write SetMenuItemCaption;
10962 {* Menu item caption text (including '&' indicating mnemonic characters,
10963 and keyboard accelerator representation string, usually following
10964 tabulation character). }
10965 property Items[ Id: HMenu ]: PMenu read GetItems;
10966 {* Returns menu item object by its index or by menu id. Since menu id
10967 values are starting from 4096, values from 0 to 4095 are interpreted
10968 as absolute index of menu item. Be careful accessing menu items or
10969 submenus by index, if you dynamically insert or delete items or
10970 submenus. In this version, separators are enumerating too, like
10971 all other items. Use index -1 to access object itself. The first
10972 item of a menu (or the first subitem of submenu item) has index 0.
10973 Children are enumerating before all siblings. The maximum available
10974 index is (Count - 1), when accessing menu items by index. }
10975 property Count: Integer read GetCount;
10976 {* Count of items together with all its nested subitems. }
10977 function IndexOf( Item: PMenu ): Integer;
10978 {* Returns index of an item. This index can be used to access
10979 menu item. Value -2 is returned, if the Item is not a child for menu
10980 or menu item, and has no parents, which are children for it, etc.
10981 Menu object itself always has index -1. }
10982 property OnMenuItem : TOnMenuItem read FOnMenuItem write FOnMenuItem;
10983 {* Is called when menu item is clicked. Absolute index of menu item
10984 clicked is passed as the second parameter. TopParent always is
10985 passed as a Sender parameter. }
10986 property ByAccel: Boolean read fByAccel;
10987 {* True, when OnMenuItem is called not by mouse, but by accelerator key.
10988 Check this flag for entire menu (TopParent), not for item itself.
10989 (Note, that Sender in OnMenuItem always is TopParent menu object). )
10991 property IsSeparator: Boolean read FIsSeparator;
10992 {* TRUE, if a separator menu item. }
10993 property MenuBreak: TMenuBreak read FMenuBreak write SetMenuBreak;
10994 {* Menu item break type. }
10995 property OnUncheckRadioItem : TOnMenuItem read FOnRadioOff write FOnRadioOff;
10996 {* Is called when radio item becomes unchecked in menu in result of
10997 checking another radio item of the same radio group. }
10998 property RadioGroup: Integer read FRadioGroup write FRadioGroup;
10999 {* Radio group index. Several neighbour items with the same radio group
11000 index form radio group. Only single item from the same group can be
11001 checked at a time. }
11002 property IsCheckItem: Boolean read FIsCheckItem;
11003 {* If menu item is defined as check item, it is checked automatically
11004 when clicked. }
11005 procedure RadioCheckItem;
11006 {* Call this method to check radio item. (Calling this method for
11007 an item, which is not belonging to a radio group, just sets its
11008 Checked state to TRUE). }
11009 property Checked: Boolean index MFS_CHECKED read GetState write SetState;
11010 {* Checked state of the item. }
11011 property Enabled: Boolean
11012 {$IFDEF F_P}
11013 index $80000000 or MFS_DISABLED
11014 {$ELSE DELPHI}
11015 index Integer( $80000000 or MFS_DISABLED )
11016 {$ENDIF F_P/DELPHI}
11017 read GetState write SetState;
11018 {* Enabled state of the item. Whaen assigned, Grayed state also is
11019 set to arbitrary value (i.e., when Enabled is set to true, Grayed
11020 is set to FALSE. }
11021 property DefaultItem: Boolean index MFS_DEFAULT read GetState write SetState;
11022 {* Set this property to TRUE to make menu item default. Default item
11023 is drawn with bold.
11024 |<br>If you change DefaultItem at run-time and whant
11025 to provide changing its visual state, recreate the item first resetting
11026 Visible property, then setting it again. }
11027 property Highlight: Boolean index MFS_HILITE read GetState write SetState;
11028 {* Highlight state of the item. }
11029 property Visible: Boolean read FVisible write SetVisible;
11030 {* Visibility of menu item. }
11031 property Data: Pointer read FData write SetData;
11032 {* Data pointer, associated with the menu item. }
11033 property Bitmap: HBitmap read FBitmap write SetBitmap;
11034 {* Bitmap used for unchecked state of the menu item. }
11035 property BitmapChecked: HBitmap read FBmpChecked write SetBmpChecked;
11036 {* Bitmap used for checked state of the menu item. }
11037 property BitmapItem: HBitmap read FBmpItem write SetBmpItem;
11038 {* Bitmap used for item itself. In addition, following special values
11039 are possible:
11040 HBMMENU_CALLBACK, HBMMENU_MBAR_CLOSE, HBMMENU_MBAR_CLOSE_D,
11041 HBMMENU_MBAR_MINIMIZE, HBMMENU_MBAR_MINIMIZE_D, HBMMENU_MBAR_RESTORE,
11042 HBMMENU_POPUP_CLOSE, HBMMENU_POPUP_MAXIMIZE, HBMMENU_POPUP_MINIMIZE,
11043 HBMMENU_POPUP_RESTORE, HBMMENU_SYSTEM. }
11044 property Accelerator: TMenuAccelerator read FAccelerator write SetAccelerator;
11045 {* Accelerator for menu item. }
11046 property HelpContext: Integer read FHelpContext write SetHelpContext;
11047 {* Help context for entire menu (help context can not be assigned to
11048 individual menu items). }
11050 procedure AssignEvents( StartIdx: Integer; Events: array of TOnMenuItem );
11051 {* It is possible to assign its own event handler to every menu item
11052 using this call. This procedure also is called automatically in
11053 a constructor NewMenuEx. }
11055 function Popup( X, Y : Integer ): Integer; {!ecm}
11056 {* Only for popup menu - to popup it at the given position on screen.
11057 Return: If you specify TPM_RETURNCMD in the uFlags parameter, the return
11058 value is the menu-item identifier of the item that the user selected.
11059 If the user cancels the menu without making a selection, or if an error
11060 occurs, then the return value is zero.
11061 If you do not specify TPM_RETURNCMD in the uFlags parameter, the return
11062 value is nonzero if the function succeeds and zero if it fails. }
11063 function PopupEx( X, Y: Integer ): Integer; {!ecm}
11064 {* This version of popup command is very useful, when popup menu is activated
11065 when its parent window is not visible (e.g., for a kind of applications,
11066 which always are invisible, and can be activated only using tray icon).
11067 PopupEx method provides correct tracking of menu disappearing when mouse
11068 is clicked anywhere else on screen, fixing strange menu behavior in some
11069 Windows versions (NT).
11070 |<br>
11071 Actually, when PopupEx used, parent form is shown but below of visible
11072 screen, and when menu is disappearing, previous state of the form (visibility
11073 and position) are restored. If such solvation is not satisfying You,
11074 You can do something else (e.g., use region clipping, etc.) }
11075 property OnPopup: TOnEvent read fOnPopup write fOnPopup;
11076 {* This event occurs before the popup menu is shown. }
11077 property NotPopup: Boolean read FNotPopup write FNotPopup;
11078 {* Set this property to true to prevent popup of popup menu, e.g. in
11079 OnPopup event handler. }
11080 property Flags: DWORD read FPopupFlags write FPopupFlags;
11081 {* Pop-up flags, which are used to call TrackPopupMenuEx, when Popup or
11082 PopupEx method is called. Can be a combination of following values:
11083 |<br>
11084 TPM_CENTERALIGN or TPM_LEFTALIGN or TPM_RIGHTALIGN
11085 |<br>
11086 TPM_BOTTOMALIGN or TPM_TOPALIGN or TPM_VCENTERALIGN
11087 |<br>
11088 TPM_NONOTIFY or TPM_RETURNCMD
11089 |<br>
11090 TPM_LEFTBUTTON or TPM_RIGHTBUTTON
11091 |<br>
11092 TPM_HORNEGANIMATION or TPM_HORPOSANIMATION or TPM_NOANIMATION or
11093 TPM_VERNEGANIMATION or TPM_VERPOSANIMATION
11094 |<br>
11095 TPM_HORIZONTAL or TPM_VERTICAL.
11096 |<br>
11097 By default, a combination TPM_LEFTALIGN or TPM_LEFTBUTTON is used. }
11098 function Insert(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;
11099 Options: TMenuOptions): PMenu;
11100 {* Inserts new menu item before item, given by Id (>=4096) or index
11101 value InsertBefore. Pointer to an object created is returned. }
11102 property SubMenu: HMenu read FHandle; // write SetSubMenu;
11103 {* Submenu associated with the menu item. The same as Handle. It was possible
11104 in ealier versions to change this value, replacing (removing, assigning)
11105 entire popup menu as a submenu for menu item.
11106 But in modern version of TMenu, this is not possible.
11107 Instead, entire menu object should be added or removed using
11108 InsertSubmenu or RemoveSubmenu methods. }
11109 procedure InsertSubMenu( SubMenuToInsert: PMenu; InsertBefore: Integer );
11110 {* Inserts existing menu item (together with its subitems if any present)
11111 into given position. See also RemoveSubMenu. }
11112 function RemoveSubMenu( ItemToRemove: Integer ): PMenu;
11113 {* Removes menu item from the menu, returning TMenu object, representing it,
11114 if submenu item, having its own children, detached. If an individual menu
11115 item is removed, nil is returned.
11116 This function can be useful to add or remove dynamically entire submenus
11117 (created together with its subitems). }
11118 property OnMeasureItem: TOnMeasureItem read FOnMeasureItem write SetOnMeasureItem;
11119 {* This event is called for owner-drawn menu items. Event handler should return
11120 menu item height in lower word of a result and item width (for menu) in
11121 high word of result. If either for height or for width returned value is 0,
11122 a default one is used. }
11123 property OnDrawItem: TOnDrawItem read FOnDrawItem write SetOnDrawItem;
11124 {* This event is called for owner-drawn menu items. }
11125 property OwnerDraw: Boolean read FOwnerDraw write SetOwnerDraw;
11126 {* Set this property to true for some items to make it owner-draw. }
11128 // For compatibility with old code (be sure that item with given index
11129 // actually exists):
11130 function GetMenuItemHandle( Idx : Integer ): DWORD;
11131 {* Returns Id of menu item with given index. }
11132 property ItemHandle[ Idx: Integer ]: DWORD read GetMenuItemHandle;
11133 {* Returns handle for item given by index. }
11134 property ItemChecked[ Idx : Integer ] : Boolean read GetItemChecked write SetItemChecked;
11135 {* True, if correspondent menu item is checked. }
11136 procedure RadioCheck( Idx : Integer );
11137 {* Call this method to check radio item. For radio items, do not
11138 use assignment to ItemChecked or Checked properties. }
11139 property ItemBitmap[ Idx: Integer ]: HBitmap read GetItemBitmap write SetItemBitmap;
11140 {* This property allows to assign bitmap to menu item (for unchecked state
11141 only - for checked menu items default checkmark bitmap is used). }
11142 procedure AssignBitmaps( StartIdx: Integer; Bitmaps: array of HBitmap );
11143 {* Can be used to assign bitmaps to several menu items during one call. }
11144 property ItemText[ Idx: Integer ]: String read GetItemText write SetItemText;
11145 {* This property allows to get / modify menu item text at run time. }
11146 property ItemEnabled[ Idx: Integer ]: Boolean read GetItemEnabled write SetItemEnabled;
11147 {* Controls enabling / disabling menu items. Disabled menu items are
11148 displayed (grayed) but inaccessible to click. }
11149 property ItemVisible[ Idx: Integer ]: Boolean read GetItemVisible write SetItemVisible;
11150 {* This property allows to simulate visibility of menu items (implementing
11151 it by removing or inserting again if needed. For items of submenu, which
11152 is made invisible, True is returned. If such item made Visible, entire
11153 submenu with all its parent menu items becomes visible. To release menu
11154 properly it is necessary to make before all its items visible again.
11155 This does not matter, if menu is released at the end of execution, but
11156 can be sensible if owner form is destroyed and re-created at run time
11157 dynamically. }
11158 function ParentItem( Idx: Integer ): Integer;
11159 {* Returns index of parent menu item (for submenu item). If there are no
11160 such item (Idx corresponds to root level menu item), -1 is returned. }
11161 property ItemAccelerator[ Idx: Integer ]: TMenuAccelerator read GetItemAccelerator write SetItemAccelerator;
11162 {* Allows to get / change accelerator key kodes assigned to menu items.
11163 Has no effect unless SupportMnemonics called for a form. }
11164 property ItemSubmenu[ Idx: Integer ]: HMenu read GetItemSubmenu; // write SetItemSubmenu;
11165 {* Retrieves submenu item dynamically. See also SubMenu property. }
11167 // by Sergey Shisminzev:
11168 function AddItem(ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;
11169 {* Adds menu item dynamically. Returns ID of the added item. }
11170 function InsertItem(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;
11171 {* Inserts menu item before an item with ID, given by InsertBefore parameter. }
11172 function InsertItemEx(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions;
11173 ByPosition: Boolean): Integer;
11174 {* Inserts menu item by command or by position, dependant on ByPosition parameter }
11175 procedure RedrawFormMenuBar;
11176 {* }
11178 {$IFDEF USE_MENU_CURCTL}
11179 property CurCtl: PControl read fCurCtl;
11180 {* By Alexander Pravdin. This property is assigned to a control which were
11181 initiated a pop-up, for popup menu. }
11182 {$ENDIF USE_MENU_CURCTL}
11184 end;
11185 //[END OF TMenu DEFINITION]
11187 //[MenuStructSize VARIABLE]
11188 function MenuStructSize: Integer;
11189 {* Returns 44 under Windows95, and 48 (=sizeof(TMenuItemInfo) under all other
11190 Windows versions. }
11192 //[NewMenu DECLARATION]
11193 function NewMenu( AParent : PControl; MaxCmdReserve: DWORD; const Template : array of PChar;
11194 aOnMenuItem: TOnMenuItem ): PMenu;
11195 {* Menu constructor. First created menu becomes main menu of form (if AParent
11196 is a form). All other menus becomes popup (can be activated using Popup
11197 method). To provide dynamic replacing of main menu, create all popup
11198 menus as children of any other control, not form itself.
11199 When Menu is created, pass FirstCmd integer value to set it
11200 as ID of first menu item (all other ID's obtained by incrementing this value),
11201 and Template, which is an array of PChar (usually array of string constants),
11202 containing list of menu item identifiers and/or formatting characters.
11203 |<br>&nbsp;&nbsp;&nbsp;
11204 FirstCmd value is assigned to first menu item created as its ID,
11205 all follow menu items are assigned to ID's obtained from FirstCmd incrementing
11206 it by 1. It is desirable to provide not intersected ranges of ID's for
11207 defferent menus in the applet.
11208 |<br>&nbsp;&nbsp;&nbsp;
11209 Following formatting characters can be used in menu template strings:
11210 |&L=<br><b>%1</b>
11211 <L &amp; (in identifier)> - to underline next character and use it as a shortcut character
11212 when possible;
11213 <L + (in front of identifier)> - to make item checked. If also
11214 |<b>!</b> is used before <b>
11216 |</b> than radioitem is defined;
11217 <L - (in front of identifier)> - item not checked;
11218 <L - (separate)> - separator (between two items);
11219 <L ( (separate)> - start of submenu;
11220 <L ) (separate)> - end of submenu;
11221 |<br>&nbsp;&nbsp;&nbsp;
11222 To get access to menu items, use constants 0, 1, etc. It is a good idea
11223 to create special enumerated type to index correspondent menu items
11224 using Ord( ) operator. Note in that case, that it is necessary only to
11225 define constants correspondent to identifiers (positions, correspondent
11226 to separators or submenu brackets are not identified by numbers).
11227 |<br>&nbsp;&nbsp;&nbsp;
11230 function NewMenuEx( AParent : PControl; FirstCmd : Integer; const Template : array of PChar;
11231 aOnMenuItems: array of TOnMenuItem ): PMenu;
11232 {* Creates menu, assigning its own event handler for every (enough) menu item. }
11234 //[MakeAccelerator DECLARATION]
11235 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;
11236 {* Creates accelerator item to assign it to TMenu.ItemAccelerator[ ] property
11237 easy.}
11239 //[GetAcceleratorText DECLARATION]
11240 // {YS} added 7 Aug 2004
11241 function GetAcceleratorText( const Accelerator: TMenuAccelerator ): string;
11242 {* Returns text representation of accelerator. }
11244 {|<hr>
11253 <R System functions and working with windows>
11255 //[Window FUNCTIONS DECLARATIONS]
11256 type
11257 TWindowChildKind = ( wcActive, wcFocus, wcCapture, wcMenuOwner,
11258 wcMoveSize, wcCaret );
11259 {* Type of window child kind. Used in function GetWindowChild. }
11261 function GetWindowChild( Wnd: HWnd; Kind: TWindowChildKind ): HWnd;
11262 {* Returns child of given top-level window, having given characteristics.
11263 For example, it is possible to get know for foreground window,
11264 which of its child window has focus. This function does not work in old
11265 Windows 95 (returns Wnd in that case). But for Windows 98, Windows NT/2000
11266 this function works fine. To obtain focused child of the window,
11267 use GetFocusedWindow, which is independant from Windows version. }
11269 function GetFocusedChild( Wnd: HWnd ): HWnd;
11270 {* Returns focused child of given window (which should be foreground
11271 and active, certainly). 0 is returned either if Wnd is not active
11272 or Wnd has no focused child window. }
11274 function Stroke2Window( Wnd: HWnd; const S: String ): Boolean;
11275 {* Posts characters from string S to those child window of Wnd, which
11276 has focus now (top-level window Wnd must be foreground, and have
11277 focused edit-aware control to receive the stroke).
11278 |<br>
11279 This function allows only to post typeable characters (including
11280 such special symbols as #13 (Enter), #9 (Tab), #8 (BackSpace), etc.
11281 |<br>
11282 See also function Stroke2WindowEx, which allows to post any key down
11283 and up events, simulating keyboard for given (automated) application. }
11285 function Stroke2WindowEx( Wnd: HWnd; const S: String; Wait: Boolean ): Boolean;
11286 {* In addition to function Stroke2Window, this one can send special keys
11287 to given window, including functional keys and navigation keys. To
11288 post special key to target window, place a combination of names of
11289 such key together with keys, which should be passed simultaneously,
11290 between square or figure brackets. For example, [Ctrl F1], [Alt Shift Home],
11291 [Ctrl E]. For letters and usual characters, it is not necessary to
11292 simulate pressing it with determining all Shift combinations and it is
11293 sufficient to pass characters as is. (E.g., not '[Shift 1]', but '!'). }
11295 function FindWindowByThreadID( ThreadID : DWORD ) : HWnd;
11296 {* Searches for window, belonging to a given thread. }
11298 function GetDesktopRect : TRect;
11299 {* Returns rectangle of screen, free of taskbar and other
11300 similar app-bars, which reduces size of available desktop
11301 when created. }
11302 function GetWorkArea: TRect;
11303 {* The same as GetDesktopRect, but obtained calling SystemParametersInfo. }
11305 function ExecuteWait( const AppPath, CmdLine, DfltDirectory: String;
11306 Show: DWORD; TimeOut: DWORD; ProcID: PDWORD ): Boolean;
11307 {* Allows to execute an application and wait when it is finished. Pass
11308 INFINITE constant as TimeOut, if You sure that application is finished
11309 anyway. If another value passed as a TimeOut (in milliseconds), and
11310 application was not finished for that time, ExecuteWait is returning
11311 FALSE, and if ProcID is not nil, than ProcID^ contains started process
11312 handle (it can be used to wait it more, or to terminate it using
11313 TerminateProcess API function).
11314 |<br>
11315 Launching application can be console or GUI - it does not matter.
11316 Pass SW_SHOW, SW_HIDE or other SW_XXX constant as Show parameter
11317 as appropriate.
11318 |<br>
11319 Trie is returned only in case when application specified was launched
11320 successfully and finished for TimeOut specified. Otherwise, check
11321 ProcID^ variable: if it is 0, process could not be launched (and it
11322 is possible to get information about error using GetLastError API
11323 function in a such case). You can freely pass nil in place of ProcID
11324 parameter, but this is acually correct only when TimeOut is INFINITE. }
11325 function ExecuteIORedirect( const AppPath, CmdLine, DfltDirectory: String;
11326 Show: DWORD; ProcID: PDWORD; InPipe, OutPipeWr, OutPipeRd: PHandle ): Boolean;
11327 {* Executes an application with its console input and output redirection.
11328 Terminating of the application is not waiting, but if ProcID pointer
11329 is defined, it receives process Id launched, so it is possible to
11330 call WaitForSingleObject for it. InPipe is a pointer to THandle variable
11331 which receives a handle to input pipe of the console redirected. The same
11332 is for OutPipeWr and OutPipeRd, but for output of the console redirected.
11333 Before reading from OutPipeRd^, first close OutPipeWr^. If you run
11334 simple console application, for which you want to read results after its
11335 termination, you can use ExecuteConsoleAppIORedirect instead.
11336 |<br>&nbsp;&nbsp;&nbsp;
11337 Notes: if your application is not console and it does not create console
11338 using AllocConsole, this function will fail to redirect input-output. }
11339 function ExecuteConsoleAppIORedirect( const AppPath, CmdLine, DfltDirectory: String;
11340 Show: DWORD; const InStr: String; var OutStr: String; WaitTimeout: DWORD )
11341 : Boolean;
11342 {* Executes an application, redirecting its console input and output.
11343 After redirecting input and output and launching the application,
11344 content of InStr is written to input stream of the application, then
11345 the application is waiting for its termination (WaitTimeout milliseconds
11346 or INFINITE, as passed) and console output of the application is read to
11347 OutStr. TRUE is returned only in case, when all these tasks are
11348 completed successfully.
11349 |<br>&nbsp;&nbsp;&nbsp;
11350 Notes: if your application is not console and it does not create console
11351 using AllocConsole, this function will fail to redirect input-output. }
11354 function WindowsShutdown( const Machine : String; Force, Reboot : Boolean ) : Boolean;
11355 {* Shut down of Windows NT. Pass Machine = '' to shutdown this PC.
11356 Pass Reboot = True to reboot immediatelly after shut down. }
11358 type
11359 TWindowsVersion = ( wv31, wv95, wv98, wvNT, wvY2K, wvXP, wvLongHorn );
11360 {* Windows versions constants. }
11361 TWindowsVersions = Set of TWindowsVersion;
11362 {* Set of Windows version (e.g. to define a range of versions supported by the
11363 application). }
11365 function WinVer : TWindowsVersion;
11366 {* Returns Windows version. }
11367 function IsWinVer( Ver : TWindowsVersions ) : Boolean;
11368 {* Returns True if Windows version is in given range of values. }
11370 //[Parameters FUNCTIONS DECLARATIONS]
11371 function ParamStr( Idx: Integer ): String;
11372 {* Returns command-line parameter by index. This function supersides
11373 standard ParamStr function. }
11374 function ParamCount: Integer;
11375 {* Returns number of parameters in command line.
11376 |<hr>
11380 //{$DEFINE CHK_BITBLT}
11381 procedure Chk_BitBlt;
11382 {$IFDEF ASM_VERSION}
11383 procedure StartDC;
11384 procedure FinishDC;
11385 {$ENDIF ASM_VERSION}
11387 //[WndProcXXX OTHER DECLARATIONS]
11388 function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
11389 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
11391 var CreatingWindow: PControl;
11392 //ActiveWindow: HWnd;
11394 //[Assert OPERATOR DECLARATION]
11396 {$IFDEF _D2}
11397 // Assert operator was not available in Delphi2. Provide here easy Assert
11398 // procedure for Delphi2.
11399 procedure Assert( Cond: Boolean; const Msg: String );
11401 var AssertErrorProc: procedure( const Message, Filename: AnsiString; LineNumber: Integer );
11402 {$ENDIF}
11406 //[CUSTOM EXTENSIONS]
11407 {$IFDEF USE_CUSTOMEXTENSIONS}
11408 {$I CUSTOM_KOL_EXTENSION.inc} // See comments in TControl
11409 {$ENDIF}
11412 {$IFDEF DEBUG_ENDSESSION}
11413 var EndSession_Initiated: Boolean;
11414 {$ENDIF}
11416 //[FMMNotify VARIABLE]
11418 FMMNotify: procedure( var Msg: TMsg );
11420 //[procedure ClearText forward declaration]
11421 procedure ClearText( Sender: PControl );
11422 //[procedure ClearListbox forward declaration]
11423 procedure ClearListbox( Sender: PControl );
11424 //[procedure ClearCombobox forward declaration]
11425 procedure ClearCombobox( Sender: PControl );
11426 //[procedure ClearListView forward declaration]
11427 procedure ClearListView( Sender: PControl );
11428 //[procedure ClearTreeView forward declaration]
11429 procedure ClearTreeView( TV: PControl );
11431 //[START OF ACTIONS]
11432 const
11433 ButtonActions: TCommandActions = (
11434 aClear: ClearText;
11435 aAddText: nil;
11436 aClick: BN_CLICKED;
11437 aEnter: BN_SETFOCUS;
11438 aLeave: BN_KILLFOCUS;
11439 aChange: 0; //BN_CLICKED;
11440 aSelChange: 0;
11441 aGetCount: 0;
11442 aSetCount: 0;
11443 aGetItemLength: 0;
11444 aGetItemText: 0;
11445 aSetItemText: 0;
11446 aGetItemData: 0;
11447 aSetItemData: 0;
11448 aAddItem: 0;
11449 aDeleteItem: 0;
11450 aInsertItem: 0;
11451 aFindItem: 0;
11452 aFindPartial: 0;
11453 aItem2Pos: 0;
11454 aPos2Item: 0;
11455 aGetSelCount: 0;
11456 aGetSelected: 0;
11457 aGetSelRange: 0;
11458 aExGetSelRange: 0;
11459 aGetCurrent: 0;
11460 aSetSelected: 0;
11461 aSetCurrent: 0;
11462 aSetSelRange: 0;
11463 aExSetSelRange: 0;
11464 aGetSelection: 0;
11465 aReplaceSel: 0;
11466 aTextAlignLeft: BS_LEFT;
11467 aTextAlignRight: BS_RIGHT;
11468 aTextAlignCenter: BS_CENTER;
11469 aTextAlignMask: 0;
11470 aVertAlignCenter: BS_VCENTER shr 8;
11471 aVertAlignTop: BS_TOP shr 8;
11472 aVertAlignBottom: BS_BOTTOM shr 8;
11473 aDir: 0;
11474 aSetLimit: 0;
11475 aSetImgList: 0;
11476 aAutoSzX: 14;
11477 aAutoSzY: 6;
11478 aSetBkColor: 0;
11481 const
11482 LabelActions: TCommandActions = (
11483 aClear: ClearText;
11484 aAddText: nil;
11485 aClick: 0;
11486 aEnter: 0;
11487 aLeave: 0;
11488 aChange: 0;
11489 aSelChange: 0;
11490 aGetCount: 0;
11491 aSetCount: 0;
11492 aGetItemLength: 0;
11493 aGetItemText: 0;
11494 aSetItemText: 0;
11495 aGetItemData: 0;
11496 aSetItemData: 0;
11497 aAddItem: 0;
11498 aDeleteItem: 0;
11499 aInsertItem: 0;
11500 aFindItem: 0;
11501 aFindPartial: 0;
11502 aItem2Pos: 0;
11503 aPos2Item: 0;
11504 aGetSelCount: 0;
11505 aGetSelected: 0;
11506 aGetSelRange: 0;
11507 aExGetSelRange: 0;
11508 aGetCurrent: 0;
11509 aSetSelected: 0;
11510 aSetCurrent: 0;
11511 aSetSelRange: 0;
11512 aExSetSelRange: 0;
11513 aGetSelection: 0;
11514 aReplaceSel: 0;
11515 aTextAlignLeft: SS_LEFT;
11516 aTextAlignRight: SS_RIGHT;
11517 aTextAlignCenter: SS_CENTER;
11518 aTextAlignMask: SS_LEFTNOWORDWRAP;
11519 aVertAlignCenter: SS_CENTERIMAGE shr 8;
11520 aVertAlignTop: 0;
11521 aVertAlignBottom: 0;
11522 aDir: 0;
11523 aSetLimit: 0;
11524 aSetImgList: 0;
11525 aAutoSzX: 1;
11526 aAutoSzY: 1;
11527 aSetBkColor: 0;
11530 const
11531 EN_LINK = $070b;
11532 EditActions: TCommandActions = (
11533 aClear: ClearText;
11534 aAddText: nil;
11535 aClick: 0;
11536 aEnter: EN_SETFOCUS;
11537 aLeave: EN_KILLFOCUS;
11538 aChange: EN_CHANGE;
11539 aSelChange: 0;
11540 aGetCount: EM_GETLINECOUNT;
11541 aSetCount: 0;
11542 aGetItemLength: EM_LINELENGTH;
11543 aGetItemText: EM_GETLINE;
11544 aSetItemText: EM_REPLACESEL;
11545 aGetItemData: 0;
11546 aSetItemData: 0;
11547 aAddItem: 0;
11548 aDeleteItem: 0;
11549 aInsertItem: 0;
11550 aFindItem: 0;
11551 aFindPartial: 0;
11552 aItem2Pos: EM_LINEINDEX;
11553 aPos2Item: EM_LINEFROMCHAR;
11554 aGetSelCount: EM_GETSEL;
11555 aGetSelected: 0;
11556 aGetSelRange: EM_GETSEL;
11557 aExGetSelRange: 0;
11558 aGetCurrent: EM_LINEINDEX;
11559 aSetSelected: 0;
11560 aSetCurrent: 0;
11561 aSetSelRange: EM_SETSEL;
11562 aExSetSelRange: 0;
11563 aGetSelection: 0;
11564 aReplaceSel: EM_REPLACESEL;
11565 aTextAlignLeft: ES_LEFT;
11566 aTextAlignRight: ES_RIGHT;
11567 aTextAlignCenter: ES_CENTER;
11568 aTextAlignMask: 0;
11569 aVertAlignCenter: 0;
11570 aVertAlignTop: 0;
11571 aVertAlignBottom: 0;
11572 aDir: 0;
11573 aSetLimit: EM_SETLIMITTEXT;
11574 aSetImgList: 0;
11575 aAutoSzX: 0;
11576 aAutoSzY: 6;
11577 aSetBkColor: 0;
11578 aItem2XY: EM_POSFROMCHAR;
11581 const
11582 ListActions: TCommandActions = (
11583 aClear: ClearListbox;
11584 aAddText: nil;
11585 aClick: LBN_DBLCLK;
11586 aEnter: LBN_SETFOCUS;
11587 aLeave: LBN_KILLFOCUS;
11588 aChange: 0;
11589 aSelChange: LBN_SELCHANGE;
11590 aGetCount: LB_GETCOUNT;
11591 aSetCount: LB_SETCOUNT;
11592 aGetItemLength: LB_GETTEXTLEN;
11593 aGetItemText: LB_GETTEXT;
11594 aSetItemText: 0;
11595 aGetItemData: LB_GETITEMDATA;
11596 aSetItemData: LB_SETITEMDATA;
11597 aAddItem: LB_ADDSTRING;
11598 aDeleteItem: LB_DELETESTRING;
11599 aInsertItem: LB_INSERTSTRING;
11600 aFindItem: LB_FINDSTRINGEXACT;
11601 aFindPartial: LB_FINDSTRING;
11602 aItem2Pos: 0;
11603 aPos2Item: 0;
11604 aGetSelCount: LB_GETSELCOUNT;
11605 aGetSelected: LB_GETSEL;
11606 aGetSelRange: 0;
11607 aExGetSelRange: 0;
11608 aGetCurrent: LB_GETCURSEL;
11609 aSetSelected: LB_SETSEL;
11610 aSetCurrent: LB_SETCURSEL;
11611 aSetSelRange: 0;
11612 aExSetSelRange: 0;
11613 aGetSelection: 0;
11614 aReplaceSel: 0;
11615 aTextAlignLeft: 0;
11616 aTextAlignRight: 0;
11617 aTextAlignCenter: 0;
11618 aTextAlignMask: 0;
11619 aVertAlignCenter: 0;
11620 aVertAlignTop: 0;
11621 aVertAlignBottom: 0;
11622 aDir: LB_DIR;
11623 aSetLimit: 0;
11624 aSetImgList: 0;
11625 aAutoSzX: 0;
11626 aAutoSzY: 0;
11627 aSetBkColor: 0;
11628 aItem2XY: LB_GETITEMRECT;
11631 const
11632 ComboActions: TCommandActions = (
11633 aClear: ClearCombobox;
11634 aAddText: nil;
11635 aClick: CBN_DBLCLK;
11636 aEnter: CBN_SETFOCUS;
11637 aLeave: CBN_KILLFOCUS;
11638 aChange: CBN_EDITCHANGE;
11639 aSelChange: CM_CBN_SELCHANGE; // CBN_SELCHANGE;
11640 aGetCount: CB_GETCOUNT;
11641 aSetCount: 0;
11642 aGetItemLength: CB_GETLBTEXTLEN;
11643 aGetItemText: CB_GETLBTEXT;
11644 aSetItemText: 0;
11645 aGetItemData: CB_GETITEMDATA;
11646 aSetItemData: CB_SETITEMDATA;
11647 aAddItem: CB_ADDSTRING;
11648 aDeleteItem: CB_DELETESTRING;
11649 aInsertItem: CB_INSERTSTRING;
11650 aFindItem: CB_FINDSTRINGEXACT;
11651 aFindPartial: CB_FINDSTRING;
11652 aItem2Pos: 0;
11653 aPos2Item: 0;
11654 aGetSelCount: 0;
11655 aGetSelected: CB_GETCURSEL;
11656 aGetSelRange: 0;
11657 aExGetSelRange: 0;
11658 aGetCurrent: CB_GETCURSEL;
11659 aSetSelected: 0;
11660 aSetCurrent: CB_SETCURSEL;
11661 aSetSelRange: 0;
11662 aExSetSelRange: 0;
11663 aGetSelection: 0;
11664 aReplaceSel: 0;
11665 aTextAlignLeft: 0; //ES_LEFT;
11666 aTextAlignRight: 0; //ES_RIGHT;
11667 aTextAlignCenter: 0; //ES_CENTER;
11668 aTextAlignMask: 0;
11669 aVertAlignCenter: 0;
11670 aVertAlignTop: 0;
11671 aVertAlignBottom: 0;
11672 aDir: CB_DIR;
11673 aSetLimit: 0;
11674 aSetImgList: 0;
11675 aAutoSzX: 0;
11676 aAutoSzY: 6;
11677 aSetBkColor: 0;
11680 const
11681 ListViewActions: TCommandActions = (
11682 aClear: ClearListView;
11683 aAddText: nil;
11684 aClick: 0;
11685 aEnter: 0;
11686 aLeave: 0;
11687 aChange: LVN_ITEMCHANGED;
11688 aSelChange: 0;
11689 aGetCount: LVM_GETITEMCOUNT;
11690 aSetCount: LVM_SETITEMCOUNT;
11691 aGetItemLength: 0;
11692 aGetItemText: 0;
11693 aSetItemText: 0;
11694 aGetItemData: 0;
11695 aSetItemData: 0;
11696 aAddItem: 0;
11697 aDeleteItem: 0;
11698 aInsertItem: 0;
11699 aFindItem: 0;
11700 aFindPartial: 0;
11701 aItem2Pos: 0;
11702 aPos2Item: 0;
11703 aGetSelCount: $8000 or LVM_GETSELECTEDCOUNT;
11704 aGetSelected: 0;
11705 aGetSelRange: 0;
11706 aExGetSelRange: 0;
11707 aGetCurrent: LVM_GETNEXTITEM;
11708 aSetSelected: 0;
11709 aSetCurrent: 0;
11710 aSetSelRange: 0;
11711 aExSetSelRange: 0;
11712 aGetSelection: 0;
11713 aReplaceSel: 0;
11714 aTextAlignLeft: 0;
11715 aTextAlignRight: 0;
11716 aTextAlignCenter: 0;
11717 aTextAlignMask: 0;
11718 aVertAlignCenter: 0;
11719 aVertAlignTop: 0;
11720 aVertAlignBottom: 0;
11721 aDir: 0;
11722 aSetLimit: 0;
11723 aSetImgList: LVM_SETIMAGELIST;
11724 aAutoSzX: 0;
11725 aAutoSzY: 0;
11726 aSetBkColor: LVM_SETBKCOLOR;
11727 aItem2XY: LVM_GETITEMRECT;
11730 const
11731 TreeViewActions: TCommandActions = (
11732 aClear: ClearTreeView;
11733 aAddText: nil;
11734 aClick: 0;
11735 aEnter: 0;
11736 aLeave: 0;
11737 aChange: TVN_ENDLABELEDIT;
11738 aSelChange: TVN_SELCHANGED;
11739 aGetCount: TVM_GETCOUNT;
11740 aSetCount: 0;
11741 aGetItemLength: 0;
11742 aGetItemText: 0;
11743 aSetItemText: 0;
11744 aGetItemData: 0;
11745 aSetItemData: 0;
11746 aAddItem: 0;
11747 aDeleteItem: 0;
11748 aInsertItem: 0;
11749 aFindItem: 0;
11750 aFindPartial: 0;
11751 aItem2Pos: 0;
11752 aPos2Item: 0;
11753 aGetSelCount: 0;
11754 aGetSelected: 0;
11755 aGetSelRange: 0;
11756 aExGetSelRange: 0;
11757 aGetCurrent: 0;
11758 aSetSelected: 0;
11759 aSetCurrent: 0;
11760 aSetSelRange: 0;
11761 aExSetSelRange: 0;
11762 aGetSelection: 0;
11763 aReplaceSel: 0;
11764 aTextAlignLeft: 0;
11765 aTextAlignRight: 0;
11766 aTextAlignCenter: 0;
11767 aTextAlignMask: 0;
11768 aVertAlignCenter: 0;
11769 aVertAlignTop: 0;
11770 aVertAlignBottom: 0;
11771 aDir: CB_DIR;
11772 aSetLimit: 0;
11773 aSetImgList: TVM_SETIMAGELIST;
11774 aAutoSzX: 0;
11775 aAutoSzY: 0;
11776 aSetBkColor: TVM_SETBKCOLOR;
11777 aItem2XY: TVM_GETITEMRECT;
11780 const
11781 TabControlActions: TCommandActions = (
11782 aClear: ClearText;
11783 aAddText: nil;
11784 aClick: 0;
11785 aEnter: 0;
11786 aLeave: 0;
11787 aChange: TCN_SELCHANGE;
11788 aSelChange: TCN_SELCHANGE;
11789 aGetCount: TCM_GETITEMCOUNT;
11790 aSetCount: 0;
11791 aGetItemLength: 0;
11792 aGetItemText: 0;
11793 aSetItemText: 0;
11794 aGetItemData: 0;
11795 aSetItemData: 0;
11796 aAddItem: 0;
11797 aDeleteItem: 0;
11798 aInsertItem: 0;
11799 aFindItem: 0;
11800 aFindPartial: 0;
11801 aItem2Pos: 0;
11802 aPos2Item: 0;
11803 aGetSelCount: 0;
11804 aGetSelected: 0;
11805 aGetSelRange: 0;
11806 aExGetSelRange: 0;
11807 aGetCurrent: TCM_GETCURSEL;
11808 aSetSelected: 0;
11809 aSetCurrent: TCM_SETCURSEL; //TCM_SETCURFOCUS;
11810 aSetSelRange: 0;
11811 aExSetSelRange: 0;
11812 aGetSelection: 0;
11813 aReplaceSel: 0;
11814 aTextAlignLeft: 0;
11815 aTextAlignRight: 0;
11816 aTextAlignCenter: 0;
11817 aTextAlignMask: 0;
11818 aVertAlignCenter: 0;
11819 aVertAlignTop: 0;
11820 aVertAlignBottom: 0;
11821 aDir: CB_DIR;
11822 aSetLimit: 0;
11823 aSetImgList: TCM_SETIMAGELIST;
11824 aAutoSzX: 0;
11825 aAutoSzY: 0;
11826 aSetBkColor: 0;
11827 aItem2XY: TCM_GETITEMRECT;
11830 const
11831 RichEditActions: TCommandActions = (
11832 aClear: ClearText;
11833 aAddText: nil;
11834 aClick: 0;
11835 aEnter: EN_SETFOCUS;
11836 aLeave: EN_KILLFOCUS;
11837 aChange: EN_CHANGE;
11838 aSelChange: EN_SELCHANGE;
11839 aGetCount: EM_GETLINECOUNT;
11840 aSetCount: 0;
11841 aGetItemLength: EM_LINELENGTH;
11842 aGetItemText: EM_GETLINE;
11843 aSetItemText: EM_REPLACESEL;
11844 aGetItemData: 0;
11845 aSetItemData: 0;
11846 aAddItem: 0;
11847 aDeleteItem: 0;
11848 aInsertItem: 0;
11849 aFindItem: 0;
11850 aFindPartial: 0;
11851 aItem2Pos: EM_LINEINDEX;
11852 aPos2Item: EM_LINEFROMCHAR;
11853 aGetSelCount: 0; //EM_EXGETSEL;
11854 aGetSelected: 0;
11855 aGetSelRange: 0;
11856 aExGetSelRange: EM_EXGETSEL;
11857 aGetCurrent: EM_LINEINDEX;
11858 aSetSelected: 0;
11859 aSetCurrent: 0;
11860 aSetSelRange: 0;
11861 aExSetSelRange: EM_EXSETSEL;
11862 aGetSelection: EM_GETSELTEXT;
11863 aReplaceSel: EM_REPLACESEL;
11864 aTextAlignLeft: ES_LEFT;
11865 aTextAlignRight: ES_RIGHT;
11866 aTextAlignCenter: ES_CENTER;
11867 aTextAlignMask: 0;
11868 aVertAlignCenter: 0;
11869 aVertAlignTop: 0;
11870 aVertAlignBottom: 0;
11871 aDir: 0;
11872 aSetLimit: EM_EXLIMITTEXT;
11873 aSetImgList: 0;
11874 aAutoSzX: 0;
11875 aAutoSzY: 0;
11876 aSetBkColor: EM_SETBKGNDCOLOR;
11877 aItem2XY: EM_POSFROMCHAR;
11880 //[IMPLEMENTATION]
11881 implementation
11883 //[USES-2]
11884 uses
11885 ShellAPI,
11886 commdlg
11887 ; //, commctrl;
11888 // in Delphi3, including of commctrl.pas increases executable
11889 // onto about 30K. So, all needed definitions are copied here
11890 // (see commctrl.inc).
11891 //[END OF USES-2]
11893 {$IFDEF _D2orD3}
11894 const
11895 OFN_ENABLESIZING = $00800000;
11896 {$ENDIF}
11898 //[procedure Chk_BitBlt_ShowError]
11899 procedure Chk_BitBlt_ShowError;
11900 var Rslt: Integer;
11901 begin
11902 Rslt := GetLastError;
11903 ShowMessage( 'BitBlt ERROR: ' + Int2Str( Rslt )
11904 + ' ' + SysErrorMessage( Rslt ) );
11905 end;
11906 //[ENDe Chk_BitBlt_ShowError]
11908 //[procedure Chk_BitBlt]
11909 procedure Chk_BitBlt;
11910 var Rslt: Integer;
11911 begin
11913 MOV Rslt, EAX
11914 end;
11915 if Rslt = 0 then
11916 begin
11917 Chk_BitBlt_ShowError;
11919 int 3;
11920 end;
11921 end;
11922 end;
11923 //[ENDe Chk_BitBlt]
11925 //[FUNCTION MulDiv]
11926 {$IFNDEF FPC}
11927 function MulDiv( A, B, C: Integer ): Integer;
11929 IMUL EDX
11930 IDIV ECX
11931 end;
11932 {$ENDIF}
11933 //[END MulDiv]
11936 {$ifdef _D2}
11938 //[PROCEDURE Assert]
11939 procedure Assert( Cond: Boolean; const Msg: String );
11940 begin
11941 if not Cond then
11942 begin
11943 AssertErrorProc( Msg, '', 0 );
11944 //MsgOK( Msg );
11946 int 3;
11947 end;
11948 end;
11949 end;
11951 //[API CreateDIBSection]
11952 function CreateDIBSection(DC: HDC; const p2: TBitmapInfo; p3: UINT;
11953 var p4: Pointer; p5: THandle; p6: DWORD): HBITMAP; stdcall;
11954 external gdi32 name 'CreateDIBSection';
11957 //[PROCEDURE _LStrFromPCharLen]
11958 procedure _LStrFromPCharLen(var Dest: AnsiString; Source: PAnsiChar; Length: Integer);
11960 { -> EAX pointer to dest }
11961 { EDX source }
11962 { ECX length }
11964 PUSH EBX
11965 PUSH ESI
11966 PUSH EDI
11968 MOV EBX,EAX
11969 MOV ESI,EDX
11970 MOV EDI,ECX
11972 { allocate new string }
11974 MOV EAX,EDI
11976 CALL System.@NewAnsiString
11977 MOV ECX,EDI
11978 MOV EDI,EAX
11980 TEST ESI,ESI
11981 JE @@noMove
11983 MOV EDX,EAX
11984 MOV EAX,ESI
11985 CALL Move
11987 { assign the result to dest }
11989 @@noMove:
11990 MOV EAX,EBX
11991 CALL System.@LStrClr
11992 MOV [EBX],EDI
11994 POP EDI
11995 POP ESI
11996 POP EBX
11997 end;
11998 {$endif}
12001 //[API InitCommonControls]
12002 procedure InitCommonControls; external cctrl name 'InitCommonControls';
12004 type
12005 TInitCommonControlsEx = packed record
12006 dwSize: DWORD;
12007 dwICC: DWORD;
12008 end;
12009 PInitCommonControlsEx = ^TInitCommonControlsEx;
12011 var ComCtl32_Module: HModule;
12012 //[procedure DoInitCommonControls]
12013 procedure DoInitCommonControls( dwICC: DWORD );
12014 var Proc: procedure( ICC: PInitCommonControlsEx ); stdcall;
12015 ICC: TInitCommonControlsEx;
12016 begin
12017 InitCommonControls;
12018 if ComCtl32_Module = 0 then
12019 ComCtl32_Module := LoadLibrary( 'comctl32.dll' );
12020 @ Proc := GetProcAddress( ComCtl32_Module, 'InitCommonControlsEx' );
12021 if Assigned( Proc ) then
12022 begin
12023 ICC.dwSize := Sizeof( ICC );
12024 ICC.dwICC := dwICC;
12025 Proc( @ ICC );
12026 end;
12027 end;
12028 //[END DoInitCommonControls]
12030 const size_TRect = 16; // used often in assembler versions of code
12033 {$IFDEF ASM_VERSION}
12034 const
12035 EmptyString: String = '';
12037 //[PROCEDURE EAX2PChar]
12038 procedure EAX2PChar;
12040 TEST EAX, EAX
12041 JNZ @@exit
12042 MOV EAX, offset[EmptyString]
12043 @@exit:
12044 end;
12046 //[PROCEDURE EDX2PChar]
12047 procedure EDX2PChar;
12049 TEST EDX, EDX
12050 JNZ @@exit
12051 MOV EDX, offset[EmptyString]
12052 @@exit:
12053 end;
12055 //[PROCEDURE ECX2PChar]
12056 procedure ECX2PChar;
12058 JECXZ @@convert
12060 @@convert:
12061 MOV ECX, offset[EmptyString]
12062 @@exit:
12063 end;
12065 //[PROCEDURE RemoveStr]
12066 procedure RemoveStr;
12068 { <- [ESP+4] = string to remove
12069 -> ESP := ESP + 4
12070 EAX = 0
12072 POP EAX
12073 XCHG EAX, [ESP]
12074 PUSH EAX
12075 MOV EAX, ESP
12076 CALL System.@LStrClr
12077 POP EAX
12078 end;
12079 {$ELSE ASM_VERSION}
12080 {$ENDIF ASM_VERSION}
12083 //[PROCEDURE MsgOK]
12084 procedure MsgOK( const S: String );
12085 begin
12086 MsgBox( S, MB_OK );
12087 end;
12089 {$IFDEF ASM_VERSION}
12090 //[function MsgBox]
12091 function MsgBox( const S: String; Flags: DWORD ): DWORD;
12093 PUSH EDX
12094 PUSH EAX
12096 MOV ECX, [Applet]
12097 XOR EAX, EAX
12098 JECXZ @@1
12099 MOV EAX, [ECX].TControl.fCaption
12100 @@1:
12101 XCHG EAX, [ESP]
12102 PUSH EAX
12103 PUSH 0
12104 CALL MessageBox
12105 end;
12106 {$ELSE ASM_VERSION} //Pascal
12107 function MsgBox( const S: String; Flags: DWORD ): DWORD;
12108 var Title: PChar;
12109 begin
12110 Title := nil;
12111 if assigned( Applet ) then
12112 begin
12113 Title := PChar( Applet.fCaption );
12114 end;
12115 Result := MessageBox( 0 {Wnd}, PChar( S ), Title, Flags );
12116 end;
12117 //[END MsgBox]
12118 {$ENDIF ASM_VERSION}
12120 //[function ShowMsg]
12121 function ShowMsg( const S: String; Flags: DWORD ): DWORD;
12122 var Title: PChar;
12123 Wnd: HWnd;
12124 begin
12125 Title := nil;
12126 Wnd := 0;
12127 if assigned( Applet ) then
12128 begin
12129 Title := PChar( Applet.fCaption );
12130 Wnd := Applet.Handle;
12131 end;
12132 Result := MessageBox( Wnd, PChar( S ), Title, Flags );
12133 end;
12134 //[END ShowMsg]
12136 //[procedure ShowMessage]
12137 procedure ShowMessage( const S: String );
12138 begin
12139 ShowMsg( S, MB_OK or MB_SETFOREGROUND );
12140 end;
12141 //[ENDe ShowMessage]
12143 //[procedure OKClick]
12144 procedure OKClick( Dialog, Btn: PControl );
12145 var Rslt: Integer;
12146 begin
12147 Rslt := -1;
12148 if Btn <> nil then
12149 Rslt := Btn.Tag;
12150 Dialog.ModalResult := Rslt;
12151 Dialog.Close;
12152 end;
12153 //[END OKClick]
12155 //[procedure KeyClick]
12156 procedure KeyClick( Dialog, Btn: PControl; var Key: Longint; Shift: DWORD );
12157 begin
12158 if (Key = VK_RETURN) or (Key = VK_ESCAPE) then
12159 begin
12160 if Key = VK_ESCAPE then
12161 Btn := nil;
12162 OKClick( Dialog, Btn );
12163 end;
12164 end;
12165 //[ENDe KeyClick]
12167 //[procedure CloseMsg]
12168 procedure CloseMsg( Dummy, Dialog: PControl; var Accept: Boolean );
12169 begin
12170 Accept := FALSE;
12171 Dialog.ModalResult := -1;
12172 end;
12173 //[ENDe CloseMsg]
12175 //[function ShowQuestionEx]
12176 function ShowQuestionEx( const S: String; Answers: String; CallBack: TOnEvent ): Integer;
12177 {$IFDEF F_P105ORBELOW}
12178 type POnEvent = ^TOnEvent;
12179 PONKey = ^TOnKey;
12180 var M: TMethod;
12181 {$ENDIF F_P105ORBELOW}
12182 var Dialog: PControl;
12183 Buttons: PList;
12184 Btn: PControl;
12185 AppTermFlag: Boolean;
12186 Lab: PControl;
12187 Y, W, I: Integer;
12188 Title: String;
12189 DlgWnd: HWnd;
12190 AppCtl: PControl;
12191 begin
12192 AppTermFlag := AppletTerminated;
12193 AppCtl := Applet;
12194 AppletTerminated := FALSE;
12195 Title := 'Information';
12196 if pos( '/', Answers ) > 0 then
12197 Title := 'Question';
12198 if Applet <> nil then
12199 Title := Applet.Caption;
12200 Dialog := NewForm( Applet, Title ).SetSize( 300, 40 );
12201 Dialog.Style := Dialog.Style and not (WS_MINIMIZEBOX or WS_MAXIMIZEBOX);
12202 Dialog.OnClose := TOnEventAccept( MakeMethod( Dialog, @CloseMsg ) );
12203 Dialog.Margin := 8;
12204 Lab := NewEditbox( Dialog, [ eoMultiline, eoReadonly, eoNoHScroll, eoNoVScroll ] ).SetSize( 278, 20 );
12205 Lab.HasBorder := FALSE;
12206 Lab.Color := clBtnFace;
12207 Lab.Caption := S;
12208 Lab.Style := Lab.Style and not WS_TABSTOP;
12209 Lab.TabStop := FALSE;
12210 //Lab.LikeSpeedButton;
12212 //Lab.CreateWindow; //virtual!!! -- not needed, window created in Perform
12213 while TRUE do
12214 begin
12215 Y := HiWord( Lab.Perform( EM_POSFROMCHAR, Length( S ) - 1, 0 ) );
12216 if Y < Lab.Height - 20 then break;
12217 Lab.Height := Lab.Height + 4;
12218 if Lab.Height + 40 > GetSystemMetrics( SM_CYSCREEN ) then break;
12219 end;
12221 Buttons := NewList;
12222 W := 0;
12223 if Answers = '' then
12224 begin
12225 Btn := NewButton( Dialog, ' OK ' ).PlaceUnder;
12226 W := Btn.Width;
12227 Buttons.Add( Btn );
12229 else
12230 while Answers <> '' do
12231 begin
12232 Btn := NewButton( Dialog, ' ' + Parse( Answers, '/' ) + ' ' );
12233 Buttons.Add( Btn );
12234 if W = 0 then
12235 Btn.PlaceUnder
12236 else
12237 Btn.PlaceRight;
12238 Btn.AutoSize( TRUE );
12239 if W > 0 then
12240 begin
12241 //Inc( W, 6 );
12242 Btn.Left := Btn.Left + 6;
12243 end;
12244 W := Btn.BoundsRect.Right + 12;
12245 end;
12246 if Dialog.ClientWidth < W then
12247 Dialog.ClientWidth := W;
12248 W := (Dialog.ClientWidth - W) div 2;
12249 for I := 0 to Buttons.Count-1 do
12250 begin
12251 Btn := Buttons.Items[ I ];
12252 Btn.Tag := I + 1;
12253 {$IFDEF F_P105ORBELOW}
12254 M := MakeMethod( Dialog, @OKClick );
12255 Btn.OnClick := POnEvent( @ M )^;
12256 M := MakeMethod( Dialog, @KeyClick );
12257 Btn.OnKeyDown := POnKey( @ M )^;
12258 {$ELSE}
12259 Btn.OnClick := TOnEvent( MakeMethod( Dialog, @OKClick ) );
12260 Btn.OnKeyDown := TOnKey( MakeMethod( Dialog, @KeyClick ) );
12261 {$ENDIF}
12262 Btn.Left := Btn.Left + W;
12263 if I = 0 then
12264 begin
12265 Btn.ResizeParentBottom;
12266 Dialog.ActiveControl := Btn;
12267 end;
12268 end;
12269 Dialog.CenterOnParent.Tabulate.CanResize := FALSE;
12270 Buttons.Free;
12272 if Assigned( CallBack ) then
12273 CallBack( Dialog );
12274 Dialog.CreateWindow; // virtual!!!
12276 if (Applet <> nil) and Applet.IsApplet then
12277 begin
12278 Dialog.ShowModal;
12279 Result := Dialog.ModalResult;
12280 Dialog.Free;
12282 else
12283 begin
12284 DlgWnd := Dialog.Handle;
12285 while IsWindow( DlgWnd ) and (Dialog.ModalResult = 0) do
12286 Dialog.ProcessMessage;
12287 Result := Dialog.ModalResult;
12288 Dialog.Free;
12289 CreatingWindow := nil;
12290 Applet := AppCtl;
12291 end;
12293 AppletTerminated := AppTermFlag;
12294 end;
12295 //[END ShowQuestionEx]
12297 //[function ShowQuestion]
12298 function ShowQuestion( const S: String; Answers: String ): Integer;
12299 begin
12300 Result := ShowQuestionEx( S, Answers, nil );
12301 end;
12302 //[END ShowQuestion]
12304 //[procedure ShowMsgModal]
12305 procedure ShowMsgModal( const S: String );
12306 begin
12307 ShowQuestion( S, '' );
12308 end;
12309 //[ENDe ShowMsgModal]
12311 //[procedure SpeakerBeep]
12312 procedure SpeakerBeep( Freq: Word; Duration: DWORD );
12313 begin
12314 if WinVer >= wvNT then
12315 Windows.Beep( Freq, Duration )
12316 else
12317 begin
12318 if Freq < 18 then Exit;
12319 Freq := 1193181 div Freq;
12320 if Freq = 0 then Exit;
12322 mov al,0b6H
12323 out 43H,al
12324 mov ax,Freq
12325 //xchg al, ah
12326 out 42h,al
12327 xchg al, ah
12328 out 42h,al
12329 in al,61H
12330 or al,03H
12331 out 61H,al
12332 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF} ;
12333 Sleep(Duration);
12335 in al,61H
12336 and al,0fcH
12337 out 61H,al
12338 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF} ;
12339 end;
12340 end;
12341 //[ENDe SpeakerBeep]
12343 {++}(*
12344 //[API FormatMessage]
12345 function FormatMessage; external kernel32 name 'FormatMessageA';
12346 *){--}
12348 //[FUNCTION SysErrorMessage]
12349 function SysErrorMessage(ErrorCode: Integer): string;
12351 Len: Integer;
12352 Buffer: array[0..255] of Char;
12353 begin
12354 Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
12355 FORMAT_MESSAGE_ARGUMENT_ARRAY, nil, ErrorCode, 0, Buffer,
12356 SizeOf(Buffer), nil);
12357 while (Len > 0) and (Buffer[Len - 1] in [#0..#32 {, '.'}]) do Dec(Len);
12358 SetString(Result, Buffer, Len);
12359 end;
12360 //[END SysErrorMessage]
12362 //[function MakeMethod]
12363 function MakeMethod( Data, Code: Pointer ): TMethod;
12364 begin
12365 Result.Data := Data;
12366 Result.Code := Code;
12367 end;
12368 //[END MakeMethod]
12370 //[function GetShiftState]
12371 function GetShiftState: DWORD;
12372 begin
12373 Result := 0;
12374 if GetKeyState( VK_SHIFT ) < 0 then
12375 Result := Result or MK_SHIFT;
12376 if GetKeyState( VK_CONTROL ) < 0 then
12377 Result := Result or MK_CONTROL;
12378 //if LONGBOOL(Msg.lParam and $20000000) then
12379 if GetKeyState( VK_MENU ) < 0 then
12380 Result := Result or MK_ALT;
12381 end;
12382 //[END GetShiftState]
12384 //[FUNCTION MakeRect]
12385 {$IFDEF ASM_VERSION}
12386 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;
12388 PUSH ESI
12389 PUSH EDI
12391 MOV EDI, @Result
12392 LEA ESI, [Left]
12394 MOVSD
12395 MOVSD
12396 MOVSD
12397 MOVSD
12399 POP EDI
12400 POP ESI
12401 end;
12402 {$ELSE ASM_VERSION} //Pascal
12403 function MakeRect( Left, Top, Right, Bottom: Integer ): TRect; stdcall;
12404 begin
12405 Result.Left := Left;
12406 Result.Top := Top;
12407 Result.Right:= Right;
12408 Result.Bottom := Bottom;
12409 end;
12410 {$ENDIF ASM_VERSION}
12411 //[END MakeRect]
12413 //[FUNCTION RectsEqual]
12414 {$IFDEF ASM_VERSION}
12415 function RectsEqual( const R1, R2: TRect ): Boolean;
12417 //LEA EAX, [R1]
12418 //LEA EDX, [R2]
12419 MOV ECX, size_TRect
12420 CALL CompareMem
12421 end;
12422 {$ELSE ASM_VERSION} //Pascal
12423 function RectsEqual( const R1, R2: TRect ): Boolean;
12424 begin
12425 Result := CompareMem( @R1, @R2, Sizeof( TRect ) );
12426 end;
12427 {$ENDIF ASM_VERSION}
12428 //[END RectsEqual]
12430 //[function RectsIntersected]
12431 function RectsIntersected( const R1, R2: TRect ): Boolean;
12432 begin
12433 Result := ((R1.Left <= R2.Left) and (R1.Right > R2.Left ) or
12434 (R1.Left <= R2.Right) and (R1.Right >= R2.Right) or
12435 (R1.Left >= R2.Left) and (R1.Right <= R2.Right))
12437 ((R1.Top <= R2.Top) and (R1.Bottom > R2.Top) or
12438 (R1.Top <= R2.Bottom) and (R1.Bottom >= R2.Bottom) or
12439 (R1.Top >= R2.Top) and (R1.Bottom <= R2.Bottom)) ;
12440 end;
12441 //[END RectsIntersected]
12444 //[FUNCTION PointInRect]
12445 {$IFDEF ASM_VERSION}
12446 function PointInRect( const P: TPoint; const R: TRect ): Boolean;
12448 PUSH ESI
12449 MOV ECX, EAX
12450 MOV ESI, EDX
12451 LODSD
12452 CMP EAX, [ECX]
12453 JG @@fail
12454 LODSD
12455 CMP EAX, [ECX+4]
12456 JG @@fail
12457 LODSD
12458 CMP [ECX], EAX
12459 JG @@fail
12460 LODSD
12461 CMP [ECX+4], EAX
12462 @@fail: SETLE AL
12463 POP ESI
12464 end;
12465 {$ELSE ASM_VERSION} //Pascal
12466 function PointInRect( const P: TPoint; const R: TRect ): Boolean;
12467 begin
12468 Result := (P.x >= R.Left) and (P.x < R.Right)
12469 and (P.y >= R.Top) and (P.y < R.Bottom);
12470 end;
12471 {$ENDIF ASM_VERSION}
12472 //[END PointInRect]
12474 //[FUNCTION MakePoint]
12475 {$IFDEF ASM_VERSION}
12476 function MakePoint( X, Y: Integer ): TPoint;
12478 MOV ECX, @Result
12479 MOV [ECX].TPoint.x, EAX
12480 MOV [ECX].TPoint.y, EDX
12481 end;
12482 {$ELSE ASM_VERSION} //Pascal
12483 function MakePoint( X, Y: Integer ): TPoint;
12484 begin
12485 Result.x := X;
12486 Result.y := Y;
12487 end;
12488 {$ENDIF ASM_VERSION}
12489 //[END MakePoint]
12491 //[FUNCTION MakeFlags]
12492 {$IFDEF ASM_VERSION}
12493 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;
12495 PUSH EBX
12496 PUSH ESI
12497 MOV EBX, [EAX]
12498 MOV ESI, EDX
12499 XOR EDX, EDX
12500 INC ECX
12501 JZ @@exit
12502 @@loo:
12503 LODSD
12504 TEST EAX, EAX
12505 JGE @@ge
12506 NOT EAX
12507 TEST BL, 1
12508 JZ @@or
12509 DEC EBX
12510 @@ge:
12511 TEST BL, 1
12512 JZ @@nx
12513 @@or:
12514 OR EDX, EAX
12515 @@nx:
12516 SHR EBX, 1
12517 LOOP @@loo
12519 @@exit:
12520 XCHG EAX, EDX
12521 POP ESI
12522 POP EBX
12523 end;
12524 {$ELSE ASM_VERSION} //Pascal
12525 function MakeFlags( FlgSet: PDWORD; FlgArray: array of Integer): Integer;
12526 var I : Integer;
12527 Mask : DWORD;
12528 begin
12529 Result := 0;
12530 Mask := FlgSet^;
12531 for I := 0 to High( FlgArray ) do
12532 begin
12533 if (FlgArray[ I ] < 0) and not LongBool( Mask and 1 ) then
12534 Result := Result or not FlgArray[ I ]
12535 else
12536 if (FlgArray[ I ] >= 0) and LongBool( Mask and 1 ) then
12537 Result := Result or FlgArray[ I ];
12538 Mask := Mask shr 1;
12539 end;
12540 end;
12541 {$ENDIF ASM_VERSION}
12542 //[END MakeFlags]
12544 //[procedure HelpFastIncNum2Els]
12545 procedure HelpFastIncNum2Els( DataArray: Pointer; Value, Count: Integer );
12547 PUSH ESI
12548 PUSH EDI
12549 {$IFDEF F_P}
12550 MOV ESI, [DataArray]
12551 MOV EDX, [Value]
12552 MOV ECX, [Count]
12553 {$ELSE DELPHI}
12554 MOV ESI, EAX
12555 {$ENDIF F_P/DELPHI}
12556 MOV EDI, ESI
12559 @@1:
12560 LODSD
12561 ADD EAX, EDX
12562 STOSD
12563 LOOP @@1
12565 POP EDI
12566 POP ESI
12567 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
12568 //[ENDe HelpFastIncNum2Els]
12570 //[procedure Swap]
12571 procedure Swap( var X, Y: Integer );
12572 {$IFDEF F_P}
12573 var Tmp: Integer;
12574 begin
12575 Tmp := X;
12576 X := Y;
12577 Y := Tmp;
12578 end;
12579 {$ELSE DELPHI}
12581 MOV ECX, [EDX]
12582 XCHG ECX, [EAX]
12583 MOV [EDX], ECX
12584 end;
12585 //[ENDe Swap]
12586 {$ENDIF F_P/DELPHI}
12588 //[function Min]
12589 function Min( X, Y: Integer ): Integer;
12591 {$IFDEF F_P}
12592 MOV EAX, [X]
12593 MOV EDX, [Y]
12594 {$ENDIF F_P}
12595 {$IFDEF USE_CMOV}
12596 CMP EAX, EDX
12597 CMOVG EAX, EDX
12598 {$ELSE}
12599 CMP EAX, EDX
12600 JLE @@exit
12601 MOV EAX, EDX
12602 @@exit:
12603 {$ENDIF}
12604 end {$IFDEF F_P} [ 'EAX', 'EDX' ] {$ENDIF};
12605 //[END Min]
12607 //[function Max]
12608 function Max( X, Y: Integer ): Integer;
12610 {$IFDEF F_P}
12611 MOV EAX, [X]
12612 MOV EDX, [Y]
12613 {$ENDIF F_P}
12614 {$IFDEF USE_CMOV}
12615 CMP EAX, EDX
12616 CMOVL EAX, EDX
12617 {$ELSE}
12618 CMP EAX, EDX
12619 JGE @@exit
12620 MOV EAX, EDX
12621 @@exit:
12622 {$ENDIF}
12623 end {$IFDEF F_P} [ 'EAX', 'EDX' ] {$ENDIF};
12624 //[END Max]
12626 {$IFDEF REDEFINE_ABS}
12627 //[function Abs]
12628 function Abs( X: Integer ): Integer;
12630 {$IFDEF F_P}
12631 MOV EAX, [X]
12632 {$ENDIF F_P}
12633 TEST EAX, EAX
12634 JGE @@1
12635 NEG EAX
12636 @@1:
12637 end {$IFDEF F_P} [ 'EAX' ] {$ENDIF};
12638 //[END Abs]
12639 {$ENDIF}
12641 //[function Sgn]
12642 function Sgn( X: Integer ): Integer;
12644 CMP EAX, 0
12645 {$IFDEF USE_CMOV}
12646 MOV EDX, -1
12647 CMOVL EAX, EDX
12648 MOV EDX, 1
12649 CMOVG EAX, EDX
12650 {$ELSE}
12651 JZ @@exit
12652 MOV EAX, 1
12653 JG @@exit
12654 MOV EAX, -1
12655 @@exit:
12656 {$ENDIF}
12657 end;
12658 //[END Sgn]
12660 //[function iSqrt]
12661 function iSQRT( X: Integer ): Integer;
12662 var I, N: Integer;
12663 begin
12664 Result := 0;
12665 while Result < X do
12666 begin
12667 I := 1;
12668 while I > 0 do
12669 begin
12670 N := (Result + I) * (Result + I);
12671 if N > X then
12672 begin
12673 I := I shr 1;
12674 break;
12676 else
12677 if N = X then
12678 begin
12679 Result := Result + I;
12680 Exit;
12681 end;
12682 I := I shl 1;
12683 end;
12684 if I <= 0 then Exit;
12685 Result := Result + I;
12686 end;
12687 end;
12688 //[END iSqrt]
12690 {$IFDEF ASM_VERSION}
12691 //[PROCEDURE StartDC]
12692 procedure StartDC;
12694 { <- EBX : PBitmap
12695 -> EAX = dc
12696 [ESP+8] = var dc
12697 [ESP+4] = var SaveBmp
12699 PUSH 0
12700 CALL CreateCompatibleDC
12701 POP EDX
12702 PUSH EAX
12703 PUSH EDX
12704 MOV EAX, EBX
12705 CALL [EBX].TBitmap.fDetachCanvas
12706 MOV EAX, EBX
12707 CALL TBitmap.GetHandle
12708 PUSH EAX
12709 PUSH dword ptr [ESP+8]
12710 CALL SelectObject
12711 POP EDX
12712 PUSH EAX
12713 PUSH EDX
12714 MOV EAX, [ESP+8]
12715 end;
12716 //[END StartDC]
12718 //[procedure FinishDC]
12719 procedure FinishDC;
12721 POP ECX
12722 POP EAX
12723 POP EDX
12724 PUSH ECX
12725 PUSH EDX
12726 PUSH EAX
12727 PUSH EDX
12728 CALL SelectObject
12729 CALL DeleteDC
12730 end;
12731 //[ENDe FinishDC]
12732 {$ELSE ASM_VERSION}
12733 {$ENDIF ASM_VERSION}
12735 //[procedure FastIncNum2Elements]
12736 procedure FastIncNum2Elements( List: TList; FromIdx, Count, Value: Integer );
12737 begin
12738 HelpFastIncNum2Els( @List.fItems[ FromIdx ], Value, Count );
12739 end;
12741 //[function EnumDynHandlers FORWARD DECLARATION]
12742 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
12743 forward;
12745 //[procedure DummyObjProc]
12746 procedure DummyObjProc( Sender: PObj );
12747 begin
12748 end;
12750 //[procedure DummyObjProcParam]
12751 procedure DummyObjProcParam( Sender: PObj; Param: Pointer );
12752 begin
12753 end;
12755 //[procedure DummyPaintProc]
12756 procedure DummyPaintProc( Sender: PControl; DC: HDC );
12757 begin
12758 end;
12760 //[procedure Free_And_Nil]
12761 procedure Free_And_Nil( var Obj );
12762 var Obj1: PObj;
12763 begin
12764 Obj1 := PObj( Obj );
12765 Pointer( Obj ) := nil;
12766 Obj1.Free;
12767 end;
12768 //[ENDe Free_And_Nil]
12770 {$IFDEF USE_NAMES}
12771 function FindObj( const Name: String ): PObj;
12772 var i: Integer;
12773 Obj: PObj;
12774 begin
12775 if NamedObjectsList = nil then
12776 NamedObjectsList := NewList;
12777 for i := 0 to NamedObjectsList.Count-1 do
12778 begin
12779 Obj := NamedObjectsList.Items[ i ];
12780 if Name = Obj.FName then
12781 begin
12782 Result := Obj; Exit;
12783 end;
12784 end;
12785 Result := nil;
12786 end;
12787 {$ENDIF}
12793 { _TObj }
12795 //[procedure _TObj.Init]
12796 procedure _TObj.Init;
12797 begin
12798 {$IFDEF _D2orD3}
12799 FillChar( Pointer( Integer(@Self) + 4 )^, Sizeof( Self ) - 4, 0 );
12800 {$ENDIF}
12801 end;
12804 //[function _TObj.VmtAddr]
12805 function _TObj.VmtAddr: Pointer;
12807 MOV EAX, [EAX]
12808 end;
12810 { TObj }
12812 class function TObj.AncestorOfObject(Obj: Pointer): Boolean;
12814 MOV ECX, [EAX]
12815 MOV EAX, EDX
12816 JMP @@loop1
12817 @@loop:
12818 MOV EAX,[EAX]
12819 @@loop1:
12820 TEST EAX,EAX
12821 JE @@exit
12822 CMP EAX,ECX
12823 JNE @@loop
12824 @@success:
12825 MOV AL,1
12826 @@exit:
12827 end;
12831 {$IFDEF ASM_VERSION}
12832 constructor TObj.Create;
12834 //CALL System.@ObjSetup - Generated always by compiler
12835 //JZ @@exit
12837 PUSH EAX
12838 MOV EDX, [EAX]
12839 CALL dword ptr [EDX]
12840 POP EAX
12842 @@exit:
12843 end;
12844 {$ELSE ASM_VERSION} //Pascal
12845 constructor TObj.Create;
12846 begin
12847 Init;
12848 {++}(* inherited; *){--}
12849 end;
12850 {$ENDIF ASM_VERSION}
12852 {$IFDEF ASM_VERSION}
12853 //[procedure TObj.DoDestroy]
12854 procedure TObj.DoDestroy;
12856 MOV EDX, [EAX].fRefCount
12857 SAR EDX, 1
12858 JZ @@1
12859 JC @@exit
12860 DEC [EAX].fRefCount
12863 @@1: JC @@exit
12864 MOV EDX, [EAX]
12865 CALL dword ptr [EDX + 4]
12866 @@exit:
12867 end;
12868 {$ELSE ASM_VERSION} //Pascal
12869 procedure TObj.DoDestroy;
12870 begin
12871 if fRefCount <> 0 then
12872 begin
12873 if not LongBool( fRefCount and 1) then
12874 Dec( fRefCount );
12876 else
12877 Destroy;
12878 end;
12879 {$ENDIF ASM_VERSION}
12881 {$IFDEF ASM_VERSION}
12882 //[procedure TObj.RefDec]
12883 procedure TObj.RefDec;
12885 SUB [EAX].fRefCount, 2
12886 JGE @@exit
12887 TEST [EAX].fRefCount, 1
12888 JZ @@exit
12889 MOV EDX, [EAX]
12890 PUSH dword ptr [EDX+4]
12891 @@exit:
12892 end;
12893 {$ELSE ASM_VERSION} //Pascal
12894 procedure TObj.RefDec;
12895 begin
12896 Dec( fRefCount, 2 );
12897 if (fRefCount < 0) and LongBool(fRefCount and 1) then
12898 Destroy;
12899 end;
12900 {$ENDIF ASM_VERSION}
12902 //[procedure TObj.RefInc]
12903 procedure TObj.RefInc;
12904 begin
12905 Inc( fRefCount, 2 );
12906 end;
12909 //[function TObj.VmtAddr]
12910 function TObj.VmtAddr: Pointer;
12912 MOV EAX, [EAX - 4]
12913 end;
12915 //[function TObj.InstanceSize]
12916 function TObj.InstanceSize: Integer;
12918 MOV EAX, [EAX]
12919 MOV EAX,[EAX-4]
12920 end;
12923 //[procedure TObj.Free]
12924 {$IFDEF F_P}
12925 procedure TObj.Free;
12926 begin
12927 if Self <> nil then
12928 DoDestroy;
12929 end;
12930 {$ELSE DELPHI}
12931 procedure TObj.Free;
12933 TEST EAX,EAX
12934 JNE DoDestroy
12935 end;
12936 {$ENDIF F_P/DELPHI}
12938 {$IFDEF ASM_VERSION}
12939 destructor TObj.Destroy;
12941 PUSH EAX
12942 CALL Final
12943 POP EAX
12944 {$IFDEF USE_NAMES}
12945 PUSH EAX
12946 XOR EDX, EDX
12947 CALL SetName
12948 POP EAX
12949 {$ENDIF}
12950 XOR EDX, EDX
12951 CALL System.@FreeMem
12952 //CALL System.@Dispose
12953 end;
12954 {$ELSE ASM_VERSION} //Pascal
12955 destructor TObj.Destroy;
12956 begin
12957 Final;
12958 {$IFDEF USE_NAMES}
12959 Name := '';
12960 {$ENDIF}
12961 {$IFDEF DEBUG_ENDSESSION}
12962 if EndSession_Initiated then
12963 LogFileOutput( GetStartDir + 'es_debug.txt',
12964 'FINALLED: ' + Int2Hex( DWORD( @ Self )
12965 {$IFDEF USE_NAMES}
12966 + ' (name:' + FName + ')'
12967 {$ENDIF}
12968 , 8 ) );
12969 {$ENDIF}
12971 Dispose( @Self );
12972 {+} {++}(*
12973 inherited; *){--}
12974 end;
12975 {$ENDIF ASM_VERSION}
12977 {++}(*
12978 //[procedure TObj.Init]
12979 procedure TObj.Init;
12980 begin
12982 end;
12983 *){--}
12985 {$IFDEF ASM_VERSION}
12986 //[procedure TObj.Final]
12987 procedure TObj.Final;
12988 asm //cmd //opd
12989 XOR ECX, ECX
12990 XCHG ECX, [EAX].fOnDestroy.TMethod.Code
12991 JECXZ @@doAutoFree
12992 PUSH EAX
12993 XCHG EDX, EAX
12994 MOV EAX, [EDX].fOnDestroy.TMethod.Data
12995 CALL ECX
12996 POP EAX
12997 @@doAutoFree:
12998 XOR ECX, ECX
12999 XCHG ECX, [EAX].fAutoFree
13000 JECXZ @@exit
13001 PUSH ESI
13002 PUSH ECX
13003 MOV ESI, [ECX].TList.fItems
13004 MOV ECX, [ECX].TList.fCount
13005 @@freeloop:
13006 LODSD
13007 XCHG EDX, EAX
13008 LODSD
13009 PUSH ECX
13010 CALL EDX
13011 POP ECX
13012 DEC ECX
13013 LOOP @@freeloop
13014 POP EAX
13015 CALL TObj.Free
13016 POP ESI
13017 @@exit:
13018 end;
13019 {$ELSE ASM_VERSION} //Pascal
13020 procedure TObj.Final;
13021 var I: Integer;
13022 ProcMethod: TMethod;
13023 Proc: TObjectMethod Absolute ProcMethod;
13024 begin
13025 if Assigned( fOnDestroy ) then
13026 begin
13027 fOnDestroy( @Self );
13028 fOnDestroy := nil;
13029 end;
13030 if fAutoFree <> nil then
13031 begin
13032 for I := 0 to fAutoFree.fCount div 2 - 1 do
13033 begin
13034 ProcMethod.Code := fAutoFree.fItems[ I * 2 ];
13035 ProcMethod.Data := fAutoFree.fItems[ I * 2 + 1 ];
13037 Proc;
13038 {+}{++}(*
13040 MOV EAX, [ProcMethod.Data]
13041 {$IFDEF F_P}
13042 PUSH EAX
13043 {$ENDIF F_P}
13044 MOV ECX, [ProcMethod.Code]
13045 CALL ECX
13046 end {$IFDEF F_P}[ 'EAX', 'EDX', 'ECX' ]{$ENDIF};
13047 *){--}
13048 end;
13049 fAutoFree.Free;
13050 fAutoFree := nil;
13051 end;
13052 end;
13053 {$ENDIF ASM_VERSION}
13055 {$IFDEF ASM_VERSION}
13056 //[procedure TObj.Add2AutoFree]
13057 procedure TObj.Add2AutoFree(Obj: PObj);
13058 asm //cmd //opd
13059 PUSH EBX
13060 PUSH EDX
13061 XCHG EBX, EAX
13062 MOV EAX, [EBX].fAutoFree
13063 TEST EAX, EAX
13064 JNZ @@1
13065 CALL NewList
13066 MOV [EBX].fAutoFree, EAX
13067 @@1: MOV EBX, EAX
13068 XOR EDX, EDX
13069 POP ECX
13070 CALL TList.Insert
13071 XCHG EAX, EBX
13072 XOR EDX, EDX
13073 MOV ECX, offset TObj.Free
13074 //XOR ECX, ECX
13075 CALL TList.Insert
13076 POP EBX
13077 end;
13078 {$ELSE ASM_VERSION} //Pascal
13079 procedure TObj.Add2AutoFree(Obj: PObj);
13080 begin
13081 if fAutoFree = nil then
13082 fAutoFree := NewList;
13083 fAutoFree.Insert( 0, Obj );
13084 fAutoFree.Insert( 0, Pointer( @TObj.Free ) );
13085 end;
13086 {$ENDIF ASM_VERSION}
13088 {$IFDEF ASM_VERSION}
13089 //[procedure TObj.Add2AutoFreeEx]
13090 procedure TObj.Add2AutoFreeEx( Proc: TObjectMethod );
13091 asm //cmd //opd
13092 PUSH EBX
13093 XCHG EAX, EBX
13094 MOV EAX, [EBX].fAutoFree
13095 TEST EAX, EAX
13096 JNZ @@1
13097 CALL NewList
13098 MOV [EBX].fAutoFree, EAX
13099 @@1: XOR EDX, EDX
13100 MOV ECX, [EBP+12] // Data
13101 MOV EBX, EAX
13102 CALL TList.Insert
13103 XCHG EAX, EBX
13104 XOR EDX, EDX
13105 MOV ECX, [EBP+8] // Code
13106 CALL TList.Insert
13107 POP EBX
13108 end;
13109 {$ELSE ASM_VERSION} //Pascal
13110 procedure TObj.Add2AutoFreeEx( Proc: TObjectMethod );
13111 {$IFDEF F_P}
13112 var Ptr1, Ptr2: Pointer;
13113 {$ENDIF F_P}
13114 begin
13115 if fAutoFree = nil then
13116 fAutoFree := NewList;
13117 {$IFDEF F_P}
13119 MOV EAX, [Proc]
13120 MOV [Ptr1], EAX
13121 MOV EAX, [Proc+4]
13122 MOV [Ptr2], EAX
13123 end [ 'EAX' ];
13124 fAutoFree.Insert( 0, Ptr2 );
13125 fAutoFree.Insert( 0, Ptr1 );
13126 {$ELSE DELPHI}
13127 fAutoFree.Insert( 0, Pointer( TMethod( Proc ).Data ) );
13128 fAutoFree.Insert( 0, Pointer( TMethod( Proc ).Code ) );
13129 {$ENDIF}
13130 end;
13131 {$ENDIF ASM_VERSION}
13133 {$IFDEF USE_NAMES}
13134 procedure TObj.SetName(const NewName: String);
13135 begin
13136 if FName <> '' then
13137 begin
13138 NamedObjectsList.Remove( @ Self );
13139 FName := '';
13140 end;
13141 if FindObj( NewName ) <> nil then Exit; // prevent duplications!
13142 FName := NewName;
13143 if FName <> '' then
13144 NamedObjectsList.Add( @ Self );
13145 end;
13146 {$ENDIF}
13161 { TList }
13163 {$IFDEF USE_CONSTRUCTORS}
13164 //[function NewList]
13165 function NewList: PList;
13166 begin
13167 New( Result, Create );
13168 //Result.fAddBy := 4;
13169 end;
13170 //[END NewList]
13172 //[procedure TList.Init]
13173 procedure TList.Init;
13174 begin
13175 inherited;
13176 fAddBy := 4;
13177 end;
13178 {$ELSE not_USE_CONSTRUCTORS}
13179 //[function NewList]
13180 function NewList: PList;
13181 begin
13183 New( Result, Create );
13184 {+} {++}(* Result := PList.Create; *){--}
13185 //Result.fAddBy := 4;
13186 end;
13187 //[END NewList]
13188 {$ENDIF USE_CONSTRUCTORS}
13190 {$IFDEF _D4orHigher}
13191 function NewListInit( const AItems: array of Pointer ): PList;
13192 var i: Integer;
13193 begin
13194 Result := NewList;
13195 Result.Capacity := Length( AItems );
13196 for i := 0 to High( AItems ) do
13197 Result.Add( AItems[ i ] );
13198 end;
13199 {$ENDIF}
13201 {$IFDEF ASM_VERSION}
13202 destructor TList.Destroy;
13204 PUSH EAX
13205 CALL TList.Clear
13206 POP EAX
13207 CALL TObj.Destroy
13208 end;
13209 {$ELSE ASM_VERSION} //Pascal
13210 destructor TList.Destroy;
13211 begin
13212 Clear;
13213 inherited;
13214 end;
13215 {$ENDIF ASM_VERSION}
13217 {$IFDEF ASM_VERSION}
13218 //[procedure TList.Release]
13219 procedure TList.Release;
13221 TEST EAX, EAX
13222 JZ @@e
13223 MOV ECX, [EAX].fCount
13224 JECXZ @@e
13225 MOV EDX, [EAX].fItems
13226 PUSH EAX
13227 @@1:
13228 MOV EAX, [EDX+ECX*4-4]
13229 TEST EAX, EAX
13230 JZ @@2
13231 PUSH EDX
13232 PUSH ECX
13233 CALL System.@FreeMem
13234 POP ECX
13235 POP EDX
13236 @@2: LOOP @@1
13237 POP EAX
13238 @@e: CALL TObj.Free
13239 end;
13240 {$ELSE ASM_VERSION} //Pascal
13241 procedure TList.Release;
13242 var I: Integer;
13243 begin
13244 if @ Self = nil then Exit;
13245 for I := 0 to fCount - 1 do
13246 if fItems[ I ] <> nil then
13247 FreeMem( fItems[ I ] );
13248 Free;
13249 end;
13250 {$ENDIF ASM_VERSION}
13252 //[procedure TList.ReleaseObjects]
13253 procedure TList.ReleaseObjects;
13254 var I: Integer;
13255 begin
13256 if @ Self = nil then Exit;
13257 for I := fCount-1 downto 0 do
13258 PObj( fItems[ I ] ).Free;
13259 Free;
13260 end;
13262 {$IFDEF ASM_VERSION}
13263 //[procedure TList.SetCapacity]
13264 procedure TList.SetCapacity( Value: Integer );
13266 CMP EDX, [EAX].fCount
13267 {$IFDEF USE_CMOV}
13268 CMOVL EDX, [EAX].fCount
13269 {$ELSE}
13270 JGE @@1
13271 MOV EDX, [EAX].fCount
13272 @@1: {$ENDIF}
13273 CMP EDX, [EAX].fCapacity
13274 JE @@exit
13276 MOV [EAX].fCapacity, EDX
13277 SAL EDX, 2
13278 LEA EAX, [EAX].fItems
13279 CALL System.@ReallocMem
13280 @@exit:
13281 end;
13282 {$ELSE ASM_VERSION} //Pascal
13283 //var NewItems: PPointerList;
13284 procedure TList.SetCapacity( Value: Integer );
13285 begin
13286 if Value < Count then
13287 Value := Count;
13288 if Value = fCapacity then Exit;
13289 ReallocMem( fItems, Value * Sizeof( Pointer ) );
13290 fCapacity := Value;
13291 end;
13292 {$ENDIF ASM_VERSION}
13294 {$IFDEF ASM_VERSION}
13295 //[procedure TList.Clear]
13296 procedure TList.Clear;
13298 PUSH [EAX].fItems
13299 XOR EDX, EDX
13300 MOV [EAX].fItems, EDX
13301 MOV [EAX].fCount, EDX
13302 MOV [EAX].fCapacity, EDX
13303 POP EAX
13304 CALL System.@FreeMem
13305 end;
13306 {$ELSE ASM_VERSION} //Pascal
13307 procedure TList.Clear;
13308 begin
13309 if fItems <> nil then
13310 FreeMem( fItems );
13311 fItems := nil;
13312 fCount := 0;
13313 fCapacity := 0;
13314 end;
13315 {$ENDIF ASM_VERSION}
13317 //[procedure TList.SetAddBy]
13318 procedure TList.SetAddBy(Value: Integer);
13319 begin
13320 if Value < 1 then Value := 1;
13321 fAddBy := Value;
13322 end;
13324 {$IFDEF ASM_VERSION}
13325 //[procedure TList.Add]
13326 procedure TList.Add( Value: Pointer );
13328 PUSH EDX
13329 LEA ECX, [EAX].fCount
13330 MOV EDX, [ECX]
13331 INC dword ptr [ECX]
13332 PUSH EDX
13333 CMP EDX, [EAX].fCapacity
13334 PUSH EAX
13335 JL @@ok
13337 MOV ECX, [EAX].fAddBy
13338 TEST ECX, ECX
13339 JNZ @@add
13340 MOV ECX, EDX
13341 SHR ECX, 2
13342 INC ECX
13343 @@add:
13344 ADD EDX, ECX
13345 CALL TList.SetCapacity
13346 @@ok:
13347 POP ECX // ECX = Self
13348 POP EAX // EAX = fCount -> Result (for TList.Insert)
13349 POP EDX // EDX = Value
13351 MOV ECX, [ECX].fItems
13352 MOV [ECX + EAX*4], EDX
13353 end;
13354 {$ELSE ASM_VERSION} //Pascal
13355 procedure TList.Add( Value: Pointer );
13356 begin
13357 //if fAddBy <= 0 then fAddBy := 4;
13358 if fCapacity <= Count then
13359 begin
13360 if fAddBy <= 0 then
13361 Capacity := Count + Min( 1000, Count div 4 + 1 )
13362 else
13363 Capacity := Count + fAddBy;
13364 end;
13365 fItems[ fCount ] := Value;
13366 Inc( fCount );
13367 end;
13368 {$ENDIF ASM_VERSION}
13370 {$IFDEF _D4orHigher}
13371 procedure TList.AddItems(const AItems: array of Pointer);
13372 var i: Integer;
13373 begin
13374 Capacity := Count + Length( AItems );
13375 for i := 0 to High( AItems ) do
13376 Add( AItems[ i ] );
13377 end;
13378 {$ENDIF}
13380 //[procedure TList.Delete]
13381 procedure TList.Delete( Idx: Integer );
13382 begin
13383 {Assert( (Idx >= 0) and (Idx < fCount), 'TList.Delete: index out of bounds' );
13384 Move( fItems[ Idx + 1 ], fItems[ Idx ], Sizeof( Pointer ) * (Count - Idx - 1) );
13385 Dec( fCount );}
13386 DeleteRange( Idx, 1 );
13387 end;
13389 {$IFDEF ASM_VERSION}
13390 //[procedure TList.DeleteRange]
13391 procedure TList.DeleteRange(Idx, Len: Integer);
13392 asm //cmd //opd
13393 TEST ECX, ECX
13394 JLE @@exit
13395 CMP EDX, [EAX].fCount
13396 JGE @@exit
13397 PUSH EBX
13398 XCHG EBX, EAX
13399 LEA EAX, [EDX+ECX]
13400 CMP EAX, [EBX].fCount
13401 JBE @@1
13402 MOV ECX, [EBX].fCount
13403 SUB ECX, EDX
13404 @@1:
13405 MOV EAX, [EBX].fItems
13406 PUSH [EBX].fCount
13407 SUB [EBX].fCount, ECX
13408 MOV EBX, EDX
13409 LEA EDX, [EAX+EDX*4]
13410 LEA EAX, [EDX+ECX*4]
13411 ADD EBX, ECX
13412 POP ECX
13413 SUB ECX, EBX
13414 SHL ECX, 2
13415 CALL System.Move
13416 POP EBX
13417 @@exit:
13418 end;
13419 {$ELSE ASM_VERSION} //Pascal
13420 procedure TList.DeleteRange(Idx, Len: Integer);
13421 begin
13422 if Len <= 0 then Exit;
13423 if Idx >= Count then Exit;
13424 Assert( (Idx >= 0), 'TList.DeleteRange: index out of bounds' );
13425 if DWORD( Idx + Len ) > DWORD( Count ) then
13426 Len := Count - Idx;
13427 Move( fItems[ Idx + Len ], fItems[ Idx ], Sizeof( Pointer ) * (Count - Idx - Len) );
13428 Dec( fCount, Len );
13429 end;
13430 {$ENDIF ASM_VERSION}
13432 //[procedure TList.Remove]
13433 procedure TList.Remove(Value: Pointer);
13434 var I: Integer;
13435 begin
13436 I := IndexOf( Value );
13437 if I >= 0 then
13438 Delete( I );
13439 end;
13441 //[procedure TList.Put]
13442 procedure TList.Put( Idx: Integer; Value: Pointer );
13443 begin
13444 if Idx < 0 then Exit;
13445 if Idx >= Count then Exit;
13446 //Assert( (Idx >= 0) and (Idx < fCount), 'TList.Put: index out of bounds' );
13447 fItems[ Idx ] := Value;
13448 end;
13450 //[function TList.Get]
13451 function TList.Get( Idx: Integer ): Pointer;
13452 begin
13453 Result := nil;
13454 if Idx < 0 then Exit;
13455 if Idx >= fCount then Exit;
13456 //Assert( (Idx >= 0) and (Idx < fCount), 'TList.Get: index out of bounds' );
13457 Result := fItems[ Idx ];
13458 end;
13460 {$IFDEF ASM_VERSION}
13461 //[function TList.IndexOf]
13462 function TList.IndexOf( Value: Pointer ): Integer;
13464 PUSH EDI
13466 MOV EDI, [EAX].fItems
13467 MOV ECX, [EAX].fCount
13468 PUSH EDI
13469 DEC EAX // make "NZ" - EAX always <> 1
13470 MOV EAX, EDX
13471 REPNZ SCASD
13472 POP EDX
13473 {$IFDEF USE_CMOV}
13474 CMOVNZ EDI, EDX
13475 {$ELSE}
13476 JZ @@succ
13477 MOV EDI, EDX
13478 @@succ: {$ENDIF}
13480 MOV EAX, EDI
13482 SBB EAX, EDX
13483 SAR EAX, 2
13485 POP EDI
13486 end;
13487 {$ELSE ASM_VERSION} //Pascal
13488 function TList.IndexOf( Value: Pointer ): Integer;
13489 var I: Integer;
13490 begin
13491 Result := -1;
13492 for I := 0 to Count - 1 do
13493 begin
13494 if fItems[ I ] = Value then
13495 begin
13496 Result := I;
13497 break;
13498 end;
13499 end;
13500 end;
13501 {$ENDIF ASM_VERSION}
13503 {$IFDEF ASM_VERSION}
13504 //[procedure TList.Insert]
13505 procedure TList.Insert(Idx: Integer; Value: Pointer);
13507 PUSH ECX
13508 PUSH EAX
13509 PUSH [EAX].fCount
13510 PUSH EDX
13511 CALL TList.Add // don't matter what to add
13512 POP EDX // EDX = Idx, Eax = Count-1
13513 POP EAX
13514 SUB EAX, EDX
13516 SAL EAX, 2
13517 MOV ECX, EAX // ECX = (Count - Idx - 1) * 4
13518 POP EAX
13519 MOV EAX, [EAX].fItems
13520 LEA EAX, [EAX + EDX*4]
13521 JL @@1
13522 PUSH EAX
13523 LEA EDX, [EAX + 4]
13524 CALL System.Move
13526 POP EAX // EAX = @fItems[ Idx ]
13527 @@1:
13528 POP ECX // ECX = Value
13529 MOV [EAX], ECX
13530 end;
13531 {$ELSE ASM_VERSION} //Pascal
13532 procedure TList.Insert(Idx: Integer; Value: Pointer);
13533 begin
13534 Assert( (Idx >= 0) and (Idx <= Count), 'List index out of bounds' );
13535 Add( nil );
13536 if fCount > Idx then
13537 Move( FItems[ Idx ], FItems[ Idx + 1 ], (fCount - Idx - 1) * Sizeof( Pointer ) );
13538 FItems[ Idx ] := Value;
13539 end;
13540 {$ENDIF ASM_VERSION}
13542 {$IFDEF ASM_VERSION}
13543 //[procedure TList.MoveItem]
13544 procedure TList.MoveItem(OldIdx, NewIdx: Integer);
13546 CMP EDX, ECX
13547 JE @@exit
13549 CMP ECX, [EAX].fCount
13550 JGE @@exit
13552 PUSH EDI
13554 MOV EDI, [EAX].fItems
13555 PUSH dword ptr [EDI + EDX*4]
13556 PUSH ECX
13557 PUSH EAX
13558 CALL TList.Delete
13559 POP EAX
13560 POP EDX
13561 POP ECX
13563 POP EDI
13564 CALL TList.Insert
13565 @@exit:
13566 end;
13567 {$ELSE ASM_VERSION} //Pascal
13568 procedure TList.MoveItem(OldIdx, NewIdx: Integer);
13569 var Item: Pointer;
13570 //I: Integer;
13571 begin
13572 if OldIdx = NewIdx then Exit;
13573 if NewIdx >= Count then Exit;
13574 Item := Items[ OldIdx ];
13575 Delete( OldIdx );
13576 Insert( NewIdx, Item );
13577 end;
13578 {$ENDIF ASM_VERSION}
13580 {$IFDEF ASM_VERSION}
13581 //[function TList.Last]
13582 function TList.Last: Pointer;
13583 asm //cmd //opd
13584 MOV ECX, [EAX].fCount
13585 JECXZ @@0
13586 MOV EAX, [EAX].fItems
13587 DEC ECX
13588 MOV ECX, [EAX + ECX*4]
13589 @@0: XCHG EAX, ECX
13590 end;
13591 {$ELSE ASM_VERSION} //Pascal
13592 function TList.Last: Pointer;
13593 begin
13594 if Count = 0 then
13595 Result := nil
13596 else
13597 Result := Items[ Count-1 ];
13598 end;
13599 {$ENDIF ASM_VERSION}
13601 {$IFDEF ASM_VERSION}
13602 //[procedure TList.Swap]
13603 procedure TList.Swap(Idx1, Idx2: Integer);
13605 MOV EAX, [EAX].fItems
13606 PUSH dword ptr [EAX + EDX*4]
13607 PUSH ECX
13608 MOV ECX, [EAX + ECX*4]
13609 MOV [EAX + EDX*4], ECX
13610 POP ECX
13611 POP EDX
13612 MOV [EAX + ECX*4], EDX
13613 end;
13614 {$ELSE ASM_VERSION} //Pascal
13615 procedure TList.Swap(Idx1, Idx2: Integer);
13616 var Tmp: Pointer;
13617 begin
13618 Tmp := FItems[ Idx1 ];
13619 FItems[ Idx1 ] := FItems[ Idx2 ];
13620 FItems[ Idx2 ] := Tmp;
13621 end;
13622 {$ENDIF ASM_VERSION}
13624 //[procedure TList.SetCount]
13625 procedure TList.SetCount(const Value: Integer);
13626 begin
13627 if Value >= Count then exit;
13628 fCount := Value;
13629 end;
13631 //[procedure TList.Assign]
13632 procedure TList.Assign(SrcList: PList);
13633 begin
13634 Clear;
13635 if SrcList.fCount > 0 then
13636 begin
13637 Capacity := SrcList.fCount;
13638 fCount := SrcList.fCount;
13639 Move( SrcList.FItems[ 0 ], FItems[ 0 ], Sizeof( Pointer ) * fCount );
13640 end;
13641 end;
13660 { -- Window procedure -- }
13662 {$IFDEF ASM_VERSION} //!!//!!
13663 //[FUNCTION CallCtlWndProc]
13664 function CallCtlWndProc( Ctl: PControl; var Msg: TMsg ): Integer;
13665 begin
13666 Result := Ctl.WndProc( Msg );
13667 end;
13668 //[END CallCtlWndProc]
13670 //[function WndFunc]
13671 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
13672 : Integer; stdcall;
13673 const size_TMsg = sizeof( TMsg );
13675 ADD ESP, -size_TMsg
13676 MOV EDX, ESP
13678 PUSH ESI
13679 PUSH EDI
13681 MOV EDI, EDX
13682 LEA ESI, [W]
13684 MOVSD
13685 MOVSD
13686 MOVSD
13687 MOVSD
13689 MOV EDI, EDX
13690 MOV EAX, [EDI]
13691 TEST EAX, EAX
13692 JZ @@self_is_nil
13694 MOV ECX, [CreatingWindow]
13695 JECXZ @@get_self_prop
13697 MOV [ECX].TControl.fHandle, EAX
13699 //set_self_prop:
13700 PUSH ECX
13701 PUSH ECX
13702 PUSH Offset[ID_SELF]
13703 PUSH EAX
13704 CALL SetProp
13706 XOR EAX, EAX
13707 MOV [CreatingWindow], EAX
13708 POP EAX // EAX = self_
13709 JMP @@self_got
13711 @@get_self_prop:
13712 PUSH Offset[ID_SELF]
13713 PUSH EAX
13714 CALL GetProp
13715 TEST EAX, EAX
13716 JNZ @@self_got
13718 @@self_is_nil:
13719 OR EAX, [ Applet ]
13720 JNZ @@self_got
13722 //try_defwndproc:
13723 POP EDI
13724 POP ESI
13725 MOV ESP, EBP
13726 POP EBP
13727 JMP DefWindowProc
13729 //@@id_self:
13730 // DB 'SELF_',0
13732 @@self_got:
13733 MOV EDX, EDI
13734 //CALL TControl.WndProc
13735 CALL CallCtlWndProc
13737 POP EDI
13738 POP ESI
13740 MOV ESP, EBP
13741 end;
13742 {$ELSE ASM_VERSION} //Pascal
13743 function WndFunc( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
13744 : Integer; stdcall;
13745 var M: TMsg;
13746 self_: PControl;
13747 begin
13748 M.hwnd := W;
13749 M.message := Msg;
13750 M.wParam := wParam;
13751 M.lParam := lParam;
13753 {$IFDEF DEBUG_ENDSESSION}
13754 if EndSession_Initiated then
13755 begin
13756 LogFileOutput( GetStartDir + 'es_debug.txt',
13757 'HWND:' + Int2Str( W ) + ' MSG:$' + Int2Hex( Msg, 4 ) +
13758 ' WParam: ' + Int2Str( wParam ) + '($' + Int2Hex( wParam, 8 ) + ')' +
13759 ' LParam: ' + Int2Str( lParam ) + '($' + Int2Hex( lParam, 8 ) + ')' );
13760 end;
13761 {$ENDIF}
13763 self_ := nil;
13764 if W <> 0 then
13765 begin
13766 if CreatingWindow <> nil then
13767 begin
13768 {$IFDEF DEBUG_CREATEWINDOW}
13769 LogFileOutput( GetStartDir + 'Session.log',
13770 'WndFunc: Creating window = ' + Int2Hex( Integer( CreatingWindow ), 4 ) +
13771 ' hwnd=' + Int2Str( M.hwnd ) +
13772 ' message=' + Int2Hex( M.message, 4 ) +
13773 ' wParam=' + Int2Str( M.wParam ) + '=$' + Int2Hex( M.wParam, 4 ) +
13774 ' lParam=' + Int2Str( M.lParam ) + '=$' + Int2Hex( M.lParam, 4 )
13776 {$ENDIF DEBUG_CREATEWINDOW}
13777 self_ := CreatingWindow;
13778 CreatingWindow.fHandle := W;
13779 SetProp( W, ID_SELF, THandle( CreatingWindow ) );
13780 CreatingWindow := nil;
13782 else
13783 self_ := Pointer( GetProp( W, ID_SELF ) );
13784 end;
13786 if self_ <> nil then
13787 Result := self_.WndProc( M )
13788 else
13789 if Assigned( Applet ) then
13790 Result := Applet.WndProc( M )
13791 else
13792 Result := DefWindowProc( W, Msg, wParam, lParam );
13793 {$IFDEF DEBUG_ENDSESSION}
13794 if EndSession_Initiated then
13795 begin
13796 LogFileOutput( GetStartDir + 'es_debug.txt',
13797 'HWND:' + Int2Str( W ) + ' MSG:$' + Int2Hex( Msg, 4 ) +
13798 ' Result: ' + Int2Str( Result ) + '($' + Int2Hex( Result, 8 ) + ')' );
13799 end;
13800 {$ENDIF}
13801 end;
13802 //[END WndFunc]
13803 {$ENDIF ASM_VERSION}
13806 IdleHandlers: PList;
13807 ProcessIdle: procedure ( Sender: PObj ) = DummyObjProc;
13809 //[procedure ProcessIdleProc]
13810 procedure ProcessIdleProc( Sender: PObj );
13812 i: integer;
13813 m: TMethod;
13814 begin
13815 if AppletTerminated then exit; // YS +
13816 i := 0;
13817 with IdleHandlers{-}^{+} do
13818 while i < Count do begin
13819 m.Code:=Items[i];
13820 Inc(i);
13821 m.Data:=Items[i];
13822 Inc(i);
13823 TOnEvent(m)(Sender);
13824 end;
13825 end;
13827 //[function FindIdleHandler]
13828 function FindIdleHandler( const OnIdle: TOnEvent ): integer;
13830 i: integer;
13831 begin
13832 i := 0;
13833 if not AppletTerminated then //+ {Maxim Pushkar}
13834 with TMethod(OnIdle), IdleHandlers{-}^{+} do
13835 while i < Count do begin
13836 if (Items[i] = Code) and (Items[i + 1] = Data) then
13837 begin
13838 Result := i;
13839 exit;
13840 end;
13841 Inc(i, 2);
13842 end;
13843 Result := -1;
13844 end;
13845 //[END FindIdleHandler]
13847 //[procedure RegisterIdleHandler]
13848 procedure RegisterIdleHandler( const OnIdle: TOnEvent );
13849 begin
13850 if IdleHandlers = nil then begin
13851 IdleHandlers := NewList;
13852 if Applet <> nil then
13853 Applet.Add2AutoFree(IdleHandlers);
13854 end;
13855 with TMethod(OnIdle) do
13856 begin
13857 IdleHandlers.Add(Code);
13858 IdleHandlers.Add(Data);
13859 end;
13860 ProcessIdle := @ProcessIdleProc;
13861 end;
13863 //[procedure UnRegisterIdleHandler]
13864 procedure UnRegisterIdleHandler( const OnIdle: TOnEvent );
13866 i: integer;
13867 begin
13868 i := FindIdleHandler(OnIdle);
13869 if i <> -1 then
13870 with IdleHandlers{-}^{+} do
13871 begin
13872 Delete(i);
13873 Delete(i);
13874 end;
13875 end;
13877 //[procedure TerminateExecution]
13878 procedure TerminateExecution( var AppletWnd: PControl );
13879 var App: PControl;
13880 Appalreadyterminated: Boolean;
13881 begin
13882 Appalreadyterminated := AppletTerminated;
13883 AppletTerminated := TRUE;
13884 AppletRunning := FALSE;
13885 App := Applet;
13886 Applet := nil;
13887 if (App <> nil) {and (App.RefCount >= 0)} then
13888 begin
13889 App.RefInc;
13890 if not Appalreadyterminated then
13891 begin
13892 App.ProcessMessages;
13893 App.Perform( WM_CLOSE, 0, 0 );
13894 end;
13895 AppletWnd := nil;
13896 App.Free;
13897 App.RefDec;
13898 end;
13899 end;
13901 //[PROCEDURE CallTControlCreateWindow]
13902 {$IFDEF ASM_VERSION}
13903 procedure CallTControlCreateWindow( Ctl: PControl );
13904 begin
13905 Ctl.CreateWindow;
13906 end;
13907 //[END CallTControlCreateWindow]
13909 //[PROCEDURE Run]
13910 procedure Run( var AppletWnd: PControl );
13912 PUSH EBX
13913 XCHG EBX, EAX
13915 INC [AppletRunning]
13916 MOV EAX, [EBX]
13917 MOV [Applet], EAX
13918 CALL CallTControlCreateWindow
13919 JMP @@2
13920 @@1:
13921 CALL WaitMessage
13922 MOV EAX, [EBX]
13923 CALL TControl.ProcessMessages
13924 {$IFNDEF NOT_USE_OnIdle}
13925 MOV EAX, [EBX]
13926 CALL [ProcessIdle]
13927 {$ENDIF}
13928 @@2:
13929 CMP [AppletTerminated],0
13930 JZ @@1
13932 XCHG EAX, EBX
13934 POP EBX
13935 TEST EAX, EAX
13936 JNZ TerminateExecution
13937 end;
13938 {$ELSE ASM_VERSION} //Pascal
13939 procedure Run( var AppletWnd: PControl );
13940 begin
13941 AppletRunning := True;
13942 Applet := AppletWnd;
13943 AppletWnd.CreateWindow; //virtual!!!
13944 while not AppletTerminated do
13945 begin
13946 WaitMessage;
13947 AppletWnd.ProcessMessages;
13948 {$IFNDEF NOT_USE_OnIdle}
13949 ProcessIdle( AppletWnd );
13950 {$ENDIF}
13951 end;
13952 if AppletWnd <> nil then
13953 TerminateExecution( AppletWnd );
13954 end;
13955 //[END Run]
13956 {$ENDIF ASM_VERSION}
13958 //[procedure AppletMinimize]
13959 procedure AppletMinimize;
13960 begin
13961 if Applet = nil then Exit;
13962 Applet.Perform( WM_SYSCOMMAND, SC_MINIMIZE, 0 );
13963 end;
13965 //[procedure AppletHide]
13966 procedure AppletHide;
13967 begin
13968 if Applet = nil then Exit;
13969 AppletMinimize;
13970 Applet.Hide;
13971 end;
13973 //[procedure AppletRestore]
13974 procedure AppletRestore;
13975 begin
13976 if Applet = nil then Exit;
13977 Applet.Show;
13978 Applet.Perform( WM_SYSCOMMAND, SC_RESTORE, 0 );
13979 end;
13981 //[function ScreenWidth]
13982 function ScreenWidth: Integer;
13983 begin
13984 Result := GetSystemMetrics( SM_CXSCREEN );
13985 end;
13986 //[END ScreenWidth]
13988 //[function ScreenHeight]
13989 function ScreenHeight: Integer;
13990 begin
13991 Result := GetSystemMetrics( SM_CYSCREEN );
13992 end;
13993 //[END ScreenHeight]
14001 {$IFDEF USE_CONSTRUCTORS}
14002 {$DEFINE WNDPROCAPP_USED}
14003 {$DEFINE WNDPROCAPP_ASM_USED}
14004 {$ENDIF USE_CONSTRUCTORS}
14005 {$IFNDEF ASM_VERSION}
14006 {$DEFINE WNDPROCAPP_USED}
14007 {$ENDIF ASM_VERSION}
14009 {$DEFINE WNDPROCAPP_USED}
14013 {$IFNDEF WNDPROCAPP_USED}
14014 //[WndProcXXX FORWARD DECLARATIONS]
14015 {$IFNDEF ASM_VERSION}
14016 function WndProcApp( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14017 {$ENDIF}
14018 {$ENDIF}
14019 function WndProcForm( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14020 //function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14021 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14022 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14023 function WndProcGradientEx( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14024 function WndProcLabelEffect( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14025 //function WndProcParentResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14026 //function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14027 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14028 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean; forward;
14029 var fGlobalProcKeybd: function( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean =
14030 WndProcDummy;
14031 //[END OF WndProcXXX FORWARD DECLARATIONS]
14045 { -- Graphics support -- }
14047 //[function _NewGraphicTool]
14048 function _NewGraphicTool: PGraphicTool;
14049 begin
14051 New( Result, Create );
14053 {++}(*Result := PGraphicTool.Create;*){--}
14054 end;
14055 //[END _NewGraphicTool]
14057 //[FUNCTION SimpleGetCtlBrushHandle]
14058 {$IFDEF ASM_VERSION}
14059 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush;
14060 asm // //
14061 @@1: MOV ECX, [EAX].TControl.fParent
14062 JECXZ @@2
14063 MOV EDX, [EAX].TControl.fColor
14064 CMP EDX, [ECX].TControl.fColor
14065 XCHG EAX, ECX
14066 JE @@1
14067 XCHG EAX, ECX
14068 @@2: PUSH EBX
14069 XCHG EBX, EAX
14070 MOV ECX, [EBX].TControl.fTmpBrush
14071 JECXZ @@3
14072 MOV EAX, [EBX].TControl.fColor
14073 CALL Color2RGB
14074 CMP EAX, [EBX].TControl.fTmpBrushColorRGB
14075 JE @@3
14076 XOR EAX, EAX
14077 XCHG [EBX].TControl.fTmpBrush, EAX
14078 PUSH EAX
14079 CALL DeleteObject
14080 @@3: MOV EAX, [EBX].TControl.fTmpBrush
14081 TEST EAX, EAX
14082 JNE @@4
14083 MOV EAX, [EBX].TControl.fColor
14084 CALL Color2RGB
14085 MOV [EBX].TControl.fTmpBrushColorRGB, EAX
14086 PUSH EAX
14087 CALL CreateSolidBrush
14088 MOV [EBX].TControl.fTmpBrush, EAX
14089 @@4: POP EBX
14090 end;
14091 {$ELSE ASM_VERSION PAS_VERSION}
14092 function SimpleGetCtlBrushHandle( Sender: PControl ): HBrush;
14093 begin
14094 if (Sender.fParent <> nil) and (Sender.fColor = Sender.fParent.fColor) then
14095 Result := SimpleGetCtlBrushHandle( Sender.fParent )
14096 else
14097 begin
14098 if (Sender.fTmpBrush <> 0) and
14099 (Color2RGB( Sender.fColor ) <> Sender.fTmpBrushColorRGB) then
14100 begin
14101 DeleteObject( Sender.fTmpBrush );
14102 Sender.fTmpBrush := 0;
14103 end;
14104 if Sender.fTmpBrush = 0 then
14105 begin
14106 Sender.fTmpBrushColorRGB := Color2RGB( Sender.fColor );
14107 Sender.fTmpBrush := CreateSolidBrush( Sender.fTmpBrushColorRGB );
14108 end;
14109 Result := Sender.fTmpBrush;
14110 end;
14111 end;
14112 {$ENDIF ASM_VERSION}
14113 //[END SimpleGetCtlBrushHandle]
14115 //[function NormalGetCtlBrushHandle]
14116 function NormalGetCtlBrushHandle( Sender: PControl ): HBrush;
14117 begin
14118 if (Sender.fParent <> nil) then
14119 Sender.Brush.fParentGDITool := Sender.fParent.Brush;
14120 {if (Sender.Brush.fHandle <> 0) and
14121 (Color2RGB( Sender.fBrush.fData.Color ) <> Sender.fBrush.fColorRGB) then
14122 DeleteObject( Sender.Brush.ReleaseHandle );}
14123 Result := Sender.Brush.Handle;
14124 end;
14125 //[END NormalGetCtlBrushHandle]
14127 {++}(*
14128 //[API CreateFontIndirect]
14129 function CreateFontIndirect(const p1: TLogFont): HFONT; stdcall;
14130 external gdi32 name 'CreateFontIndirectA';
14131 *){--}
14132 //[MakeXXXHandle FORWARD DECLARATIONS]
14133 function MakeFontHandle( Self_: PGraphicTool ): THandle; forward;
14134 function MakeBrushHandle( Self_: PGraphicTool ): THandle; forward;
14135 function MakePenHandle( Self_: PGraphicTool ): THandle; forward;
14136 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle; forward;
14137 //[END OF MakeXXXHandle FORWARD DECLARATIONS]
14139 //[FUNCTION NewBrush]
14140 {$IFDEF ASM_VERSION}
14141 function NewBrush: PGraphicTool;
14143 MOV [Global_GetCtlBrushHandle], offset NormalGetCtlBrushHandle
14144 CALL _NewGraphicTool
14145 MOV [EAX].TGraphicTool.fNewProc, offset[NewBrush]
14146 MOV [EAX].TGraphicTool.fType, gttBrush
14147 MOV [EAX].TGraphicTool.fMakeHandleProc, offset[MakeBrushHandle]
14148 MOV [EAX].TGraphicTool.fData.Color, clBtnFace
14149 end;
14150 {$ELSE ASM_VERSION} //Pascal
14151 function NewBrush: PGraphicTool;
14152 begin
14153 Global_GetCtlBrushHandle := NormalGetCtlBrushHandle;
14154 Result := _NewGraphicTool;
14155 with Result {-}^{+} do
14156 begin
14157 fNewProc := @ NewBrush;
14158 fType := gttBrush;
14159 fMakeHandleProc := @ MakeBrushHandle;
14160 Result.fData.Color := clBtnFace;
14161 //Result.fData.Brush.Style := bsSolid;
14162 end;
14163 end;
14164 {$ENDIF ASM_VERSION}
14165 //[END NewBrush]
14167 const size_FontData = sizeof( Integer {fFontHeight} ) + sizeof( Integer {fFontWidth} ) +
14168 sizeof( TFontPitch ) + sizeof( TFontStyle ) +
14169 sizeof( Integer {fFontOrientation} ) +
14170 sizeof( Integer {fFontWeight} ) + sizeof( TFontCharset ) +
14171 sizeof( TFontQuality );
14173 //[FUNCTION NewFont]
14174 {$IFDEF ASM_VERSION}
14175 function NewFont: PGraphicTool;
14176 const FontDtSz = sizeof( TGDIFont );
14178 CALL _NewGraphicTool
14179 MOV [EAX].TGraphicTool.fNewProc, offset[NewFont]
14180 MOV [EAX].TGraphicTool.fType, gttFont
14181 MOV [EAX].TGraphicTool.fMakeHandleProc, offset[MakeFontHandle]
14182 MOV EDX, [DefFontColor]
14183 MOV [EAX].TGraphicTool.fData.Color, EDX
14185 PUSH EAX
14186 LEA EDX, [EAX].TGraphicTool.fData.Font
14187 MOV EAX, offset[ DefFont ]
14188 XOR ECX, ECX
14189 MOV CL, FontDtSz
14190 CALL System.Move
14191 POP EAX
14192 end;
14193 {$ELSE ASM_VERSION} //Pascal
14194 function NewFont: PGraphicTool;
14195 begin
14196 Result := _NewGraphicTool;
14197 with Result {-}^{+} do
14198 begin
14199 fNewProc := @ NewFont;
14200 fType := gttFont;
14201 fMakeHandleProc := @ MakeFontHandle;
14202 fData.Color := DefFontColor;
14203 Move( DefFont, fData.Font, Sizeof( TGDIFont ) );
14204 end;
14205 end;
14206 {$ENDIF ASM_VERSION}
14207 //[END NewFont]
14209 //[FUNCTION NewPen]
14210 {$IFDEF ASM_VERSION}
14211 function NewPen: PGraphicTool;
14213 CALL _NewGraphicTool
14214 MOV [EAX].TGraphicTool.fNewProc, offset[NewPen]
14215 MOV [EAX].TGraphicTool.fType, gttPen
14216 MOV [EAX].TGraphicTool.fMakeHandleProc, offset[MakePenHandle]
14217 MOV [EAX].TGraphicTool.fData.Pen.Mode, pmCopy
14218 end;
14219 {$ELSE ASM_VERSION} //Pascal
14220 function NewPen: PGraphicTool;
14221 begin
14222 Result := _NewGraphicTool;
14223 with Result{-}^{+} do
14224 begin
14225 fNewProc := @ NewPen;
14226 fType := gttPen;
14227 fMakeHandleProc := @ MakePenHandle;
14228 fData.Pen.Mode := pmCopy;
14229 end;
14230 end;
14231 {$ENDIF ASM_VERSION}
14232 //[END NewPen]
14235 //[function Color2RGB]
14236 function Color2RGB( Color: TColor ): TColor;
14237 begin
14238 if Color < 0 then
14239 Result := GetSysColor(Color and $FF) else
14240 Result := Color;
14241 end;
14242 //[END Color2RGB]
14244 //[function ColorsMix]
14245 function ColorsMix( Color1, Color2: TColor ): TColor;
14246 {$IFDEF F_P}
14247 begin
14248 Result := ((Color2RGB( Color1 ) and $FEFEFE) shr 1) +
14249 ((Color2RGB( Color2 ) and $FEFEFE) shr 1);
14250 end;
14251 {$ELSE DELPHI}
14253 PUSH EDX
14254 CALL Color2Rgb
14255 XCHG EAX, [ESP]
14256 CALL Color2Rgb
14257 POP EDX
14258 AND EAX, 0FEFEFEh
14259 AND EDX, 0FEFEFEh
14260 SHR EAX, 1
14261 SHR EDX, 1
14262 ADD EAX, EDX
14263 end;
14264 {$ENDIF F_P/DELPHI}
14265 //[END ColorsMix]
14267 //[FUNCTION Color2RGBQuad]
14268 {$IFDEF ASM_VERSION}
14269 function Color2RGBQuad( Color: TColor ): TRGBQuad;
14271 CALL Color2RGB
14272 // code by bart:
14273 xchg ah,al // xxRRGGBB
14274 ror eax,16 // BBGGxxRR
14275 xchg ah,al // BBGGRRxx
14276 shr eax,8 // 00BBGGRR
14277 end;
14278 {$ELSE ASM_VERSION} //Pascal
14279 function Color2RGBQuad( Color: TColor ): TRGBQuad;
14280 var C: Integer;
14281 begin
14282 C := Color2RGB( Color );
14283 C := ((C shr 16) and $FF)
14284 or ((C shl 16) and $FF0000)
14285 or (C and $FF00);
14286 Result := TRGBQuad( C );
14287 end;
14288 {$ENDIF ASM_VERSION}
14289 //[END Color2RGBQuad]
14291 //[FUNCTION Color2Color16]
14292 {$IFDEF ASM_VERSION}
14293 function Color2Color16( Color: TColor ): WORD;
14295 MOV EDX, EAX
14296 SHR EDX, 19
14297 AND EDX, $1F
14298 MOV ECX, EAX
14299 SHR ECX, 5
14300 AND ECX, $7E0;
14301 MOV AH, AL
14302 AND EAX, $F800
14303 OR EAX, EDX
14304 OR EAX, ECX
14305 end;
14306 {$ELSE ASM_VERSION}
14307 function Color2Color16( Color: TColor ): WORD;
14308 begin
14309 Color := Color2RGB( Color );
14310 Result := (Color shr 19) and $1F or
14311 (Color shr 5) and $7E0 or
14312 (Color shl 8) and $F800;
14313 end;
14314 {$ENDIF ASM_VERSION}
14315 //[END Color2Color16]
14317 { TGraphicTool }
14319 {$IFDEF ASM_VERSION}
14320 //[function TGraphicTool.Assign]
14321 function TGraphicTool.Assign(Value: PGraphicTool): PGraphicTool;
14322 const SzfData = sizeof( fData );
14323 asm // //
14324 TEST EDX, EDX
14325 JNZ @@1
14326 TEST EAX, EAX
14327 JZ @@0
14328 CALL TObj.DoDestroy
14329 XOR EAX, EAX
14330 @@0: RET
14331 @@1: PUSH EDI
14332 MOV EDI, EDX
14333 TEST EAX, EAX
14334 JNZ @@2
14335 XCHG EAX, EDX
14336 CALL dword ptr[EAX].TGraphicTool.fNewProc
14337 @@2: CMP EAX, EDI
14338 JE @@exit
14339 PUSH EBX
14340 XCHG EBX, EAX
14342 MOV ECX, [EBX].TGraphicTool.fHandle
14343 JECXZ @@3
14344 CMP ECX, [EDI].TGraphicTool.fHandle
14345 JE @@exit1
14346 @@3:
14347 MOV EAX, EBX
14348 CALL TGraphicTool.Changed
14349 LEA EDX, [EBX].TGraphicTool.fData
14350 LEA EAX, [EDI].TGraphicTool.fData
14351 MOV ECX, SzfData
14352 CALL System.Move
14353 MOV EAX, EBX
14354 CALL TGraphicTool.Changed
14356 @@exit1:
14357 XCHG EAX, EBX
14358 POP EBX
14359 @@exit: POP EDI
14360 end;
14361 {$ELSE ASM_VERSION}
14362 function TGraphicTool.Assign(Value: PGraphicTool): PGraphicTool;
14363 var _Self: PGraphicTool;
14364 begin
14365 Result := nil;
14366 if Value = nil then
14367 begin
14368 if @Self <> nil then
14369 DoDestroy;
14370 Exit;
14371 end;
14372 _Self := @Self;
14373 if _Self = nil then
14374 _Self := Value.fNewProc();
14375 Result := _Self;
14376 if _Self = Value then Exit; // to avoid infinite loop when assigning to itself
14377 if _Self.fHandle <> 0 then
14378 if Value.fHandle = _Self.fHandle then Exit;
14379 _Self.Changed; // to destroy handle if allocated and release it from the canvas (if any uses it)
14380 Assert( Value.fType = _Self.fType, 'Attempt to assign to different GDI tool type' );
14381 Move( Value.fData, _Self.fData, Sizeof( fData ) );
14382 _Self.Changed; // to inform owner control, that its tool (font, brush) changed
14383 end;
14384 {$ENDIF ASM_VERSION}
14386 //[procedure TGraphicTool.AssignHandle]
14387 procedure TGraphicTool.AssignHandle(NewHandle: Integer);
14388 begin
14389 //------------ by Yury Sidorov --------
14390 //Changed;
14391 //-------------------------------------//
14392 if fHandle <> 0 then //
14393 DeleteObject( fHandle ); //
14394 //-------------------------------------//
14395 fHandle := NewHandle;
14396 GetObject( fHandle, Sizeof( TGDIFont ), @ fData.Font );
14397 Changed;
14398 end;
14400 {$IFDEF ASM_VERSION}
14401 //[procedure TGraphicTool.Changed]
14402 procedure TGraphicTool.Changed;
14404 XOR ECX, ECX
14405 XCHG ECX, [EAX].fHandle
14406 JECXZ @@exit
14407 PUSH EAX
14408 PUSH ECX
14410 CALL @@CallOnChange
14412 CALL DeleteObject
14413 POP EAX
14414 @@exit:
14416 @@CallOnChange:
14417 MOV ECX, [EAX].fOnChange.TMethod.Code
14418 JECXZ @@no_onChange
14419 PUSH EAX
14420 XCHG EDX, EAX
14421 MOV EAX, [EDX].fOnChange.TMethod.Data
14422 CALL ECX
14423 POP EAX
14424 @@no_onChange:
14425 end;
14426 {$ELSE ASM_VERSION} //Pascal
14427 procedure TGraphicTool.Changed;
14428 var H: THandle;
14429 begin
14430 if fHandle <> 0 then
14431 begin
14432 H := fHandle;
14433 fHandle := 0;
14434 ////////////////////////////////
14435 if Assigned( fOnChange ) then
14436 fOnChange( @Self );
14437 ////////////////////////////////
14438 DeleteObject( H );
14439 {$IFDEF DEBUG_GDIOBJECTS}
14440 case fType of
14441 gttBrush: Dec( BrushCount );
14442 gttFont: Dec( FontCount );
14443 gttPen: Dec( PenCount );
14444 end;
14445 {$ENDIF}
14446 end;
14447 //////////////////////////////////
14448 if Assigned( fOnChange ) then
14449 fOnChange( @Self );
14450 //////////////////////////////////
14451 end;
14452 {$ENDIF ASM_VERSION}
14454 {$IFDEF ASM_VERSION}
14455 //[destructor TGraphicTool.Destroy]
14456 destructor TGraphicTool.Destroy;
14458 PUSH EAX
14459 CMP [EAX].fType, gttFont
14460 JE @@0
14461 MOV ECX, [EAX].fData.Brush.Bitmap
14462 JECXZ @@0
14463 PUSH ECX
14464 CALL DeleteObject
14465 POP EAX
14466 PUSH EAX
14467 @@0:
14468 MOV ECX, [EAX].fHandle
14469 JECXZ @@1
14470 PUSH ECX
14471 CALL DeleteObject
14472 @@1:
14473 POP EAX
14474 CALL TObj.Destroy
14475 end;
14476 {$ELSE ASM_VERSION} //Pascal
14477 destructor TGraphicTool.Destroy;
14478 begin
14479 case fType of
14480 gttBrush: if fData.Brush.Bitmap <> 0 then
14481 DeleteObject( fData.Brush.Bitmap );
14482 gttPen: if fData.Pen.BrushBitmap <> 0 then
14483 DeleteObject( fData.Pen.BrushBitmap )
14484 end;
14485 if fHandle <> 0 then
14486 begin
14487 DeleteObject( fHandle );
14488 {$IFDEF DEBUG_GDIOBJECTS}
14489 case fType of
14490 gttPen: Dec( PenCount );
14491 gttBrush: Dec( BrushCount );
14492 gttFont: Dec( FontCount );
14493 end;
14494 {$ENDIF}
14495 //fHandle := 0; Why to do this? It is now destroying!
14496 end;
14497 inherited;
14498 end;
14499 {$ENDIF ASM_VERSION}
14501 //[function TGraphicTool.HandleAllocated]
14502 function TGraphicTool.HandleAllocated: Boolean;
14503 begin
14504 Result := fHandle <> 0;
14505 end;
14507 {$IFDEF ASM_VERSION}
14508 //[function TGraphicTool.ReleaseHandle]
14509 function TGraphicTool.ReleaseHandle: Integer;
14510 asm // //
14511 PUSH EAX
14512 CALL Changed
14513 POP EDX
14514 XOR EAX, EAX
14515 XCHG [EDX].fHandle, EAX
14516 end;
14517 {$ELSE ASM_VERSION PAS_VERSION}
14518 function TGraphicTool.ReleaseHandle: Integer;
14519 begin
14520 Changed;
14521 Result := fHandle;
14522 fHandle := 0;
14523 end;
14524 {$ENDIF ASM_VERSION}
14526 {$IFDEF ASM_VERSION}
14527 //[procedure TGraphicTool.SetInt]
14528 procedure TGraphicTool.SetInt( const Index: Integer; Value: Integer );
14530 LEA EDX, [EDX+EAX].fData
14531 CMP [EDX], ECX
14532 JE @@exit
14533 MOV [EDX], ECX
14534 CALL Changed
14535 @@exit:
14536 end;
14537 {$ELSE ASM_VERSION} //Pascal
14538 procedure TGraphicTool.SetInt( const Index: Integer; Value: Integer );
14539 var Where: PInteger;
14540 begin
14541 Where := Pointer( Integer( @ fData ) + Index );
14542 if Where^ = Value then Exit;
14543 Where^ := Value;
14544 Changed;
14545 end;
14546 {$ENDIF ASM_VERSION}
14548 {$IFDEF F_P}
14549 //[function TGraphicTool.GetInt]
14550 function TGraphicTool.GetInt(const Index: Integer): Integer;
14551 var Where: PInteger;
14552 begin
14553 Where := Pointer( Integer( @ fData ) + Index );
14554 Result := Where^;
14555 end;
14556 {$ENDIF}
14558 //[procedure TGraphicTool.SetColor]
14559 procedure TGraphicTool.SetColor( Value: TColor );
14560 begin
14561 SetInt( go_Color, Value );
14562 fColorRGB := Color2RGB( Value );
14563 end;
14565 {$IFDEF ASM_VERSION}
14566 //[function TGraphicTool.IsFontTrueType]
14567 function TGraphicTool.IsFontTrueType: Boolean;
14569 CALL GetHandle
14570 TEST EAX, EAX
14571 JZ @@exit
14573 PUSH EBX
14575 PUSH EAX // fHandle
14577 PUSH 0
14578 CALL GetDC
14580 PUSH EAX // DC
14581 MOV EBX, EAX
14582 CALL SelectObject
14583 PUSH EAX
14585 XOR ECX, ECX
14586 PUSH ECX
14587 PUSH ECX
14588 PUSH ECX
14589 PUSH ECX
14590 PUSH EBX
14591 CALL GetFontData
14593 XCHG EAX, [ESP]
14595 PUSH EAX
14596 PUSH EBX
14597 CALL SelectObject
14599 PUSH EBX
14600 PUSH 0
14601 CALL ReleaseDC
14603 POP EAX
14604 INC EAX
14605 SETNZ AL
14607 POP EBX
14608 @@exit:
14609 end;
14610 {$ELSE ASM_VERSION} //Pascal
14611 function TGraphicTool.IsFontTrueType: Boolean;
14612 var OldFont: HFont;
14613 DC: HDC;
14614 begin
14615 Result := False;
14616 if GetHandle = 0 then Exit;
14617 DC := GetDC( 0 );
14618 OldFont := SelectObject( DC, fHandle );
14619 if GetFontData( DC, 0, 0, nil, 0 ) <> GDI_ERROR then
14620 Result := True;
14621 SelectObject( DC, OldFont );
14622 ReleaseDC( 0, DC );
14623 end;
14624 {$ENDIF ASM_VERSION}
14626 //[procedure TGraphicTool.SetBrushBitmap]
14627 procedure TGraphicTool.SetBrushBitmap(const Value: HBitmap);
14628 begin
14629 if fData.Brush.Bitmap = Value then Exit;
14630 if fData.Brush.Bitmap <> 0 then
14631 begin
14632 ///////////
14633 Changed; // !!!
14634 ///////////
14635 DeleteObject( fData.Brush.Bitmap );
14636 end;
14637 fData.Brush.Bitmap := Value;
14638 Changed;
14639 end;
14641 //[procedure TGraphicTool.SetBrushStyle]
14642 procedure TGraphicTool.SetBrushStyle(const Value: TBrushStyle);
14643 begin
14644 if fData.Brush.Style = Value then Exit;
14645 fData.Brush.Style := Value;
14646 Changed;
14647 end;
14649 //[procedure TGraphicTool.SetFontCharset]
14650 procedure TGraphicTool.SetFontCharset(const Value: TFontCharset);
14651 begin
14652 if fData.Font.Charset = Value then Exit;
14653 fData.Font.Charset := Value;
14654 Changed;
14655 end;
14657 //[procedure TGraphicTool.SetFontQuality]
14658 procedure TGraphicTool.SetFontQuality(const Value: TFontQuality);
14659 begin
14660 if fData.Font.Quality = Value then Exit;
14661 fData.Font.Quality := Value;
14662 Changed;
14663 end;
14665 //[function TGraphicTool.GetFontName]
14666 function TGraphicTool.GetFontName: String;
14667 begin
14668 Result := fData.Font.Name;
14669 end;
14671 //[procedure TGraphicTool.SetFontName]
14672 procedure TGraphicTool.SetFontName(const Value: String);
14673 begin
14674 if fData.Font.Name = Value then Exit;
14675 FillChar( fData.Font.Name[ 0 ], LF_FACESIZE, 0 );
14676 StrLCopy( fData.Font.Name, PChar( Value ), LF_FACESIZE );
14677 Changed;
14678 end;
14680 {$IFDEF ASM_VERSION}
14681 //[procedure TextAreaEx]
14682 procedure TextAreaEx( Sender: PCanvas; var Sz : TSize; var Pt : TPoint );
14684 PUSH EBX
14685 PUSH ESI
14686 PUSH EDI
14687 PUSH EBP
14688 MOV EBP, ESP
14689 PUSH EDX // [EBP-4] = @Sz
14690 PUSH ECX // [EBP-8] = @Pt
14691 MOV EBX, EAX
14692 CALL TCanvas.GetFont
14693 MOV ESI, [EAX].TGraphicTool.fData.Font.Orientation
14694 CALL TGraphicTool.IsFontTrueType
14695 TEST AL, AL
14696 JZ @@exit
14698 MOV EDI, [EBP-8]
14699 XOR EAX, EAX
14700 STOSD
14701 STOSD
14702 TEST ESI, ESI
14703 JZ @@exit
14705 PUSH EAX // Pts[1].x
14706 PUSH EAX // Pts[1].y
14708 PUSH ESI
14709 FILD dword ptr [ESP]
14710 POP EDX
14712 FILD word ptr [@@1800]
14713 FDIV
14714 //FWAIT
14715 FLDPI
14716 FMUL
14717 //FWAIT
14719 FLD ST(0)
14720 FSINCOS
14721 FWAIT
14723 MOV ESI, [EBP-4]
14724 LODSD // Sz.cx
14725 PUSH EAX
14726 FILD dword ptr [ESP]
14727 FMUL
14728 FISTP dword ptr [ESP] // Pts[2].x
14729 FWAIT
14730 NEG EAX
14731 PUSH EAX
14732 FILD dword ptr [ESP]
14733 FMUL
14734 FISTP dword ptr [ESP] // Pts[2].y
14735 FWAIT
14737 FLDPI
14738 FLD1
14739 FLD1
14740 FADD
14741 FDIV
14742 FADD
14743 FSINCOS
14744 FWAIT
14746 LODSD
14747 NEG EAX
14748 PUSH EAX
14749 FILD dword ptr [ESP]
14750 FMUL
14751 FISTP dword ptr [ESP] // Pts[4].x
14752 FWAIT
14753 NEG EAX
14754 PUSH EAX
14755 FILD dword ptr [ESP]
14756 FMUL
14757 FISTP dword ptr [ESP] // Pts[4].y
14758 FWAIT
14760 POP ECX
14761 POP EDX
14762 PUSH EDX
14763 PUSH ECX
14764 ADD EDX, [ESP+12]
14765 ADD ECX, [ESP+8]
14766 PUSH EDX
14767 PUSH ECX
14769 MOV ESI, ESP
14770 XOR EDX, EDX // MinX
14771 XOR EDI, EDI // MinY
14772 XOR ECX, ECX
14773 MOV CL, 3
14775 @@loo1: LODSD
14776 CMP EAX, EDI
14777 JGE @@1
14778 XCHG EDI, EAX
14779 @@1: LODSD
14780 CMP EAX, EDX
14781 JGE @@2
14782 XCHG EDX, EAX
14783 @@2: LOOP @@loo1
14785 MOV ESI, [EBP-4]
14786 MOV [ESI], ECX
14787 MOV [ESI+4], ECX
14788 MOV CL, 4
14789 @@loo2:
14790 POP EBX
14791 SUB EBX, EDI
14792 CMP EBX, [ESI+4]
14793 JLE @@3
14794 MOV [ESI+4], EBX
14795 @@3:
14796 POP EAX
14797 SUB EAX, EDX
14798 CMP EAX, [ESI]
14799 JLE @@4
14800 MOV [ESI], EAX
14801 @@4:
14802 LOOP @@loo2
14804 MOV EDI, [EBP-8]
14805 STOSD
14806 XCHG EAX, EBX
14807 STOSD
14808 JMP @@exit
14810 @@1800: DW 1800
14812 @@exit:
14813 MOV ESP, EBP
14814 POP EBP
14815 POP EDI
14816 POP ESI
14817 POP EBX
14818 end;
14819 {$ELSE ASM_VERSION} //Pascal
14820 procedure TextAreaEx( Sender: PCanvas; var Sz : TSize; var Pt : TPoint );
14821 var Orient : Integer;
14822 Pts : array[ 1..4 ] of TPoint;
14823 MinX, MinY, I : Integer;
14824 A : Double;
14825 begin
14826 if not Sender.Font.IsFontTrueType then Exit;
14827 Orient := Sender.Font.FontOrientation;
14828 Pt.x := 0; Pt.y := 0;
14829 if Orient = 0 then
14830 Exit;
14831 A := Orient / 1800.0 * PI;
14832 Pts[ 1 ] := Pt;
14833 Pts[ 2 ].x := Round( Sz.cx * cos( A ) );
14834 Pts[ 2 ].y := - Round( Sz.cx * sin( A ) );
14835 Pts[ 4 ].x := - Round( Sz.cy * cos( A + PI / 2 ) );
14836 Pts[ 4 ].y := Round( Sz.cy * sin( A + PI / 2 ) );
14837 Pts[ 3 ].x := Pts[ 2 ].x + Pts[ 4 ].x;
14838 Pts[ 3 ].y := Pts[ 2 ].y + Pts[ 4 ].y;
14839 MinX := 0; MinY := 0;
14840 for I := 2 to 4 do
14841 begin
14842 if Pts[ I ].x < MinX then
14843 MinX := Pts[ I ].x;
14844 if Pts[ I ].y < MinY then
14845 MinY := Pts[ I ].y;
14846 end;
14847 Sz.cx := 0;
14848 Sz.cy := 0;
14849 for I := 1 to 4 do
14850 begin
14851 Pts[ I ].x := Pts[ I ].x - MinX;
14852 Pts[ I ].y := Pts[ I ].y - MinY;
14853 if Pts[ I ].x > Sz.cx then
14854 Sz.cx := Pts[ I ].x;
14855 if Pts[ I ].y > Sz.cy then
14856 Sz.cy := Pts[ I ].y;
14857 end;
14858 Pt := Pts[ 1 ];
14859 end;
14860 {$ENDIF ASM_VERSION}
14862 {$IFDEF ASM_VERSION}
14863 //[procedure TGraphicTool.SetFontOrientation]
14864 procedure TGraphicTool.SetFontOrientation(Value: Integer);
14866 PUSH EAX
14867 @@1: MOV EAX, EDX
14868 MOV ECX, 3600
14870 IDIV ECX // EDX = Value mod 3600
14871 POP EAX
14873 MOV byte ptr [GlobalGraphics_UseFontOrient], 1
14874 MOV [GlobalCanvas_OnTextArea], offset[TextAreaEx]
14876 MOV [EAX].fData.Font.Escapement, EDX
14877 MOV ECX, EDX
14878 MOV DX, go_FontOrientation
14879 CALL SetInt
14880 end;
14881 {$ELSE ASM_VERSION} //Pascal
14882 procedure TGraphicTool.SetFontOrientation(Value: Integer);
14883 begin
14884 GlobalGraphics_UseFontOrient := True;
14885 GlobalCanvas_OnTextArea := TextAreaEx;
14886 Value := Value mod 3600; // -3599..+3599
14887 SetInt( go_FontOrientation, Value );
14888 SetInt( go_FontEscapement, Value );
14889 end;
14890 {$ENDIF ASM_VERSION}
14892 //[procedure TGraphicTool.SetFontPitch]
14893 procedure TGraphicTool.SetFontPitch(const Value: TFontPitch);
14894 begin
14895 if fData.Font.Pitch = Value then Exit;
14896 fData.Font.Pitch := Value;
14897 Changed;
14898 end;
14900 {$IFDEF ASM_VERSION}
14901 //[function TGraphicTool.GetFontStyle]
14902 function TGraphicTool.GetFontStyle: TFontStyle;
14904 MOV EDX, dword ptr [EAX].fData.Font.Italic
14905 AND EDX, $010101
14906 MOV EAX, [EAX].fData.Font.Weight
14907 CMP EAX, 700
14908 SETGE AL //AL:1 = fsBold
14909 ADD EDX, EDX
14910 OR EAX, EDX //AL:2 = fsItalic
14911 SHR EDX, 7
14912 OR EAX, EDX //AL:3 = fsUnderline
14913 SHR EDX, 7
14914 OR EAX, EDX //AL:4 = fsStrikeOut
14915 end;
14916 {$ELSE ASM_VERSION} //Pascal
14917 function TGraphicTool.GetFontStyle: TFontStyle;
14918 type PFontStyle = ^TFontStyle;
14919 begin
14920 Result := [ ];
14921 if fData.Font.Weight >= 700 then Result := [ fsBold ];
14922 if fData.Font.Italic then Result := Result + [ fsItalic ];
14923 if fData.Font.Underline then Result := Result + [ fsUnderline ];
14924 if fData.Font.StrikeOut then Result := Result + [ fsStrikeOut ];
14925 end;
14926 {$ENDIF ASM_VERSION}
14928 {$IFDEF ASM_VERSION}
14929 //[procedure TGraphicTool.SetFontStyle]
14930 procedure TGraphicTool.SetFontStyle(const Value: TFontStyle);
14932 PUSH EDI
14933 MOV EDI, EAX
14934 PUSH EDX
14935 CALL GetFontStyle
14936 POP EDX
14937 CMP AL, DL
14938 JE @@exit
14939 PUSH EDI
14941 LEA EDI, [EDI].fData.Font.Weight
14942 MOV ECX, [EDI]
14943 SHR EDX, 1
14944 JNC @@1
14945 CMP ECX, 700
14946 JGE @@2
14947 MOV ECX, 700
14948 JMP @@2
14949 @@1: CMP ECX, 700
14950 JL @@2
14951 XOR ECX, ECX
14952 @@2: XCHG EAX, ECX
14953 STOSD // change Weight
14954 SHR EDX, 1
14955 SETC AL
14956 STOSB // change Italic
14957 SHR EDX, 1
14958 SETC AL
14959 STOSB // change Underline
14960 SHR EDX, 1
14961 SETC AL
14962 STOSB // change StrikeOut
14963 POP EAX
14964 CALL Changed
14965 @@exit: POP EDI
14966 end;
14967 {$ELSE ASM_VERSION} //Pascal
14968 procedure TGraphicTool.SetFontStyle(const Value: TFontStyle);
14969 begin
14970 if FontStyle = Value then Exit;
14971 if fsBold in Value then
14972 begin
14973 if fData.Font.Weight < 700 then
14974 fData.Font.Weight := 700;
14976 else
14977 begin
14978 if fData.Font.Weight >= 700 then
14979 fData.Font.Weight := 0;
14980 end;
14981 fData.Font.Italic := fsItalic in Value;
14982 fData.Font.Underline := fsUnderline in Value;
14983 fData.Font.StrikeOut := fsStrikeOut in Value;
14984 Changed;
14985 end;
14986 {$ENDIF ASM_VERSION}
14988 //[procedure TGraphicTool.SetPenMode]
14989 procedure TGraphicTool.SetPenMode(const Value: TPenMode);
14990 begin
14991 if fData.Pen.Mode = Value then Exit;
14992 fData.Pen.Mode := Value;
14993 Changed;
14994 end;
14996 //[procedure TGraphicTool.SetPenStyle]
14997 procedure TGraphicTool.SetPenStyle(const Value: TPenStyle);
14998 begin
14999 if fData.Pen.Style = Value then Exit;
15000 fData.Pen.Style := Value;
15001 Changed;
15002 end;
15004 {$IFDEF ASM_VERSION}
15005 //[function TGraphicTool.GetHandle]
15006 function TGraphicTool.GetHandle: THandle;
15007 const DataSz = sizeof( TGDIToolData );
15009 PUSH EBX
15010 @@start:
15011 XCHG EBX, EAX
15012 MOV ECX, [EBX].fHandle
15013 JECXZ @@1
15015 MOV EAX, [EBX].fData.Color
15016 CALL Color2RGB
15017 CMP EAX, [EBX].fColorRGB
15018 JE @@1
15020 MOV EAX, EBX
15021 CALL ReleaseHandle
15022 PUSH EAX
15023 CALL DeleteObject
15025 @@1: MOV ECX, [EBX].fHandle
15026 INC ECX
15027 LOOP @@exit
15029 MOV ECX, [EBX].fParentGDITool
15030 JECXZ @@2
15031 LEA EDX, [ECX].fData
15032 LEA EAX, [EBX].fData
15033 MOV ECX, DataSz
15034 CALL CompareMem
15035 TEST AL, AL
15036 MOV EAX, [EBX].fParentGDITool
15037 JNZ @@start
15039 @@2: MOV ECX, [EBX].fHandle
15040 INC ECX
15041 LOOP @@exit
15043 MOV EAX, [EBX].fData.Color
15044 CALL Color2RGB
15045 MOV [EBX].fColorRGB, EAX
15046 XCHG EAX, EBX
15047 CALL dword ptr [EAX].fMakeHandleProc
15048 XCHG ECX, EAX
15050 @@exit: XCHG EAX, ECX
15051 POP EBX
15052 end;
15053 {$ELSE ASM_VERSION} //Pascal
15054 function TGraphicTool.GetHandle: THandle;
15055 begin
15056 Result := fHandle;
15057 if Result <> 0 then
15058 begin
15059 if Color2RGB( fData.Color ) <> fColorRGB then
15060 begin
15061 DeleteObject( ReleaseHandle );
15062 Result := 0;
15063 end;
15064 end;
15065 if Result = 0 then
15066 begin
15067 if Assigned( fParentGDITool ) then
15068 begin
15069 if CompareMem( @ fData, @ fParentGDITool.fData, Sizeof( fData ) ) then
15070 begin
15071 Result := fParentGDITool.Handle;
15072 Exit;
15073 end;
15074 end;
15076 if fHandle = 0 then
15077 begin
15078 fColorRGB := Color2RGB( fData.Color );
15079 fMakeHandleProc( @Self );
15080 end;
15081 Result := fHandle;
15082 end;
15083 end;
15084 {$ENDIF ASM_VERSION}
15086 //[FUNCTION MakeBrushHandle]
15087 {$IFDEF ASM_VERSION}
15088 function MakeBrushHandle( Self_: PGraphicTool ): THandle;
15090 PUSH EBX
15091 XCHG EBX, EAX
15092 MOV EAX, [EBX].TGraphicTool.fHandle
15093 TEST EAX, EAX
15094 JNZ @@exit
15096 MOV EAX, [EBX].TGraphicTool.fData.Color
15097 CALL Color2RGB // EAX = ColorRef
15099 XOR EDX, EDX
15101 MOV ECX, [EBX].TGraphicTool.fData.Brush.Bitmap
15102 PUSH ECX
15103 JECXZ @@1
15105 MOV DL, BS_PATTERN
15106 JMP @@2
15108 @@1:
15109 MOV CL, [EBX].TGraphicTool.fData.Brush.Style
15110 MOV DL, CL
15111 SUB CL, 2
15112 JL @@2
15114 XCHG ECX, [ESP]
15116 @@2: PUSH EAX
15117 PUSH EDX
15119 PUSH ESP
15120 CALL CreateBrushIndirect
15121 MOV [EBX].TGraphicTool.fHandle, EAX
15123 ADD ESP, 12
15125 @@exit:
15126 POP EBX
15127 end;
15128 {$ELSE ASM_VERSION} //Pascal
15129 function MakeBrushHandle( Self_: PGraphicTool ): THandle;
15131 LogBrush: TLogBrush;
15132 begin
15133 if Self_.fHandle = 0 then
15134 begin
15135 LogBrush.lbColor := Color2RGB( Self_.fData.Color );
15136 if Self_.fData.Brush.Bitmap <> 0 then
15137 begin
15138 LogBrush.lbStyle := BS_PATTERN;
15139 LogBrush.lbHatch := Self_.fData.Brush.Bitmap;
15141 else
15142 begin
15143 LogBrush.lbHatch := 0;
15144 case Self_.fData.Brush.Style of
15145 bsSolid: LogBrush.lbStyle := BS_SOLID;
15146 bsClear: LogBrush.lbStyle := BS_NULL;
15147 else
15148 LogBrush.lbStyle := BS_HATCHED;
15149 LogBrush.lbHatch := Ord( Self_.fData.Brush.Style ) - Ord( bsHorizontal );
15150 LogBrush.lbColor := Color2RGB( Self_.fData.Brush.LineColor );
15151 end;
15152 end;
15153 Self_.fHandle := CreateBrushIndirect(LogBrush);
15154 {$IFDEF DEBUG_GDIOBJECTS}
15155 if Self_.fHandle <> 0 then
15156 Inc( BrushCount )
15157 else
15158 ShowMessage( 'Could not create brush, error ' + Int2Str( GetLastError ) +
15159 ': ' + SysErrorMessage( GetLastError ) );
15160 {$ENDIF}
15161 end;
15162 //GlobalGraphics_OnObjectCreated( @Self );
15163 Result := Self_.fHandle;
15164 end;
15165 {$ENDIF ASM_VERSION}
15166 //[END MakeBrushHandle]
15168 //[FUNCTION MakeFontHandle]
15169 {$IFDEF ASM_VERSION}
15170 function MakeFontHandle( Self_: PGraphicTool ): THandle;
15172 XCHG EDX, EAX
15173 MOV EAX, [EDX].TGraphicTool.fHandle
15174 TEST EAX, EAX
15175 JNZ @@exit
15176 PUSH EDX
15177 LEA ECX, [EDX].TGraphicTool.fData.Font
15178 PUSH ECX
15179 CALL CreateFontIndirect
15180 POP EDX
15181 MOV [EDX].TGraphicTool.fHandle, EAX
15182 @@exit:
15183 end;
15184 {$ELSE ASM_VERSION} //Pascal
15185 function MakeFontHandle( Self_: PGraphicTool ): THandle;
15186 //var LogFont: TLogFont;
15187 begin
15188 with Self_{-}^{+} do
15189 begin
15190 if fHandle = 0 then
15191 begin
15192 fHandle := CreateFontIndirect( PLogFont( @ fData.Font )^ );
15193 {$IFDEF DEBUG_GDIOBJECTS}
15194 Inc( FontCount );
15195 {$ENDIF}
15196 end;
15197 Result := fHandle;
15198 end;
15199 end;
15200 {$ENDIF ASM_VERSION}
15201 //[END MakeFontHandle]
15203 //[FUNCTION MakePenHandle]
15204 {$IFDEF ASM_VERSION}
15205 function MakePenHandle( Self_: PGraphicTool ): THandle;
15207 PUSH EBX
15208 MOV EBX, EAX
15210 MOV EAX, [EBX].TGraphicTool.fHandle
15211 TEST EAX, EAX
15212 JNZ @@exit
15214 MOV EAX, [EBX].TGraphicTool.fData.Color
15215 CALL Color2RGB
15216 PUSH EAX
15217 PUSH EAX
15218 PUSH [EBX].TGraphicTool.fData.Pen.Width
15219 MOVZX EAX, [EBX].TGraphicTool.fData.Pen.Style
15220 PUSH EAX
15221 PUSH ESP
15222 CALL CreatePenIndirect
15223 MOV [EBX].TGraphicTool.fHandle, EAX
15224 ADD ESP, 16
15225 @@exit:
15226 POP EBX
15227 end;
15228 {$ELSE ASM_VERSION} //Pascal
15229 function MakePenHandle( Self_: PGraphicTool ): THandle;
15231 LogPen: TLogPen;
15232 begin
15233 with Self_{-}^{+} do
15234 begin
15235 //GlobalGraphics_OnObjectCreating( @Self );
15236 if fHandle = 0 then
15237 with LogPen do
15238 begin
15239 lopnStyle := Byte( fData.Pen.Style );
15240 lopnWidth.X := fData.Pen.Width;
15241 lopnColor := Color2RGB( fData.Color );
15242 fHandle := CreatePenIndirect( LogPen );
15243 {$IFDEF DEBUG_GDIOBJECTS}
15244 Inc( PenCount );
15245 {$ENDIF}
15246 end;
15247 //GlobalGraphics_OnObjectCreated( @Self );
15248 Result := fHandle;
15249 end;
15250 end;
15251 {$ENDIF ASM_VERSION}
15252 //[END MakePenHandle]
15255 //[procedure TGraphicTool.SetGeometricPen]
15256 procedure TGraphicTool.SetGeometricPen(const Value: Boolean);
15257 begin
15258 if fData.Pen.Geometric = Value then Exit;
15259 fData.Pen.Geometric := Value;
15260 fMakeHandleProc := MakeGeometricPenHandle;
15261 Changed;
15262 end;
15264 //[procedure TGraphicTool.SetPenEndCap]
15265 procedure TGraphicTool.SetPenEndCap(const Value: TPenEndCap);
15266 begin
15267 if fData.Pen.EndCap = Value then Exit;
15268 fData.Pen.EndCap := Value;
15269 Changed;
15270 end;
15272 //[procedure TGraphicTool.SetPenJoin]
15273 procedure TGraphicTool.SetPenJoin(const Value: TPenJoin);
15274 begin
15275 if fData.Pen.Join = Value then Exit;
15276 fData.Pen.Join := Value;
15277 Changed;
15278 end;
15280 //[FUNCTION MakeGeometricPenHandle]
15281 {$IFDEF ASM_VERSION}
15282 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle;
15284 MOV ECX, [EAX].TGraphicTool.fHandle
15285 INC ECX
15286 LOOP @@exit
15288 PUSH EBX
15289 XCHG EBX, EAX
15290 MOV EAX, [EBX].TGraphicTool.fData.Color
15291 CALL Color2RGB // EAX = Color2RGB( fColor )
15292 CDQ // EDX = lbHatch (0)
15293 MOV ECX, [EBX].TGraphicTool.fData.Pen.BrushBitmap
15294 JECXZ @@no_brush_bitmap
15296 XCHG EDX, ECX // lbHatch = fPenBrushBitmap
15297 MOV CL, BS_PATTERN // = 3
15298 JMP @@create_pen
15300 @@no_brush_bitmap:
15301 MOVZX ECX, [EBX].TGraphicTool.fData.Pen.BrushStyle
15302 CMP CL, 1
15303 JLE @@create_pen
15304 MOV EDX, ECX
15305 MOV CL, 2
15306 SUB EDX, ECX
15308 @@create_pen:
15309 PUSH EDX
15310 PUSH EAX
15311 PUSH ECX
15312 MOV ECX, ESP
15315 PUSH EDX
15316 PUSH EDX
15317 PUSH ECX
15318 PUSH [EBX].TGraphicTool.fData.Pen.Width
15319 MOVZX ECX, [EBX].TGraphicTool.fData.Pen.Join
15320 SHL ECX, 12
15321 MOVZX EDX, [EBX].TGraphicTool.fData.Pen.EndCap
15322 SHL EDX, 8
15323 OR EDX, ECX
15324 OR DL, byte ptr [EBX].TGraphicTool.fData.Pen.Style
15325 OR EDX, PS_GEOMETRIC
15326 PUSH EDX
15327 CALL ExtCreatePen
15329 POP ECX
15330 POP ECX
15331 POP ECX
15333 MOV [EBX].TGraphicTool.fHandle, EAX
15334 POP EBX
15336 @@exit:
15337 XCHG EAX, ECX
15338 end;
15339 {$ELSE ASM_VERSION} //Pascal
15340 function MakeGeometricPenHandle( Self_: PGraphicTool ): THandle;
15341 const
15342 PenStyles: array[ TPenStyle ] of Word =
15343 (PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL,
15344 PS_INSIDEFRAME);
15345 PenEndCapStyles: array[ TPenEndCap ] of Word =
15346 (PS_ENDCAP_ROUND, PS_ENDCAP_SQUARE, PS_ENDCAP_FLAT);
15347 PenJoinStyles: array[ TPenJoin ] of Word =
15348 (PS_JOIN_ROUND, PS_JOIN_BEVEL, PS_JOIN_MITER );
15350 LogBrush: TLogBrush;
15351 begin
15352 if Self_.fHandle = 0 then
15353 with Self_{-}^{+}, LogBrush do
15354 begin
15355 lbColor := Color2RGB( fData.Color );
15356 lbHatch := 0;
15357 if fData.Pen.BrushBitmap <> 0 then
15358 begin
15359 lbStyle := BS_PATTERN;
15360 lbHatch := fData.Pen.BrushBitmap;
15362 else
15363 case fData.Pen.BrushStyle of
15364 bsSolid: lbStyle := BS_SOLID;
15365 bsClear: lbStyle := BS_NULL;
15366 else begin
15367 lbStyle := BS_HATCHED;
15368 case fData.Pen.BrushStyle of
15369 bsHorizontal: lbHatch := HS_HORIZONTAL;
15370 bsVertical: lbHatch := HS_VERTICAL;
15371 bsFDiagonal: lbHatch := HS_FDIAGONAL;
15372 bsBDiagonal: lbHatch := HS_BDIAGONAL;
15373 bsCross: lbHatch := HS_CROSS;
15374 bsDiagCross: lbHatch := HS_DIAGCROSS;
15375 end;
15376 end;
15377 end;
15378 end;
15379 Self_.fHandle := ExtCreatePen( PS_GEOMETRIC or Byte( Self_.fData.Pen.Style ) or
15380 PenEndCapStyles[ Self_.fData.Pen.EndCap ] or
15381 PenJoinStyles[ Self_.fData.Pen.Join ],
15382 Self_.fData.Pen.Width, LogBrush, 0, nil );
15383 {Assert( Self_.fHandle <> 0, 'Error ' + Int2Str( GetLastError ) +
15384 ': ' + SysErrorMessage( GetLastError ) );}
15385 {$IFDEF DEBUG_GDIOBJECTS}
15386 Inc( PenCount );
15387 {$ENDIF}
15388 Result := Self_.fHandle;
15389 end;
15390 {$ENDIF ASM_VERSION}
15391 //[END MakeGeometricPenHandle]
15393 //[procedure TGraphicTool.SetFontWeight]
15394 procedure TGraphicTool.SetFontWeight(const Value: Integer);
15395 begin
15396 if fData.Font.Weight = Value then Exit;
15397 fData.Font.Weight := Value;
15398 Changed;
15399 end;
15401 //[procedure TGraphicTool.SetLogFontStruct]
15402 procedure TGraphicTool.SetLogFontStruct(const Value: TLogFont);
15403 begin
15404 if CompareMem(@fData.Font, @Value, SizeOf(TLogFont)) then Exit;
15405 Move(Value, fData.Font, SizeOF(TLogFont));
15406 Changed;
15407 end;
15409 //[function TGraphicTool.GetLogFontStruct]
15410 function TGraphicTool.GetLogFontStruct: TLogFont;
15411 begin
15412 Move(fData.Font, Result, SizeOf(TLogFont));
15413 end;
15426 { TCanvas }
15428 type
15429 TStock = Packed Record
15430 StockPen: HPEN;
15431 StockBrush: HBRUSH;
15432 StockFont: HFONT;
15433 end;
15436 Stock: TStock;
15438 //[destructor TCanvas.Destroy]
15439 destructor TCanvas.Destroy;
15440 begin
15441 Handle := 0;
15442 fPen.Free;
15443 fBrush.Free;
15444 fFont.Free;
15445 //if Assigned( GlobalCanvas_OnDestroyCanvas ) then
15446 // GlobalCanvas_OnDestroyCanvas( Self );
15447 inherited;
15448 end;
15450 {$IFDEF ASM_VERSION}
15451 //[function TCanvas.Assign]
15452 function TCanvas.Assign(SrcCanvas: PCanvas): Boolean;
15454 PUSH EBX
15455 PUSH ESI
15456 XCHG EBX, EAX
15457 MOV ESI, EDX
15459 MOV EAX, [EBX].fFont
15460 MOV EDX, [ESI].fFont
15461 CALL TGraphicTool.Assign
15462 MOV [EBX].fFont, EAX
15464 MOV EAX, [EBX].fBrush
15465 MOV EDX, [ESI].fBrush
15466 CALL TGraphicTool.Assign
15467 MOV [EBX].fBrush, EAX
15469 MOV EAX, [EBX].fPen
15470 MOV EDX, [ESI].fPen
15471 CALL TGraphicTool.Assign
15472 MOV [EBX].fPen, EAX
15474 CALL AssignChangeEvents
15476 MOV ECX, [EBX].fFont
15477 OR ECX, [EBX].fBrush
15478 OR ECX, [EBX].fPen
15479 SETNZ AL
15481 MOV EDX, [ESI].fPenPos.x
15482 MOV ECX, [ESI].fPenPos.y
15483 CMP EDX, [EBX].fPenPos.x
15484 JNE @@chg_penpos
15485 CMP ECX, [EBX].fPenPos.y
15486 JE @@1
15487 @@chg_penpos:
15488 MOV AL, 1
15489 MOV [EBX].fPenPos.x, EDX
15490 MOV [EBX].fPenPos.y, ECX
15491 @@1:
15492 MOV EDX, [ESI].fCopyMode
15493 CMP EDX, [EBX].fCopyMode
15494 JE @@2
15495 MOV [EBX].fCopyMode, EDX
15496 MOV AL, 1
15497 @@2:
15498 POP ESI
15499 POP EBX
15500 end;
15501 {$ELSE ASM_VERSION} //Pascal
15502 function TCanvas.Assign(SrcCanvas: PCanvas): Boolean;
15503 begin
15504 fFont := fFont.Assign( SrcCanvas.fFont );
15505 fBrush := fBrush.Assign( SrcCanvas.fBrush );
15506 fPen := fPen.Assign( SrcCanvas.fPen );
15507 AssignChangeEvents;
15508 Result := (fFont <> nil) or (fBrush <> nil) or (fPen <> nil);
15509 if (SrcCanvas.PenPos.x <> PenPos.x) or (SrcCanvas.PenPos.y <> PenPos.y) then
15510 begin
15511 Result := True;
15512 PenPos := SrcCanvas.PenPos;
15513 end;
15514 if SrcCanvas.ModeCopy <> ModeCopy then
15515 begin
15516 Result := True;
15517 ModeCopy := SrcCanvas.ModeCopy;
15518 end;
15519 end;
15520 {$ENDIF ASM_VERSION}
15522 {$IFDEF ASM_VERSION}
15523 //[procedure TCanvas.CreateBrush]
15524 procedure TCanvas.CreateBrush;
15526 PUSH EBX
15527 MOV EBX, EAX
15529 MOV ECX, [EAX].fBrush
15530 JECXZ @@chk_owner
15532 MOV EAX, ECX
15533 CALL TGraphicTool.GetHandle
15534 PUSH EAX
15536 MOV EAX, EBX
15537 CALL AssignChangeEvents
15539 MOV EAX, EBX
15540 CALL TCanvas.GetHandle
15541 PUSH EAX
15543 CALL SelectObject
15545 MOV EDX, [EBX].TCanvas.fBrush
15546 CMP [EDX].TGraphicTool.fData.Brush.Style, bsSolid
15548 MOV EAX, [EDX].TGraphicTool.fData.Color
15549 @@0:
15550 MOV EBX, [EBX].TCanvas.fHandle
15551 MOV ECX, offset[Color2RGB]
15552 JNZ @@1
15554 PUSH OPAQUE
15555 PUSH EBX
15557 CALL ECX //Color2RGB
15558 PUSH EAX
15559 PUSH EBX
15560 JMP @@2
15561 @@1:
15562 PUSH TRANSPARENT
15563 PUSH EBX
15565 CALL ECX //Color2RGB
15566 NOT EAX
15567 PUSH EAX
15568 PUSH EBX
15569 @@2:
15570 CALL SetBkColor
15571 CALL SetBkMode
15572 @@exit:
15573 POP EBX
15576 @@chk_owner:
15577 MOV ECX, [EBX].fOwnerControl
15578 JECXZ @@exit
15580 MOV EAX, [ECX].TControl.fColor
15581 XOR ECX, ECX
15582 JMP @@0
15583 end;
15584 {$ELSE ASM_VERSION} //Pascal
15585 procedure TCanvas.CreateBrush;
15586 begin
15587 //UnrealizeObject( Brush.Handle );
15588 // if GdiObject parameter of UnrealizeObject is brush handle,
15589 // this call does nothing (from Win32.hlp)
15591 if assigned( fBrush ) then
15592 begin
15593 SelectObject( GetHandle, fBrush.Handle );
15594 //fBrush.fOnChange := ObjectChanged;
15595 AssignChangeEvents;
15596 if fBrush.fData.Brush.Style = bsSolid then
15597 begin
15598 SetBkColor( fHandle, Color2RGB( fBrush.fData.Color ) );
15599 SetBkMode( fHandle, OPAQUE );
15601 else
15602 begin
15603 { Win95 doesn't draw brush hatches if bkcolor = brush color }
15604 { Since bkmode is transparent, nothing should use bkcolor anyway }
15605 SetBkColor( fHandle, not Color2RGB( fBrush.fData.Color ) );
15606 SetBkMode( fHandle, TRANSPARENT );
15607 end;
15609 else
15610 if Assigned( fOwnerControl ) then
15611 begin
15612 SetBkColor( GetHandle, Color2RGB( PControl( fOwnerControl ).fColor ) );
15613 SetBkMode( fHandle, OPAQUE );
15614 end;
15615 end;
15616 {$ENDIF ASM_VERSION}
15618 {$IFDEF ASM_VERSION}
15619 //[procedure TCanvas.CreateFont]
15620 procedure TCanvas.CreateFont;
15622 PUSH EBX
15623 MOV EBX, EAX
15625 MOV ECX, [EAX].TCanvas.fFont
15626 JECXZ @@chk_owner
15628 MOV EAX, [ECX].TGraphicTool.fData.Color
15629 PUSH ECX
15630 CALL Color2RGB
15631 XCHG EAX, [ESP]
15633 CALL TGraphicTool.GetHandle
15634 PUSH EAX
15636 MOV EAX, EBX
15637 CALL AssignChangeEvents;
15639 MOV EAX, EBX
15640 CALL TCanvas.GetHandle
15641 PUSH EAX
15642 MOV EBX, EAX
15644 CALL SelectObject
15646 @@set_txcolor:
15647 PUSH EBX
15648 CALL SetTextColor
15650 @@exit:
15651 POP EBX
15654 @@chk_owner:
15655 MOV ECX, [EBX].fOwnerControl
15656 JECXZ @@exit
15658 MOV EBX, [EBX].fHandle
15659 MOV EAX, [ECX].TControl.fTextColor
15660 CALL Color2RGB
15661 PUSH EAX
15662 JMP @@set_txcolor
15663 end;
15664 {$ELSE ASM_VERSION} //Pascal
15665 procedure TCanvas.CreateFont;
15666 begin
15667 if assigned( fFont ) then
15668 begin
15669 SelectObject( GetHandle, fFont.Handle );
15670 SetTextColor( fHandle, Color2RGB( fFont.fData.Color ) );
15671 //fFont.fOnChange := ObjectChanged;
15672 AssignChangeEvents;
15674 else
15675 if Assigned( fOwnerControl ) then
15676 begin
15677 SetTextColor( fHandle, Color2RGB( PControl( fOwnerControl ).fTextColor ) );
15678 end;
15679 end;
15680 {$ENDIF ASM_VERSION}
15682 {$IFDEF ASM_VERSION}
15683 //[procedure TCanvas.CreatePen]
15684 procedure TCanvas.CreatePen;
15686 MOV ECX, [EAX].TCanvas.fPen
15687 JECXZ @@exit
15689 PUSH EBX
15690 MOV EBX, EAX
15692 MOV DL, [ECX].TGraphicTool.fData.Pen.Mode
15693 MOVZX EDX, DL
15694 INC EDX
15695 PUSH EDX
15697 MOV EAX, ECX
15698 CALL TGraphicTool.GetHandle
15699 PUSH EAX
15701 MOV EAX, EBX
15702 CALL AssignChangeEvents
15704 MOV EAX, EBX
15705 CALL TCanvas.GetHandle
15706 PUSH EAX
15707 MOV EBX, EAX
15709 CALL SelectObject
15710 PUSH EBX
15711 CALL SetROP2
15713 POP EBX
15714 @@exit:
15715 end;
15716 {$ELSE ASM_VERSION} //Pascal
15717 procedure TCanvas.CreatePen;
15718 begin
15719 if assigned( fPen ) then
15720 begin
15721 SelectObject( GetHandle, fPen.Handle );
15722 SetROP2( fHandle, Ord( fPen.fData.Pen.Mode ) + 1 );
15723 //fPen.fOnChange := ObjectChanged;
15724 AssignChangeEvents;
15725 end;
15726 end;
15727 {$ENDIF ASM_VERSION}
15729 //[function TCanvas.GetPixels]
15730 function TCanvas.GetPixels(X, Y: Integer): TColor;
15731 begin
15732 RequiredState( HandleValid );
15733 Result := Windows.GetPixel(FHandle, X, Y);
15734 end;
15736 //[procedure TCanvas.SetPixels]
15737 procedure TCanvas.SetPixels(X, Y: Integer; const Value: TColor);
15738 begin
15739 Changing;
15740 RequiredState( HandleValid );
15741 Windows.SetPixel(FHandle, X, Y, Color2RGB( Value ));
15742 end;
15744 {$IFDEF ASM_VERSION}
15745 //[procedure TCanvas.DeselectHandles]
15746 procedure TCanvas.DeselectHandles;
15748 PUSH EBX
15749 PUSH ESI
15750 PUSH EDI
15751 LEA EBX, [EAX].TCanvas.fState
15752 //CALL TCanvas.GetHandle
15753 MOV EAX, [EAX].TCanvas.fHandle
15754 TEST EAX, EAX
15755 JZ @@exit
15757 MOVZX EDX, byte ptr[EBX]
15758 AND DL, PenValid or BrushValid or FontValid
15759 JZ @@exit
15761 PUSH EAX
15762 LEA EDI, [Stock]
15764 MOV ECX, [EDI]
15765 INC ECX
15766 LOOP @@1
15768 MOV ESI, offset[ GetStockObject ]
15770 PUSH BLACK_PEN
15771 CALL ESI
15772 STOSD
15774 PUSH HOLLOW_BRUSH
15775 CALL ESI
15776 STOSD
15778 PUSH SYSTEM_FONT
15779 CALL ESI
15780 STOSD
15782 @@1:
15783 LEA ESI, [Stock]
15784 POP EDX
15786 LODSD
15787 PUSH EAX
15788 PUSH EDX
15790 LODSD
15791 PUSH EAX
15792 PUSH EDX
15794 LODSD
15795 PUSH EAX
15796 PUSH EDX
15798 MOV ESI, offset[ SelectObject ]
15799 CALL ESI
15800 CALL ESI
15801 CALL ESI
15803 AND byte ptr [EBX], not( PenValid or BrushValid or FontValid )
15804 @@exit:
15805 POP EDI
15806 POP ESI
15807 POP EBX
15808 end;
15809 {$ELSE ASM_VERSION} //Pascal
15810 procedure TCanvas.DeselectHandles;
15811 begin
15812 //if (GetHandle <> 0) and
15813 if (fHandle <> 0) and
15814 LongBool(fState and (PenValid or BrushValid or FontValid)) then
15815 with Stock do
15816 begin
15817 if StockPen = 0 then
15818 begin
15819 StockPen := GetStockObject(BLACK_PEN);
15820 StockBrush := GetStockObject(HOLLOW_BRUSH);
15821 StockFont := GetStockObject(SYSTEM_FONT);
15822 end;
15823 SelectObject( fHandle, StockPen );
15824 SelectObject( fHandle, StockBrush );
15825 SelectObject( fHandle, StockFont );
15826 fState := fState and not( PenValid or BrushValid or FontValid );
15827 end;
15828 end;
15829 {$ENDIF ASM_VERSION}
15831 {$IFDEF ASM_VERSION}
15832 //[function TCanvas.RequiredState]
15833 function TCanvas.RequiredState(ReqState: DWORD): Integer; stdcall;
15835 PUSH EBX
15836 PUSH ESI
15837 MOV EBX, ReqState
15838 MOV ESI, [EBP+8] //Self
15839 MOV EAX, ESI
15840 TEST BL, ChangingCanvas
15841 JZ @@1
15842 CALL Changing
15843 @@1: AND BL, 0Fh
15845 TEST BL, HandleValid
15846 JZ @@2
15847 CALL TCanvas.GetHandle
15848 TEST EAX, EAX
15849 JZ @@ret_0
15850 @@2:
15851 MOV AL, [ESI].TCanvas.fState
15852 NOT EAX
15853 AND BL, AL
15854 JZ @@ret_handle
15856 TEST BL, FontValid
15857 JZ @@3
15858 MOV EAX, ESI
15859 CALL CreateFont
15860 @@3: TEST BL, PenValid
15861 JZ @@5
15862 MOV EAX, ESI
15863 CALL CreatePen
15864 MOV ECX, [ESI].TCanvas.fPen
15865 JCXZ @@5
15866 MOV AL, [ECX].TGraphicTool.fData.Pen.Style
15867 DEC AL
15868 {$IFDEF PARANOIA}
15869 DB $2C, 3
15870 {$ELSE}
15871 SUB AL, 3
15872 {$ENDIF}
15873 JB @@6
15874 @@5: TEST BL, BrushValid
15875 JZ @@7
15876 @@6: MOV EAX, ESI
15877 CALL CreateBrush
15878 @@7: OR [ESI].TCanvas.fState, BL
15879 @@ret_handle:
15880 MOV EAX, [ESI].TCanvas.fHandle
15881 @@ret_0:
15882 POP ESI
15883 POP EBX
15884 end;
15885 {$ELSE ASM_VERSION} //Pascal
15886 function TCanvas.RequiredState(ReqState: DWORD): Integer; stdcall;
15888 NeededState: Byte;
15889 begin
15890 if Boolean(ReqState and ChangingCanvas) then
15891 Changing;
15892 ReqState := ReqState and 15;
15893 NeededState := Byte( ReqState ) and not fState;
15894 Result := 0;
15895 if Boolean(ReqState and HandleValid) then
15896 begin
15897 if GetHandle = 0 then Exit;
15898 // Important!
15899 end;
15900 if NeededState <> 0 then
15901 begin
15902 if Boolean( NeededState and FontValid ) then
15903 CreateFont;
15904 if Boolean( NeededState and PenValid ) then
15905 begin
15906 CreatePen;
15907 if assigned( fPen ) then
15908 if fPen.fData.Pen.Style in [psDash, psDot, psDashDot, psDashDotDot] then
15909 NeededState := NeededState or BrushValid;
15910 end;
15911 if Boolean( NeededState and BrushValid ) then
15912 CreateBrush;
15913 fState := fState or NeededState;
15914 end;
15915 Result := fHandle;
15916 end;
15917 {$ENDIF ASM_VERSION}
15919 {$IFDEF ASM_VERSION}
15920 //[procedure TCanvas.SetHandle]
15921 procedure TCanvas.SetHandle(Value: HDC);
15923 PUSH EBX
15924 MOV EBX, EAX
15925 MOV ECX, [EBX].fHandle
15926 CMP ECX, EDX
15927 JZ @@exit
15928 JECXZ @@chk_val
15930 PUSH EDX
15931 PUSH ECX
15932 CALL DeselectHandles
15933 POP EDX
15935 MOV ECX, [EBX].fOwnerControl
15936 JECXZ @@chk_Release
15937 CMP [ECX].TControl.fPaintDC, EDX
15938 JE @@clr_Handle
15940 @@chk_Release:
15941 PUSH EDX
15942 CMP [EBX].fOnGetHandle.TMethod.Code, offset[TControl.DC2Canvas]
15943 JNE @@deldc
15944 PUSH [ECX].TControl.fHandle
15945 CALL ReleaseDC
15946 JMP @@clr_Handle
15947 @@deldc:
15948 CALL DeleteDC
15950 @@clr_Handle:
15951 XOR ECX, ECX
15952 MOV [EBX].TCanvas.fHandle, ECX
15953 MOV [EBX].TCanvas.fIsPaintDC, CL
15954 AND [EBX].TCanvas.fState, not HandleValid
15956 POP EDX
15957 @@chk_val:
15958 TEST EDX, EDX
15959 JZ @@exit
15961 OR [EBX].TCanvas.fState, HandleValid
15962 MOV [EBX].TCanvas.fHandle, EDX
15963 LEA EDX, [EBX].TCanvas.fPenPos
15964 MOV EAX, EBX
15965 CALL SetPenPos
15967 @@exit: POP EBX
15968 end;
15969 {$ELSE ASM_VERSION} //Pascal
15970 procedure TCanvas.SetHandle(Value: HDC);
15971 {$IFDEF F_P}
15972 var Ptr1: Pointer;
15973 {$ENDIF F_P}
15974 begin
15975 if fHandle = Value then Exit;
15976 if fHandle <> 0 then
15977 begin
15978 DeselectHandles;
15979 {if not fIsPaintDC and
15980 not( assigned(fOwnerControl) and
15981 PControl(fOwnerControl).fDoubleBuffered )
15982 then}
15983 if not( assigned(fOwnerControl) and
15984 (PControl(fOwnerControl).fPaintDC = fHandle) ) then
15985 begin
15986 {$IFDEF F_P}
15987 Ptr1 := Self;
15989 MOV EAX, [Ptr1]
15990 MOV EAX, [EAX].TCanvas.fOnGetHandle
15991 MOV [Ptr1], EAX
15992 end [ 'EAX' ];
15993 if Ptr1 = @ TControl.DC2Canvas then
15994 {$ELSE DELPHI}
15995 //////////////////// SLAG
15996 if TMethod(fOnGetHandle).Code =
15997 @TControl.Dc2Canvas then
15998 {$ENDIF F_P/DELPHI}
15999 ReleaseDC(PControl(fOwnerControl).Handle, fHandle )
16000 else
16001 DeleteDC( fHandle );
16002 ////////////////////
16003 end;
16004 fHandle := 0;
16005 fIsPaintDC := False;
16006 fState := fState and not HandleValid;
16007 end;
16008 if Value <> 0 then
16009 begin
16010 fState := fState or HandleValid;
16011 fHandle := Value;
16012 SetPenPos( fPenPos );
16013 end;
16014 end;
16015 {$ENDIF ASM_VERSION}
16017 {$IFDEF ASM_VERSION}
16018 //[procedure TCanvas.SetPenPos]
16019 procedure TCanvas.SetPenPos(const Value: TPoint);
16021 MOV ECX, [EDX].TPoint.y
16022 MOV EDX, [EDX].TPoint.x
16023 MOV [EAX].fPenPos.x, EDX
16024 MOV [EAX].fPenPos.y, ECX
16025 CALL MoveTo
16026 end;
16027 {$ELSE ASM_VERSION} //Pascal
16028 procedure TCanvas.SetPenPos(const Value: TPoint);
16029 begin
16030 fPenPos := Value;
16031 MoveTo( Value.x, Value.y );
16032 end;
16033 {$ENDIF ASM_VERSION}
16035 {$IFDEF ASM_VERSION}
16036 //[procedure TCanvas.Changing]
16037 procedure TCanvas.Changing;
16039 PUSHAD
16040 MOV ECX, [EAX].fOnChange.TMethod.Code
16041 JECXZ @@exit
16042 XCHG EDX, EAX
16043 MOV EAX, [EDX].fOnChange.TMethod.Data
16044 CALL ECX
16045 @@exit:
16046 POPAD
16047 end;
16048 {$ELSE ASM_VERSION} //Pascal
16049 procedure TCanvas.Changing;
16050 begin
16051 if Assigned( fOnChange ) then
16052 fOnChange( @Self );
16053 end;
16054 {$ENDIF ASM_VERSION}
16056 {$IFDEF ASM_VERSION}
16057 //[procedure TCanvas.Arc]
16058 procedure TCanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16060 PUSH ESI
16062 PUSH HandleValid or PenValid or ChangingCanvas
16063 PUSH dword ptr [EBP+8]
16064 CALL RequiredState
16066 MOV EDX, EAX
16068 LEA ESI, [Y4]
16071 XOR ECX, ECX
16072 MOV CL, 8
16073 @@1:
16074 LODSD
16075 PUSH EAX
16077 LOOP @@1
16080 PUSH EDX //Canvas.fHandle
16081 CALL Windows.Arc
16082 POP ESI
16083 end;
16084 {$ELSE ASM_VERSION} //Pascal
16085 procedure TCanvas.Arc(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16086 begin
16087 RequiredState( HandleValid or PenValid or ChangingCanvas );
16088 Windows.Arc(FHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);
16089 end;
16090 {$ENDIF ASM_VERSION}
16092 {$IFDEF ASM_VERSION}
16093 //[procedure TCanvas.Chord]
16094 procedure TCanvas.Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16096 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16097 PUSH dword ptr [EBP + 8]
16098 CALL RequiredState
16100 MOV EDX, EAX
16102 PUSH ESI
16103 LEA ESI, [Y4]
16106 XOR ECX, ECX
16107 MOV CL, 8
16108 @@1:
16109 LODSD
16110 PUSH EAX
16112 LOOP @@1
16115 PUSH EDX //Canvas.fHandle
16116 CALL Windows.Chord
16117 POP ESI
16118 end;
16119 {$ELSE ASM_VERSION} //Pascal
16120 procedure TCanvas.Chord(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16121 begin
16122 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16123 Windows.Chord(FHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);
16124 end;
16125 {$ENDIF ASM_VERSION}
16127 {$IFDEF ASM_VERSION}
16128 //[procedure TCanvas.CopyRect]
16129 procedure TCanvas.CopyRect(const DstRect: TRect; SrcCanvas: PCanvas;
16130 const SrcRect: TRect);
16132 PUSH ESI
16133 PUSH EDI
16135 PUSH [EAX].fCopyMode
16137 PUSH EDX
16139 PUSH HandleValid or BrushValid
16140 PUSH ECX
16142 PUSH HandleValid or FontValid or BrushValid or ChangingCanvas
16143 PUSH EAX
16144 MOV ESI, offset[ RequiredState ]
16145 CALL ESI
16146 MOV EDI, EAX // EDI = @Self.fHandle
16148 CALL ESI
16149 MOV EDX, EAX // EDX = SrcCanvas.fHandle
16151 POP ECX // ECX = @DstRect
16153 MOV ESI, [SrcRect]
16155 MOV EAX, [ESI].TRect.Bottom
16156 SUB EAX, [ESI].TRect.Top
16157 PUSH EAX
16159 MOV EAX, [ESI].TRect.Right
16160 SUB EAX, [ESI].TRect.Left
16161 PUSH EAX
16163 PUSH [ESI].TRect.Top
16165 LODSD
16166 PUSH EAX
16168 PUSH EDX
16170 MOV EAX, [ECX].TRect.Bottom
16171 MOV EDX, [ECX].TRect.Top
16172 SUB EAX, EDX
16173 PUSH EAX
16175 MOV EAX, [ECX].TRect.Right
16176 MOV ESI, [ECX].TRect.Left
16177 SUB EAX, ESI
16178 PUSH EAX
16180 PUSH EDX
16182 PUSH ESI
16184 PUSH EDI
16186 CALL StretchBlt
16188 POP EDI
16189 POP ESI
16190 end;
16191 {$ELSE ASM_VERSION} //Pascal
16192 procedure TCanvas.CopyRect(const DstRect: TRect; SrcCanvas: PCanvas;
16193 const SrcRect: TRect);
16194 begin
16195 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
16196 SrcCanvas.RequiredState( HandleValid or BrushValid );
16197 StretchBlt( fHandle, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left,
16198 DstRect.Bottom - DstRect.Top, SrcCanvas.Handle, SrcRect.Left, SrcRect.Top,
16199 SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top, ModeCopy);
16200 end;
16201 {$ENDIF ASM_VERSION}
16203 {$IFDEF ASM_VERSION}
16204 //[procedure TCanvas.DrawFocusRect]
16205 procedure TCanvas.DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16207 PUSH EDX
16209 PUSH HandleValid or BrushValid or FontValid or ChangingCanvas
16210 PUSH EAX
16211 CALL RequiredState
16213 PUSH EAX
16214 CALL Windows.DrawFocusRect
16215 end;
16216 {$ELSE ASM_VERSION} //Pascal
16217 procedure TCanvas.DrawFocusRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16218 begin
16219 RequiredState( HandleValid or BrushValid or FontValid or ChangingCanvas );
16220 Windows.DrawFocusRect(FHandle, Rect);
16221 end;
16222 {$ENDIF ASM_VERSION}
16224 {$IFDEF ASM_VERSION}
16225 //[procedure TCanvas.Ellipse]
16226 procedure TCanvas.Ellipse(X1, Y1, X2, Y2: Integer);
16228 PUSH [Y2]
16229 PUSH [X2]
16230 PUSH ECX
16231 PUSH EDX
16233 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16234 PUSH EAX
16235 CALL RequiredState
16237 PUSH EAX
16238 CALL Windows.Ellipse
16239 end;
16240 {$ELSE ASM_VERSION} //Pascal
16241 procedure TCanvas.Ellipse(X1, Y1, X2, Y2: Integer);
16242 begin
16243 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16244 Windows.Ellipse(FHandle, X1, Y1, X2, Y2);
16245 end;
16246 {$ENDIF ASM_VERSION}
16248 {$IFDEF ASM_VERSION}
16249 //[procedure TCanvas.FillRect]
16250 procedure TCanvas.FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16252 PUSH EBX
16253 XCHG EBX, EAX
16254 PUSH EDX
16255 PUSH HandleValid or BrushValid or ChangingCanvas
16256 PUSH EBX
16257 CALL RequiredState
16258 MOV ECX, [EBX].fBrush
16259 JECXZ @@chk_ctl
16261 @@fill_with_Brush:
16262 XCHG EAX, ECX
16263 CALL TGraphicTool.GetHandle
16264 POP EDX
16265 PUSH EAX
16266 JMP @@fin
16267 @@chk_ctl:
16268 MOV ECX, [EBX].fOwnerControl
16269 JECXZ @@dflt_fill
16270 XCHG EAX, ECX
16271 MOV ECX, [EAX].TControl.fBrush
16272 INC ECX
16273 LOOP @@fill_with_Brush
16274 MOV EAX, [EAX].TControl.fColor
16275 CALL Color2RGB
16276 PUSH EAX
16277 CALL CreateSolidBrush
16278 POP EDX
16279 PUSH EAX
16280 PUSH EAX
16281 PUSH EDX
16282 PUSH [EBX].fHandle
16283 CALL Windows.FillRect
16284 CALL DeleteObject
16285 POP EBX
16287 @@dflt_fill:
16288 POP EDX
16289 PUSH COLOR_WINDOW + 1
16290 @@fin:
16291 PUSH EDX
16292 PUSH [EBX].fHandle
16293 CALL Windows.FillRect
16294 POP EBX
16295 end;
16296 {$ELSE ASM_VERSION} //Pascal
16297 procedure TCanvas.FillRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16298 var Br: HBrush;
16299 begin
16300 RequiredState( HandleValid or BrushValid or ChangingCanvas );
16301 if assigned( fBrush ) then
16302 begin
16303 Windows.FillRect(fHandle, Rect, fBrush.Handle);
16305 else
16306 if assigned( fOwnerControl ) then
16307 begin
16308 if assigned( PControl( fOwnerControl ).fBrush ) then
16309 Windows.FillRect( fHandle, Rect, PControl( fOwnerControl ).fBrush.Handle )
16310 else
16311 begin
16312 Br := CreateSolidBrush( Color2RGB(PControl(fOwnerControl).fColor) );
16313 Windows.FillRect(fHandle, Rect, Br );
16314 DeleteObject( Br );
16315 end;
16317 else
16318 begin
16319 Windows.FillRect(fHandle, Rect, HBrush(COLOR_WINDOW + 1) );
16320 end;
16321 end;
16322 {$ENDIF ASM_VERSION}
16324 {$IFDEF ASM_VERSION}
16325 //[procedure TCanvas.FillRgn]
16326 procedure TCanvas.FillRgn(const Rgn: HRgn);
16328 PUSH EBX
16329 XCHG EBX, EAX
16330 PUSH EDX
16332 PUSH HandleValid or BrushValid or ChangingCanvas
16333 PUSH EBX
16334 CALL RequiredState
16336 MOV ECX, [EBX].TCanvas.fBrush
16337 JECXZ @@1
16339 //PUSH [ECX].TGraphicTool.fData.Color
16340 //JMP @@cr_br
16342 @@fill_rgn_using_Brush:
16343 XCHG EAX, ECX
16344 CALL TGraphicTool.GetHandle
16345 POP EDX
16346 PUSH EAX
16347 PUSH EDX
16348 PUSH [EBX].fHandle
16349 CALL Windows.FillRgn
16350 JMP @@fin
16352 @@1: MOV ECX, [EBX].TCanvas.fOwnerControl
16353 MOV EAX, -1 // clWhite
16354 JECXZ @@2
16356 XCHG EAX, ECX
16357 MOV ECX, [EAX].TControl.fBrush
16358 INC ECX
16359 LOOP @@fill_rgn_using_Brush
16361 MOV EAX, [EAX].TControl.fColor
16362 @@2:
16363 CALL Color2RGB
16364 PUSH EAX
16365 CALL CreateSolidBrush // EAX = Br
16367 POP EDX // Rgn
16369 PUSH EAX //-------------------//
16370 PUSH EAX // Br
16371 PUSH EDX // Rgn
16372 PUSH [EBX].FHandle // fHandle
16373 CALL Windows.FillRgn
16375 CALL DeleteObject
16377 @@fin:
16378 POP EBX
16379 end;
16380 {$ELSE ASM_VERSION} //Pascal
16381 procedure TCanvas.FillRgn(const Rgn: HRgn);
16382 var Br : HBrush;
16383 begin
16384 RequiredState( HandleValid or BrushValid or ChangingCanvas );
16385 if assigned( fBrush ) then
16386 Windows.FillRgn(FHandle, Rgn, fBrush.Handle )
16387 else
16388 if assigned( fOwnerControl ) then
16389 begin
16390 if Assigned( PControl( fOwnerControl ).fBrush ) then
16391 Windows.FillRgn( FHandle, Rgn, PControl( fOwnerControl ).fBrush.Handle )
16392 else
16393 begin
16394 Br := CreateSolidBrush( Color2RGB(PControl(fOwnerControl).fColor) );
16395 Windows.FillRgn( fHandle, Rgn, Br );
16396 DeleteObject( Br );
16397 end;
16399 else
16400 begin
16401 Br := CreateSolidBrush( DWORD(clWindow) );
16402 Windows.FillRgn( fHandle, Rgn, Br );
16403 DeleteObject( Br );
16404 end;
16405 end;
16406 {$ENDIF ASM_VERSION}
16408 {$IFDEF ASM_VERSION}
16409 //[procedure TCanvas.FloodFill]
16410 procedure TCanvas.FloodFill(X, Y: Integer; Color: TColor;
16411 FillStyle: TFillStyle);
16413 PUSH EBX
16414 MOV EBX, EAX
16416 MOVZX EAX, [FillStyle]
16417 TEST EAX, EAX
16418 MOV EAX, FLOODFILLSURFACE // = 1
16419 JZ @@1
16420 //MOV EAX, FLOODFILLBORDER // = 0
16421 DEC EAX
16422 @@1:
16423 PUSH EAX
16424 PUSH [Color]
16425 PUSH ECX
16426 PUSH EDX
16428 PUSH HandleValid or BrushValid or ChangingCanvas
16429 PUSH EBX
16430 CALL RequiredState
16431 PUSH EAX
16432 CALL Windows.ExtFloodFill
16434 POP EBX
16435 end;
16436 {$ELSE ASM_VERSION} //Pascal
16437 procedure TCanvas.FloodFill(X, Y: Integer; Color: TColor;
16438 FillStyle: TFillStyle);
16439 const
16440 FillStyles: array[TFillStyle] of Word =
16441 (FLOODFILLSURFACE, FLOODFILLBORDER);
16442 begin
16443 RequiredState( HandleValid or BrushValid or ChangingCanvas );
16444 Windows.ExtFloodFill(FHandle, X, Y, Color, FillStyles[FillStyle]);
16445 end;
16446 {$ENDIF ASM_VERSION}
16448 {$IFDEF ASM_VERSION}
16449 //[procedure TCanvas.FrameRect]
16450 procedure TCanvas.FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16452 PUSH EBX
16453 XCHG EBX, EAX
16454 PUSH EDX
16456 MOV ECX, [EBX].TCanvas.fBrush
16457 JECXZ @@1
16459 PUSH [ECX].TGraphicTool.fData.Color
16460 JMP @@cr_br
16462 @@1: MOV ECX, [EBX].TCanvas.fOwnerControl
16463 JECXZ @@2
16465 PUSH [ECX].TControl.fColor
16466 JMP @@cr_br
16468 @@2: PUSH clWhite
16469 @@cr_br:POP EAX // @Rect
16470 CALL Color2RGB
16471 PUSH EAX
16472 CALL CreateSolidBrush
16473 POP EDX
16474 PUSH EAX
16475 PUSH EAX
16476 PUSH EDX
16478 PUSH HandleValid or ChangingCanvas
16479 PUSH EBX
16480 ///MOV EBX, EDX
16481 CALL RequiredState
16483 PUSH EAX
16484 CALL Windows.FrameRect
16486 ///PUSH EBX
16487 CALL DeleteObject
16489 POP EBX
16490 end;
16491 {$ELSE ASM_VERSION} //Pascal
16492 procedure TCanvas.FrameRect({$IFNDEF FPC}const{$ENDIF} Rect: TRect);
16493 var SolidBr : HBrush;
16494 begin
16495 RequiredState( HandleValid or ChangingCanvas );
16496 if assigned( fBrush ) then
16497 SolidBr := CreateSolidBrush( Color2RGB( fBrush.fData.Color ) )
16498 else
16499 if assigned( fOwnerControl ) then
16500 SolidBr := CreateSolidBrush( PControl(fOwnerControl).fColor )
16501 else
16502 SolidBr := CreateSolidBrush( clWhite );
16503 Windows.FrameRect(FHandle, Rect, SolidBr);
16504 DeleteObject( SolidBr );
16505 end;
16506 {$ENDIF ASM_VERSION}
16508 {$IFDEF ASM_VERSION}
16509 //[procedure TCanvas.LineTo]
16510 procedure TCanvas.LineTo(X, Y: Integer);
16512 PUSH ECX
16513 PUSH EDX
16514 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16515 PUSH EAX
16516 CALL RequiredState
16517 PUSH EAX //Canvas.fHandle
16518 CALL Windows.LineTo
16519 end;
16520 {$ELSE ASM_VERSION} //Pascal
16521 procedure TCanvas.LineTo(X, Y: Integer);
16522 begin
16523 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16524 Windows.LineTo( fHandle, X, Y );
16525 end;
16526 {$ENDIF ASM_VERSION}
16528 {$IFDEF ASM_VERSION}
16529 //[procedure TCanvas.MoveTo]
16530 procedure TCanvas.MoveTo(X, Y: Integer);
16532 PUSH 0
16533 PUSH ECX
16534 PUSH EDX
16535 PUSH HandleValid
16536 PUSH EAX
16537 CALL RequiredState
16538 PUSH EAX //Canvas.fHandle
16539 CALL Windows.MoveToEx
16540 end;
16541 {$ELSE ASM_VERSION} //Pascal
16542 procedure TCanvas.MoveTo(X, Y: Integer);
16543 begin
16544 RequiredState( HandleValid );
16545 Windows.MoveToEx( fHandle, X, Y, nil );
16546 end;
16547 {$ENDIF ASM_VERSION}
16549 //[procedure TCanvas.ObjectChanged]
16550 procedure TCanvas.ObjectChanged(Sender: PGraphicTool);
16551 begin
16552 DeselectHandles;
16553 //if Assigned( GlobalCanvas_OnObjectChanged ) then
16554 // GlobalCanvas_OnObjectChanged( Sender );
16555 end;
16557 {$IFDEF ASM_VERSION}
16558 //[procedure TCanvas.Pie]
16559 procedure TCanvas.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16561 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16562 PUSH dword ptr [EBP + 8]
16563 CALL RequiredState
16565 MOV EDX, EAX
16567 PUSH ESI
16568 LEA ESI, [Y4]
16571 XOR ECX, ECX
16572 MOV CL, 8
16573 @@1:
16574 LODSD
16575 PUSH EAX
16577 LOOP @@1
16580 PUSH EDX //Canvas.fHandle
16581 CALL Windows.Pie
16582 POP ESI
16583 end;
16584 {$ELSE ASM_VERSION} //Pascal
16585 procedure TCanvas.Pie(X1, Y1, X2, Y2, X3, Y3, X4, Y4: Integer); stdcall;
16586 begin
16587 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16588 Windows.Pie( fHandle, X1, Y1, X2, Y2, X3, Y3, X4, Y4);
16589 end;
16590 {$ENDIF ASM_VERSION}
16592 {++}(*
16593 {$IFDEF F_P}
16594 //[Windows API FUNCTIONS ADDITIONAL DECLARATIONS FOR Free Pascal]
16595 function Windows_Polygon; external gdi32 name 'Polygon';
16596 function Windows_Polyline; external gdi32 name 'Polyline';
16597 function FillRect; external user32 name 'FillRect';
16598 function OffsetRect; external user32 name 'OffsetRect';
16599 function CreateAcceleratorTable; external user32 name 'CreateAcceleratorTableA';
16600 function TrackPopupMenu; external user32 name 'TrackPopupMenu';
16601 function AdjustTokenPrivileges(TokenHandle: THandle; DisableAllPrivileges: BOOL;
16602 const NewState: TTokenPrivileges; BufferLength: DWORD;
16603 var PreviousState: TTokenPrivileges; var ReturnLength: DWORD): BOOL; external advapi32 name 'AdjustTokenPrivileges';
16604 function InflateRect; external user32 name 'InflateRect';
16605 {$IFDEF F_P105ORBELOW}
16606 function InvalidateRect; external user32 name 'InvalidateRect';
16607 function ValidateRect; external user32 name 'ValidateRect';
16608 {$ENDIF F_P105ORBELOW}
16609 //[END OF Windows API FUNCTIONS ADDITIONAL DECLARATIONS FOR Free Pascal]
16610 {$ENDIF}
16611 *){--}
16613 {$IFDEF ASM_VERSION}
16614 //[procedure TCanvas.Polygon]
16615 procedure TCanvas.Polygon(const Points: array of TPoint);
16617 INC ECX
16618 PUSH ECX
16619 PUSH EDX
16621 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16622 PUSH EAX
16623 CALL RequiredState
16625 PUSH EAX
16626 CALL Windows.Polygon
16627 end;
16628 {$ELSE ASM_VERSION} //Pascal
16629 procedure TCanvas.Polygon(const Points: array of TPoint);
16630 type
16631 PPoints = ^TPoints;
16632 TPoints = array[0..0] of TPoint;
16633 begin
16634 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16635 {$IFDEF F_P} Windows_Polygon
16636 {$ELSE DELPHI} Windows.Polygon
16637 {$ENDIF}( fHandle, PPoints(@Points)^, High(Points) + 1);
16638 end;
16639 {$ENDIF ASM_VERSION}
16641 {$IFDEF ASM_VERSION}
16642 //[procedure TCanvas.Polyline]
16643 procedure TCanvas.Polyline(const Points: array of TPoint);
16645 INC ECX
16646 PUSH ECX
16647 PUSH EDX
16649 PUSH HandleValid or PenValid or BrushValid or ChangingCanvas
16650 PUSH EAX
16651 CALL RequiredState
16653 PUSH EAX
16654 CALL Windows.Polyline
16655 end;
16656 {$ELSE ASM_VERSION} //Pascal
16657 procedure TCanvas.Polyline(const Points: array of TPoint);
16658 type
16659 PPoints = ^TPoints;
16660 TPoints = array[0..0] of TPoint;
16661 begin
16662 RequiredState( HandleValid or PenValid or BrushValid or ChangingCanvas );
16663 {$IFDEF F_P}Windows_Polyline
16664 {$ELSE DELPHI}Windows.Polyline
16665 {$ENDIF}( fHandle, PPoints(@Points)^, High(Points) + 1);
16666 end;
16667 {$ENDIF ASM_VERSION}
16669 {$IFDEF ASM_VERSION}
16670 //[procedure TCanvas.Rectangle]
16671 procedure TCanvas.Rectangle(X1, Y1, X2, Y2: Integer);
16673 PUSH [Y2]
16674 PUSH [X2]
16675 PUSH ECX
16676 PUSH EDX
16678 PUSH HandleValid or BrushValid or PenValid or ChangingCanvas
16679 PUSH EAX
16680 CALL RequiredState
16682 PUSH EAX
16683 CALL Windows.Rectangle
16684 end;
16685 {$ELSE ASM_VERSION} //Pascal
16686 procedure TCanvas.Rectangle(X1, Y1, X2, Y2: Integer);
16687 begin
16688 RequiredState( HandleValid or BrushValid or PenValid or ChangingCanvas );
16689 Windows.Rectangle( fHandle, X1, Y1, X2, Y2);
16690 end;
16691 {$ENDIF ASM_VERSION}
16693 {$IFDEF ASM_VERSION}
16694 //[procedure TCanvas.RoundRect]
16695 procedure TCanvas.RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
16697 PUSH [Y3]
16698 PUSH [X3]
16699 PUSH [Y2]
16700 PUSH [X2]
16701 PUSH ECX
16702 PUSH EDX
16704 PUSH HandleValid or BrushValid or PenValid or ChangingCanvas
16705 PUSH EAX
16706 CALL RequiredState
16708 PUSH EAX
16709 CALL Windows.RoundRect
16710 end;
16711 {$ELSE ASM_VERSION} //Pascal
16712 procedure TCanvas.RoundRect(X1, Y1, X2, Y2, X3, Y3: Integer);
16713 begin
16714 RequiredState( HandleValid or BrushValid or PenValid or ChangingCanvas );
16715 Windows.RoundRect( fHandle, X1, Y1, X2, Y2, X3, Y3);
16716 end;
16717 {$ENDIF ASM_VERSION}
16719 {$IFDEF ASM_VERSION}
16720 //[procedure TCanvas.TextArea]
16721 procedure TCanvas.TextArea(const Text: String; var Sz: TSize;
16722 var P0: TPoint);
16724 PUSH EBX
16725 MOV EBX, EAX
16727 PUSH ECX
16728 CALL TextExtent
16729 POP EDX
16731 MOV ECX, [P0]
16732 XOR EAX, EAX
16733 MOV [ECX].TPoint.x, EAX
16734 MOV [ECX].TPoint.y, EAX
16736 CMP [GlobalCanvas_OnTextArea], EAX
16737 JZ @@exit
16738 MOV EAX, EBX
16739 CALL [GlobalCanvas_OnTextArea]
16741 @@exit:
16742 POP EBX
16743 end;
16744 {$ELSE ASM_VERSION} //Pascal
16745 procedure TCanvas.TextArea(const Text: String; var Sz: TSize;
16746 var P0: TPoint);
16747 begin
16748 Sz := TextExtent( Text );
16749 P0.x := 0; P0.y := 0;
16750 if Assigned( GlobalCanvas_OnTextArea ) then
16751 GlobalCanvas_OnTextArea( @Self, Sz, P0 );
16752 end;
16753 {$ENDIF ASM_VERSION}
16755 {$IFDEF ASM_VERSION}
16756 //[function TCanvas.TextExtent]
16757 function TCanvas.TextExtent(const Text: string): TSize;
16759 PUSH EBX
16760 PUSH ESI
16761 MOV EBX, EAX
16763 PUSH ECX // prepare @Result
16765 MOV EAX, EDX
16766 CALL System.@LStrLen
16767 PUSH EAX // prepare Length(Text)
16769 CALL EDX2PChar
16770 PUSH EDX // prepare PChar(Text)
16772 PUSH HandleValid or FontValid
16773 PUSH EBX
16774 CALL RequiredState
16776 XCHG ESI, EAX
16777 TEST ESI, ESI // ESI = fHandle before
16778 JNZ @@1
16780 PUSH ESI
16781 CALL CreateCompatibleDC
16783 MOV EDX, EBX
16784 XCHG EAX, EDX // EAX := @Self; EDX := DC
16785 CALL SetHandle
16786 @@1:
16787 //********************************************************** // Added By M.Gerasimov
16789 CMP [EBX].TCanvas.fIsPaintDC, 1
16790 JZ @@2
16791 XOR ESI,ESI
16792 @@2:
16794 //********************************************************** // Added By M.Gerasimov
16795 PUSH HandleValid or FontValid
16796 PUSH EBX
16797 CALL RequiredState
16798 PUSH EAX // prepare DC
16800 CALL Windows.GetTextExtentPoint32
16802 TEST ESI, ESI
16803 JNZ @@exit
16805 XOR EDX, EDX
16806 XCHG EAX, EBX
16807 CALL SetHandle
16809 @@exit:
16810 POP ESI
16811 POP EBX
16812 end;
16813 {$ELSE ASM_VERSION} //Pascal
16814 function TCanvas.TextExtent(const Text: string): TSize;
16815 var DC : HDC;
16816 ClearHandle : Boolean;
16817 begin
16818 //Result.cX := 0;
16819 //Result.cY := 0;
16820 ClearHandle := False;
16821 RequiredState( HandleValid or FontValid );
16822 DC := fHandle;
16823 if DC = 0 then
16824 begin
16825 DC := CreateCompatibleDC( 0 );
16826 ClearHandle := True;
16827 SetHandle( DC );
16828 end;
16829 //********************************************************** // Added By Gerasimov
16831 If Not fIsPaintDC then ClearHandle := True;
16833 //********************************************************** // Added By Gerasimov
16834 RequiredState( HandleValid or FontValid );
16835 Windows.GetTextExtentPoint32( fHandle, PChar(Text), Length(Text), Result);
16836 if ClearHandle then
16837 SetHandle( 0 );
16838 { DC must be freed here automatically (never leaks):
16839 if Canvas created on base of existing DC, no memDC created,
16840 if Canvas has fHandle:HDC = 0, it is not fIsPaintDC always. }
16841 end;
16842 {$ENDIF ASM_VERSION}
16844 //[function TCanvas.TextHeight]
16845 function TCanvas.TextHeight(const Text: string): Integer;
16846 begin
16847 Result := TextExtent(Text).cY;
16848 end;
16850 {$IFDEF ASM_VERSION}
16851 //[procedure TCanvas.TextOut]
16852 procedure TCanvas.TextOut(X, Y: Integer; const Text: String); stdcall;
16854 PUSH EBX
16855 MOV EBX, [EBP+8]
16857 MOV EAX, [Text]
16858 PUSH EAX
16859 CALL System.@LStrLen
16860 XCHG EAX, [ESP] // prepare Length(Text)
16862 //CALL System.@LStrToPChar // string does not need to be null-terminated !
16863 PUSH EAX // prepare PChar(Text)
16864 PUSH [Y] // prepare Y
16865 PUSH [X] // prepare X
16867 PUSH HandleValid or FontValid or BrushValid or ChangingCanvas
16868 PUSH EBX
16869 CALL RequiredState
16870 PUSH EAX // prepare fHandle
16871 CALL Windows.TextOut
16873 { -- by suggetion of Alexey (Lecha2002)
16874 MOV EAX, EBX
16875 MOV EDX, [Text]
16876 CALL TextWidth
16877 MOV EDX, [X]
16878 ADD EDX, EAX
16880 MOV ECX, [Y]
16881 MOV EAX, EBX
16882 CALL MoveTo
16885 POP EBX
16886 end;
16887 {$ELSE ASM_VERSION} //Pascal
16888 procedure TCanvas.TextOut(X, Y: Integer; const Text: String); stdcall;
16889 begin
16890 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
16891 Windows.TextOut(FHandle, X, Y, PChar(Text), Length(Text));
16892 //MoveTo(X + TextWidth(Text), Y); -- by suggestion of Alexey (Lecha2002)
16893 end;
16894 {$ENDIF ASM_VERSION}
16896 {$IFDEF ASM_VERSION}
16897 //[procedure TCanvas.TextRect]
16898 procedure TCanvas.TextRect(const Rect: TRect; X, Y: Integer; const Text: string);
16900 PUSH EBX
16901 XCHG EBX, EAX
16903 PUSH 0 // prepare 0
16905 PUSH EDX
16906 PUSH ECX
16908 MOV EAX, [Text]
16909 //CALL System.@LStrToPChar
16910 PUSH EAX
16912 //MOV EAX, [Text]
16913 CALL System.@LStrLen
16915 POP ECX // ECX = @Text[1]
16917 POP EDX // EDX = X
16918 XCHG EAX, [ESP] // prepare Length(Text), EAX = @Rect
16919 PUSH ECX // prepare PChar(Text)
16920 PUSH EAX // prepare @Rect
16922 XOR EAX, EAX
16923 MOV AL, ETO_CLIPPED // = 4
16924 MOV ECX, [EBX].fBrush
16925 JECXZ @@opaque
16927 CMP [ECX].TGraphicTool.fData.Brush.Style, bsClear
16928 JZ @@txtout
16930 @@opaque:
16931 DB $0C, ETO_OPAQUE //OR AL, ETO_OPAQUE
16932 @@txtout:
16933 PUSH EAX // prepare Options
16934 PUSH [Y] // prepare Y
16935 PUSH EDX // prepare X
16937 PUSH HandleValid or FontValid or BrushValid or ChangingCanvas
16938 PUSH EBX
16939 CALL RequiredState // EAX = fHandle
16940 PUSH EAX // prepare fHandle
16942 CALL Windows.ExtTextOut
16944 POP EBX
16945 end;
16946 {$ELSE ASM_VERSION} //Pascal
16947 procedure TCanvas.TextRect(const Rect: TRect; X, Y: Integer; const Text: string);
16949 Options: Integer;
16950 begin
16951 //Changing;
16952 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
16953 Options := ETO_CLIPPED;
16954 if assigned( fBrush ) and (fBrush.fData.Brush.Style <> bsClear)
16955 or not assigned( fBrush ) then Inc(Options, ETO_OPAQUE);
16956 Windows.ExtTextOut( fHandle, X, Y, Options,
16957 @Rect, PChar(Text),
16958 Length(Text), nil);
16959 end;
16960 {$ENDIF ASM_VERSION}
16962 //[procedure TCanvas.ExtTextOut]
16963 procedure TCanvas.ExtTextOut( X, Y: Integer; Options: DWORD; const Rect: TRect; const Text: String;
16964 const Spacing: array of Integer );
16965 begin
16966 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
16967 Windows.ExtTextOut(FHandle, X, Y, Options, @Rect, PChar(Text), Length(Text), @Spacing[ 0 ]);
16968 end;
16970 //[procedure TCanvas.DrawText]
16971 procedure TCanvas.DrawText(Text:String; var Rect:TRect; Flags:DWord);
16972 begin
16973 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
16974 Windows.DrawText(Handle,PChar(Text),Length(Text),Rect,Flags);
16975 end;
16977 //[function TCanvas.ClipRect]
16978 function TCanvas.ClipRect: TRect;
16979 begin
16980 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
16981 GetClipBox(Handle, Result);
16982 end;
16984 //[function TCanvas.TextWidth]
16985 function TCanvas.TextWidth(const Text: string): Integer;
16986 begin
16987 Result := TextExtent(Text).cX;
16988 end;
16990 {$IFDEF ASM_VERSION}
16991 //[function TCanvas.GetBrush]
16992 function TCanvas.GetBrush: PGraphicTool;
16994 MOV ECX, [EAX].fBrush
16995 INC ECX
16996 LOOP @@exit
16998 PUSH EAX
16999 CALL NewBrush
17000 POP EDX
17001 PUSH EAX
17003 MOV [EDX].fBrush, EAX
17005 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, Offset[TCanvas.ObjectChanged]
17006 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
17007 MOV ECX, [EDX].fOwnerControl
17008 JECXZ @@1
17010 PUSH [ECX].TControl.fBrush
17011 MOV ECX, [ECX].TControl.fColor
17012 MOV [EAX].TGraphicTool.fData.Color, ECX
17013 POP EDX
17014 TEST EDX, EDX
17015 JZ @@1
17017 CALL TGraphicTool.Assign
17019 @@1: POP ECX
17021 @@exit: XCHG EAX, ECX
17022 end;
17023 {$ELSE ASM_VERSION} //Pascal
17024 function TCanvas.GetBrush: PGraphicTool;
17025 begin
17026 if not assigned( fBrush ) then
17027 begin
17028 fBrush := NewBrush;
17029 if assigned( fOwnerControl ) then
17030 begin
17031 fBrush.fData.Color := PControl(fOwnerControl).fColor;
17032 if assigned( PControl(fOwnerControl).fBrush ) then
17033 {fBrush := }fBrush.Assign( PControl(fOwnerControl).fBrush );
17034 // both statements above needed
17035 end;
17036 //fBrush.OnChange := ObjectChanged;
17037 AssignChangeEvents;
17038 end;
17039 Result := fBrush;
17040 end;
17041 {$ENDIF ASM_VERSION}
17043 {$IFDEF ASM_VERSION}
17044 //[function TCanvas.GetFont]
17045 function TCanvas.GetFont: PGraphicTool;
17047 MOV ECX, [EAX].TCanvas.fFont
17048 INC ECX
17049 LOOP @@exit
17051 PUSH EAX
17052 CALL NewFont
17053 POP EDX
17054 PUSH EAX
17056 MOV [EDX].TCanvas.fFont, EAX
17057 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, Offset[TCanvas.ObjectChanged]
17058 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
17060 MOV ECX, [EDX].fOwnerControl
17061 JECXZ @@1
17063 PUSH [ECX].TControl.fFont
17064 MOV ECX, [ECX].TControl.fTextColor
17065 MOV [EAX].TGraphicTool.fData.Color, ECX
17066 POP EDX
17067 TEST EDX, EDX
17068 JZ @@1
17070 CALL TGraphicTool.Assign
17072 @@1: POP ECX
17074 @@exit: MOV EAX, ECX
17075 end;
17076 {$ELSE ASM_VERSION} //Pascal
17077 function TCanvas.GetFont: PGraphicTool;
17078 begin
17079 if not assigned( fFont ) then
17080 begin
17081 fFont := NewFont;
17082 if assigned( fOwnerControl ) then
17083 begin
17084 fFont.Color := PControl(fOwnerControl).fTextColor;
17085 if assigned( PControl(fOwnerControl).fFont ) then
17086 {fFont := }fFont.Assign( PControl(fOwnerControl).fFont );
17087 end;
17088 //fFont.OnChange := ObjectChanged;
17089 AssignChangeEvents;
17090 end;
17091 Result := fFont;
17092 end;
17093 {$ENDIF ASM_VERSION}
17095 {$IFDEF ASM_VERSION}
17096 //[function TCanvas.GetPen]
17097 function TCanvas.GetPen: PGraphicTool;
17099 MOV ECX, [EAX].TCanvas.fPen
17100 INC ECX
17101 LOOP @@exit
17103 PUSH EAX
17104 CALL NewPen
17105 POP EDX
17106 MOV [EDX].fPen, EAX
17107 PUSH EAX
17108 MOV EAX, EDX
17109 CALL AssignChangeEvents
17110 POP ECX
17112 @@exit: MOV EAX, ECX
17113 end;
17114 {$ELSE ASM_VERSION} //Pascal
17115 function TCanvas.GetPen: PGraphicTool;
17116 begin
17117 if not assigned( fPen ) then
17118 begin
17119 fPen := NewPen;
17120 AssignChangeEvents;
17121 end;
17122 Result := fPen;
17123 end;
17124 {$ENDIF ASM_VERSION}
17126 {$IFDEF ASM_VERSION}
17127 //[function TCanvas.GetHandle]
17128 function TCanvas.GetHandle: HDC;
17130 CMP word ptr[EAX].fOnGetHandle.TMethod.Code+2, 0
17131 MOV EDX, EAX
17132 MOV EAX, [EDX].fHandle
17133 JZ @@exit
17134 MOV EAX, [EDX].fOnGetHandle.TMethod.Data
17135 PUSH EDX
17136 CALL [EDX].fOnGetHandle.TMethod.Code
17137 XCHG EAX, [ESP]
17138 POP EDX
17139 PUSH EDX
17140 CALL SetHandle
17141 POP EAX
17142 @@exit:
17143 end;
17144 {$ELSE ASM_VERSION} //Pascal
17145 function TCanvas.GetHandle: HDC;
17146 begin
17147 if assigned( fOnGetHandle ) then
17148 begin
17149 Result := fOnGetHandle( @Self );
17150 //fHandle := Result;
17151 SetHandle( Result );
17153 else
17154 Result := fHandle;
17155 end;
17156 {$ENDIF ASM_VERSION}
17158 {$IFDEF ASM_VERSION}
17159 //[procedure TCanvas.AssignChangeEvents]
17160 procedure TCanvas.AssignChangeEvents;
17162 PUSH ESI
17163 LEA ESI, [EAX].fBrush
17164 MOV CL, 3
17165 MOV EDX, EAX
17166 @@1: LODSD
17167 TEST EAX, EAX
17168 JZ @@nxt
17169 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
17170 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[ ObjectChanged ]
17171 @@nxt: DEC CL
17172 JNZ @@1
17173 POP ESI
17174 end;
17175 {$ELSE ASM_VERSION} //Pascal
17176 procedure TCanvas.AssignChangeEvents;
17177 begin
17178 if assigned( fFont ) then
17179 fFont.fOnChange := ObjectChanged;
17180 if assigned( fBrush ) then
17181 fBrush.fOnChange := ObjectChanged;
17182 if assigned( fPen ) then
17183 fPen.fOnChange := ObjectChanged;
17184 end;
17185 {$ENDIF ASM_VERSION}
17187 {$IFNDEF _FPC}
17188 {$IFNDEF _D2}
17189 //[procedure TCanvas.WDrawText]
17190 procedure TCanvas.WDrawText(WText: WideString; var Rect: TRect;
17191 Flags: DWord);
17192 begin
17193 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17194 Windows.DrawTextW(Handle,PWideChar(WText),Length(WText),Rect,Flags);
17195 end;
17197 //[procedure TCanvas.WExtTextOut]
17198 procedure TCanvas.WExtTextOut(X, Y: Integer; Options: DWORD;
17199 const Rect: TRect; const WText: WideString;
17200 const Spacing: array of Integer);
17201 begin
17202 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17203 Windows.ExtTextOutW(FHandle, X, Y, Options, @Rect, PWideChar(WText), Length(WText), @Spacing[ 0 ]);
17204 end;
17206 //[procedure TCanvas.WTextOut]
17207 procedure TCanvas.WTextOut(X, Y: Integer; const WText: WideString);
17208 begin
17209 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17210 Windows.TextOutW(FHandle, X, Y, PWideChar(WText), Length(WText));
17211 MoveTo(X + WTextWidth(WText), Y);
17212 end;
17214 //[procedure TCanvas.WTextRect]
17215 procedure TCanvas.WTextRect(const Rect: TRect; X, Y: Integer;
17216 const WText: WideString);
17218 Options: Integer;
17219 begin
17220 //Changing;
17221 RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
17222 Options := ETO_CLIPPED;
17223 if assigned( fBrush ) and (fBrush.fData.Brush.Style <> bsClear)
17224 or not assigned( fBrush ) then Inc(Options, ETO_OPAQUE);
17225 Windows.ExtTextOutW( fHandle, X, Y, Options,
17226 @Rect, PWideChar(WText),
17227 Length(WText), nil);
17228 end;
17230 //[function TCanvas.WTextExtent]
17231 function TCanvas.WTextExtent(const WText: WideString): TSize;
17232 var DC : HDC;
17233 ClearHandle : Boolean;
17234 begin
17235 ClearHandle := False;
17236 RequiredState( HandleValid or FontValid );
17237 DC := fHandle;
17238 if DC = 0 then
17239 begin
17240 DC := CreateCompatibleDC( 0 );
17241 ClearHandle := True;
17242 SetHandle( DC );
17243 end;
17244 RequiredState( HandleValid or FontValid );
17245 Windows.GetTextExtentPoint32W( fHandle, PWideChar(WText), Length(WText), Result);
17246 if ClearHandle then
17247 SetHandle( 0 );
17248 end;
17250 //[function TCanvas.WTextHeight]
17251 function TCanvas.WTextHeight(const WText: WideString): Integer;
17252 begin
17253 Result := WTextExtent( WText ).cy;
17254 end;
17256 //[function TCanvas.WTextWidth]
17257 function TCanvas.WTextWidth(const WText: WideString): Integer;
17258 begin
17259 Result := WTextExtent( WText ).cx;
17260 end;
17261 {$ENDIF _D2}
17262 {$ENDIF _FPC}
17274 //[function MakeInt64]
17275 function MakeInt64( Lo, Hi: DWORD ): I64;
17276 begin
17277 Result.Lo := Lo;
17278 Result.Hi := Hi;
17279 end;
17281 //[function Int2Int64]
17282 function Int2Int64( X: Integer ): I64;
17284 MOV [EDX], EAX
17285 MOV ECX, EDX
17287 MOV [ECX+4], EDX
17288 end;
17290 //[procedure IncInt64]
17291 procedure IncInt64( var I64: I64; Delta: Integer );
17293 ADD [EAX], EDX
17294 ADC dword ptr [EAX+4], 0
17295 end;
17297 //[procedure DecInt64]
17298 procedure DecInt64( var I64: I64; Delta: Integer );
17300 SUB [EAX], EDX
17301 SBB dword ptr [EDX], 0
17302 end;
17304 //[function Add64]
17305 function Add64( const X, Y: I64 ): I64;
17307 PUSH ESI
17308 XCHG ESI, EAX
17309 LODSD
17310 ADD EAX, [EDX]
17311 MOV [ECX], EAX
17312 LODSD
17313 ADC EAX, [EDX+4]
17314 MOV [ECX+4], EAX
17315 POP ESI
17316 end;
17318 //[function Sub64]
17319 function Sub64( const X, Y: I64 ): I64;
17321 PUSH ESI
17322 XCHG ESI, EAX
17323 LODSD
17324 SUB EAX, [EDX]
17325 MOV [ECX], EAX
17326 LODSD
17327 SBB EAX, [EDX+4]
17328 MOV [ECX+4], EAX
17329 POP ESI
17330 end;
17332 //[function Neg64]
17333 function Neg64( const X: I64 ): I64;
17335 MOV ECX, [EAX]
17336 NEG ECX
17337 MOV [EDX], ECX
17338 MOV ECX, 0
17339 SBB ECX, [EAX+4]
17340 MOV [EDX+4], ECX
17341 end;
17343 //[function Mul64EDX]
17344 function Mul64EDX( const X: I64; M: Integer ): I64;
17346 PUSH ESI
17347 PUSH EDI
17348 XCHG ESI, EAX
17349 MOV EDI, ECX
17350 MOV ECX, EDX
17351 LODSD
17352 MUL ECX
17353 STOSD
17354 XCHG EDX, ECX
17355 LODSD
17356 MUL EDX
17357 ADD EAX, ECX
17358 STOSD
17359 POP EDI
17360 POP ESI
17361 end;
17363 //[FUNCTION Mul64i]
17364 {$IFDEF ASM_VERSION}
17365 function Mul64i( const X: I64; Mul: Integer ): I64;
17366 asm //cmd //opd
17367 TEST EDX, EDX
17368 PUSHFD
17369 JGE @@1
17370 NEG EDX
17371 @@1: PUSH ECX
17372 CALL Mul64EDX
17373 POP EAX
17374 POPFD
17375 JGE @@2
17376 MOV EDX, EAX
17377 CALL Neg64
17378 @@2:
17379 end;
17380 {$ELSE ASM_VERSION} //Pascal
17381 function Mul64i( const X: I64; Mul: Integer ): I64;
17382 var Minus: Boolean;
17383 begin
17384 Minus := FALSE;
17385 if Mul < 0 then
17386 begin
17387 Minus := TRUE;
17388 Mul := -Mul;
17389 end;
17390 Result := Mul64EDX( X, Mul );
17391 if Minus then
17392 Result := Neg64( Result );
17393 end;
17394 {$ENDIF ASM_VERSION}
17395 //[END Mul64i]
17397 //[function Div64EDX]
17398 function Div64EDX( const X: I64; D: Integer ): I64;
17400 PUSH ESI
17401 PUSH EDI
17402 XCHG ESI, EAX
17403 MOV EDI, ECX
17404 MOV ECX, EDX
17405 MOV EAX, [ESI+4]
17407 DIV ECX
17408 MOV [EDI+4], EAX
17409 LODSD
17410 DIV ECX
17411 STOSD
17412 POP EDI
17413 POP ESI
17414 end;
17416 //[FUNCTION Div64i]
17417 {$IFDEF ASM_VERSION}
17418 function Div64i( const X: I64; D: Integer ): I64;
17419 asm //cmd //opd
17420 PUSH EBX
17421 XOR EBX, EBX
17422 PUSH ESI
17423 XCHG ESI, EAX
17424 LODSD
17425 MOV [ECX], EAX
17426 LODSD
17427 MOV [ECX+4], EAX
17428 MOV ESI, ECX
17429 PUSH EDX
17430 XCHG EAX, ECX
17431 CALL Sgn64
17432 TEST EAX, EAX
17433 JGE @@1
17434 INC EBX
17435 MOV EAX, ESI
17436 MOV EDX, ESI
17437 CALL Neg64
17438 @@1: POP EDX
17439 TEST EDX, EDX
17440 JGE @@2
17441 XOR EBX, 1
17442 NEG EDX
17443 @@2: MOV EAX, ESI
17444 MOV ECX, ESI
17445 CALL Div64EDX
17446 DEC EBX
17447 JNZ @@3
17448 MOV EDX, ESI
17449 XCHG EAX, ESI
17450 CALL Neg64
17451 @@3: POP ESI
17452 POP EBX
17453 end;
17454 {$ELSE ASM_VERSION} //Pascal
17455 function Div64i( const X: I64; D: Integer ): I64;
17456 var Minus: Boolean;
17457 begin
17458 Minus := FALSE;
17459 if D < 0 then
17460 begin
17461 D := -D;
17462 Minus := TRUE;
17463 end;
17464 Result := X;
17465 if Sgn64( Result ) < 0 then
17466 begin
17467 Result := Neg64( Result );
17468 Minus := not Minus;
17469 end;
17470 Result := Div64EDX( Result, D );
17471 if Minus then
17472 Result := Neg64( Result );
17473 end;
17474 {$ENDIF ASM_VERSION}
17475 //[END Div64i]
17477 //[function Mod64i]
17478 function Mod64i( const X: I64; D: Integer ): Integer;
17479 begin
17480 Result := Sub64( X, Mul64i( Div64i( X, D ), D ) ).Lo;
17481 end;
17483 //[function Sgn64]
17484 function Sgn64( const X: I64 ): Integer;
17486 XOR EDX, EDX
17487 CMP [EAX+4], EDX
17488 XCHG EAX, EDX
17489 JG @@ret_1
17490 JL @@ret_neg
17491 CMP [EDX], EAX
17492 JZ @@exit
17493 @@ret_1:
17494 INC EAX
17496 @@ret_neg:
17497 DEC EAX
17498 @@exit:
17499 end;
17501 //[function Cmp64]
17502 function Cmp64( const X, Y: I64 ): Integer;
17503 begin
17504 Result := Sgn64( Sub64( X, Y ) );
17505 end;
17507 //[function Int64_2Str]
17508 function Int64_2Str( X: I64 ): String;
17509 var M: Boolean;
17510 Y: Integer;
17511 Buf: array[ 0..31 ] of Char;
17512 I: Integer;
17513 begin
17514 M := FALSE;
17515 case Sgn64( X ) of
17516 -1: begin M := TRUE; X := Neg64( X ); end;
17517 0: begin Result := '0'; Exit; end;
17518 end;
17519 I := 31;
17520 Buf[ 31 ] := #0;
17521 while Sgn64( X ) > 0 do
17522 begin
17523 Dec( I );
17524 Y := Mod64i( X, 10 );
17525 Buf[ I ] := Char( Y + Integer( '0' ) );
17526 X := Div64i( X, 10 );
17527 end;
17528 if M then
17529 begin
17530 Dec( I );
17531 Buf[ I ] := '-';
17532 end;
17533 Result := PChar( @Buf[ I ] );
17534 end;
17536 //[function Str2Int64]
17537 function Str2Int64( const S: String ): I64;
17538 var I: Integer;
17539 M: Boolean;
17540 begin
17541 Result.Lo := 0;
17542 Result.Hi := 0;
17543 I := 1;
17544 if S = '' then Exit;
17545 M := FALSE;
17546 if S[ 1 ] = '-' then
17547 begin
17548 M := TRUE;
17549 Inc( I );
17551 else
17552 if S[ 1 ] = '+' then
17553 Inc( I );
17554 while I <= Length( S ) do
17555 begin
17556 if not( S[ I ] in [ '0'..'9' ] ) then
17557 break;
17558 Result := Mul64i( Result, 10 );
17559 IncInt64( Result, Integer( S[ I ] ) - Integer( '0' ) );
17560 Inc( I );
17561 end;
17562 if M then
17563 Result := Neg64( Result );
17564 end;
17566 //[function Int64_2Double]
17567 function Int64_2Double( const X: I64 ): Double;
17569 FILD qword ptr [EAX]
17570 FSTP @Result
17571 end;
17573 //[function Double2Int64]
17574 function Double2Int64( D: Double ): I64;
17576 FLD D
17577 FISTP qword ptr [EAX]
17578 end;
17581 function IsNan(const AValue: Double): Boolean;
17582 {$IFDEF _D2orD3}
17583 type PI64 = ^I64;
17584 {$ENDIF}
17585 begin
17587 Result := (PI64(@AValue).Hi and $7FF00000 = $7FF00000) and
17588 ((PI64(@AValue).Hi and $000FFFFF <> 0) or (PI64(@AValue).Lo <> 0));
17589 {+}{++}(*Result := AValue = NAN;*){--}
17590 end;
17592 //[function IntPower]
17593 function IntPower(Base: Extended; Exponent: Integer): Extended;
17594 {$IFDEF F_P}
17595 begin
17596 if Exponent = 0 then
17597 begin
17598 Result := 1.0;
17599 Exit;
17600 end;
17601 if Exponent < 0 then
17602 begin
17603 Exponent := -Exponent;
17604 Base := 1.0 / Base;
17605 end;
17606 Result := Base;
17607 REPEAT
17608 Result := Result * Base;
17609 Dec( Exponent );
17610 UNTIL Exponent <= 0;
17611 end;
17612 {$ELSE DELPHI}
17613 // This version of code by Galkov:
17614 // Changes in comparison to Delphi standard:
17615 // no Overflow exception if Exponent is very big negative value
17616 // (just 0 in result in such case).
17618 fld1 { Result := 1 }
17619 test eax,eax // check Exponent for 0, return 0 ** 0 = 1
17620 jz @@3 // (though Mathematics says that this is not so...)
17621 fld Base
17622 jg @@2
17623 fdivr ST,ST(1) { Base := 1 / Base }
17624 neg eax
17625 jmp @@2
17626 @@1: fmul ST,ST { X := Base * Base }
17627 @@2: shr eax,1
17628 jnc @@1
17629 fmul ST(1),ST { Result := Result * X }
17630 jnz @@1
17631 fstp st { pop X from FPU stack }
17632 @@3: fwait
17633 end;
17634 (* version of code by Borland:
17636 mov ecx, eax
17638 fld1 { Result := 1 }
17639 xor eax, edx
17640 sub eax, edx { eax := Abs(Exponent) }
17641 jz @@3
17642 fld Base
17643 jmp @@2
17644 @@1: fmul ST, ST { X := Base * Base }
17645 @@2: shr eax,1
17646 jnc @@1
17647 fmul ST(1),ST { Result := Result * X }
17648 jnz @@1
17649 fstp st { pop X from FPU stack }
17650 cmp ecx, 0
17651 jge @@3
17652 fld1
17653 fdivrp { Result := 1 / Result }
17654 @@3:
17655 fwait
17656 end;*)
17657 {$ENDIF F_P/DELPHI}
17659 //[function Str2Double]
17660 function Str2Double( const S: String ): Double;
17661 var I: Integer;
17662 M, Pt: Boolean;
17663 D: Double;
17664 Ex: Integer;
17665 begin
17666 Result := 0.0;
17667 if S = '' then Exit;
17668 M := FALSE;
17669 I := 1;
17670 if S[ 1 ] = '-' then
17671 begin
17672 M := TRUE;
17673 Inc( I );
17674 end;
17675 Pt := FALSE;
17676 D := 1.0;
17677 while I <= Length( S ) do
17678 begin
17679 case S[ I ] of
17680 '.': if not Pt then Pt := TRUE else break;
17681 '0'..'9': if not Pt then
17682 Result := Result * 10.0 + Integer( S[ I ] ) - Integer( '0' )
17683 else
17684 begin
17685 D := D * 0.1;
17686 Result := Result + (Integer( S[ I ] ) - Integer( '0' )) * D;
17687 end;
17688 'e', 'E': begin
17689 Ex := Str2Int( CopyEnd( S, I + 1 ) );
17690 Result := Result * IntPower( 10.0, Ex );
17691 break;
17692 end;
17693 end;
17694 Inc( I );
17695 end;
17696 if M then
17697 Result := -Result;
17698 end;
17700 //[function TruncD]
17701 function TruncD( D: Double ): Double;
17704 FLD D
17705 PUSH ECX
17706 FNSTCW [ESP]
17707 POP ECX
17708 PUSH ECX
17709 OR byte ptr [ESP+1], $0C
17710 FLDCW [ESP]
17711 PUSH ECX
17712 FRNDINT
17713 FSTP @Result
17714 FLDCW [ESP]
17715 POP ECX
17716 POP ECX
17717 end;
17718 {+}{++}(*
17719 begin
17720 Result := Trunc( D );
17721 end;
17722 *){--}
17724 // Precision 15
17725 //[function Extended2Str]
17726 function Extended2Str( E: Extended ): String;
17727 function UnpackFromBuf( const Buf: array of Byte; N: Integer ): String;
17728 var I, J, K, L: Integer;
17729 begin
17730 SetLength( Result, 16 );
17731 J := 1;
17732 for I := 7 downto 0 do
17733 begin
17734 K := Buf[ I ] shr 4;
17735 Result[ J ] := Char( Ord('0') + K );
17736 Inc( J );
17737 K := Buf[ I ] and $F;
17738 Result[ J ] := Char( Ord('0') + K );
17739 Inc( J );
17740 end;
17742 Assert( Result[ 1 ] = '0', 'error!' );
17743 Delete( Result, 1, 1 );
17745 if N <= 0 then
17746 begin
17747 while N < 0 do
17748 begin
17749 Result := '0' + Result;
17750 Inc( N );
17751 end;
17752 Result := '0.' + Result;
17754 else
17755 if N < Length( Result ) then
17756 begin
17757 Result := Copy( Result, 1, N ) + '.' + CopyEnd( Result, N + 1 );
17759 else
17760 begin
17761 while N > Length( Result ) do
17762 begin
17763 Result := Result + '0';
17764 end;
17765 Exit;
17766 end;
17768 L := Length( Result );
17769 while L > 1 do
17770 begin
17771 if not (Result[ L ] in ['0','.']) then break;
17772 Dec( L );
17773 if Result[ L + 1 ] = '.' then break;
17774 end;
17775 if L < Length( Result ) then Delete( Result, L + 1, MaxInt );
17777 end;
17780 S: Boolean;
17781 var F: Extended;
17782 N: Integer;
17783 Buf1: array[ 0..9 ] of Byte;
17784 I10: Integer;
17785 begin
17786 Result := '0';
17787 if E = 0 then Exit;
17788 S := E < 0;
17789 if S then E := -E;
17791 N := 15;
17792 F := 5E12;
17793 I10 := 10;
17794 while E < F do
17795 begin
17796 Dec( N );
17797 E := E * I10;
17798 end;
17799 if N = 15 then
17800 while E >= 1E13 do
17801 begin
17802 Inc( N );
17803 E := E / I10;
17804 end;
17806 while TRUE do
17807 begin
17809 FLD [E]
17810 FBSTP [Buf1]
17811 end;
17812 if Buf1[ 7 ] <> 0 then break;
17813 E := E * I10;
17814 Dec( N );
17815 end;
17817 Result := UnpackFromBuf( Buf1, N );
17819 if S then Result := '-' + Result;
17820 end;
17822 //[function Double2Str]
17823 function Double2Str( D: Double ): String;
17824 begin
17825 Result := Extended2Str( D );
17826 end;
17828 //[function Double2StrEx]
17829 function Double2StrEx( D: Double ): String;
17830 var E, E1, E2: Double;
17831 S: String;
17832 begin
17833 Result := Double2Str( D );
17834 E := Str2Double( Result );
17835 E1 := E - D;
17836 if E1 < 0.0 then E1 := -E1;
17837 if E1 < 1e-307 then Exit;
17838 while TRUE do
17839 begin
17840 E := D - (E - D) * 0.3;
17841 S := Double2Str( E );
17842 if S = Result then break;
17843 E := Str2Double( S );
17844 E2 := E - D;
17845 if E2 < 0.0 then E2 := -E2;
17846 if E2 > E1 * 0.75 then break;
17847 Result := S;
17848 if E2 < E1 * 0.1 then break;
17849 end;
17850 end;
17852 //[function GetBits]
17853 function GetBits( N: DWORD; first, last: Byte ): DWord;
17854 {$IFDEF F_P}
17855 begin
17856 Result := 0;
17857 if last > 31 then last := 31;
17858 if first > last then Exit;
17859 Result := (N and not ($FFFFFFFF shl last)) shr first;
17860 end;
17861 {$ELSE DELPHI}
17863 XCHG EAX, EDX // (1) EDX=N, AL=first
17864 {$IFDEF PARANOIA}
17865 DB $3C, 31
17866 {$ELSE}
17867 CMP AL, 31 // first(AL) > 31 ?
17868 {$ENDIF}
17869 JBE @@1 // (2) åñëè äà, òî Result := 0;
17870 @@0:
17871 XOR EAX, EAX // (2)
17872 RET // (1)
17873 @@1:
17875 XCHG EAX, ECX // (1) AL = last CL = first
17876 SHR EDX, CL // (2) EDX = N shr first
17877 SUB AL, CL // (2) AL = last - first
17878 JL @@0 // (2) åñëè last < first òî Result := 0;
17880 {$IFDEF PARANOIA}
17881 DB $3C, 32
17882 {$ELSE}
17883 CMP AL, 32 // (2) last - first >= 32 ?
17884 {$ENDIF}
17885 XCHG ECX, EAX // (1) CL = last - first
17886 XCHG EAX, EDX // (1) EAX = N shr first
17887 JAE @@exit // (2) åñëè last - first > 31, òî Result := EAX;
17888 SBB EDX, EDX // (2) EDX = -1
17889 DEC EDX // (1) EDX = 1111...10 = -2
17890 SHL EDX, CL // (2) EDX = 111...100..0 (ãäå n(0)=last-first+1)
17891 NOT EDX // (2) EDX = ìàñêà 000..0111...1 (ãäå n(1)=last-first+1)
17892 AND EAX, EDX // (2)
17893 @@exit:
17894 // EAX = ðåçóëüòàò, (1 áàéò íà êîìàíäó RET)
17895 end;
17896 {$ENDIF F_P/DELPHI}
17898 //[function GetBitsL]
17899 function GetBitsL( N: DWORD; from, len: Byte ): DWord;
17900 {$IFDEF F_P}
17901 begin
17902 Result := GetBits( N, from, from + len - 1 );
17903 end;
17904 {$ELSE DELPHI}
17906 ADD CL, DL
17907 DEC CL
17908 JMP GetBits
17909 end;
17910 {$ENDIF F_P/DELPHI}
17912 //[FUNCTION Int2Hex]
17913 {$IFDEF ASM_VERSION}
17914 function Int2Hex( Value : DWord; Digits : Integer ) : String;
17917 // EAX = Value
17918 // EDX = Digits (actually DL needed)
17919 // ECX = @Result
17921 PUSH 0
17922 ADD ESP, -0Ch
17924 PUSH EBX
17925 PUSH ECX
17927 LEA EBX, [ESP+8+0Fh] // EBX := @Buf[ 15 ]
17928 AND EDX, $F
17930 @@loop: DEC EBX
17931 DEC EDX
17933 PUSH EAX
17934 {$IFDEF PARANOIA}
17935 DB $24, $0F
17936 {$ELSE}
17937 AND AL, 0Fh
17938 {$ENDIF}
17939 {$IFDEF PARANOIA}
17940 DB $3C, 9
17941 {$ELSE}
17942 CMP AL, 9
17943 {$ENDIF}
17944 JA @@10
17945 {$IFDEF PARANOIA}
17946 DB $04, 30h-41h+0Ah
17947 {$ELSE}
17948 ADD AL,30h-41h+0Ah
17949 {$ENDIF}
17950 @@10:
17951 {$IFDEF PARANOIA}
17952 DB $04, 41h-0Ah
17953 {$ELSE}
17954 ADD AL,41h-0Ah
17955 {$ENDIF}
17956 MOV byte ptr [EBX], AL
17957 POP EAX
17958 SHR EAX, 4
17960 JNZ @@loop
17962 TEST EDX, EDX
17963 JG @@loop
17965 POP EAX // EAX = @Result
17966 MOV EDX, EBX // EDX = @resulting string
17967 CALL System.@LStrFromPChar
17969 POP EBX
17970 ADD ESP, 10h
17972 {== by KSer - to test it only.
17973 function Int2Hex( Value : DWord; Digits : Integer ) : shortString;
17975 MOV [ECX], DL
17976 XADD EDX, ECX
17977 @@loop1:
17978 PUSH EAX
17979 db $24, $0F // and al,$0F
17981 //AAD
17982 DB $D5, $11
17983 db $04, $30 // add al,$30
17984 MOV [EDX], AL
17985 POP EAX
17986 SHR EAX, 4
17987 DEC EDX
17988 LOOP @@loop1
17990 end;
17991 {$ELSE ASM_VERSION} //Pascal (mixed)
17992 function Int2Hex( Value : DWord; Digits : Integer ) : String;
17993 var Buf: array[ 0..8 ] of Char;
17994 Dest : PChar;
17996 function HexDigit( B : Byte ) : Char;
17997 {$IFDEF F_P}
17998 const
17999 HexDigitChr: array[ 0..15 ] of Char = ( '0','1','2','3','4','5','6','7',
18000 '8','9','A','B','C','D','E','F' );
18001 begin
18002 Result := HexDigitChr[ B and $F ];
18003 end;
18004 {$ELSE DELPHI}
18006 {$IFDEF PARANOIA}
18007 DB $3C,9
18008 {$ELSE}
18009 CMP AL,9
18010 {$ENDIF}
18011 JA @@1
18012 {$IFDEF PARANOIA}
18013 DB $04, $30-$41+$0A
18014 {$ELSE}
18015 ADD AL,30h-41h+0Ah
18016 {$ENDIF}
18017 @@1:
18018 {$IFDEF PARANOIA}
18019 DB $04, $41-$0A
18020 {$ELSE}
18021 ADD AL,41h-0Ah
18022 {$ENDIF}
18023 end;
18024 {$ENDIF F_P/DELPHI}
18025 begin
18026 Dest := @Buf[ 8 ];
18027 Dest^ := #0;
18028 repeat
18029 Dec( Dest );
18030 Dest^ := '0';
18031 if Value <> 0 then
18032 begin
18033 Dest^ := HexDigit( Value and $F );
18034 Value := Value shr 4;
18035 end;
18036 Dec( Digits );
18037 until (Value = 0) and (Digits <= 0);
18038 Result := Dest;
18039 end;
18040 {$ENDIF ASM_VERSION}
18041 //[END Int2Hex]
18043 //[FUNCTION Hex2Int]
18044 {$IFDEF ASM_VERSION}
18045 function Hex2Int( const Value : String) : Integer;
18047 CALL EAX2PChar
18048 PUSH ESI
18049 XCHG ESI, EAX
18050 XOR EDX, EDX
18051 TEST ESI, ESI
18052 JE @@exit
18053 LODSB
18054 {$IFDEF PARANOIA}
18055 DB $3C, '$'
18056 {$ELSE}
18057 CMP AL, '$'
18058 {$ENDIF}
18059 JNE @@1
18060 @@0: LODSB
18061 @@1: TEST AL, AL
18062 JE @@exit
18063 {$IFDEF PARANOIA}
18064 DB $2C, '0'
18065 {$ELSE}
18066 SUB AL, '0'
18067 {$ENDIF}
18068 {$IFDEF PARANOIA}
18069 DB $3C, 9
18070 {$ELSE}
18071 CMP AL, '9' - '0'
18072 {$ENDIF}
18073 JBE @@3
18075 {$IFDEF PARANOIA}
18076 DB $2C, $11
18077 {$ELSE}
18078 SUB AL, 'A' - '0'
18079 {$ENDIF}
18080 {$IFDEF PARANOIA}
18081 DB $3C, 5
18082 {$ELSE}
18083 CMP AL, 'F' - 'A'
18084 {$ENDIF}
18085 JBE @@2
18087 {$IFDEF PARANOIA}
18088 DB $2C, 32
18089 {$ELSE}
18090 SUB AL, 32
18091 {$ENDIF}
18092 {$IFDEF PARANOIA}
18093 DB $3C, 5
18094 {$ELSE}
18095 CMP AL, 'F' - 'A'
18096 {$ENDIF}
18097 JA @@exit
18098 @@2:
18099 {$IFDEF PARANOIA}
18100 DB $04, 0Ah
18101 {$ELSE}
18102 ADD AL, 0Ah
18103 {$ENDIF}
18104 @@3:
18105 SHL EDX, 4
18106 ADD DL, AL
18107 JMP @@0
18109 @@exit: XCHG EAX, EDX
18110 POP ESI
18111 end;
18112 {$ELSE ASM_VERSION} //Pascal
18113 function Hex2Int( const Value : String) : Integer;
18114 var I : Integer;
18115 begin
18116 Result := 0;
18117 I := 1;
18118 if Value = '' then Exit;
18119 if Value[ 1 ] = '$' then Inc( I );
18120 while I <= Length( Value ) do
18121 begin
18122 if Value[ I ] in [ '0'..'9' ] then
18123 Result := (Result shl 4) or (Ord(Value[I]) - Ord('0'))
18124 else
18125 if Value[ I ] in [ 'A'..'F' ] then
18126 Result := (Result shl 4) or (Ord(Value[I]) - Ord('A') + 10)
18127 else
18128 if Value[ I ] in [ 'a'..'f' ] then
18129 Result := (Result shl 4) or (Ord(Value[I]) - Ord('a') + 10)
18130 else
18131 break;
18132 Inc( I );
18133 end;
18134 end;
18135 {$ENDIF ASM_VERSION}
18136 //[END Hex2Int]
18138 //[FUNCTION Octal2Int]
18139 function Octal2Int( const Value: String ) : Integer;
18140 var I: Integer;
18141 begin
18142 Result := 0;
18143 for I := 1 to Length( Value ) do
18144 begin
18145 if Value[ I ] in [ '0'..'7' ] then
18146 Result := Result * 8 + Ord( Value[ I ] ) - Ord( '0' )
18147 else break;
18148 end;
18149 end;
18150 //[END Octal2Int]
18152 //[FUNCTION Binary2Int]
18153 function Binary2Int( const Value: String ) : Integer;
18154 var I: Integer;
18155 begin
18156 Result := 0;
18157 for I := 1 to Length( Value ) do
18158 begin
18159 if Value[ I ] in [ '0'..'1' ] then
18160 Result := Result * 2 + Ord( Value[ I ] ) - Ord( '0' )
18161 else break;
18162 end;
18163 end;
18164 //[END Binary2Int]
18166 //[FUNCTION cHex2Int]
18167 {$IFDEF ASM_VERSION}
18168 function cHex2Int( const Value : String) : Integer;
18170 TEST EAX, EAX
18171 JZ @@exit
18172 CMP word ptr [EAX], '0x'
18173 JZ @@skip_2_chars
18174 CMP word ptr [EAX], '0X'
18175 JNZ @@2Hex2Int
18176 @@skip_2_chars:
18177 INC EAX
18178 INC EAX
18179 @@2Hex2Int:
18180 JMP Hex2Int
18181 @@exit:
18182 end;
18183 {$ELSE ASM_VERSION}
18184 function cHex2Int( const Value : String) : Integer;
18185 begin
18186 if StrEq( Copy( Value, 1, 2 ), '0x' ) then
18187 Result := Hex2Int( CopyEnd( Value, 3 ) )
18188 else Result := Hex2Int( Value );
18189 end;
18190 {$ENDIF ASM_VERSION}
18191 //[END cHex2Int]
18193 //[FUNCTION Int2Str]
18194 {$IFDEF ASM_VERSION}
18195 function Int2Str( Value : Integer ) : String;
18197 XOR ECX, ECX
18198 PUSH ECX
18199 ADD ESP, -0Ch
18201 PUSH EBX
18202 LEA EBX, [ESP + 15 + 4]
18203 PUSH EDX
18204 CMP EAX, ECX
18205 PUSHFD
18206 JGE @@1
18207 NEG EAX
18208 @@1:
18209 MOV CL, 10
18211 @@2:
18212 DEC EBX
18213 XOR EDX, EDX
18214 DIV ECX
18215 ADD DL, 30h
18216 MOV [EBX], DL
18217 TEST EAX, EAX
18218 JNZ @@2
18220 POPFD
18221 JGE @@3
18223 DEC EBX
18224 MOV byte ptr [EBX], '-'
18225 @@3:
18226 POP EAX
18227 MOV EDX, EBX
18228 CALL System.@LStrFromPChar
18230 POP EBX
18231 ADD ESP, 10h
18232 end;
18233 {$ELSE ASM_VERSION} //Pascal
18234 function Int2Str( Value : Integer ) : String;
18235 var Buf : array[ 0..15 ] of Char;
18236 Dst : PChar;
18237 Minus : Boolean;
18238 D: DWORD;
18239 begin
18240 Dst := @Buf[ 15 ];
18241 Dst^ := #0;
18242 Minus := False;
18243 if Value < 0 then
18244 begin
18245 Value := -Value;
18246 Minus := True;
18247 end;
18248 D := Value;
18249 repeat
18250 Dec( Dst );
18251 Dst^ := Char( (D mod 10) + Byte( '0' ) );
18252 D := D div 10;
18253 until D = 0;
18254 if Minus then
18255 begin
18256 Dec( Dst );
18257 Dst^ := '-';
18258 end;
18259 Result := Dst;
18260 end;
18261 {$ENDIF ASM_VERSION}
18262 //[END Int2Str]
18264 //[function UInt2Str]
18265 function UInt2Str( Value: DWORD ): String;
18266 var Buf : array[ 0..15 ] of Char;
18267 Dst : PChar;
18268 D: DWORD;
18269 begin
18270 Dst := @Buf[ 15 ];
18271 Dst^ := #0;
18272 D := Value;
18273 repeat
18274 Dec( Dst );
18275 Dst^ := Char( (D mod 10) + Byte( '0' ) );
18276 D := D div 10;
18277 until D = 0;
18278 Result := Dst;
18279 end;
18281 //[function Int2StrEx]
18282 function Int2StrEx( Value, MinWidth: Integer ): String;
18283 begin
18284 Result := Int2Str( Value );
18285 while Length( Result ) < MinWidth do
18286 Result := ' ' + Result;
18287 end;
18289 //[function Int2Rome]
18290 function Int2Rome( Value: Integer ): String;
18291 const RomeDigs: String = 'IVXLCDMT';
18292 function RomeNum( N, FromIdx: Integer ): String;
18293 begin
18294 CASE N OF
18295 1, 2, 3: Result := StrRepeat( RomeDigs[ FromIdx ], N );
18296 4: Result := RomeDigs[ FromIdx ] + RomeDigs[ FromIdx + 1 ];
18297 5, 6, 7, 8: Result := RomeDigs[ FromIdx + 1 ] + StrRepeat( RomeDigs[ FromIdx ],
18298 N - 5 );
18299 9: Result := RomeDigs[ FromIdx ] + RomeDigs[ FromIdx + 2 ]
18300 else Result := '';
18301 END;
18302 end;
18303 var I, J: Integer;
18304 begin
18305 Result := '';
18306 if Value < 1 then Exit;
18307 if Value > 8999 then Exit;
18308 // maximum possible is TMMMCMXCIX, i.e. 8999
18309 J := 1;
18310 for I := 1 to 3 do
18311 begin
18312 Result := RomeNum( Value mod 10, J ) + Result;
18313 Value := Value div 10;
18314 if Value = 0 then Exit;
18315 Inc( J, 2 );
18316 end;
18317 end;
18319 //[FUNCTION Int2Ths]
18320 {$IFDEF ASM_VERSION}
18321 function Int2Ths( I : Integer ) : String;
18323 PUSH EBP
18324 MOV EBP, ESP
18325 PUSH EAX
18326 PUSH EDX
18327 CALL Int2Str
18328 POP EDX
18329 POP EAX
18330 TEST EAX, EAX
18331 JGE @@0
18332 NEG EAX
18333 @@0:
18334 CMP EAX, 1000
18335 JL @@Exit
18336 PUSH EDX
18337 MOV EAX, [EDX]
18338 PUSH EAX
18339 CALL System.@LStrLen // EAX = Length(Result)
18340 POP EDX
18341 PUSH EDX // EDX = @Result[ 1 ]
18342 XOR ECX, ECX
18344 @@1:
18345 ROL ECX, 8
18346 DEC EAX
18347 MOV CL, [EDX+EAX]
18348 JZ @@fin
18349 CMP ECX, 300000h
18350 JL @@1
18352 PUSH ECX
18353 XOR ECX, ECX
18354 MOV CL, [ThsSeparator]
18355 JMP @@1
18357 @@fin: //CMP CX, ',-'
18358 CMP CL, '-'
18359 JNE @@fin1
18360 CMP CH, [ThsSeparator]
18361 JNE @@fin1
18362 MOV CH, 0 // this corrects -,ddd,...
18363 @@fin1: CMP ECX, 01000000h
18364 JGE @@fin2
18365 INC EAX
18366 ROL ECX, 8
18367 JMP @@fin1
18368 @@fin2: PUSH ECX
18370 LEA EDX, [ESP+EAX]
18371 MOV EAX, [EBP-4]
18372 CALL System.@LStrFromPChar
18373 @@Exit:
18374 MOV ESP, EBP
18375 POP EBP
18376 end;
18377 {$ELSE ASM_VERSION} //Pascal
18378 function Int2Ths( I : Integer ) : String;
18379 var S : String;
18380 begin
18381 S := Int2Str( I );
18382 Result := '';
18383 while S <> '' do
18384 begin
18385 if Result <> '' then
18386 Result := ThsSeparator + Result;
18387 Result := CopyTail( S, 3 ) + Result;
18388 S := Copy( S, 1, Length( S ) - 3 );
18389 end;
18390 if Copy( Result, 1, 2 ) = '-' + ThsSeparator then
18391 Result := '-' + CopyEnd( Result, 3 );
18392 end;
18393 {$ENDIF ASM_VERSION}
18394 //[END Int2Ths]
18396 //[FUNCTION Int2Digs]
18397 {$IFDEF ASM_VERSION}
18398 function Int2Digs( Value, Digits : Integer ) : String;
18400 PUSH EBP
18401 MOV EBP, ESP
18402 PUSH EDX // [EBP-4] = Digits
18403 PUSH ECX
18404 MOV EDX, ECX
18405 CALL Int2Str
18406 POP ECX
18407 PUSH ECX // [EBP-8] = @Result
18408 MOV EAX, [ECX]
18409 PUSH EAX
18410 CALL System.@LStrLen
18411 POP EDX // EDX = @Result[1]
18412 MOV ECX, EAX // ECX = Length( Result )
18413 ADD EAX, EAX
18414 SUB ESP, EAX
18415 MOV EAX, ESP
18416 PUSHAD
18417 CALL StrCopy
18418 POPAD
18419 MOV EDX, EAX
18420 ADD ESP, -100
18421 CMP byte ptr [EDX], '-'
18422 PUSHFD
18423 JNE @@1
18424 INC EDX
18425 @@1:
18426 MOV EAX, [EBP-4] // EAX = Digits
18427 CMP ECX, EAX
18428 JGE @@2
18429 DEC EDX
18430 MOV byte ptr [EDX], '0'
18431 INC ECX
18432 JMP @@1
18433 @@2:
18434 POPFD
18435 JNE @@3
18436 DEC EDX
18437 MOV byte ptr [EDX], '-'
18438 @@3:
18439 MOV EAX, [EBP-8]
18440 CALL System.@LStrFromPChar
18441 MOV ESP, EBP
18442 POP EBP
18443 end;
18444 {$ELSE ASM_VERSION} //Pascal
18445 function Int2Digs( Value, Digits : Integer ) : String;
18446 var M : String;
18447 begin
18448 Result := Int2Str( Value );
18449 M := '';
18450 if Value < 0 then
18451 begin
18452 M := '-';
18453 Result := CopyEnd( Result, 2 );
18454 end;
18455 if Digits >= 0 then
18456 while Length( M + Result ) < Digits do
18457 Result := '0' + Result
18458 else
18459 while Length( Result ) < -Digits do
18460 Result := '0' + Result;
18461 Result := M + Result;
18462 end;
18463 {$ENDIF ASM_VERSION}
18464 //[END Int2Digs]
18466 //[FUNCTION Num2Bytes]
18467 {$IFDEF ASM_VERSION}
18468 function Num2Bytes( Value : Double ) : String;
18470 PUSH EBX
18471 PUSH ESI
18472 PUSH EDI
18473 MOV EBX, ESP
18474 MOV ESI, EAX
18476 MOV ECX, 4
18477 MOV EDX, 'TGMk'
18478 @@1:
18479 FLD [Value]
18480 @@10:
18481 FICOM dword ptr [@@1024]
18482 FSTSW AX
18483 SAHF
18484 JB @@2
18486 FIDIV dword ptr [@@1024]
18487 FST [Value]
18488 WAIT
18490 TEST DL, 20h
18491 JE @@ror
18492 AND DL, not 20h
18493 JMP @@nxt
18494 @@1024: DD 1024
18495 @@100: DD 100
18497 @@ror:
18498 ROR EDX, 8
18499 @@nxt:
18500 LOOP @@10
18501 @@2:
18502 TEST DL, 20h
18503 JZ @@3
18504 MOV DL, 0
18505 @@3: MOV DH, 0
18506 PUSH DX
18507 MOV EDI, ESP
18509 FLD ST(0)
18510 CALL System.@TRUNC
18511 {$IFDEF _D2orD3}
18512 PUSH 0
18513 {$ELSE}
18514 PUSH EDX
18515 {$ENDIF}
18516 PUSH EAX
18517 FILD qword ptr [ESP]
18518 POP EDX
18519 POP EDX
18521 MOV EDX, ESI
18522 CALL Int2Str
18524 FSUBP ST(1), ST
18525 FIMUL dword ptr [@@100]
18526 CALL System.@TRUNC
18528 TEST EAX, EAX
18529 JZ @@4
18531 XOR ECX, ECX
18532 MOV CL, 0Ah
18534 IDIV ECX
18535 TEST EDX, EDX
18536 JZ @@5
18538 MOV AH, DL
18539 SHL EAX, 16
18540 ADD EAX, '00. '
18541 PUSH EAX
18542 MOV EDI, ESP
18543 INC EDI
18544 JMP @@4
18546 @@5: SHL EAX, 8
18547 ADD AX, '0.'
18548 PUSH AX
18549 MOV EDI, ESP
18551 @@4:
18552 MOV EAX, [ESI]
18553 CALL System.@LStrLen
18554 ADD ESP, -100
18556 SUB EDI, EAX
18557 PUSH ESI
18558 PUSH EDI
18559 MOV ESI, [ESI]
18560 MOV ECX, EAX
18561 REP MOVSB
18563 POP EDX
18564 POP EAX
18565 CALL System.@LStrFromPChar
18567 MOV ESP, EBX
18568 POP EDI
18569 POP ESI
18570 POP EBX
18571 end;
18572 {$ELSE ASM_VERSION} //Pascal
18573 function Num2Bytes( Value : Double ) : String;
18574 const Suffix = 'KMGT';
18575 var V, I : Integer;
18576 begin
18577 Result := '';
18578 I := 0;
18579 while (Value >= 1024) and (I < 4) do
18580 begin
18581 Inc( I );
18582 Value := Value / 1024.0;
18583 end;
18584 Result := Int2Str( Trunc( Value ) );
18585 V := Trunc( (Value - Trunc( Value )) * 100 );
18586 if V <> 0 then
18587 begin
18588 if (V mod 10) = 0 then
18589 V := V div 10;
18590 Result := Result + ',' + Int2Str( V );
18591 end;
18592 if I > 0 then
18593 Result := Result + Suffix[ I ];
18594 end;
18595 {$ENDIF ASM_VERSION}
18596 //[END Num2Bytes]
18598 //[FUNCTION S2Int]
18599 {$IFDEF ASM_VERSION}
18600 function S2Int( S: PChar ): Integer;
18602 XCHG EDX, EAX
18603 XOR EAX, EAX
18604 TEST EDX, EDX
18605 JZ @@exit
18607 XOR ECX, ECX
18608 MOV CL, [EDX]
18609 INC EDX
18610 CMP CL, '-'
18611 PUSHFD
18612 JE @@0
18613 @@1: CMP CL, '+'
18614 JNE @@2
18615 @@0: MOV CL, [EDX]
18616 INC EDX
18617 @@2: SUB CL, '0'
18618 CMP CL, '9'-'0'
18619 JA @@fin
18620 LEA EAX, [EAX+EAX*4] //
18621 LEA EAX, [ECX+EAX*2] //
18622 JMP @@0
18623 @@fin: POPFD
18624 JNE @@exit
18625 NEG EAX
18626 @@exit:
18627 end;
18628 {$ELSE ASM_VERSION} //Pascal
18629 function S2Int( S: PChar ): Integer;
18630 var M : Integer;
18631 begin
18632 Result := 0;
18633 if S = '' then Exit;
18634 M := 1;
18635 if S^ = '-' then
18636 begin
18637 M := -1;
18638 Inc( S );
18640 else
18641 if S^ = '+' then
18642 Inc( S );
18643 while S^ in [ '0'..'9' ] do
18644 begin
18645 Result := Result * 10 + Integer( S^ ) - Integer( '0' );
18646 Inc( S );
18647 end;
18648 if M < 0 then
18649 Result := -Result;
18650 end;
18651 {$ENDIF ASM_VERSION}
18652 //[END S2Int]
18654 //[FUNCTION Str2Int]
18655 {$IFDEF ASM_VERSION}
18656 function Str2Int(const Value : String) : Integer;
18658 CALL EAX2PChar
18659 CALL S2Int
18660 end;
18661 {$ELSE ASM_VERSION} //Pascal
18662 function Str2Int(const Value : String) : Integer;
18663 begin
18664 Result := S2Int( PChar( Value ) );
18665 end;
18666 {$ENDIF ASM_VERSION}
18667 //[END Str2Int]
18669 //[function StrCopy]
18670 function StrCopy( Dest, Source: PChar ): PChar; assembler;
18672 {$IFDEF F_P}
18673 MOV EAX, [Dest]
18674 MOV EDX, [Source]
18675 {$ENDIF F_P}
18676 PUSH EDI
18677 PUSH ESI
18678 MOV ESI,EAX
18679 MOV EDI,EDX
18680 OR ECX, -1
18681 XOR AL,AL
18682 REPNE SCASB
18683 NOT ECX
18684 MOV EDI,ESI
18685 MOV ESI,EDX
18686 MOV EDX,ECX
18687 MOV EAX,EDI
18688 SHR ECX,2
18689 REP MOVSD
18690 MOV ECX,EDX
18691 AND ECX,3
18692 REP MOVSB
18693 POP ESI
18694 POP EDI
18695 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
18697 function StrCat( Dest, Source: PChar ): PChar;
18698 begin
18699 StrCopy( StrScan( Dest, #0 ), Source );
18700 Result := Dest;
18701 end;
18703 //[function StrScan]
18704 function StrScan(Str: PChar; Chr: Char): PChar; assembler;
18706 {$IFDEF F_P}
18707 MOV EAX, [Str]
18708 MOVZX EDX, [Chr]
18709 {$ENDIF}
18710 PUSH EDI
18711 PUSH EAX
18712 MOV EDI,Str
18713 OR ECX, -1
18714 XOR AL,AL
18715 REPNE SCASB
18716 NOT ECX
18717 POP EDI
18718 XCHG EAX, EDX
18719 REPNE SCASB
18721 XCHG EAX, EDI
18722 POP EDI
18724 JE @@1
18725 XOR EAX, EAX
18728 @@1: DEC EAX
18729 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
18731 //[function StrRScan]
18732 function StrRScan(const Str: PChar; Chr: Char): PChar; assembler;
18734 {$IFDEF F_P}
18735 MOV EAX, [Str]
18736 MOVZX EDX, [Chr]
18737 {$ENDIF F_P}
18738 PUSH EDI
18739 MOV EDI,Str
18740 MOV ECX,0FFFFFFFFH
18741 XOR AL,AL
18742 REPNE SCASB
18743 NOT ECX
18745 DEC EDI
18746 MOV AL,Chr
18747 REPNE SCASB
18748 MOV EAX,0
18749 JNE @@1
18750 MOV EAX,EDI
18751 INC EAX
18752 @@1: CLD
18753 POP EDI
18754 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
18756 //[function StrScanLen]
18757 function StrScanLen(Str: PChar; Chr: Char; Len: Integer): PChar; assembler;
18759 {$IFDEF F_P}
18760 MOV EAX, [Str]
18761 MOVZX EDX, [Chr]
18762 MOV ECX, [Len]
18763 {$ENDIF F_P}
18764 PUSH EDI
18765 XCHG EDI, EAX
18766 XCHG EAX, EDX
18767 REPNE SCASB
18769 XCHG EAX, EDI
18770 POP EDI
18771 { -> EAX => to next character after found or to the end of Str,
18772 ZF = 0 if character found. }
18773 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
18775 //[FUNCTION TrimLeft]
18776 {$IFDEF ASM_VERSION}
18777 function TrimLeft(const S: string): string;
18779 XCHG EAX, EDX
18780 CALL EDX2PChar
18781 DEC EDX
18782 @@1: INC EDX
18783 MOVZX ECX, byte ptr [EDX]
18784 JECXZ @@fin
18785 CMP CL, ' '
18786 JBE @@1
18787 @@fin:
18788 CALL System.@LStrFromPChar
18789 end;
18790 {$ELSE ASM_VERSION} //Pascal
18791 function TrimLeft(const S: string): string;
18793 I, L: Integer;
18794 begin
18795 L := Length(S);
18796 I := 1;
18797 while (I <= L) and (S[I] <= ' ') do Inc(I);
18798 Result := Copy(S, I, Maxint);
18799 end;
18800 {$ENDIF ASM_VERSION}
18801 //[END TrimLeft]
18803 //[FUNCTION TrimRight]
18804 {$IFDEF ASM_VERSION}
18805 function TrimRight(const S: string): string;
18807 PUSH EDX
18808 PUSH EAX
18810 PUSH EAX
18811 CALL System.@LStrLen
18812 XCHG EAX, [ESP]
18813 //CALL System.@LStrToPChar
18814 CALL EAX2PChar
18815 POP ECX
18816 INC ECX
18817 @@1: DEC ECX
18818 MOV DL, [EAX+ECX]
18819 JL @@fin
18820 CMP DL, ' '
18821 JBE @@1
18822 @@fin:
18823 INC ECX
18824 POP EAX
18825 XOR EDX, EDX
18826 INC EDX
18827 CALL System.@LStrCopy
18828 end;
18829 {$ELSE ASM_VERSION} //Pascal
18830 function TrimRight(const S: string): string;
18832 I: Integer;
18833 begin
18834 I := Length(S);
18835 while (I > 0) and (S[I] <= ' ') do Dec(I);
18836 Result := Copy(S, 1, I);
18837 end;
18838 {$ENDIF ASM_VERSION}
18839 //[END TrimRight]
18841 //[FUNCTION Trim]
18842 {$IFDEF ASM_VERSION}
18843 function Trim( const S : string): string;
18845 PUSH EDX
18846 CALL TrimRight
18847 POP EDX
18848 MOV EAX, [EDX]
18849 CALL TrimLeft
18850 end;
18851 {$ELSE ASM_VERSION} //Pascal
18852 function Trim( const S : string): string;
18853 begin
18854 Result := TrimLeft( TrimRight( S ) );
18855 end;
18856 {$ENDIF ASM_VERSION}
18857 //[END Trim]
18859 //[function RemoveSpaces]
18860 function RemoveSpaces( const S: String ): String;
18861 var I: Integer;
18862 begin
18863 Result := S;
18864 for I := Length( S ) downto 1 do
18865 if S[ I ] <= ' ' then Delete( Result, I, 1 );
18866 end;
18868 //[procedure Str2LowerCase]
18869 procedure Str2LowerCase( S: PChar );
18871 {$IFDEF F_P}
18872 MOV EAX, [S]
18873 {$ENDIF}
18874 XOR ECX, ECX
18875 @@1:
18876 MOV CL, byte ptr [EAX]
18877 JECXZ @@exit
18878 SUB CL, 'A'
18879 CMP CL, 'Z'-'A'
18880 JA @@2
18881 ADD byte ptr [EAX], 32
18882 @@2: INC EAX
18883 JMP @@1
18884 @@exit:
18885 end {$IFDEF F_P} [ 'EAX', 'ECX' ] {$ENDIF};
18887 //[FUNCTION LowerCase]
18888 {$IFDEF ASM_VERSION}
18889 function LowerCase(const S: string): string;
18891 PUSH ESI
18892 XCHG EAX, EDX
18893 PUSH EAX
18894 CALL System.@LStrAsg
18895 POP EAX
18897 CALL UniqueString
18899 PUSH EAX
18900 CALL System.@LStrLen
18901 POP ESI
18903 XCHG ECX, EAX
18905 JECXZ @@exit
18907 @@go:
18908 LODSB
18909 {$IFDEF PARANOIA}
18910 DB $2C, 'A'
18911 {$ELSE}
18912 SUB AL, 'A'
18913 {$ENDIF}
18914 {$IFDEF PARANOIA}
18915 DB $3C, 26
18916 {$ELSE}
18917 CMP AL, 'Z'-'A'+1
18918 {$ENDIF}
18919 JNB @@1
18921 ADD byte ptr [ESI - 1], 20h
18922 @@1:
18923 LOOP @@go
18924 @@exit:
18925 POP ESI
18926 end;
18927 {$ELSE ASM_VERSION} //Pascal
18928 function LowerCase(const S: string): string;
18929 var I : Integer;
18930 begin
18931 Result := S;
18932 for I := 1 to Length( S ) do
18933 if Result[ I ] in [ 'A'..'Z' ] then
18934 Inc( Result[ I ], 32 );
18935 end;
18936 {$ENDIF ASM_VERSION}
18937 //[END LowerCase]
18939 //[FUNCTION UpperCase]
18940 {$IFDEF ASM_VERSION}
18941 function UpperCase(const S: string): string;
18943 PUSH ESI
18944 XCHG EAX, EDX
18945 PUSH EAX
18946 CALL System.@LStrAsg
18947 POP EAX
18949 CALL UniqueString
18951 PUSH EAX
18952 CALL System.@LStrLen
18953 POP ESI
18955 XCHG ECX, EAX
18957 JECXZ @@exit
18959 @@go:
18960 LODSB
18961 {$IFDEF PARANOIA}
18962 DB $2C, 'a'
18963 {$ELSE}
18964 SUB AL, 'a'
18965 {$ENDIF}
18966 {$IFDEF PARANOIA}
18967 DB $3C, $1A
18968 {$ELSE}
18969 CMP AL, 'z'-'a'+1
18970 {$ENDIF}
18971 JNB @@1
18973 SUB byte ptr [ESI - 1], 20h
18974 @@1:
18975 LOOP @@go
18976 @@exit:
18977 POP ESI
18978 end;
18979 {$ELSE ASM_VERSION} //Pascal
18980 function UpperCase(const S: string): string;
18981 var I : Integer;
18982 begin
18983 Result := S;
18984 for I := 1 to Length( S ) do
18985 if Result[ I ] in [ 'a'..'z' ] then
18986 Dec( Result[ I ], 32 );
18987 end;
18988 {$ENDIF ASM_VERSION}
18989 //[END UpperCase]
18991 {$IFDEF F_P}
18992 //[function DummyStrFun]
18993 function DummyStrFun( const S: String ): String;
18994 begin
18995 Result := S;
18996 end;
18997 {$ENDIF F_P}
18999 //[FUNCTION CopyEnd]
19000 {$IFDEF ASM_VERSION}
19001 function CopyEnd( const S : String; Idx : Integer ) : String;
19003 PUSH ECX
19004 PUSH EAX
19005 PUSH EDX
19007 CALL System.@LStrLen
19009 POP EDX
19010 TEST EDX, EDX
19011 JG @@1
19012 XOR EDX, EDX
19013 INC EDX
19014 @@1:
19015 SUB EAX, EDX
19016 MOV ECX, EAX
19018 POP EAX
19019 JGE @@ret_end
19021 POP EAX
19022 JL System.@LStrClr
19024 @@ret_end:
19025 INC ECX
19026 CALL System.@LStrCopy
19027 end;
19028 {$ELSE ASM_VERSION} //Pascal
19029 function CopyEnd( const S : String; Idx : Integer ) : String;
19030 begin
19031 Result := Copy( S, Idx, MaxInt );
19032 end;
19033 {$ENDIF ASM_VERSION}
19034 //[END CopyEnd]
19036 //[FUNCTION CopyTail]
19037 {$IFDEF ASM_VERSION}
19038 function CopyTail( const S : String; Len : Integer ) : String;
19040 PUSH ECX
19041 PUSH EAX
19042 PUSH EDX
19043 CALL System.@LStrLen
19044 POP ECX
19045 CMP ECX, EAX
19046 {$IFDEF USE_CMOV}
19047 CMOVG ECX, EAX
19048 {$ELSE}
19049 JLE @@1
19050 MOV ECX, EAX
19051 @@1: {$ENDIF}
19053 MOV EDX, EAX
19054 SUB EDX, ECX
19055 INC EDX
19056 POP EAX
19057 CALL System.@LStrCopy
19058 end;
19059 {$ELSE ASM_VERSION} //Pascal
19060 function CopyTail( const S : String; Len : Integer ) : String;
19061 var L : Integer;
19062 begin
19063 L := Length( S );
19064 if L < Len then
19065 Len := L;
19066 Result := '';
19067 if Len = 0 then Exit;
19068 Result := Copy( S, L - Len + 1, Len );
19069 end;
19070 {$ENDIF ASM_VERSION}
19071 //[END CopyTail]
19073 //[PROCEDURE DeleteTail]
19074 {$IFDEF ASM_VERSION}
19075 procedure DeleteTail( var S : String; Len : Integer );
19077 PUSH EAX
19078 PUSH EDX
19079 MOV EAX, [EAX]
19080 CALL System.@LStrLen
19081 POP ECX
19082 CMP ECX, EAX
19083 {$IFDEF USE_CMOV}
19084 CMOVG ECX, EAX
19085 {$ELSE}
19086 JLE @@1
19087 MOV ECX, EAX
19088 @@1: {$ENDIF}
19090 MOV EDX, EAX
19091 SUB EDX, ECX
19092 INC EDX
19093 POP EAX
19094 CALL System.@LStrDelete
19095 end;
19096 {$ELSE ASM_VERSION} //Pascal
19097 procedure DeleteTail( var S : String; Len : Integer );
19098 var L : Integer;
19099 begin
19100 L := Length( S );
19101 if Len > L then
19102 Len := L;
19103 Delete( S, L - Len + 1, Len );
19104 end;
19105 {$ENDIF ASM_VERSION}
19106 //[END DeleteTail]
19108 //[FUNCTION IndexOfChar]
19109 {$IFDEF ASM_VERSION}
19110 function IndexOfChar( const S : String; Chr : Char ) : Integer;
19112 //PUSH EDX
19113 //CALL System.@LStrToPChar
19114 //POP EDX
19115 CALL EAX2PChar
19116 PUSH EAX
19117 CALL StrScan
19118 POP EDX
19119 TEST EAX, EAX
19120 JE @@exit__1
19121 SUB EAX, EDX
19122 INC EAX
19124 @@exit__1:
19125 DEC EAX
19126 end;
19127 {$ELSE ASM_VERSION} //Pascal
19128 function IndexOfChar( const S : String; Chr : Char ) : Integer;
19129 var P, F : PChar;
19130 begin
19131 P := PChar( S );
19132 F := StrScan( P, Chr );
19133 Result := -1;
19134 if F = nil then Exit;
19135 Result := Integer( F ) - Integer( P ) + 1;
19136 end;
19137 {$ENDIF ASM_VERSION}
19138 //[END IndexOfChar]
19140 //[FUNCTION IndexOfCharsMin]
19141 {$IFDEF ASM_VERSION}
19142 function IndexOfCharsMin( const S, Chars : String ) : Integer;
19144 PUSH ESI
19145 PUSH EAX
19146 CALL EDX2PChar
19147 MOV ESI, EDX
19149 XOR ECX, ECX
19150 DEC ECX
19152 @@1: LODSB
19153 TEST AL, AL
19154 JZ @@exit
19156 XCHG EDX, EAX
19157 POP EAX
19158 PUSH EAX
19160 PUSH ECX
19161 CALL IndexOfChar
19162 POP ECX
19163 TEST EAX, EAX
19164 JLE @@1
19166 TEST ECX, ECX
19167 JLE @@2
19168 CMP EAX, ECX
19169 JGE @@1
19170 @@2: //XCHG ECX, EAX
19171 //JMP @@1
19173 @@exit: XCHG EAX, ECX
19174 JL @@1
19175 POP ECX
19176 POP ESI
19177 end;
19178 {$ELSE ASM_VERSION} //Pascal
19179 function IndexOfCharsMin( const S, Chars : String ) : Integer;
19180 var I, J : Integer;
19181 begin
19182 Result := -1;
19183 for I := 1 to Length( Chars ) do
19184 begin
19185 J := IndexOfChar( S, Chars[ I ] );
19186 if J > 0 then
19187 begin
19188 if (Result < 0) or (J < Result) then
19189 Result := J;
19190 end;
19191 end;
19192 end;
19193 {$ENDIF ASM_VERSION}
19194 //[END IndexOfCharsMin]
19196 {$IFNDEF _FPC}
19197 {$IFNDEF _D2}
19198 //[function IndexOfWideCharsMin]
19199 function IndexOfWideCharsMin( const S, Chars : WideString ) : Integer;
19200 var I, J : Integer;
19201 begin
19202 Result := -1;
19203 for I := 1 to Length( Chars ) do
19204 begin
19205 J := pos( Chars[ I ], S );
19206 if J > 0 then
19207 begin
19208 if (Result < 0) or (J < Result) then
19209 Result := J;
19210 end;
19211 end;
19212 end;
19213 {$ENDIF _D2}
19214 {$ENDIF _FPC}
19216 //[FUNCTION IndexOfStr]
19217 {$IFDEF ASM_VERSION}
19218 function IndexOfStr( const S, Sub : String ) : Integer;
19220 PUSH EBX
19221 PUSH ESI
19222 PUSH EDI
19224 PUSH EAX
19225 MOV EAX, EDX
19226 PUSH EDX
19227 CALL System.@LStrLen
19228 MOV EDI, EAX
19229 POP EAX
19230 //CALL System.@LStrToPChar
19231 CALL EAX2PChar
19232 MOV BL, [EAX]
19233 XCHG EAX, [ESP]
19234 //CALL System.@LStrToPChar
19235 CALL EAX2PChar
19237 MOV ESI, EAX
19239 DEC EAX
19240 @@1: INC EAX
19241 MOV DL, BL
19242 CALL StrScan
19243 TEST EAX, EAX
19244 JE @@exit__1
19246 POP EDX
19247 PUSH EDX
19249 MOV ECX, EDI
19250 PUSH EAX
19251 CALL StrLComp
19252 POP EAX
19253 JNE @@1
19255 SUB EAX, ESI
19256 INC EAX
19257 JMP @@exit
19259 @@exit__1:
19260 DEC EAX
19261 @@exit:
19262 POP EDX
19263 POP EDI
19264 POP ESI
19265 POP EBX
19266 end;
19267 {$ELSE ASM_VERSION} //Pascal
19268 function IndexOfStr( const S, Sub : String ) : Integer;
19269 var I : Integer;
19270 begin
19271 Result := Length( S );
19272 if Sub = '' then Exit;
19273 Result := 0;
19274 if S = '' then Exit;
19275 if Length( Sub ) > Length( S ) then Exit;
19276 Result := 1;
19277 while Result + Length( Sub ) - 1 <= Length( S ) do
19278 begin
19279 I := IndexOfChar( CopyEnd( S, Result ), Sub[ 1 ] );
19280 if I <= 0 then break;
19281 Result := Result + I - 1;
19282 if Result <= 0 then Exit;
19283 if Copy( S, Result, Length( Sub ) ) = Sub then Exit;
19284 Inc( Result );
19285 end;
19286 Result := -1;
19287 end;
19288 {$ENDIF ASM_VERSION}
19289 //[END IndexOfStr]
19291 //[FUNCTION Parse]
19292 {$IFDEF ASM_VERSION} //???
19293 function Parse( var S : String; const Separators : String ) : String;
19295 PUSH EBX
19296 PUSH EDI
19297 MOV EBX, EAX
19299 PUSH ECX
19300 MOV EAX, [EBX]
19301 CALL IndexOfCharsMin
19302 INC EAX
19303 JNE @@1
19304 MOV EAX, [EBX]
19305 CALL System.@LStrLen
19306 INC EAX
19307 INC EAX
19308 @@1:
19309 DEC EAX
19310 MOV EDI, EAX
19311 MOV ECX, EAX
19312 DEC ECX
19313 XOR EDX, EDX
19314 INC EDX
19315 MOV EAX, [EBX]
19316 CALL System.@LStrCopy
19318 MOV EAX, [EBX]
19319 MOV EDX, EDI
19320 INC EDX
19321 MOV ECX, EBX
19322 CALL CopyEnd
19324 POP EDI
19325 POP EBX
19326 end;
19327 {$ELSE ASM_VERSION} //Pascal
19328 function Parse( var S : String; const Separators : String ) : String;
19329 var Pos : Integer;
19330 begin
19331 Pos := IndexOfCharsMin( S, Separators );
19332 if Pos <= 0 then
19333 Pos := Length( S ) + 1;
19334 Result := S;
19335 S := Copy( Result, Pos + 1, MaxInt );
19336 Result := Copy( Result, 1, Pos - 1 );
19337 end;
19338 {$ENDIF ASM_VERSION}
19339 //[END Parse]
19341 {$IFNDEF _FPC}
19342 {$IFNDEF _D2}
19343 //[function WParse]
19344 function WParse( var S : WideString; const Separators : WideString ) : WideString;
19345 var Pos : Integer;
19346 begin
19347 Pos := IndexOfWideCharsMin( S, Separators );
19348 if Pos <= 0 then
19349 Pos := Length( S ) + 1;
19350 Result := S;
19351 S := Copy( Result, Pos + 1, MaxInt );
19352 Result := Copy( Result, 1, Pos - 1 );
19353 end;
19354 {$ENDIF _D2}
19355 {$ENDIF _FPC}
19357 //[function ParsePascalString]
19358 function ParsePascalString( var S : String; const Separators : String ) : String;
19359 var Pos, Idx : Integer;
19360 Hex, Spc : boolean;
19361 procedure SkipSpaces;
19362 begin
19363 if not Spc then
19364 while (Length( S ) >= Pos) and (S[ Pos ] = ' ') do
19365 Inc( Pos );
19366 end;
19367 var Buf : String;
19368 Ou, Val : Integer;
19369 begin
19370 Pos := 1;
19371 Spc := IndexOfChar( Separators, ' ' ) >= 0;
19372 SkipSpaces;
19373 if Length( S ) < Pos then
19374 begin
19375 Result := S;
19376 S := '';
19377 exit;
19378 end;
19379 Buf := PChar( S );
19380 Ou := 1;
19381 if S[ Pos ] in [ '''', '#' ] then
19382 begin
19383 // skip here string constant expression
19384 while Pos <= Length( S ) do
19385 begin
19386 if S[ Pos ] = '''' then
19387 begin
19388 Inc( Pos );
19389 while Pos <= Length( S ) do
19390 begin
19391 if S[ Pos ] = '''' then
19392 if (Pos = Length( S )) or (S[ Pos+1 ] <> '''') then
19393 begin
19394 Inc( Pos );
19395 break;
19397 else Inc( Pos );
19398 Buf[ Ou ] := S[ Pos ];
19399 Inc( Ou );
19400 Inc( Pos );
19401 end;
19402 //if Pos < Length( S ) then Inc( Pos );
19404 else
19405 if S[ Pos ] = '#' then
19406 begin
19407 Inc( Pos ); Hex := False; Val := 0;
19408 if (Pos < Length( S )) and (S[ Pos ] = '$') then
19409 begin
19410 Inc( Pos ); Hex := True;
19411 end;
19412 Dec( Pos );
19413 while Pos < Length( S ) do
19414 begin
19415 Inc( Pos );
19416 if (S[ Pos ] in [ '0'..'9' ]) or
19417 Hex and (S[ Pos ] in [ 'a'..'f', 'A'..'F' ]) then
19418 begin
19419 if Hex then
19420 Val := Val * 16
19421 else
19422 Val := Val * 10;
19423 if S[ Pos ] <= '9' then
19424 Val := Val + Integer( S[ Pos ] ) - Integer( '0' )
19425 else
19426 if S[ Pos ] <= 'F' then
19427 Val := Val + 10 + Integer( S[ Pos ] ) - Integer( 'A' )
19428 else
19429 Val := Val + 10 + Integer( S[ Pos ] ) - Integer( 'a' );
19430 continue;
19431 end;
19432 Inc( Pos ); break;
19433 end;
19434 Buf[ Ou ] := Char( Val );
19435 Inc( Ou );
19437 else break;
19438 SkipSpaces;
19439 if S[ Pos ] <> '+' then break;
19440 SkipSpaces;
19441 end;
19442 end;
19443 Idx := IndexOfCharsMin( CopyEnd( S, Pos ), Separators );
19444 if Idx <= 0 then
19445 begin
19446 Result := Copy( Buf, 1, Ou - 1 ) + CopyEnd( S, Pos );
19447 S := '';
19449 else
19450 begin
19451 Result := Copy( Buf, 1, Ou - 1 ) + Copy( S, Pos, Idx - 1 );
19452 S := CopyEnd( S, Pos + Idx );
19453 end;
19454 end;
19456 //[function String2PascalStrExpr]
19457 function String2PascalStrExpr( const S : String ) : String;
19458 var I, Strt : Integer;
19459 function String2DoubleQuotas( const S : String ) : String;
19460 var I, J : Integer;
19461 begin
19462 if IndexOfChar( S, '''' ) <= 0 then
19463 Result := S
19464 else
19465 begin
19466 J := 0;
19467 for I := 1 to Length( S ) do
19468 if S[ I ] = '''' then Inc( J );
19469 SetLength( Result, Length( S ) + J );
19470 J := 1;
19471 for I := 1 to Length( S ) do
19472 begin
19473 Result[ J ] := S[ I ];
19474 Inc( J );
19475 if S[ I ] = '''' then
19476 begin
19477 Result[ J ] := '''';
19478 Inc( J );
19479 end;
19480 end;
19481 end;
19482 end;
19483 begin
19484 Result := '';
19485 if S = '' then
19486 begin
19487 Result := '''''';
19488 exit;
19489 end;
19490 Strt := 1;
19491 for I := 1 to Length( S ) + 1 do
19492 begin
19493 if (I > Length( S )) or (S[ I ] < ' ') then
19494 begin
19495 if (I > Strt) and (I > 1) then
19496 begin
19497 if Result <> '' then
19498 Result := Result + '+';
19499 Result := Result + '''' + String2DoubleQuotas( Copy( S, Strt, I - Strt ) ) + '''';
19500 end;
19501 if I > Length( S ) then break;
19502 if Result <> '' then
19503 Result := Result + '+'
19504 else
19505 Result := Result + '''''+';
19506 Result := Result + '#' + Int2Str( Integer( S[ I ] ) );
19507 Strt := I + 1;
19508 end;
19509 end;
19510 end;
19512 //[function CompareMem]
19513 function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
19515 {$IFDEF F_P}
19516 MOV EAX, [P1]
19517 MOV EDX, [P2]
19518 MOV ECX, [Length]
19519 {$ENDIF}
19520 PUSH ESI
19521 PUSH EDI
19522 MOV ESI,P1
19523 MOV EDI,P2
19524 MOV EDX,ECX
19525 XOR EAX,EAX
19526 AND EDX,3
19527 SHR ECX,1
19528 SHR ECX,1
19529 REPE CMPSD
19530 JNE @@2
19531 MOV ECX,EDX
19532 REPE CMPSB
19533 JNE @@2
19534 @@1: INC EAX
19535 @@2: POP EDI
19536 POP ESI
19537 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
19539 //[FUNCTION AllocMem]
19540 {$IFDEF ASM_VERSION}
19541 function AllocMem( Size : Integer ) : Pointer;
19542 asm //cmd //opd
19543 TEST EAX, EAX
19544 JZ @@exit
19545 PUSH EAX
19546 CALL System.@GetMem
19547 POP EDX
19548 PUSH EAX
19549 MOV CL, 0
19550 CALL System.@FillChar
19551 POP EAX
19552 @@exit:
19553 end;
19554 {$ELSE ASM_VERSION} //Pascal
19555 function AllocMem( Size : Integer ) : Pointer;
19556 begin
19557 Result := nil;
19558 if Size > 0 then
19559 begin
19560 GetMem( Result, Size );
19561 FillChar( Result^, Size, 0 );
19562 end;
19563 end;
19564 {$ENDIF ASM_VERSION}
19565 //[END AllocMem]
19567 //[procedure DisposeMem]
19568 procedure DisposeMem( var Addr : Pointer );
19569 begin
19570 if Addr <> nil then
19571 FreeMem( Addr );
19572 Addr := nil;
19573 end;
19575 //[function AnsiUpperCase]
19576 function AnsiUpperCase(const S: string): string;
19578 Len: Integer;
19579 begin
19580 Len := Length(S);
19581 SetString(Result, PChar(S), Len);
19582 if Len > 0 then CharUpperBuff(Pointer(Result), Len);
19583 end;
19585 //[function AnsiLowerCase]
19586 function AnsiLowerCase(const S: string): string;
19588 Len: Integer;
19589 begin
19590 Len := Length(S);
19591 SetString(Result, PChar(S), Len);
19592 if Len > 0 then CharLowerBuff(Pointer(Result), Len);
19593 end;
19595 {$IFNDEF _D2}
19596 {$IFNDEF _FPC}
19597 //[function WAnsiUpperCase]
19598 function WAnsiUpperCase(const S: WideString): WideString;
19599 var Len: Integer;
19600 begin
19601 Len := Length(S);
19602 Result := S;
19603 if Len > 0 then CharUpperBuffW(Pointer(Result), Len);
19604 end;
19606 //[function WAnsiLowerCase]
19607 function WAnsiLowerCase(const S: WideString): WideString;
19608 var Len: Integer;
19609 begin
19610 Len := Length(S);
19611 Result := S;
19612 if Len > 0 then CharLowerBuffW(Pointer(Result), Len);
19613 end;
19614 {$ENDIF _FPC}
19615 {$ENDIF _D2}
19617 //[function AnsiCompareStr]
19618 function AnsiCompareStr(const S1, S2: string): Integer;
19619 begin
19620 Result := CompareString(LOCALE_USER_DEFAULT, 0, PChar(S1), -1,
19621 PChar(S2), -1 ) - 2;
19622 end;
19624 //[function _AnsiCompareStr]
19625 function _AnsiCompareStr(S1, S2: PChar): Integer;
19626 begin
19627 Result := CompareString( LOCALE_USER_DEFAULT, 0, S1, -1,
19628 S2, -1) - 2;
19629 end;
19631 //[function AnsiCompareStrNoCase]
19632 function AnsiCompareStrNoCase(const S1, S2: string): Integer;
19633 begin
19634 Result := CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, PChar(S1), -1,
19635 PChar(S2), -1 ) - 2;
19636 end;
19638 //[function _AnsiCompareStrNoCase]
19639 function _AnsiCompareStrNoCase(S1, S2: PChar): Integer;
19640 begin
19641 Result := CompareString( LOCALE_USER_DEFAULT, NORM_IGNORECASE, S1, -1,
19642 S2, -1) - 2;
19643 end;
19645 //[function AnsiCompareText]
19646 function AnsiCompareText( const S1, S2: String ): Integer;
19647 begin
19648 Result := AnsiCompareStrNoCase( S1, S2 );
19649 end;
19651 //[function StrLCopy]
19652 function StrLCopy(Dest: PChar; const Source: PChar; MaxLen: Cardinal): PChar; assembler;
19654 {$IFDEF F_P}
19655 MOV EAX, [Dest]
19656 MOV EDX, [Source]
19657 MOV ECX, [MaxLen]
19658 {$ENDIF F_P}
19659 PUSH EDI
19660 PUSH ESI
19661 PUSH EBX
19662 MOV ESI,EAX
19663 MOV EDI,EDX
19664 MOV EBX,ECX
19665 XOR AL,AL
19666 TEST ECX,ECX
19667 JZ @@1
19668 REPNE SCASB
19669 JNE @@1
19670 INC ECX
19671 @@1: SUB EBX,ECX
19672 MOV EDI,ESI
19673 MOV ESI,EDX
19674 MOV EDX,EDI
19675 MOV ECX,EBX
19676 SHR ECX,2
19677 REP MOVSD
19678 MOV ECX,EBX
19679 AND ECX,3
19680 REP MOVSB
19681 STOSB
19682 MOV EAX,EDX
19683 POP EBX
19684 POP ESI
19685 POP EDI
19686 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
19688 //[FUNCTION StrPCopy]
19689 {$IFDEF ASM_VERSION}
19690 function StrPCopy(Dest: PChar; const Source: string): PChar;
19692 PUSH EAX
19693 MOV EAX, EDX
19694 CALL System.@LStrLen
19695 MOV ECX, EAX
19696 POP EAX
19697 CALL EDX2PChar
19698 CALL StrLCopy
19699 end;
19700 {$ELSE ASM_VERSION} //Pascal
19701 function StrPCopy(Dest: PChar; const Source: string): PChar;
19702 begin
19703 Result := StrLCopy(Dest, PChar(Source), Length(Source));
19704 end;
19705 {$ENDIF ASM_VERSION}
19706 //[END StrPCopy]
19708 //[FUNCTION StrEq]
19709 {$IFDEF ASM_VERSION}
19710 function StrEq( const S1, S2 : String ) : Boolean;
19712 TEST EDX, EDX
19713 JNZ @@1
19714 @@0: CMP EAX, EDX
19715 JMP @@exit
19716 @@1: TEST EAX, EAX
19717 JZ @@0
19718 MOV ECX, [EAX-4]
19719 CMP ECX, [EDX-4]
19720 JNE @@exit
19721 PUSH EAX
19722 PUSH EDX
19723 PUSH 0
19724 MOV EDX, ESP
19725 CALL LowerCase
19726 PUSH 0
19727 MOV EAX, [ESP + 8]
19728 MOV EDX, ESP
19729 CALL LowerCase
19730 POP EAX
19731 POP EDX
19732 PUSH EDX
19733 PUSH EAX
19734 CALL System.@LStrCmp
19735 MOV EAX, ESP
19736 PUSHFD
19737 XOR EDX, EDX
19738 MOV DL, 2
19739 CALL System.@LStrArrayClr
19740 POPFD
19741 POP EDX
19742 POP EDX
19743 POP EDX
19744 POP EDX
19745 @@exit:
19746 SETZ AL
19747 end;
19748 {$ELSE ASM_VERSION} //Pascal
19749 function StrEq( const S1, S2 : String ) : Boolean;
19750 begin
19751 Result := (Length( S1 ) = Length( S2 )) and
19752 (LowerCase( S1 ) = LowerCase( S2 ));
19753 end;
19754 {$ENDIF ASM_VERSION}
19755 //[END StrEq]
19757 //[FUNCTION AnsiEq]
19758 {$IFDEF ASM_VERSION}
19759 function AnsiEq( const S1, S2 : String ) : Boolean;
19761 CALL AnsiCompareStrNoCase
19762 TEST EAX, EAX
19763 SETZ AL
19764 end;
19765 {$ELSE ASM_VERSION} //Pascal
19766 function AnsiEq( const S1, S2 : String ) : Boolean;
19767 begin
19768 Result := AnsiCompareStrNoCase( S1, S2 ) = 0;
19769 end;
19770 {$ENDIF ASM_VERSION}
19771 //[END AnsiEq]
19773 {$IFNDEF _D2}
19774 {$IFNDEF _FPC}
19775 //[function WAnsiEq]
19776 function WAnsiEq( const S1, S2 : WideString ) : Boolean;
19777 begin
19778 Result := WAnsiLowerCase( S1 )=WAnsiLowerCase( S2 );
19779 end;
19780 {$ENDIF _FPC}
19781 {$ENDIF _D2}
19783 //[FUNCTION StrIn]
19784 {$IFDEF ASM_VERSION}
19785 function StrIn(const S: String; const A: array of String): Boolean;
19787 @@1:
19788 TEST ECX, ECX
19789 JL @@ret_0
19791 PUSH EDX
19792 MOV EDX, [EDX+ECX*4]
19793 DEC ECX
19795 PUSH ECX
19796 PUSH EAX
19797 CALL StrEq
19798 DEC AL
19799 POP EAX
19800 POP ECX
19802 POP EDX
19803 JNZ @@1
19805 MOV AL, 1
19808 @@ret_0:XOR EAX, EAX
19809 end;
19810 {$ELSE ASM_VERSION} //Pascal
19811 function StrIn(const S: String; const A: array of String): Boolean;
19812 var I : Integer;
19813 begin
19814 for I := Low( A ) to High( A ) do
19815 if StrEq( S, A[ I ] ) then
19816 begin
19817 Result := True;
19818 Exit;
19819 end;
19820 Result := False;
19821 end;
19822 {$ENDIF ASM_VERSION}
19823 //[END StrIn]
19825 {$IFNDEF _D2}
19826 {$IFNDEF _FPC}
19827 //[function WStrIn]
19828 function WStrIn( const S : WideString; const A : array of WideString ) : Boolean;
19829 var I : Integer;
19830 begin
19831 for I := Low( A ) to High( A ) do
19832 if WAnsiEq( S, A[ I ] ) then
19833 begin
19834 Result := True;
19835 Exit;
19836 end;
19837 Result := False;
19838 end;
19839 {$ENDIF _FPC}
19840 {$ENDIF _D2}
19842 //[function StrIs]
19843 function StrIs( const S : String; const A : array of String; var Idx: Integer ) : Boolean;
19844 var I : Integer;
19845 begin
19846 Idx := -1;
19847 for I := Low( A ) to High( A ) do
19848 if StrEq( S, A[ I ] ) then
19849 begin
19850 Idx := I;
19851 Result := True;
19852 Exit;
19853 end;
19854 Result := False;
19855 end;
19857 //[function IntIn]
19858 function IntIn( Value: Integer; const List: array of Integer ): Boolean;
19859 var I: Integer;
19860 begin
19861 Result := FALSE;
19862 for I := 0 to High( List ) do
19863 begin
19864 if Value = List[ I ] then
19865 begin
19866 Result := TRUE;
19867 break;
19868 end;
19869 end;
19870 end;
19872 //[FUNCTION _StrSatisfy]
19873 {$IFDEF ASM_VERSION}
19874 function _StrSatisfy( S, Mask : PChar ) : Boolean;
19876 TEST EAX, EAX
19877 JZ @@exit
19878 XCHG ECX, EAX
19879 // EDX <- Mask
19880 // ECX <- S
19881 XOR EAX, EAX
19882 MOV AL, '*'
19883 @@rest_satisfy:
19884 PUSH ECX
19885 PUSH EDX
19887 @@nx_char:
19888 MOV AH, [EDX]
19889 OR AH, [ECX]
19890 JZ @@fin //@@ret_true
19892 MOV AH, 0
19894 CMP word ptr [EDX], AX //'*'
19895 JE @@fin //@@ret_true
19897 CMP byte ptr [ECX], AH
19898 JNE @@10
19900 DEC EDX
19901 @@1:
19902 INC EDX
19903 CMP byte ptr [EDX], AL //'*'
19904 JE @@1
19905 //CMP byte ptr [EDX], '?'
19906 //JE @@1
19908 CMP byte ptr [EDX], AH
19909 SETZ AL
19910 JMP @@fin
19912 @@10: CMP byte ptr [EDX], AH
19913 JE @@ret_false
19915 CMP byte ptr [EDX], '?'
19916 JNE @@11
19918 @@go_nx_char:
19919 INC ECX
19920 INC EDX
19921 JMP @@nx_char
19923 @@11:
19924 CMP byte ptr [EDX], AL //'*'
19925 JNE @@20
19927 INC EDX
19928 @@12: CMP byte ptr [ECX], AH
19929 JE @@ret_false
19931 CALL @@rest_satisfy
19932 TEST AL, AL
19933 JNE @@fin
19934 MOV AL, '*'
19936 INC ECX
19937 JMP @@12
19939 @@20: MOV AH, [EDX]
19940 XOR AH, [ECX]
19942 JE @@go_nx_char
19943 @@ret_false:
19944 XOR EAX, EAX
19946 @@fin:
19947 POP EDX
19948 POP ECX
19949 @@exit:
19950 end;
19951 {$ELSE ASM_VERSION} //Pascal
19952 function _StrSatisfy( S, Mask : PChar ) : Boolean;
19953 label next_char;
19954 begin
19955 next_char:
19956 Result := True;
19957 if (S^ = #0) and (Mask^ = #0) then exit;
19958 if (Mask^ = '*') and (Mask[1] = #0) then exit;
19959 if S^ = #0 then
19960 begin
19961 while Mask^ = '*' do
19962 Inc( Mask );
19963 Result := Mask^ = #0;
19964 exit;
19965 end;
19966 Result := False;
19967 if Mask^ = #0 then exit;
19968 if Mask^ = '?' then
19969 begin
19970 Inc( S ); Inc( Mask ); goto next_char;
19971 end;
19972 if Mask^ = '*' then
19973 begin
19974 Inc( Mask );
19975 while S^ <> #0 do
19976 begin
19977 Result := _StrSatisfy( S, Mask );
19978 if Result then exit;
19979 Inc( S );
19980 end;
19981 exit; // (Result = False)
19982 end;
19983 Result := S^ = Mask^;
19984 Inc( S ); Inc( Mask );
19985 if Result then goto next_char;
19986 end;
19987 {$ENDIF ASM_VERSION}
19988 //[END _StrSatisfy]
19990 //[FUNCTION StrSatisfy]
19991 {$IFDEF ASM_VERSION}
19992 function StrSatisfy( const S, Mask: String ): Boolean;
19994 PUSH ESI
19995 XCHG ESI, EAX
19996 PUSH 0
19997 XCHG EAX, EDX
19998 CALL EAX2PChar
19999 MOV EDX, ESP
20001 CMP byte ptr [EAX], 0
20002 JZ @@0
20003 CALL AnsiLowerCase
20004 @@0:
20005 XCHG EAX, ESI
20006 PUSH 0
20007 CALL EAX2PChar
20008 MOV EDX, ESP
20010 CMP byte ptr [EAX], 0
20011 JZ @@1
20012 CALL AnsiLowerCase
20013 @@1:
20014 POP EAX
20015 POP EDX
20016 PUSH EDX
20017 PUSH EAX
20018 CALL _StrSatisfy
20020 XCHG ESI, EAX
20022 CALL RemoveStr
20023 CALL RemoveStr
20024 XCHG EAX, ESI
20026 POP ESI
20027 end;
20028 {$ELSE ASM_VERSION} //Pascal
20029 function StrSatisfy( const S, Mask: String ): Boolean;
20030 begin
20031 Result := _StrSatisfy( PChar( AnsiLowerCase( S ) ),
20032 PChar( AnsiLowerCase( Mask ) ) );
20033 end;
20034 {$ENDIF ASM_VERSION}
20035 //[END StrSatisfy]
20037 //[FUNCTION _2StrSatisfy]
20038 {$IFDEF ASM_VERSION}
20039 function _2StrSatisfy( S, Mask: PChar ): Boolean;
20040 asm // //
20041 PUSH EBX
20042 XCHG EBX, EAX
20043 PUSH 0
20044 MOV EAX, ESP
20045 CALL System.@LStrFromPChar
20046 PUSH 0
20047 MOV EAX, ESP
20048 MOV EDX, EBX
20049 CALL System.@LStrFromPChar
20050 POP EAX
20051 POP EDX
20052 PUSH EDX
20053 PUSH EAX
20054 CALL StrSatisfy
20055 XCHG EBX, EAX
20056 CALL RemoveStr
20057 CALL RemoveStr
20058 XCHG EAX, EBX
20059 POP EBX
20060 end;
20061 {$ELSE ASM_VERSION} // Pascal
20062 function _2StrSatisfy( S, Mask: PChar ): Boolean;
20063 begin
20064 Result := StrSatisfy( S, Mask );
20065 end;
20066 {$ENDIF ASM_VERSION}
20067 //[END _2StrSatisfy]
20069 //[function StrReplace]
20070 function StrReplace( var S: String; const From, ReplTo: String ): Boolean;
20071 var I: Integer;
20072 begin
20073 I := pos( From, S );
20074 if I > 0 then
20075 begin
20076 S := Copy( S, 1, I - 1 ) + ReplTo + CopyEnd( S, I + Length( From ) );
20077 Result := TRUE;
20079 else Result := FALSE;
20080 end;
20083 {$IFDEF _FPC}
20084 //[procedure SetLengthW]
20085 procedure SetLengthW( var W: WideString; NewLength: Integer );
20086 begin
20087 while Length( W ) < NewLength do
20088 W := W + ' ' + W;
20089 if Length( W ) > NewLength then
20090 Delete( W, NewLength + 1, Length( W ) - NewLength );
20091 end;
20093 //[function CopyW]
20094 function CopyW( const W: WideString; From, Count: Integer ): WideString;
20095 begin
20096 Result := '';
20097 if Count <= 0 then Exit;
20098 SetLengthW( Result, Count );
20099 Move( W[ From ], Result[ 1 ], Count * Sizeof( WideChar ) );
20100 end;
20102 //[function posW]
20103 function posW( const S1, S2: String ): Integer;
20104 var I, L1: Integer;
20105 begin
20106 L1 := Length( S1 );
20107 for I := 1 to Length( S2 )-L1+1 do
20108 begin
20109 if Copy( S2, I, L1 ) = S1 then
20110 begin
20111 Result := I;
20112 Exit;
20113 end;
20114 end;
20115 Result := 0;
20116 end;
20117 {$ENDIF _FPC}
20119 {$IFNDEF _FPC}
20120 {$IFNDEF _D2}
20121 //[function WStrReplace]
20122 function WStrReplace( var S: WideString; const From, ReplTo: WideString ): Boolean;
20123 var I: Integer;
20124 begin
20125 I := pos( From, S );
20126 if I > 0 then
20127 begin
20128 S := Copy( S, 1, I - 1 ) + ReplTo + Copy( S, I + Length( From ), MaxInt );
20129 Result := TRUE;
20131 else Result := FALSE;
20132 end;
20134 //[function WStrRepeat]
20135 function WStrRepeat( const S: WideString; Count: Integer ): WideString;
20136 var I, L: Integer;
20137 begin
20138 L := Length( S );
20139 SetLength( Result, L * Count );
20140 for I := 0 to Count-1 do
20141 Move( S[ 1 ], Result[ 1 + I * L ], L * Sizeof( WideChar ) );
20142 end;
20143 {$ENDIF _D2}
20144 {$ENDIF _FPC}
20147 //[function StrRepeat]
20148 function StrRepeat( const S: String; Count: Integer ): String;
20149 var I, L: Integer;
20150 begin
20151 L := Length( S );
20152 SetLength( Result, L * Count );
20153 for I := 0 to Count-1 do
20154 Move( S[ 1 ], Result[ 1 + I * L ], L );
20155 end;
20158 //[PROCEDURE NormalizeUnixText]
20159 {$IFDEF ASM_VERSION}
20160 procedure NormalizeUnixText( var S: String );
20161 asm //cmd //opd
20162 CMP dword ptr [EAX], 0
20163 JZ @@exit
20164 PUSH EBX
20165 PUSH EDI
20166 MOV EBX, EAX
20167 CALL UniqueString
20168 MOV EDI, [EBX]
20169 @@1: MOV EAX, EDI
20170 CALL System.@LStrLen
20171 XCHG ECX, EAX
20172 MOV AX, $0D0A
20174 CMP byte ptr [EDI], AL
20175 JNE @@loo
20176 MOV byte ptr [EDI], AH
20177 @@loo:
20178 TEST ECX, ECX
20179 JZ @@fin
20180 @@loo1:
20181 REPNZ SCASB
20182 JNZ @@fin
20183 CMP byte ptr [EDI-2], AH
20184 JE @@loo
20185 MOV byte ptr [EDI-1], AH
20186 JNE @@loo1
20187 @@fin: POP EDI
20188 POP EBX
20189 @@exit:
20190 end;
20191 {$ELSE ASM_VERSION} //Pascal
20192 procedure NormalizeUnixText( var S: String );
20193 var I: Integer;
20194 begin
20195 if S <> '' then
20196 begin
20197 if S[ 1 ] = #10 then
20198 S[ 1 ] := #13;
20199 for I := 2 to Length(S) do
20200 if (S[I]=#10) and (S[I-1]<>#13) then
20201 S[I] := #13;
20202 end;
20203 end;
20204 {$ENDIF ASM_VERSION}
20205 //[END NormalizeUnixText]
20207 //[function StrComp]
20208 function StrComp(const Str1, Str2: PChar): Integer; assembler;
20210 {$IFDEF F_P}
20211 MOV EAX, [Str1]
20212 MOV EDX, [Str2]
20213 {$ENDIF F_P}
20214 PUSH EDI
20215 PUSH ESI
20216 MOV EDI,EDX
20217 XCHG ESI,EAX
20218 OR ECX, -1
20219 XOR EAX,EAX
20220 REPNE SCASB
20221 NOT ECX
20222 MOV EDI,EDX
20223 XOR EDX,EDX
20224 REPE CMPSB
20225 MOV AL,[ESI-1]
20226 MOV DL,[EDI-1]
20227 SUB EAX,EDX
20228 POP ESI
20229 POP EDI
20230 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20232 function StrComp_NoCase(const Str1, Str2: PChar): Integer;
20234 {$IFDEF F_P}
20235 MOV EAX, [Str1]
20236 MOV EDX, [Str2]
20237 {$ENDIF F_P}
20238 PUSH EDI
20239 PUSH ESI
20240 MOV EDI,EDX
20241 XCHG ESI,EAX
20242 OR ECX, -1
20243 XOR EAX,EAX
20244 REPNE SCASB
20246 NOT ECX
20247 MOV EDI,EDX
20248 @@0:
20249 XOR EDX,EDX
20250 REPE CMPSB
20251 MOV AL,[ESI-1]
20252 MOV AH, AL
20253 SUB AH, 'a'
20254 CMP AH, 25
20255 JA @@1
20256 SUB AL, $20
20257 @@1:
20258 MOV DL,[EDI-1]
20259 MOV AH, DL
20260 SUB AH, 'a'
20261 CMP AH, 25
20262 JA @@2
20263 SUB DL, $20
20264 @@2:
20265 MOV AH, 0
20266 SUB EAX,EDX
20267 JNZ @@exit
20268 CMP DL, 0
20269 JNZ @@0
20271 @@exit:
20272 POP ESI
20273 POP EDI
20274 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20276 //[function StrLComp_NoCase]
20277 function StrLComp_NoCase(const Str1, Str2: PChar; MaxLen: Cardinal): Integer;
20279 {$IFDEF F_P}
20280 MOV EAX, [Str1]
20281 MOV EDX, [Str2]
20282 MOV ECX, [MaxLen]
20283 {$ENDIF F_P}
20284 PUSH EDI
20285 PUSH ESI
20286 PUSH EBX
20287 MOV EDI,EDX
20288 MOV ESI,EAX
20289 MOV EBX,ECX
20290 XOR EAX,EAX
20291 OR ECX,ECX
20292 JE @@exit
20293 REPNE SCASB
20294 SUB EBX,ECX
20295 MOV ECX,EBX
20296 MOV EDI,EDX
20297 @@0:
20298 XOR EDX,EDX
20299 REPE CMPSB
20300 MOV AL,[ESI-1]
20301 MOV AH, AL
20302 SUB AH, 'a'
20303 CMP AH, 25
20304 JA @@1
20305 SUB AL, $20
20306 @@1:
20307 MOV DL,[EDI-1]
20308 MOV AH, DL
20309 SUB AH, 'a'
20310 CMP AH, 25
20311 JA @@2
20312 SUB DL, $20
20313 @@2:
20314 MOV AH, 0
20315 SUB EAX,EDX
20316 JECXZ @@exit
20317 JZ @@0
20319 @@exit:
20320 POP EBX
20321 POP ESI
20322 POP EDI
20323 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20325 //[function StrLComp]
20326 function StrLComp(const Str1, Str2: PChar; MaxLen: Cardinal): Integer; assembler;
20328 {$IFDEF F_P}
20329 MOV EAX, [Str1]
20330 MOV EDX, [Str2]
20331 MOV ECX, [MaxLen]
20332 {$ENDIF F_P}
20333 PUSH EDI
20334 PUSH ESI
20335 PUSH EBX
20336 MOV EDI,EDX
20337 MOV ESI,EAX
20338 MOV EBX,ECX
20339 XOR EAX,EAX
20340 OR ECX,ECX
20341 JE @@1
20342 REPNE SCASB
20343 SUB EBX,ECX
20344 MOV ECX,EBX
20345 MOV EDI,EDX
20346 XOR EDX,EDX
20347 REPE CMPSB
20348 MOV AL,[ESI-1]
20349 MOV DL,[EDI-1]
20350 SUB EAX,EDX
20351 @@1: POP EBX
20352 POP ESI
20353 POP EDI
20354 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20356 //[function StrLen]
20357 function StrLen(const Str: PChar): Cardinal; assembler;
20359 {$IFDEF F_P}
20360 MOV EAX, [Str]
20361 {$ENDIF F_P}
20362 XCHG EAX, EDI
20363 XCHG EDX, EAX
20364 OR ECX, -1
20365 XOR EAX, EAX
20366 CMP EAX, EDI
20367 JE @@exit0
20368 REPNE SCASB
20369 DEC EAX
20370 DEC EAX
20371 SUB EAX,ECX
20372 @@exit0:
20373 MOV EDI,EDX
20374 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20376 //[FUNCTION __DelimiterLast]
20377 {$IFDEF ASM_VERSION}
20378 function __DelimiterLast( Str: PChar; Delimiters: PChar ): PChar;
20380 PUSH ESI
20382 CALL EAX2PChar
20384 MOV ESI, EDX
20385 MOV EDX, EAX
20387 @@tolast:
20388 CMP byte ptr [EAX], 0
20389 JZ @@next1
20390 INC EAX
20391 JMP @@tolast
20393 @@next1:
20394 PUSH EAX
20396 @@next:
20397 LODSB
20398 TEST AL, AL
20399 JZ @@exit
20401 PUSH EDX
20402 XCHG EDX, EAX
20403 CALL StrRScan
20404 POP EDX
20406 TEST EAX, EAX
20407 JZ @@next
20409 POP ECX
20410 CMP byte ptr [ECX], 0
20411 JZ @@next1
20413 CMP EAX, ECX
20414 JG @@next1
20416 PUSH ECX
20417 JLE @@next
20419 @@exit: POP EAX
20420 POP ESI
20421 end;
20422 {$ELSE ASM_VERSION} //Pascal
20423 function __DelimiterLast( Str: PChar; Delimiters: PChar ): PChar;
20425 P, F : PChar;
20426 begin
20427 P := Str;
20428 Result := P + StrLen( Str );
20429 while Delimiters^ <> #0 do
20430 begin
20431 F := StrRScan( P, Delimiters^ );
20432 if F <> nil then
20433 if (Result^ = #0) or (Integer(F) > Integer(Result)) then
20434 Result := F;
20435 Inc( Delimiters );
20436 end;
20437 end;
20438 {$ENDIF ASM_VERSION}
20439 //[END __DelimiterLast]
20441 //[function SkipSpaces]
20442 function SkipSpaces( P: PChar ): PChar;
20443 begin
20444 while True do
20445 begin
20446 while (P[0] <> #0) and (P[0] <= ' ') do Inc(P);
20447 if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break;
20448 end;
20449 Result := P;
20450 end;
20452 //[function SkipParam]
20453 function SkipParam(P: PChar): PChar;
20454 begin
20455 P := SkipSpaces( P );
20456 while P[0] > ' ' do
20457 if P[0] = '"' then
20458 begin
20459 Inc(P);
20460 while (P[0] <> #0) and (P[0] <> '"') do
20461 Inc(P);
20462 if P[0] <> #0 then Inc(P);
20464 else
20465 Inc(P);
20466 Result := P;
20467 end;
20469 //[FUNCTION ParamStr]
20470 function ParamStr( Idx: Integer ): String;
20472 P, P1: PChar;
20473 Buffer: array[ 0..260 ] of Char;
20474 begin
20475 if Idx = 0 then
20476 SetString( Result, Buffer, GetModuleFileName( 0, Buffer, Sizeof( Buffer ) ) )
20477 else
20478 begin
20479 P := GetCommandLine;
20480 repeat
20481 P := SkipSpaces( P );
20482 P1 := P;
20483 P := SkipParam(P);
20484 if Idx = 0 then Break;
20485 Dec(Idx);
20486 until (Idx < 0) or (P = P1);
20487 Result := Copy( P1, 1, P - P1 );
20488 if Length( Result ) >= 2 then
20489 if (Result[ 1 ] = '"') and (Result[ Length( Result ) ] = '"') then
20490 Result := Copy( Result, 2, Length( Result ) - 2 );
20491 end;
20492 end;
20493 //[END ParamStr]
20495 //[FUNCTION ParamCount]
20496 function ParamCount: Integer;
20498 S: string;
20499 begin
20500 Result := 0;
20501 while True do
20502 begin
20503 S := ParamStr(Result + 1);
20504 if S = '' then Break;
20505 Inc(Result);
20506 end;
20507 end;
20508 //[END ParamCount]
20510 //[FUNCTION DelimiterLast]
20511 {$IFDEF ASM_VERSION}
20512 function DelimiterLast( const Str, Delimiters: String ): Integer;
20514 CALL EAX2PChar
20515 CALL EDX2PChar
20516 PUSH EAX
20517 CALL __DelimiterLast
20518 POP EDX
20519 SUB EAX, EDX
20520 INC EAX
20521 end;
20522 {$ELSE ASM_VERSION} //Pascal
20523 function DelimiterLast( const Str, Delimiters: String ): Integer;
20524 var PStr: PChar;
20525 begin
20526 PStr := PChar( Str );
20527 Result := Integer( __DelimiterLast( PStr, PChar( Delimiters ) ) )
20528 - Integer( PStr )
20529 + 1; // {Viman}
20530 end;
20531 {$ENDIF ASM_VERSION}
20532 //[END DelimiterLast]
20534 // Thanks to Marco Bobba - Marisa Bo for this code
20535 //[function StrIsStartingFrom]
20536 function StrIsStartingFrom( Str, Pattern: PChar ): Boolean;
20538 {$IFDEF F_P}
20539 MOV EAX, [Str]
20540 MOV EDX, [Pattern]
20541 {$ENDIF F_P}
20542 XOR ECX, ECX
20543 @@1:
20544 MOV CL, [EDX] // pattern[ i ]
20545 INC EDX
20546 MOV CH, [EAX] // str[ i ]
20547 INC EAX
20548 JECXZ @@2 // str = pattern; CL = #0, CH = #0
20549 CMP CL, CH
20550 JE @@1
20551 @@2:
20552 TEST CL, CL
20553 SETZ AL
20554 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20556 function StrIsStartingFromNoCase( Str, Pattern: PChar ): Boolean;
20558 {$IFDEF F_P}
20559 MOV EAX, [Str]
20560 MOV EDX, [Pattern]
20561 {$ENDIF F_P}
20562 XOR ECX, ECX
20563 @@1:
20564 MOV CL, [EDX] // pattern[ i ]
20565 INC EDX
20566 MOV CH, [EAX] // str[ i ]
20567 INC EAX
20568 JECXZ @@2 // str = pattern; CL = #0, CH = #0
20569 CMP CL, 'a'
20570 JB @@cl_ok
20571 CMP CL, 'z'
20572 JA @@cl_ok
20573 SUB CL, 32
20574 @@cl_ok:
20575 CMP CH, 'a'
20576 JB @@ch_ok
20577 CMP CH, 'z'
20578 JA @@ch_ok
20579 SUB CH, 32
20580 @@ch_ok:
20581 CMP CL, CH
20582 JE @@1
20583 @@2:
20584 TEST CL, CL
20585 SETZ AL
20586 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20588 {$IFNDEF _FPC}
20589 //[FUNCTION Format]
20590 {$IFDEF ASM_VERSION}
20591 function Format( const fmt: string; params: array of const ): String;
20593 PUSH ESI
20594 PUSH EDI
20595 PUSH EBX
20596 MOV EBX, ESP
20597 ADD ESP, -2048
20598 MOV ESI, ESP
20600 INC ECX
20601 JZ @@2
20602 @@1:
20603 MOV EDI, [EDX + ECX*8 - 8]
20604 PUSH EDI
20605 LOOP @@1
20606 @@2:
20607 PUSH ESP
20608 PUSH EAX
20609 PUSH ESI
20611 CALL wvsprintf
20613 MOV EDX, ESI
20614 MOV EAX, @Result
20615 CALL System.@LStrFromPChar
20617 MOV ESP, EBX
20618 POP EBX
20619 POP EDI
20620 POP ESI
20621 end;
20622 {$ELSE ASM_VERSION} //Pascal
20623 function Format( const fmt: string; params: array of const ): String;
20624 var Buffer: array[ 0..2047 ] of Char;
20625 ElsArray, El: PDWORD;
20626 I : Integer;
20627 P : PDWORD;
20628 begin
20629 ElsArray := nil;
20630 if High( params ) >= 0 then
20631 GetMem( ElsArray, (High( params ) + 1) * sizeof( Pointer ) );
20632 El := ElsArray;
20633 for I := 0 to High( params ) do
20634 begin
20635 P := @params[ I ];
20636 P := Pointer( P^ );
20637 El^ := DWORD( P );
20638 Inc( El );
20639 end;
20640 wvsprintf( @Buffer[0], PChar( fmt ), PChar( ElsArray ) );
20641 Result := Buffer;
20642 if ElsArray <> nil then
20643 FreeMem( ElsArray );
20644 end;
20645 {$ENDIF ASM_VERSION}
20646 //[END Format]
20648 //[function LStrFromPWCharLen]
20649 function LStrFromPWCharLen(Source: PWideChar; Length: Integer): String;
20651 DestLen: Integer;
20652 Buffer: array[0..2047] of Char;
20653 begin
20654 if Length <= 0 then
20655 begin
20656 //_LStrClr(Result);
20657 Result := '';
20658 Exit;
20659 end;
20660 if Length < SizeOf(Buffer) div 2 then
20661 begin
20662 DestLen := WideCharToMultiByte(0, 0, Source, Length,
20663 Buffer, SizeOf(Buffer), nil, nil);
20664 if DestLen > 0 then
20665 begin
20666 Result := Buffer;
20667 //System.LStrFromPCharLen(Result, Buffer, DestLen);
20668 Exit;
20669 end;
20670 end;
20671 DestLen := WideCharToMultiByte(0, 0, Source, Length, nil, 0, nil, nil);
20672 // _LStrFromPCharLen(Dest, nil, DestLen);
20673 SetLength( Result, DestLen );
20674 WideCharToMultiByte(0, 0, Source, Length, Pointer(Result), DestLen, nil, nil);
20675 end;
20677 //[function LStrFromPWChar]
20678 function LStrFromPWChar(Source: PWideChar): String;
20679 {* from Delphi5 - because D2 does not contain it. }
20681 PUSH EDX
20682 XOR EDX,EDX
20683 TEST EAX,EAX
20684 JE @@5
20685 PUSH EAX
20686 @@0: CMP DX,[EAX+0]
20687 JE @@4
20688 CMP DX,[EAX+2]
20689 JE @@3
20690 CMP DX,[EAX+4]
20691 JE @@2
20692 CMP DX,[EAX+6]
20693 JE @@1
20694 ADD EAX,8
20695 JMP @@0
20696 @@1: ADD EAX,2
20697 @@2: ADD EAX,2
20698 @@3: ADD EAX,2
20699 @@4: XCHG EDX,EAX
20700 POP EAX
20701 SUB EDX,EAX
20702 SHR EDX,1
20703 @@5: POP ECX
20704 JMP LStrFromPWCharLen
20705 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
20706 {$ENDIF _FPC}
20709 /////////////////////////////////////////////////////////////////////////
20712 // F I L E S
20715 /////////////////////////////////////////////////////////////////////////
20716 //[FILES]
20718 This part of the unit modified by Tim Slusher and Vladimir Kladov.
20721 {* Set of utility methods to work with files
20722 and reqistry.
20723 When programming KOL, which is Windows API-oriented, You should
20724 avoid alien (for Windows) embedded Pascal files handling, and
20725 use API-calls which implemented very well. This set of functions
20726 is intended to make this easier.
20727 Also TDirList object implementation present here and some registry
20728 access functions, which allow to make code more elegant.
20731 {$UNDEF ASM_LOCAL}
20732 {$IFDEF ASM_VERSION}
20733 {$DEFINE ASM_LOCAL}
20734 {$ENDIF ASM_VERSION}
20736 //[FUNCTION FileCreate]
20737 {$IFDEF ASM_VERSION}
20738 function FileCreate( const FileName: string; OpenFlags: DWord): THandle;
20740 XOR ECX, ECX
20741 PUSH ECX
20742 MOV ECX, EDX
20743 SHR ECX, 16
20744 AND CX, $1FFF
20745 JNZ @@1
20746 MOV CL, FILE_ATTRIBUTE_NORMAL
20747 @@1: PUSH ECX
20748 MOV CL, DH
20749 PUSH ECX // CreationMode
20750 PUSH 0
20751 MOV CL, DL
20752 PUSH ECX // ShareMode
20753 MOV DX, 0
20754 PUSH EDX // AccessMode
20755 //CALL System.@LStrToPChar // FileName must not be ''
20756 PUSH EAX
20757 CALL CreateFile
20758 end;
20759 {$ELSE ASM_VERSION} //Pascal
20760 function FileCreate(const FileName: string; OpenFlags: DWord): THandle;
20761 var Attr: DWORD;
20762 begin
20763 Attr := (OpenFlags shr 16) and $1FFF;
20764 if Attr = 0 then Attr := FILE_ATTRIBUTE_NORMAL;
20765 Result := CreateFile( PChar(FileName), OpenFlags and $F0000000,
20766 OpenFlags and $F, nil, (OpenFlags shr 8) and $F,
20767 Attr, 0 );
20768 end;
20769 {$ENDIF ASM_VERSION}
20770 //[END FileCreate]
20772 //[FUNCTION FileClose]
20773 {$IFDEF ASM_VERSION}
20774 function FileClose( Handle: THandle): Boolean;
20776 PUSH EAX
20777 CALL CloseHandle
20778 TEST EAX, EAX
20779 SETNZ AL
20780 end;
20781 {$ELSE ASM_VERSION} //Pascal
20782 function FileClose(Handle: THandle): boolean;
20783 begin
20784 Result := CloseHandle(Handle);
20785 end;
20786 {$ENDIF ASM_VERSION}
20787 //[END FileClose]
20789 //[FUNCTION FileExists]
20790 {$IFDEF ASM_VERSION}
20791 function FileExists( const FileName : String ) : Boolean;
20792 const size_TWin32FindData = sizeof( TWin32FindData );
20794 CALL EAX2PChar
20795 PUSH EAX
20796 CALL GetFileAttributes
20797 INC EAX
20798 JZ @@exit
20799 DEC EAX
20800 {$IFDEF PARANOIA}
20801 DB $24, FILE_ATTRIBUTE_DIRECTORY
20802 {$ELSE}
20803 AND AL, FILE_ATTRIBUTE_DIRECTORY
20804 {$ENDIF}
20805 SETZ AL
20806 @@exit:
20807 end;
20808 {$ELSE ASM_VERSION} //Pascal
20809 function FileExists( const FileName : String ) : Boolean;
20811 Code: Integer;
20812 begin
20813 Code := GetFileAttributes(PChar(FileName));
20814 Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code = 0);
20815 end;
20816 {$ENDIF ASM_VERSION}
20817 //[END FileExists]
20819 //[FUNCTION FileSeek]
20820 {$IFDEF ASM_VERSION}
20821 function FileSeek( Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
20823 MOVZX ECX, CL
20824 PUSH ECX
20825 PUSH 0
20826 PUSH EDX
20827 PUSH EAX
20828 CALL SetFilePointer
20829 end;
20830 {$ELSE ASM_VERSION} //Pascal
20831 function FileSeek(Handle: THandle; MoveTo: integer; MoveMethod: TMoveMethod): DWord;
20832 begin
20833 Result := SetFilePointer(Handle, MoveTo, nil, Ord( MoveMethod ) );
20834 end;
20835 {$ENDIF ASM_VERSION}
20836 //[END FileSeek]
20838 //[FUNCTION FileRead]
20839 {$IFDEF ASM_VERSION}
20840 function FileRead( Handle: THandle; var Buffer; Count: DWord): DWord;
20842 PUSH EBP
20843 PUSH 0
20844 MOV EBP, ESP
20845 PUSH 0
20846 PUSH EBP
20847 PUSH ECX
20848 PUSH EDX
20849 PUSH EAX
20850 CALL ReadFile
20851 TEST EAX, EAX
20852 POP EAX
20853 JNZ @@exit
20854 XOR EAX, EAX
20855 @@exit:
20856 POP EBP
20857 end;
20858 {$ELSE ASM_VERSION} //Pascal
20859 function FileRead(Handle: THandle; var Buffer; Count: DWord): DWord;
20860 begin
20861 if not ReadFile(Handle, Buffer, Count, Result, nil) then
20862 Result := 0;
20863 end;
20864 {$ENDIF ASM_VERSION}
20865 //[END FileRead]
20867 //[FUNCTION File2Str]
20868 {$IFDEF ASM_VERSION}
20869 function File2Str( Handle: THandle): String;
20871 PUSH EDX
20872 TEST EAX, EAX
20873 JZ @@exit // return ''
20875 PUSH EBX
20876 MOV EBX, EAX // EBX = Handle
20877 XOR EDX, EDX
20878 XOR ECX, ECX
20879 INC ECX
20880 CALL FileSeek
20881 PUSH EAX // Pos
20882 PUSH 0
20883 PUSH EBX
20884 CALL GetFileSize
20885 POP EDX
20886 SUB EAX, EDX // EAX = Size - Pos
20887 JZ @@exitEBX
20889 PUSH EAX
20890 CALL System.@GetMem
20891 XCHG EAX, EBX
20892 MOV EDX, EBX
20893 POP ECX
20894 PUSH ECX
20895 CALL FileRead
20896 POP ECX
20897 MOV EDX, EBX
20898 POP EBX
20899 POP EAX
20900 PUSH EDX
20901 {$IFDEF _D2}
20902 CALL _LStrFromPCharLen
20903 {$ELSE}
20904 CALL System.@LStrFromPCharLen
20905 {$ENDIF}
20906 JMP @@freebuf
20908 @@exitEBX:
20909 POP EBX
20910 @@exit:
20911 XCHG EDX, EAX
20912 POP EAX // @Result
20913 PUSH EDX
20914 CALL System.@LStrFromPChar
20915 @@freebuf:
20916 POP EAX
20917 TEST EAX, EAX
20918 JZ @@fin
20919 CALL System.@FreeMem
20920 @@fin:
20921 end;
20922 {$ELSE ASM_VERSION} //Pascal
20923 function File2Str(Handle: THandle): String;
20924 var Pos, Size: DWORD;
20925 begin
20926 Result := '';
20927 if Handle = 0 then Exit;
20928 Pos := FileSeek( Handle, 0, spCurrent );
20929 Size := GetFileSize( Handle, nil );
20930 SetString( Result, nil, Size - Pos + 1 );
20931 FileRead( Handle, Result[ 1 ], Size - Pos );
20932 Result[ Size - Pos + 1 ] := #0;
20933 end;
20934 {$ENDIF ASM_VERSION}
20935 //[END File2Str]
20937 //[FUNCTION FileWrite]
20938 {$IFDEF ASM_VERSION}
20939 function FileWrite( Handle: THandle; const Buffer; Count: DWord): DWord;
20941 PUSH EBP
20942 PUSH EBP
20943 MOV EBP, ESP
20944 PUSH 0
20945 PUSH EBP
20946 PUSH ECX
20947 PUSH EDX
20948 PUSH EAX
20949 CALL WriteFile
20950 TEST EAX, EAX
20951 POP EAX
20952 JNZ @@exit
20953 XOR EAX, EAX
20954 @@exit:
20955 POP EBP
20956 end;
20957 {$ELSE ASM_VERSION} //Pascal
20958 function FileWrite(Handle: THandle; const Buffer; Count: DWord): DWord;
20959 begin
20960 if not WriteFile(Handle, Buffer, Count, Result, nil) then
20961 Result := 0;
20962 end;
20963 {$ENDIF ASM_VERSION}
20964 //[END FileWrite]
20966 //[FUNCTION FileEOF]
20967 {$IFDEF ASM_VERSION}
20968 function FileEOF( Handle: THandle ) : Boolean;
20970 PUSH EAX
20972 PUSH 0
20973 PUSH EAX
20974 CALL GetFileSize
20976 XCHG EAX, [ESP]
20978 MOV CL, spCurrent
20979 XOR EDX, EDX
20980 CALL FileSeek
20982 POP EDX
20983 CMP EAX, EDX
20984 SETGE AL
20985 end;
20986 {$ELSE ASM_VERSION} //Pascal
20987 function FileEOF( Handle: THandle ) : Boolean;
20988 var Siz, Pos : DWord;
20989 begin
20990 Siz := GetFileSize( Handle, nil );
20991 Pos := FileSeek( Handle, 0, spCurrent );
20992 Result := Pos >= Siz;
20993 end;
20994 {$ENDIF ASM_VERSION}
20995 //[END FileEOF]
20997 //[FUNCTION FileFullPath]
20998 {$IFDEF ASM_noVERSION}
20999 function FileFullPath( const FileName: String ) : String;
21000 const
21001 BkSlash: String = '\';
21002 szTShFileInfo = sizeof( TShFileInfo );
21004 PUSH EBX
21005 PUSH ESI
21006 MOV EBX, EDX
21007 PUSH EAX
21009 XCHG EAX, EDX
21010 CALL System.@LStrClr
21012 POP EDX
21013 PUSH 0
21014 MOV EAX, ESP
21015 CALL System.@LStrAsg
21016 MOV ESI, ESP
21018 @@loo: CMP dword ptr [ESI], 0
21019 JZ @@fin
21021 MOV EAX, ESI
21022 MOV EDX, [BkSlash]
21023 PUSH 0
21024 MOV ECX, ESP
21025 CALL Parse
21027 CMP dword ptr [EBX], 0
21028 JE @@1
21029 MOV EAX, EBX
21030 MOV EDX, [BkSlash]
21031 CALL System.@LStrCat
21032 JMP @@2
21033 @@1:
21034 POP EAX
21035 PUSH EAX
21036 CALL System.@LStrLen
21037 CMP EAX, 2
21038 JNE @@2
21039 POP EAX
21040 PUSH EAX
21041 CMP byte ptr [EAX+1], ':'
21042 JNE @@2
21044 MOV EAX, EBX
21045 POP EDX
21046 PUSH EDX
21047 CALL System.@LStrAsg
21048 JMP @@3
21049 @@2:
21050 PUSH 0
21051 MOV EAX, ESP
21052 MOV EDX, [EBX]
21053 CALL System.@LStrAsg
21054 MOV EAX, ESP
21055 MOV EDX, [ESP+4]
21056 CALL System.@LStrCat
21057 POP EAX
21058 PUSH EAX
21059 SUB ESP, szTShFileInfo
21060 MOV EDX, ESP
21061 PUSH SHGFI_DISPLAYNAME
21062 PUSH szTShFileInfo
21063 PUSH EDX
21064 PUSH 0
21065 PUSH EAX
21066 CALL ShGetFileInfo
21067 LEA EDX, [ESP].TShFileInfo.szDisplayName
21068 CMP byte ptr [EDX], 0
21069 JE @@clr_stk
21070 LEA EAX, [ESP+szTShFileInfo+4]
21071 CALL System.@LStrFromPChar
21072 @@clr_stk:
21073 ADD ESP, szTShFileInfo
21074 CALL RemoveStr
21075 POP EDX
21076 PUSH EDX
21077 MOV EAX, EBX
21078 CALL System.@LStrCat
21080 @@3: CALL RemoveStr
21081 JMP @@loo
21083 @@fin: CALL RemoveStr
21084 POP ESI
21085 POP EBX
21086 end;
21087 {$ELSE ASM_VERSION} //Pascal
21088 function FileFullPath( const FileName: String ) : String;
21089 var SFI: TShFileInfo;
21090 Src, S: String;
21091 begin
21092 Result := '';
21093 Src := FileName;
21094 while Src <> '' do
21095 begin
21096 S := Parse( Src, '\' );
21097 if Result <> '' then
21098 Result := Result + '\';
21099 if (Result = '') and (Length( S ) = 2) and (S[ 2 ] = ':') then
21100 Result := S
21101 else
21102 begin
21103 ShGetFileInfo( PChar( Result + S ), 0, SFI, Sizeof( SFI ),
21104 SHGFI_DISPLAYNAME );
21105 if SFI.szDisplayName[ 0 ] <> #0 then
21106 S := SFI.szDisplayName;
21107 Result := Result + S;
21108 end;
21109 end;
21110 if ExtractFileExt( Result ) = '' then
21111 // case when flag 'Hide extensions for registered file types' is set on
21112 // in the Explorer:
21113 Result := Result + ExtractFileExt( FileName );
21114 end;
21115 {$ENDIF ASM_VERSION}
21116 //[END FileFullPath]
21118 //[function FileShortPath]
21119 function FileShortPath( const FileName: String ): String;
21120 var Buf: array[ 0..MAX_PATH ] of Char;
21121 begin
21122 GetShortPathName( PChar( FileName ), Buf, Sizeof( Buf ) );
21123 Result := Buf;
21124 end;
21126 //[function FileIconSystemIdx]
21127 function FileIconSystemIdx( const Path: String ): Integer;
21128 var SFI: TShFileInfo;
21129 begin
21130 SFI.iIcon := 0; // Bartov
21131 ShGetFileInfo( PChar( Path ), 0, SFI, sizeof( SFI ),
21132 //-- Babenko Alexey: -----------------//
21133 // SHGFI_ICON or //
21134 //----------------------------------//
21135 SHGFI_SMALLICON or SHGFI_SYSICONINDEX );
21136 Result := SFI.iIcon;
21137 end;
21139 //[function FileIconSysIdxOffline]
21140 function FileIconSysIdxOffline( const Path: String ): Integer;
21141 var SFI: TShFileInfo;
21142 begin
21143 SFI.iIcon := 0; // Bartov
21144 ShGetFileInfo( PChar( Path ), FILE_ATTRIBUTE_NORMAL, SFI, sizeof( SFI ),
21145 //-- Babenko Alexey: -----------------//
21146 //SHGFI_ATTRIBUTES or SHGFI_ICON or //
21147 //----------------------------------//
21148 SHGFI_SMALLICON or SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES );
21149 Result := SFI.iIcon;
21150 end;
21152 //[procedure LogFileOutput]
21153 procedure LogFileOutput( const filepath, str: String );
21154 var F: HFile;
21155 begin
21156 F := FileCreate( filepath, ofOpenWrite or ofOpenAlways );
21157 if F = INVALID_HANDLE_VALUE then Exit;
21158 FileSeek( F, 0, spEnd );
21159 FileWrite( F, {$IFNDEF _D2} String {$ENDIF}
21160 ( str + #13#10 )[ 1 ], Length( str ) + 2 );
21161 FileClose( F );
21162 end;
21164 //[function StrSaveToFile]
21165 function StrSaveToFile( const Filename, Str: String ): Boolean;
21166 begin
21167 Result := Mem2File( PChar( Filename ), PChar( Str ), Length( Str ) )
21168 = Length( Str );
21169 end;
21171 //[function StrLoadFromFile]
21172 function StrLoadFromFile( const Filename: String ): String;
21173 var F: HFile;
21174 begin
21175 if StrEq( Filename, 'CON' ) then
21176 Result := File2Str(GetStdHandle(STD_INPUT_HANDLE))
21177 else
21178 begin
21179 Result := '';
21180 F := FileCreate( Filename, ofOpenRead or ofOpenExisting or ofShareDenyWrite );
21181 if F = INVALID_HANDLE_VALUE then Exit;
21182 Result := File2Str( F );
21183 FileClose( F ); {Dark Knight}
21184 end;
21185 end;
21187 //[function Mem2File]
21188 function Mem2File( Filename: PChar; Mem: Pointer; Len: Integer ): Integer;
21189 var F: HFile;
21190 begin
21191 Result := 0;
21192 F := FileCreate( Filename, ofOpenWrite or ofCreateAlways );
21193 if F = INVALID_HANDLE_VALUE then Exit;
21194 Result := FileWrite( F, Mem^, Len );
21195 FileClose( F );
21196 end;
21198 //[function File2Mem]
21199 function File2Mem( Filename: PChar; Mem: Pointer; MaxLen: Integer ): Integer;
21200 var F: HFile;
21201 begin
21202 Result := 0;
21203 F := FileCreate( Filename, ofOpenRead or ofOpenExisting or ofShareDenyWrite );
21204 if F = INVALID_HANDLE_VALUE then Exit;
21205 Result := FileRead( F, Mem^, MaxLen );
21206 FileClose( F );
21207 end;
21209 //[FUNCTION DirectoryExists]
21210 {$IFDEF ASM_VERSION}
21211 function DirectoryExists( const Name: string): Boolean;
21213 //CALL System.@LStrToPChar // Name must not be ''
21214 PUSH EAX
21215 CALL GetFileAttributes
21216 INC EAX
21217 JZ @@exit
21218 DEC EAX
21219 {$IFDEF PARANOIA}
21220 DB $24, FILE_ATTRIBUTE_DIRECTORY
21221 {$ELSE}
21222 AND AL, FILE_ATTRIBUTE_DIRECTORY
21223 {$ENDIF}
21224 SETNZ AL
21225 @@exit:
21226 end;
21227 {$ELSE ASM_VERSION} //Pascal
21228 function DirectoryExists(const Name: string): Boolean;
21230 Code: Integer;
21231 begin
21232 Code := GetFileAttributes(PChar(Name));
21233 Result := (Code <> -1) and (FILE_ATTRIBUTE_DIRECTORY and Code <> 0);
21234 end;
21235 {$ENDIF ASM_VERSION}
21236 //[END DirectoryExists]
21238 //[function CheckDirectoryContent]
21239 function CheckDirectoryContent( const Name: String; SubDirsOnly: Boolean; const Mask: String ): Boolean;
21240 var FD: TWin32FindData;
21241 FH: THandle;
21242 begin
21243 if not DirectoryExists( Name ) then
21244 Result := TRUE
21245 else
21246 begin
21247 FH := Windows.FindFirstFile( PChar( IncludeTrailingPathDelimiter( Name )
21248 + Mask ), FD );
21249 if FH = INVALID_HANDLE_VALUE then
21250 Result := TRUE
21251 else
21252 begin
21253 Result := TRUE;
21254 repeat
21255 if not StrIn( FD.cFileName, ['.','..'] ) then
21256 begin
21257 if SubDirsOnly and LongBool(FD.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)
21258 or not SubDirsOnly then
21259 begin
21260 Result := FALSE;
21261 break;
21262 end;
21263 end;
21264 until not Windows.FindNextFile( FH, FD );
21265 Windows.FindClose( FH );
21266 end;
21267 end;
21268 end;
21270 //[function DirectoryEmpty]
21271 function DirectoryEmpty(const Name: String): Boolean;
21272 begin
21273 Result := CheckDirectoryContent( Name, FALSE, '*.*' );
21274 end;
21277 //[function DirectorySize]
21278 function DirectorySize( const Path: String ): I64;
21279 var DirList: PDirList;
21280 I: Integer;
21281 begin
21282 Result := MakeInt64( 0, 0 );
21283 DirList := NewDirList( Path, '*.*', 0 );
21284 for I := 0 to DirList.Count-1 do
21285 begin
21286 if LongBool( DirList.Items[ I ].dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY ) then
21287 Result := Add64( Result, DirectorySize( DirList.Path + DirList.Names[ I ] ) )
21288 else
21289 Result := Add64( Result, MakeInt64( DirList.Items[ I ].nFileSizeLow,
21290 DirList.Items[ I ].nFileSizeHigh ) );
21291 end;
21292 DirList.Free;
21293 end;
21296 //[function DirectoryHasSubdirs]
21297 function DirectoryHasSubdirs( const Path: String ): Boolean;
21298 begin
21299 Result := not CheckDirectoryContent( Path, TRUE, '*.*' );
21300 end;
21302 //[function GetFileList]
21303 function GetFileList(const dir: string): PStrList;
21305 Srch: TWin32FindData;
21306 flag: Integer;
21307 succ: boolean;
21308 begin
21309 result := nil;
21310 flag := FindFirstFile(PChar(dir), Srch);
21311 //succ := flag <> 0; //---------------------------------------
21312 succ := flag <> Integer(INVALID_HANDLE_VALUE); // M.V.Chirikov
21313 while succ do begin
21314 if (not (Srch.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0))then begin
21315 if Result = nil then begin
21316 Result := NewStrList;
21317 end;
21318 Result.Add(Srch.cFileName);
21319 end;
21320 succ := FindNextFile(Flag, Srch);
21321 end;
21322 FindClose(Flag);
21323 end;
21325 //[function ExcludeTrailingChar]
21326 function ExcludeTrailingChar( const S: String; C: Char ): String;
21327 begin
21328 Result := S;
21329 if Result <> '' then
21330 if Result[ Length( Result ) ] = C then
21331 Delete( Result, Length( Result ), 1 );
21332 end;
21334 //[function IncludeTrailingChar]
21335 function IncludeTrailingChar( const S: String; C: Char ): String;
21336 begin
21337 Result := S;
21338 if (Result = '') or (Result[ Length( Result ) ] <> C) then
21339 Result := Result + C;
21340 end;
21342 //---------------------------------------------------------
21343 // Following functions/procedures are created by Edward Aretino:
21344 // IncludeTrailingPathDelimiter, ExcludeTrailingPathDelimiter,
21345 // ForceDirectories, CreateDir, ChangeFileExt
21346 //---------------------------------------------------------
21347 //[function IncludeTrailingPathDelimiter]
21348 function IncludeTrailingPathDelimiter(const S: string): string;
21349 begin
21350 {if CopyTail(S, 1) <> '\' then
21351 Result := S + '\'
21352 else
21353 Result := S;}
21354 Result := IncludeTrailingChar( S, '\' );
21355 end;
21357 //[function ExcludeTrailingPathDelimiter]
21358 function ExcludeTrailingPathDelimiter(const S: string): string;
21359 begin
21360 {Result := S;
21361 if Length(Result) = 0 then Exit;
21363 if (CopyTail(Result, 1) = '\') then
21364 DeleteTail(Result, 1);}
21365 Result := ExcludeTrailingChar( S, '\' );
21366 end;
21368 //[function ForceDirectories]
21369 function ForceDirectories(Dir: string): Boolean;
21370 begin
21371 Result := Length(Dir) > 0; {Centronix}
21372 If not Result then Exit;
21373 Dir := ExcludeTrailingPathDelimiter(Dir);
21374 If (Length(Dir) < 3) or DirectoryExists(Dir) or
21375 (ExtractFilePath(Dir) = Dir) then Exit; // avoid 'xyz:\' problem.
21376 Result := ForceDirectories(ExtractFilePath(Dir)) and CreateDir(Dir);
21377 end;
21379 //[function CreateDir]
21380 function CreateDir(const Dir: string): Boolean;
21381 begin
21382 Result := Windows.CreateDirectory(PChar(Dir), nil);
21383 end;
21385 //[function ChangeFileExt]
21386 function ChangeFileExt(FileName: String; const Extension: string): string;
21388 FileExt: String;
21389 begin
21390 FileExt := ExtractFileExt(FileName);
21391 DeleteTail(FileName, Length(FileExt));
21392 Result := FileName+ Extension;
21393 end;
21395 {$IFDEF ASM_VERSION}
21396 {$IFNDEF _D2}
21397 {$DEFINE ASM_LStrFromPCharLen}
21398 {$ENDIF}
21399 {$ENDIF ASM_VERSION}
21401 {$IFDEF ASM_LStrFromPCharLen}
21402 {$DEFINE ASM_DIRDelimiters}
21403 {$ENDIF}
21405 {$IFDEF ASM_VERSION}
21406 {$DEFINE ASM_DIRDelimiters}
21407 {$ENDIF ASM_VERSION}
21409 {$IFDEF ASM_DIRDelimiters}
21410 const
21411 DirDelimiters: PChar = ':\';
21412 {$ENDIF}
21414 //[FUNCTION ExtractFileName]
21415 {$IFDEF ASM_VERSION}
21416 function ExtractFileName( const Path : String ) : String;
21418 PUSH EDX
21419 PUSH EAX
21420 MOV EDX, [DirDelimiters]
21421 CALL __DelimiterLast
21422 POP EDX
21423 CMP byte ptr [EAX], 0
21424 JZ @@1
21425 XCHG EDX, EAX
21426 INC EDX
21427 @@1: POP EAX
21428 CALL System.@LStrFromPChar
21429 end;
21430 {$ELSE ASM_VERSION} //Pascal
21431 function ExtractFileName( const Path : String ) : String;
21432 var P: PChar;
21433 begin
21434 P := __DelimiterLast( PChar( Path ), ':\' );
21435 if P^ = #0 then
21436 Result := Path
21437 else
21438 Result := P + 1;
21439 end;
21440 {$ENDIF ASM_VERSION}
21441 //[END ExtractFileName]
21443 //[FUNCTION ExtractFilePath]
21444 {$IFDEF ASM_LStrFromPCharLen} // LStrFromPCharLen - there are no in D2
21445 function ExtractFilePath( const Path : String ) : String;
21447 PUSH EDX
21448 MOV EDX, [DirDelimiters]
21449 CALL EAX2PChar
21450 PUSH EAX
21451 CALL __DelimiterLast
21452 XCHG EDX, EAX
21453 XOR ECX, ECX
21454 POP EAX
21455 CMP byte ptr [EDX], CL
21456 JZ @@ret_0
21457 SUB EDX, EAX
21458 INC EDX
21459 XCHG EDX, EAX
21460 XCHG ECX, EAX
21461 @@ret_0:
21462 POP EAX
21463 CALL System.@LStrFromPCharLen
21464 end;
21465 {$ELSE} //Pascal
21466 function ExtractFilePath( const Path : String ) : String;
21467 //var I : Integer;
21468 var P, P0: PChar;
21469 begin
21470 P0 := PChar( Path );
21471 P := __DelimiterLast( P0, ':\' );
21472 if P^ = #0 then
21473 Result := ''
21474 else
21475 Result := Copy( Path, 1, P - P0 + 1 );
21476 end;
21477 {$ENDIF}
21479 //[function ExtractFileNameWOext]
21480 function ExtractFileNameWOext( const Path : String ) : String;
21481 begin
21482 Result := ExtractFileName( Path );
21483 Result := Copy( Result, 1, Length( Result ) - Length( ExtractFileExt( Result ) ) );
21484 end;
21486 {$IFDEF ASM_VERSION}
21487 const
21488 ExtDelimeters: PChar = '.';
21490 //[function ExtractFileExt]
21491 function ExtractFileExt( const Path : String ) : String;
21493 PUSH EDX
21494 MOV EDX, [ExtDelimeters]
21495 CALL EAX2PChar
21496 CALL __DelimiterLast
21497 @@1: XCHG EDX, EAX
21498 POP EAX
21499 CALL System.@LStrFromPChar
21500 end;
21501 {$ELSE ASM_VERSION} //Pascal
21502 function ExtractFileExt( const Path : String ) : String;
21503 var P: PChar;
21504 begin
21505 P := __DelimiterLast( PChar( Path ), '.' );
21506 Result := P;
21507 end;
21508 {$ENDIF ASM_VERSION}
21509 //[END ExtractFilePath]
21511 //[function ReplaceFileExt]
21512 function ReplaceFileExt( const Path, NewExt: String ): String;
21513 begin
21514 Result := ExtractFilePath( Path ) +
21515 ExtractFileNameWOext( ExtractFileName( Path ) ) +
21516 NewExt;
21517 end;
21519 //[function ExtractShortPathName]
21520 function ExtractShortPathName( const Path: String ): String;
21522 Buffer: array[0..MAX_PATH - 1] of Char;
21523 begin
21524 SetString(Result, Buffer,
21525 GetShortPathName(PChar(Path), Buffer, SizeOf(Buffer)));
21526 end;
21528 //[function FilePathShortened]
21529 function FilePathShortened( const Path: String; MaxLen: Integer ): String;
21530 begin
21531 Result := FilePathShortenPixels( Path, 0, MaxLen );
21532 end;
21534 //[function PixelsLength]
21535 function PixelsLength( DC: HDC; const Text: String ): Integer;
21536 var Sz: TSize;
21537 begin
21538 if DC = 0 then
21539 Result := Length( Text )
21540 else
21541 begin
21542 Windows.GetTextExtentPoint32( DC, PChar( Text ), Length( Text ), Sz );
21543 Result := Sz.cx;
21544 end;
21545 end;
21547 //[function FilePathShortenPixels]
21548 function FilePathShortenPixels( const Path: String; DC: HDC; MaxPixels: Integer ): String;
21549 var L0, L1: Integer;
21550 Prev: String;
21551 begin
21552 Result := Path;
21553 L0 := PixelsLength( DC, Result );
21554 while L0 > MaxPixels do
21555 begin
21556 Prev := Result;
21557 L1 := pos( '\...\', Result );
21558 if L1 <= 0 then
21559 Result := ExcludeTrailingPathDelimiter( ExtractFilePath( Result ) )
21560 else
21561 Result := Copy( Result, 1, L1 - 1 );
21562 if Result <> '' then
21563 Result := IncludeTrailingPathDelimiter( ExtractFilePath( Result ) ) + '...\' + ExtractFileName( Path );
21564 if (Result = '') or (Result = Prev) then
21565 begin
21566 L1 := Length( ExtractFilePath( Result ) );
21567 while (PixelsLength( DC, Result ) > MaxPixels) and (L1 > 1) do
21568 begin
21569 Dec( L1 );
21570 Result := Copy( Result, 1, L1 ) + '...\' + ExtractFileName( Result );
21571 end;
21572 if PixelsLength( DC, Result ) > MaxPixels then
21573 begin
21574 L1 := MaxPixels + 1;
21575 while ((MaxPixels > 0) and (L1 > 1) or (MaxPixels = 0) and (L1 > 0)) and
21576 (PixelsLength( DC, Result ) > MaxPixels) do
21577 begin
21578 Dec( L1 );
21579 Result := Copy( ExtractFileName( Path ), 1, L1 ) + '...';
21580 end;
21581 end;
21582 break;
21583 end;
21584 L0 := PixelsLength( DC, Result );
21585 end;
21586 end;
21588 //[procedure CutFirstDirectory]
21589 procedure CutFirstDirectory(var S: String);
21591 Root: Boolean;
21592 P: Integer;
21593 begin
21594 if S = '\' then
21595 S := ''
21596 else
21597 begin
21598 if S[1] = '\' then
21599 begin
21600 Root := True;
21601 Delete(S, 1, 1);
21603 else
21604 Root := False;
21605 if S[1] = '.' then
21606 Delete(S, 1, 4);
21607 P := pos('\',S);
21608 if P <> 0 then
21609 begin
21610 Delete(S, 1, P);
21611 S := '...\' + S;
21613 else
21614 S := '';
21615 if Root then
21616 S := '\' + S;
21617 end;
21618 end;
21620 //[function MinimizeName]
21621 function MinimizeName( const Path: String; DC: HDC; MaxPixels: Integer ): String;
21623 Drive, Dir, Name: String;
21624 begin
21625 Result := Path;
21626 Dir := ExtractFilePath(Result);
21627 Name := ExtractFileName(Result);
21629 if (Length(Dir) >= 2) and (Dir[2] = ':') then
21630 begin
21631 Drive := Copy(Dir, 1, 2);
21632 Delete(Dir, 1, 2);
21634 else
21635 Drive := '';
21636 while ((Dir <> '') or (Drive <> '')) and (PixelsLength(DC, Result) > MaxPixels) do
21637 begin
21638 if Dir = '\...\' then
21639 begin
21640 Drive := '';
21641 Dir := '...\';
21643 else if Dir = '' then
21644 Drive := ''
21645 else
21646 CutFirstDirectory(Dir);
21647 Result := Drive + Dir + Name;
21648 end;
21649 end;
21651 //[FUNCTION FileSize]
21652 {$IFDEF ASM_VERSION}
21653 function FileSize( const Path : String ) : Integer;
21654 const size_TWin32FindData = sizeof( TWin32FindData );
21656 ADD ESP, - size_TWin32FindData
21657 PUSH ESP
21658 //CALL System.@LStrToPChar // Path must not be ''
21659 PUSH EAX
21660 CALL FindFirstFile
21661 INC EAX
21662 JZ @@exit
21663 DEC EAX
21664 PUSH EAX
21665 CALL FindClose
21667 MOV EAX, [ESP].TWin32FindData.nFileSizeLow
21668 @@exit:
21669 ADD ESP, size_TWin32FindData
21670 end;
21671 {$ELSE ASM_VERSION} //Pascal
21672 function FileSize( const Path : String ) : Integer;
21673 var FD : TWin32FindData;
21674 FH : THandle;
21675 begin
21676 FH := FindFirstFile( PChar( Path ), FD );
21677 Result := 0;
21678 if FH = INVALID_HANDLE_VALUE then exit;
21679 Result := FD.nFileSizeLow;
21680 if ((FD.nFileSizeLow and $80000000) <> 0) or
21681 (FD.nFileSizeHigh <> 0) then Result := -1;
21682 FindClose( FH );
21683 end;
21684 {$ENDIF ASM_VERSION}
21685 //[END FileSize]
21688 //[function FileTimeCompare]
21689 function FileTimeCompare( const FT1, FT2 : TFileTime ) : Integer;
21690 var ST1, ST2 : TSystemTime;
21691 begin
21692 FileTimeToSystemTime( FT1, ST1 );
21693 FileTimeToSystemTime( FT2, ST2 );
21694 Result := CompareSystemTime( ST1, ST2 );
21695 end;
21697 //[function GetSystemDir]
21698 function GetSystemDir: String;
21699 var Buf: array[ 0..MAX_PATH ] of Char;
21700 begin
21701 GetSystemDirectory( @ Buf[ 0 ], MAX_PATH + 1 );
21702 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
21703 end;
21706 //[function GetWindowsDir]
21707 function GetWindowsDir : string;
21708 var Buf : array[ 0..MAX_PATH ] of Char;
21709 begin
21710 GetWindowsDirectory( @Buf[ 0 ], MAX_PATH + 1 );
21711 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
21712 end;
21714 //[function GetWorkDir]
21715 function GetWorkDir : string;
21716 var Buf: array[ 0..MAX_PATH ] of Char;
21717 begin
21718 GetCurrentDirectory( MAX_PATH + 1, @ Buf[ 0 ] );
21719 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
21720 end;
21723 //[function GetTempDir]
21724 function GetTempDir : string;
21725 var Buf : array[ 0..MAX_PATH ] of Char;
21726 begin
21727 Windows.GetTempPath( MAX_PATH + 1, @Buf[ 0 ] );
21728 Result := IncludeTrailingPathDelimiter( PChar( @ Buf[ 0 ] ) );
21729 end;
21731 //[function CreateTempFile]
21732 function CreateTempFile( const DirPath, Prefix: String ): String;
21733 var Buf: array[ 0..MAX_PATH ] of Char;
21734 begin
21735 GetTempFileName( PChar( DirPath ), PChar( Prefix ), 0, Buf );
21736 Result := Buf;
21737 end;
21739 //[function GetFileListStr]
21740 function GetFileListStr(FPath{e.g.'c:\tmp\'}, FMask{e.g.'*.*'}: string): string;
21741 {* List of files in string, separating each path from others with semicolon (';').
21742 E.g.: 'c:\tmp\unit1.dcu;c:\tmp\unit1.~pa' (for use with DeleteFile2Recycle())}
21744 Srch: TWin32FindData;
21745 flag: Integer;
21746 succ: boolean;
21747 dir:string;
21748 begin
21749 result := '';
21750 if (FPath<>'') and (FPath[length(FPath)]<>'\') then FPath:=FPath+'\';
21751 if (FMask<>'') and (FMask[1]='\') then FMask:=CopyEnd(FMask,2);
21752 dir:=FPath+FMask;
21753 flag := FindFirstFile(PChar(dir), Srch);
21754 succ := flag <> Integer(INVALID_HANDLE_VALUE);
21755 while succ do begin
21756 if (not (Srch.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY > 0))then begin
21757 if Result<>''then Result:=Result+';';
21758 Result:=Result+FPath+Srch.cFileName;
21759 end;
21760 succ := FindNextFile(Flag, Srch);
21761 end;
21762 FindClose(Flag);
21763 end;
21765 //[function DeleteFiles]
21766 function DeleteFiles( const DirPath: String ): Boolean;
21767 var Files, Name: String;
21768 begin
21769 Files := GetFileListStr( ExtractFilePath( DirPath ), ExtractFileName( DirPath ) );
21770 Result := TRUE;
21771 while Files <> '' do
21772 begin
21773 Name := Parse( Files, ';' );
21774 Result := Result and DeleteFile( PChar( Name ) );
21775 end;
21776 end;
21779 //[function DeleteFile2Recycle]
21780 function DeleteFile2Recycle( const Filename : String ) : Boolean;
21781 var FOS : TSHFileOpStruct;
21782 Buf : PChar;
21783 L : Integer;
21784 begin
21785 L := Length( Filename );
21786 GetMem( Buf, L + 2 );
21787 StrCopy( Buf, PChar( Filename ) );
21788 Buf[ L + 1 ] := #0;
21789 for L := L downto 0 do
21790 if Buf[ L ] = ';' then Buf[ L ] := #0;
21791 FillChar( FOS, Sizeof( FOS ), 0 );
21792 if Applet <> nil then
21793 FOS.Wnd := Applet.Handle;
21794 FOS.wFunc := FO_DELETE;
21795 FOS.pFrom := Buf;
21796 FOS.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION;
21797 FOS.fAnyOperationsAborted := True;
21798 FOS.lpszProgressTitle := PChar( 'Delete ' + Filename + ' to Recycle bin' );
21799 Result := SHFileOperation( FOS ) = 0;
21800 if Result then
21801 Result := not FOS.fAnyOperationsAborted;
21802 FreeMem( Buf );
21803 end;
21805 //[function CopyMoveFiles]
21806 function CopyMoveFiles( const FromList, ToList: String; Move: Boolean ): Boolean;
21807 var FOS : TSHFileOpStruct;
21808 Buf : PChar;
21809 L : Integer;
21810 begin
21811 L := Length( FromList );
21812 GetMem( Buf, L + 2 );
21813 StrCopy( Buf, PChar( FromList ) );
21814 Buf[ L + 1 ] := #0;
21815 for L := L downto 0 do
21816 if Buf[ L ] = ';' then Buf[ L ] := #0;
21817 FillChar( FOS, Sizeof( FOS ), 0 );
21818 if Applet <> nil then
21819 FOS.Wnd := Applet.Handle;
21820 if Move then
21821 begin
21822 FOS.wFunc := FO_MOVE;
21823 FOS.lpszProgressTitle := PChar( 'Move files' );
21825 else
21826 begin
21827 FOS.wFunc := FO_COPY;
21828 FOS.lpszProgressTitle := PChar( 'Copy files' );
21829 end;
21830 FOS.pFrom := Buf;
21831 FOS.pTo := PChar( ToList + #0 );
21832 FOS.fFlags := FOF_ALLOWUNDO;
21833 FOS.fAnyOperationsAborted := True;
21834 Result := SHFileOperation( FOS ) = 0;
21835 if Result then
21836 Result := not FOS.fAnyOperationsAborted;
21837 FreeMem( Buf );
21838 end;
21841 //[function DiskFreeSpace]
21842 function DiskFreeSpace( const Path: String ): I64;
21843 type TGetDFSEx = function( Path: PChar; CallerFreeBytes, TotalBytes, FreeBytes: Pointer )
21844 : Bool; stdcall;
21845 var GetDFSEx: TGetDFSEx;
21846 Kern32: THandle;
21847 V: TOSVersionInfo;
21848 Ex: Boolean;
21849 SpC, BpS, NFC, TNC: DWORD;
21850 FBA, TNB: I64;
21851 begin
21852 GetDFSEx := nil;
21853 V.dwOSVersionInfoSize := Sizeof( V );
21854 GetVersionEx( V );
21855 Ex := FALSE;
21856 if V.dwPlatformId = VER_PLATFORM_WIN32_NT then
21857 begin
21858 Ex := V.dwMajorVersion >= 4;
21860 else
21861 if V.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then
21862 begin
21863 Ex := V.dwMajorVersion > 4;
21864 if not Ex then
21865 if V.dwMajorVersion = 4 then
21866 begin
21867 Ex := V.dwMinorVersion > 0;
21868 if not Ex then
21869 Ex := LoWord( V.dwBuildNumber ) >= $1111;
21870 end;
21871 end;
21872 if Ex then
21873 begin
21874 Kern32 := GetModuleHandle( 'kernel32.dll' );
21875 GetDFSEx := GetProcAddress( Kern32, 'GetDiskFreeSpaceExA' );
21876 end;
21877 if Assigned( GetDFSEx ) then
21878 GetDFSEx( PChar( Path ), @ FBA, @ TNB, @Result )
21879 else
21880 begin
21881 GetDiskFreeSpace( PChar( Path ), SpC, BpS, NFC, TNC );
21882 Result := Mul64i( MakeInt64( SpC * BpS, 0 ), NFC );
21883 end;
21884 end;
21888 //[function GetUniqueFilename]
21889 function GetUniqueFilename( PathName: string ) : String;
21890 var Path, Nam, Ext : String;
21891 I, J, K : Integer;
21892 begin
21893 Result := PathName;
21894 Path := ExtractFilePath( PathName );
21895 if not DirectoryExists( Path ) then Exit;
21896 Nam := ExtractFileNameWOext( PathName );
21897 if Nam = '' then
21898 begin
21899 if Path[ Length( Path ) ] = '\' then
21900 Path := Copy( Path, 1, Length( Path ) - 1 );
21901 PathName := Path;
21902 Result := Path;
21903 end;
21904 Nam := ExtractFileNameWOext( PathName );
21905 Ext := ExtractFileExt( PathName );
21906 I := Length( Nam );
21907 for J := I downto 1 do
21908 if not (Nam[ J ] in [ '0'..'9' ]) then
21909 begin
21910 I := J;
21911 break;
21912 end;
21913 K := Str2Int( CopyEnd( Nam, I + 1 ) );
21914 while FileExists( Result ) do
21915 begin
21916 Inc( K );
21917 Result := Path + Copy( Nam, 1, I ) + Int2Str( K ) + Ext;
21918 end;
21919 end;
21921 //[FUNCTION GetStartDir]
21922 {$IFDEF ASM_VERSION}
21923 function GetStartDir : String;
21925 PUSH EBX
21926 MOV EBX, EAX
21928 XOR EAX, EAX
21929 MOV AH, 2
21930 SUB ESP, EAX
21931 MOV EDX, ESP
21932 PUSH EAX
21933 PUSH EDX
21934 PUSH 0
21935 CALL GetModuleFileName
21937 LEA EDX, [ESP + EAX]
21938 @@1: DEC EDX
21939 CMP byte ptr [EDX], '\'
21940 JNZ @@1
21942 INC EDX
21943 MOV byte ptr [EDX], 0
21945 MOV EAX, EBX
21946 MOV EDX, ESP
21947 CALL System.@LStrFromPChar
21949 ADD ESP, 200h
21950 POP EBX
21951 end;
21952 {$ELSE ASM_VERSION} //Pascal
21953 function GetStartDir : String;
21954 var Buffer:array[0..260] of Char;
21955 I : Integer;
21956 begin
21957 I := GetModuleFileName( 0, Buffer, Sizeof( Buffer ) );
21958 for I := I downto 0 do
21959 if Buffer[ I ] = '\' then
21960 begin
21961 Buffer[ I + 1 ] := #0;
21962 break;
21963 end;
21964 Result := Buffer;
21965 end;
21966 {$ENDIF ASM_VERSION}
21967 //[END GetStartDir]
21969 //[END FILES]
21973 { TDirList }
21975 //[function NewDirList]
21976 function NewDirList( const DirPath, Filter: String; Attr: DWORD ): PDirList;
21977 begin
21979 New( Result, Create );
21980 {+}{++}(*Result := PDirList.Create;*){--}
21981 Result.ScanDirectory( DirPath, Filter, Attr );
21982 end;
21983 //[END NewDirList]
21985 //[function NewDirListEx]
21986 function NewDirListEx( const DirPath, Filters: String; Attr: DWORD ): PDirList;
21987 begin
21989 New( Result, Create );
21990 {+}{++}(*Result := PDirList.Create;*){--}
21991 Result.ScanDirectoryEx( DirPath, Filters, Attr );
21992 end;
21993 //[END NewDirListEx]
21995 {$IFDEF ASM_VERSION}
21996 //[procedure TDirList.Clear]
21997 procedure TDirList.Clear;
21999 XOR ECX, ECX
22000 XCHG ECX, [EAX].fList
22001 JECXZ @@exit
22002 XCHG EAX, ECX
22003 CALL TList.Release
22004 @@exit:
22005 end;
22006 {$ELSE ASM_VERSION} //Pascal
22007 procedure TDirList.Clear;
22008 begin
22009 if FList <> nil then
22010 FList.Release;
22011 FList := nil;
22012 end;
22013 {$ENDIF ASM_VERSION}
22015 {$IFDEF ASM_VERSION}
22016 //[destructor TDirList.Destroy]
22017 destructor TDirList.Destroy;
22019 PUSH EBX
22020 MOV EBX, EAX
22021 CALL Clear
22022 LEA EAX, [EBX].FPath
22023 CALL System.@LStrClr
22024 XCHG EAX, EBX
22025 CALL TObj.Destroy
22026 POP EBX
22027 end;
22028 {$ELSE ASM_VERSION} //Pascal
22029 destructor TDirList.Destroy;
22030 begin
22031 Clear;
22032 FPath := '';
22033 inherited;
22034 end;
22035 {$ENDIF ASM_VERSION}
22037 //[FUNCTION FindFilter]
22038 {$IFDEF ASM_VERSION}
22039 function FindFilter( const Filter: String): String;
22041 XCHG EAX, EDX
22042 PUSH EAX
22043 CALL System.@LStrAsg
22044 POP EAX
22045 CMP dword ptr [EAX], 0
22046 JNE @@exit
22047 LEA EDX, @@mask_all
22048 JE System.@LStrFromPChar
22049 @@mask_all: DB '*.*',0
22050 @@exit:
22051 end;
22052 {$ELSE ASM_VERSION} //Pascal
22053 function FindFilter(const Filter: String): String;
22054 begin
22055 Result := Filter;
22056 if Result = '' then Result := '*.*';
22057 end;
22058 {$ENDIF ASM_VERSION}
22059 //[END FindFilter]
22062 //[function TDirList.Get]
22063 function TDirList.Get(Idx: Integer): PWin32FindData;
22064 begin
22065 Result := FList.fItems[ Idx ];
22066 end;
22068 {$IFDEF ASM_VERSION}
22069 //[function TDirList.GetCount]
22070 function TDirList.GetCount: Integer;
22072 MOV EAX, [EAX].fList
22073 TEST EAX, EAX
22074 {$IFDEF USE_CMOV}
22075 CMOVNZ EAX, [EAX].TList.fCount
22076 {$ELSE}
22077 JZ @@exit
22078 MOV EAX, [EAX].TList.fCount
22079 @@exit: {$ENDIF}
22080 end;
22081 {$ELSE ASM_VERSION} //Pascal
22082 function TDirList.GetCount: Integer;
22083 begin
22084 Result := 0;
22085 if FList = nil then Exit;
22086 Result := FList.Count;
22087 end;
22088 {$ENDIF ASM_VERSION}
22090 {$IFDEF ASM_VERSION}
22091 //[function TDirList.GetNames]
22092 function TDirList.GetNames(Idx: Integer): string;
22094 MOV EAX, [EAX].fList
22095 MOV EAX, [EAX].TList.fItems
22096 MOV EDX, [EAX + EDX*4]
22097 //*/////////////////////////////////////////////////////
22098 // ADD EDX, TWin32FindData.cFileName
22099 //*/////////////////////////////////////////////////////
22100 ADD EDX, offset TWin32FindData.cFileName //
22101 //*/////////////////////////////////////////////////////
22102 MOV EAX, ECX
22103 CALL System.@LStrFromPChar
22104 end;
22105 {$ELSE ASM_VERSION} //Pascal
22106 function TDirList.GetNames(Idx: Integer): string;
22107 begin
22108 Result := PChar(@PWin32FindData(fList.fItems[ Idx ]).cFileName[0]);
22109 //Result := PChar(@Items[Idx].cFileName[0]);
22110 end;
22111 {$ENDIF ASM_VERSION}
22113 //[function TDirList.GetIsDirectory]
22114 function TDirList.GetIsDirectory(Idx: Integer): Boolean;
22115 begin
22116 Result := LongBool( Items[ Idx ].dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY );
22117 end;
22119 {$IFDEF ASM_noVERSION}
22120 //[function TDirList.SatisfyFilter]
22121 function TDirList.SatisfyFilter(FileName: PChar; FileAttr,
22122 FindAttr: DWord): Boolean;
22124 PUSH EBX
22125 PUSH ESI
22126 PUSH EDI
22127 XCHG EBX, EAX // EBX = @ Self
22128 MOV EAX, [FindAttr]
22129 MOV EDI, EDX // EDI = FileName
22130 MOV EDX, EAX
22131 AND EDX, ECX
22132 CMP EDX, EAX
22133 JE @@1
22135 TEST AL, FILE_ATTRIBUTE_NORMAL
22136 JZ @@ret_false
22137 @@1:
22138 CMP word ptr [EDI], '.'
22139 JE @@1_1
22140 CMP word ptr [EDI], '..'
22141 JNE @@1_1
22142 CMP byte ptr [EDI+2], 0
22143 JNE @@1_1
22144 @@1_0:
22145 MOV ECX, [FindAttr]
22146 TEST CL, FILE_ATTRIBUTE_NORMAL
22147 JZ @@1_1
22148 CMP ECX, FILE_ATTRIBUTE_NORMAL
22149 JE @@1_1
22150 TEST AL, FILE_ATTRIBUTE_DIRECTORY
22151 JZ @@1_1
22152 TEST CL, FILE_ATTRIBUTE_DIRECTORY
22153 JNZ @@ret_true
22155 @@1_1:
22156 MOV ECX, [EBX].fFilters
22157 JECXZ @@ret_false //?
22159 MOV ESI, [ECX].TStrList.fList
22160 MOV ESI, [ESI].TList.fItems
22161 MOV ECX, [ECX].TStrList.fCount
22162 JECXZ @@ret_false
22164 @@2:
22165 LODSD
22166 TEST EAX, EAX
22167 JZ @@nx_filter
22169 PUSHAD
22171 MOV EDX, [EAX]
22172 CMP DX, $002E
22173 JE @@F_d_dd
22174 AND EDX, $FFFFFF
22175 CMP EDX, $002E2E
22176 JE @@F_d_dd
22178 MOV EDX, [EDI]
22179 CMP DX, $002E
22180 JE @@4
22181 AND EDX, $FFFFFF
22182 CMP EDX, $002E2E
22183 JE @@4
22184 JMP @@chk_anti
22186 @@F_d_dd:
22187 MOV EDX, EDI
22188 PUSH EAX
22189 CALL StrComp
22190 TEST EAX, EAX
22191 POP EAX
22192 JZ @@popad_ret_true
22194 @@chk_anti:
22195 XCHG EDX, EAX // EDX = filter[ i ]
22196 MOV EAX, EDI // EAX = FileName
22197 CMP byte ptr [EDX], '^'
22198 JNE @@3
22200 INC EDX
22201 CALL _2StrSatisfy
22202 TEST AL, AL
22203 JZ @@4
22204 POPAD
22205 JMP @@ret_false
22207 @@3: CALL _2StrSatisfy
22208 TEST AL, AL
22209 JZ @@4
22210 @@popad_ret_true:
22211 POPAD
22212 @@ret_true:
22213 MOV AL, 1
22214 JMP @@exit
22216 @@4: POPAD
22217 @@nx_filter:
22218 LOOP @@2
22220 @@ret_false:
22221 XOR EAX, EAX
22222 @@exit:
22223 POP EDI
22224 POP ESI
22225 POP EBX
22226 end;
22227 {$ELSE ASM_VERSION} //Pascal
22228 function TDirList.SatisfyFilter(FileName: PChar; FileAttr,
22229 FindAttr: DWord): Boolean;
22230 {$IFDEF F_P}
22231 const Dot: String = '.';
22232 {$ENDIF F_P}
22233 var I: Integer;
22234 F: PChar;
22235 HasOnlyNegFilters: Boolean;
22236 begin
22237 Result := (((FileAttr and FindAttr) = FindAttr) or
22238 LongBool(FindAttr and FILE_ATTRIBUTE_NORMAL));
22239 if not Result then Exit;
22241 if (FileName <> {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) and
22242 (FileName <> '..') then
22243 if LongBool( FindAttr and FILE_ATTRIBUTE_NORMAL ) and
22244 (FindAttr <> FILE_ATTRIBUTE_NORMAL) then
22245 if LongBool( FindAttr and FILE_ATTRIBUTE_DIRECTORY ) and
22246 LongBool( FileAttr and FILE_ATTRIBUTE_DIRECTORY ) then Exit;
22248 HasOnlyNegFilters := TRUE;
22249 for I := 0 to fFilters.fCount - 1 do
22250 begin
22251 F := PChar(fFilters.fList.fItems[ I ]);
22252 if F = '' then continue;
22254 if (F = {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) or (F = '..') then
22255 begin
22256 if FileName = F then
22257 Exit;
22259 else
22260 if (Filename = {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) or (FileName = '..') then
22261 begin
22262 //Result := FALSE;
22263 continue;
22264 end;
22266 if F[ 0 ] = '^' then
22267 begin
22268 if StrSatisfy( FileName, PChar(@F[ 1 ]) ) then
22269 begin
22270 Result := False;
22271 Exit;
22272 end;
22274 else
22275 begin
22276 HasOnlyNegFilters := FALSE;
22277 if StrSatisfy( FileName, F ) then
22278 begin
22279 Result := True;
22280 Exit;
22281 end;
22282 end;
22283 end;
22285 Result := HasOnlyNegFilters and
22286 (FileName <> {$IFDEF F_P}Dot{$ELSE}'.'{$ENDIF}) and
22287 (FileName <> '..');
22289 end;
22290 {$ENDIF ASM_VERSION}
22292 {$IFDEF ASM_VERSION}
22293 //[procedure TDirList.ScanDirectory]
22294 procedure TDirList.ScanDirectory(const DirPath, Filter: String;
22295 Attr: DWord);
22296 const sz_win32finddata = sizeof(TWin32FindData);
22298 PUSH EBX
22299 PUSH EDI
22300 MOV EBX, EAX
22302 PUSHAD
22303 CALL Clear
22304 CALL NewList
22305 MOV [EBX].fList, EAX
22306 POPAD
22308 PUSHAD
22309 LEA EAX, [EBX].fPath
22310 CALL System.@LStrAsg
22311 POPAD
22313 MOV EAX, [EBX].fPath
22314 TEST EAX, EAX
22315 JE @@exit
22317 PUSHAD
22318 LEA EDX, [EBX].fPath
22319 MOV EAX, [EDX]
22320 CALL IncludeTrailingPathDelimiter
22322 MOV EAX, [EBX].fFilters
22323 TEST EAX, EAX
22324 JNZ @@1
22325 CALL NewStrList
22326 MOV [EBX].fFilters, EAX
22327 POPAD
22329 PUSHAD
22330 PUSH ECX
22331 XCHG EAX, ECX
22332 MOV EDX, offset[@@star_d_star]
22333 CALL StrComp
22334 TEST AL, AL
22335 POP EDX
22336 JNZ @@asg_Filter
22337 MOV EDX, offset[@@star]
22338 @@asg_Filter:
22339 MOV EAX, [EBX].fFilters
22340 CALL TStrList.Add
22341 JMP @@1
22343 @@star_d_star:
22344 DB '*.*', 0
22345 DD -1, 1
22346 @@star: DB '*', 0
22348 @@1:
22349 POPAD
22351 ADD ESP, -sz_win32finddata
22352 XOR EDX, EDX
22353 PUSH EDX
22354 PUSH EDX
22355 XCHG EAX, ECX
22356 MOV EDX, ESP
22357 CALL FindFilter
22359 LEA EAX, [ESP+4]
22360 MOV EDX, [EBX].fPath
22361 POP ECX
22362 PUSH ECX
22363 CALL System.@LStrCat3
22364 CALL RemoveStr
22366 POP EAX
22367 MOV EDX, ESP
22368 PUSH EAX
22369 PUSH EDX
22370 PUSH EAX
22371 CALL FindFirstFile
22372 MOV EDI, EAX
22373 INC EAX
22374 MOV EAX, ESP
22376 PUSHFD
22377 CALL System.@LStrClr
22378 POPFD
22379 POP ECX
22381 JZ @@fin
22383 @@loop:
22384 MOV ECX, [ESP].TWin32FindData.dwFileAttributes
22385 PUSH [Attr]
22386 LEA EDX, [ESP+4].TWin32FindData.cFileName
22387 MOV EAX, EBX
22388 CALL SatisfyFilter
22390 TEST AL, AL
22391 JZ @@next
22393 MOV ECX, [EBX].fOnItem.TMethod.Code
22394 JECXZ @@accept
22395 MOV EAX, [EBX].fOnItem.TMethod.Data
22396 MOV ECX, ESP
22397 PUSH 1
22398 MOV EDX, ESP
22399 PUSH EDX
22400 MOV EDX, EBX
22401 CALL dword ptr [EBX].fOnItem.TMethod.Code
22402 POP ECX
22403 JECXZ @@next
22404 LOOP @@fin
22406 @@accept:
22407 MOV EAX, sz_win32finddata
22408 PUSH EAX
22409 CALL System.@GetMem
22410 PUSH EAX
22411 XCHG EDX, EAX
22412 MOV EAX, [EBX].fList
22413 CALL TList.Add
22414 POP EDX
22415 POP ECX
22416 MOV EAX, ESP
22417 CALL System.Move
22419 @@next:
22420 PUSH ESP
22421 PUSH EDI
22422 CALL FindNextFile
22423 TEST EAX, EAX
22424 JNZ @@loop
22426 PUSH EDI
22427 CALL FindClose
22429 @@fin:
22430 ADD ESP, sz_win32finddata
22431 @@exit:
22432 XOR EAX, EAX
22433 XCHG EAX, [EBX].fFilters
22434 CALL TObj.Free
22435 POP EDI
22436 POP EBX
22437 end;
22438 {$ELSE ASM_VERSION} //Pascal
22439 procedure TDirList.ScanDirectory(const DirPath, Filter: String;
22440 Attr: DWord);
22441 var FindData : TWin32FindData;
22442 E : PWin32FindData;
22443 FindHandle : THandle;
22444 Action: TDirItemAction;
22445 begin
22446 Clear;
22447 FList := NewList;
22448 FPath := DirPath;
22449 if FPath = '' then Exit;
22450 FPath := IncludeTrailingPathDelimiter( FPath );
22451 if fFilters = nil then
22452 begin
22453 fFilters := NewStrList;
22454 if Filter = '*.*' then
22455 fFilters.Add( '*' )
22456 else
22457 fFilters.Add( Filter );
22458 end;
22459 FindHandle := FindFirstFile( PChar( FPath + FindFilter( Filter ) ),
22460 FindData );
22461 if FindHandle = INVALID_HANDLE_VALUE then Exit;
22462 while True do
22463 begin
22464 if SatisfyFilter( PChar(@FindData.cFileName[0]),
22465 FindData.dwFileAttributes, Attr ) then
22466 begin
22467 Action := diAccept;
22468 if Assigned( OnItem ) then
22469 OnItem( @Self, FindData, Action );
22470 CASE Action OF
22471 diSkip: ;
22472 diAccept:
22473 begin
22474 GetMem( E, Sizeof( FindData ) );
22475 E^ := FindData;
22476 FList.Add( E );
22477 end;
22478 diCancel: break;
22479 END;
22480 end;
22481 if not FindNextFile( FindHandle, FindData ) then break;
22482 end;
22483 FindClose( FindHandle );
22484 fFilters.Free;
22485 fFilters := nil;
22486 end;
22487 {$ENDIF ASM_VERSION}
22489 {$IFDEF ASM_VERSION}
22490 //[procedure TDirList.ScanDirectoryEx]
22491 procedure TDirList.ScanDirectoryEx(const DirPath, Filters: String;
22492 Attr: DWord);
22494 PUSH EBX
22495 MOV EBX, EAX
22497 PUSHAD
22498 CALL NewStrList
22499 MOV [EBX].fFilters, EAX
22500 POPAD
22502 PUSHAD
22503 PUSH 0
22504 MOV EAX, ESP
22505 MOV EDX, ECX
22506 CALL System.@LStrLAsg
22507 @@1: MOV ECX, [ESP]
22508 JECXZ @@2
22509 MOV EAX, ESP
22510 MOV EDX, offset[@@semicolon]
22511 PUSH 0
22512 MOV ECX, ESP
22513 CALL Parse
22514 MOV EAX, [ESP]
22515 MOV EDX, ESP
22516 CALL Trim
22517 POP EDX
22518 PUSH EDX
22519 TEST EDX, EDX
22520 JZ @@filt_added
22521 MOV EAX, [EBX].fFilters
22522 CALL TStrList.Add
22523 @@filt_added:
22524 CALL RemoveStr
22525 JMP @@1
22527 // ';' string literal
22528 DD -1, 1
22529 @@semicolon:
22530 DB ';',0
22532 @@2: POP ECX
22533 POPAD
22534 XOR ECX, ECX
22535 PUSH [Attr]
22536 CALL ScanDirectory
22537 {XOR EAX, EAX
22538 XCHG EAX, [EBX].fFilters
22539 CALL TObj.Free}
22540 POP EBX
22541 @@exit:
22542 end;
22543 {$ELSE ASM_VERSION} //Pascal
22544 procedure TDirList.ScanDirectoryEx(const DirPath, Filters: String;
22545 Attr: DWord);
22546 var F, FF: String;
22547 begin
22548 FF := Filters;
22549 fFilters := NewStrList;
22550 while FF <> '' do
22551 begin
22552 F := Trim( Parse( FF, ';' ) );
22553 if F <> '' then
22554 fFilters.Add( F );
22555 end;
22556 ScanDirectory( DirPath, '', Attr );
22557 end;
22558 {$ENDIF ASM_VERSION}
22560 type
22561 PSortDirData = ^TSortDirData;
22562 TSortDirData = packed Record
22563 FoldersFirst, CaseSensitive : Boolean;
22564 Rules : array[ 0..11 ] of TSortDirRules;
22565 Dir : PDirList;
22566 end;
22568 //[FUNCTION CompareDirItems]
22569 {$IFDEF ASM_noVERSION}
22570 function CompareDirItems( const Data : PSortDirData; const e1, e2 : DWORD ) : Integer;
22572 PUSH EBX
22573 PUSH ESI
22574 PUSH EDI
22575 XCHG EBX, EAX
22576 MOV EAX, [EBX].TSortDirData.Dir
22577 MOV EAX, [EAX].TDirList.fList
22578 MOV EAX, [EAX].TList.fItems
22579 MOV ESI, [EAX+EDX*4]
22580 MOV EDI, [EAX+ECX*4]
22581 MOV DL, byte ptr[ESI].TWin32FindData.dwFileAttributes
22582 MOV DH, byte ptr[EDI].TWin32FindData.dwFileAttributes
22583 AND DX, 2020h
22584 XOR EAX, EAX
22585 CMP DL, DH
22586 JE @@1
22587 CMP [EBX].TSortDirData.FoldersFirst, AL
22588 JE @@1
22589 OR AL, DL
22590 JNE @@exit_near
22591 DEC EAX
22592 //JMP @@exit
22593 @@exit_near:
22594 POP EDI
22595 POP ESI
22596 POP EBX
22599 @@sdrByDateChanged:
22600 LEA EAX, [ESI].TWin32FindData.ftLastWriteTime
22601 LEA EDX, [EDI].TWin32FindData.ftLastWriteTime
22602 JMP @@sdrByDate1
22604 @@sdrByDateAccessed:
22605 LEA EAX, [ESI].TWin32FindData.ftLastAccessTime
22606 LEA EDX, [EDI].TWin32FindData.ftLastAccessTime
22607 JMP @@sdrByDate1
22609 @@jmp_table:
22610 DD offset[@@exit1], offset[@@2], offset[@@2]
22611 DD offset[@@sdrByName], offset[@@sdrByExt]
22612 DD offset[@@sdrBySize], offset[@@sdrBySize]
22613 DD offset[@@sdrByDateCreate], offset[@@sdrByDateChanged]
22614 DD offset[@@sdrByDateAccessed]
22616 @@1:
22617 LEA EDX, [EBX].TSortDirData.Rules
22618 PUSH EDX
22619 @@2:
22620 POP EDX
22621 XOR EAX, EAX
22622 MOV AL, [EDX]
22623 INC EDX
22624 PUSH EDX
22626 JMP dword ptr [@@jmp_table+EAX*4]
22627 //////// ///////////////////
22629 @@sdrByDateCreate:
22630 LEA EAX, [ESI].TWin32FindData.ftCreationTime
22631 LEA EDX, [EDI].TWin32FindData.ftCreationTime
22632 @@sdrByDate1:
22633 PUSH EDX
22634 PUSH EAX
22635 CALL CompareFileTime
22636 TEST EAX, EAX
22637 JE @@2
22638 JMP @@exit1
22640 @@sdrBySize:
22641 MOV EAX, [ESI].TWin32FindData.nFileSizeHigh
22642 SUB EAX, [EDI].TWin32FindData.nFileSizeHigh
22643 JNE @@sdrBySize1
22644 MOV EAX, [ESI].TWin32FindData.nFileSizeLow
22645 SUB EAX, [EDI].TWin32FindData.nFileSizeLow
22646 @@to_2:
22647 JE @@2
22648 @@sdrBySize1:
22649 POP EDX
22650 DEC EDX
22651 CMP byte ptr[EDX], sdrBySizeDescending
22652 JNE @@sdrBySize2
22653 NEG EAX
22654 @@sdrBySize2:
22655 JNE @@exit
22656 //////// ///////////////////
22658 DD -1, 1
22659 @@point:DB '.',0
22661 @@sdrByExt:
22662 LEA EAX, [EDI].TWin32FindData.cFileName
22663 MOV EDX, offset[@@point]
22664 PUSH EDX
22665 CALL __DelimiterLast
22666 POP EDX
22667 PUSH EAX
22668 LEA EAX, [ESI].TWin32FindData.cFileName
22669 CALL __DelimiterLast
22670 POP EDX
22671 JMP @@sdrByName0
22673 @@sdrByName:
22674 LEA EAX, [ESI].TWin32FindData.cFileName
22675 LEA EDX, [EDI].TWin32FindData.cFileName
22676 @@sdrByName0:
22677 CMP [EBX].TSortDirData.CaseSensitive, 0
22678 JNE @@sdrByName1
22679 CALL _AnsiCompareStrNoCase
22680 JMP @@sdrByName2
22681 @@sdrByName1:
22682 CALL _AnsiCompareStr
22683 @@sdrByName2:
22684 TEST EAX, EAX
22685 JE @@to_2
22686 //JMP @@exit1
22688 @@exit1:
22689 POP EDX
22690 @@exit:
22691 POP EDI
22692 POP ESI
22693 POP EBX
22694 end;
22695 {$ELSE ASM_VERSION} //Pascal
22696 function CompareDirItems( const Data : PSortDirData; const e1, e2 : DWORD ) : Integer;
22697 var I : Integer;
22698 Item1, Item2 : PWin32FindData;
22699 S1, S2 : PChar;
22700 IsDir1, IsDir2 : Boolean;
22701 Date1, Date2 : PFileTime;
22702 begin
22703 Item1 := Data.Dir.fList.fItems[ e1 ];
22704 Item2 := Data.Dir.fList.fItems[ e2 ];
22705 Result := 0;
22706 IsDir1 := (Item1.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0;
22707 IsDir2 := (Item2.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) <> 0;
22708 if (IsDir1 <> IsDir2) and Data.FoldersFirst then
22709 begin
22710 if IsDir1 then Result := -1 else Result := 1;
22711 exit;
22712 end;
22713 for I := 0 to High(Data.Rules) do
22714 begin
22715 case Data.Rules[ I ] of
22716 sdrByName:
22717 begin
22718 S1 := Item1.cFileName;
22719 S2 := Item2.cFileName;
22720 if not Data.CaseSensitive then
22721 Result := _AnsiCompareStrNoCase( S1, S2 )
22722 else
22723 Result := _AnsiCompareStr( S1, S2 );
22724 end;
22725 sdrByExt:
22726 begin
22727 S1 := Item1.cFileName;
22728 S2 := Item2.cFileName;
22729 S1 := __DelimiterLast( S1, '.' );
22730 S2 := __DelimiterLast( S2, '.' );
22731 if not Data.CaseSensitive then
22732 Result := _AnsiCompareStrNoCase( S1, S2 )
22733 else
22734 Result := _AnsiCompareStr( S1, S2 );
22735 end;
22736 sdrBySize, sdrBySizeDescending:
22737 begin
22738 if Item1.nFileSizeHigh < Item2.nFileSizeHigh then
22739 Result := -1
22740 else
22741 if Item1.nFileSizeHigh > Item2.nFileSizeHigh then
22742 Result := 1
22743 else
22744 if Item1.nFileSizeLow < Item2.nFileSizeLow then
22745 Result := -1
22746 else
22747 if Item1.nFileSizeLow > Item2.nFileSizeLow then
22748 Result := 1;
22749 if Data.Rules[ I ] = sdrBySizeDescending then
22750 Result := -Result;
22751 end;
22752 sdrByDateCreate:
22753 begin
22754 Date1 := @Item1.ftCreationTime;
22755 Date2 := @Item2.ftCreationTime;
22756 Result := CompareFileTime( Date1^, Date2^ );
22757 end;
22758 sdrByDateChanged:
22759 begin
22760 Date1 := @Item1.ftLastWriteTime;
22761 Date2 := @Item2.ftLastWriteTime;
22762 Result := CompareFileTime( Date1^, Date2^ );
22763 end;
22764 sdrByDateAccessed:
22765 begin
22766 Date1 := @Item1.ftLastAccessTime;
22767 Date2 := @Item2.ftLastAccessTime;
22768 Result := CompareFileTime( Date1^, Date2^ );
22769 end;
22770 end; {case}
22771 if Result <> 0 then break;
22772 end;
22773 end;
22774 {$ENDIF ASM_VERSION}
22775 //[END CompareDirItems]
22777 //[PROCEDURE SwapDirItems]
22778 {$IFDEF ASM_VERSION}
22779 procedure SwapDirItems( const Data : PSortDirData; const e1, e2 : DWORD );
22781 MOV EAX, [EAX].TSortDirData.Dir
22782 MOV EAX, [EAX].TDirList.fList
22783 MOV EAX, [EAX].TList.fItems
22784 LEA EDX, [EAX+EDX*4]
22785 LEA ECX, [EAX+ECX*4]
22786 MOV EAX, [EDX]
22787 XCHG EAX, [ECX]
22788 MOV [EDX], EAX
22789 end;
22790 {$ELSE ASM_VERSION} //Pascal
22791 procedure SwapDirItems( const Data : PSortDirData; const e1, e2 : DWORD );
22792 var Tmp : Pointer;
22793 begin
22794 Tmp := Data.Dir.FList.fItems[ e1 ];
22795 Data.Dir.FList.fItems[ e1 ] := Data.Dir.FList.fItems[ e2 ];
22796 Data.Dir.FList.fItems[ e2 ] := Tmp;
22797 end;
22798 {$ENDIF ASM_VERSION}
22799 //[END SwapDirItems]
22802 TSortDirData = packed Record
22803 FoldersFirst, CaseSensitive : Boolean;
22804 Rules : array[ 0..11 ] of TSortDirRules;
22805 Dir : PDirList;
22806 end;
22808 {$IFDEF ASM_VERSION}
22809 procedure TDirList.Sort(Rules: array of TSortDirRules);
22810 const high_DefSortDirRules = High( DefSortDirRules );
22812 PUSH EBX
22813 PUSH ESI
22814 XOR EBX,EBX
22815 CMP [EAX].fList, EBX
22816 JE @@exit
22818 PUSH EAX // prepare Dir = @Self
22819 XOR EAX, EAX
22820 PUSH EAX
22821 PUSH EAX
22822 PUSH EAX
22823 MOV ESI, ESP
22824 INC ECX // ECX = High(Rules)
22825 JZ @@2
22826 @@1: MOV AH, [EDX] // AH = Rules[ I ]
22827 INC EDX
22828 CALL @@add_rule
22829 LOOP @@1
22830 @@2: LEA EDX, [DefSortDirRules]
22831 MOV CL, high_DefSortDirRules + 1
22832 @@21: MOV AH, [EDX]
22833 INC EDX
22834 CALL @@add_rule
22835 LOOP @@21
22837 PUSH BX // prepare FoldersFirst(BL), CaseSensitive(BH)
22838 MOV EBX, [ESP].TSortDirData.Dir
22839 MOV EAX, ESP
22840 PUSH offset[SwapDirItems]
22841 MOV ECX, offset[CompareDirItems]
22842 MOV EDX, [EBX].fList
22843 MOV EDX, [EDX].TList.fCount
22844 CALL SortData
22846 ADD ESP, 18
22847 JMP @@exit
22849 @@add_rule:
22850 PUSH ESI
22851 PUSH ECX
22852 MOV CL, 11
22853 @@a1: LODSB
22854 TEST AL, AL
22855 JZ @@a2
22856 CMP AL, AH
22857 JE @@a3
22858 LOOP @@a1
22859 @@a2: DEC ESI
22860 MOV [ESI], AH
22861 CMP AH, sdrFoldersFirst
22862 JNE @@a4
22863 INC BL
22864 @@a4: CMP AH, sdrCaseSensitive
22865 JNE @@a3
22866 INC BH
22867 @@a3: POP ECX
22868 POP ESI
22871 @@exit:
22872 POP ESI
22873 POP EBX
22874 end;
22875 {$ELSE ASM_VERSION} //Pascal
22876 procedure TDirList.Sort(Rules: array of TSortDirRules);
22877 var SortDirData : TSortDirData;
22878 I, J : Integer;
22880 function RulePresent( Rule : TSortDirRules ) : Boolean;
22881 var K : Integer;
22882 begin
22883 Result := True;
22884 for K := J - 1 downto 0 do
22885 if Rule = SortDirData.Rules[ K ] then exit;
22886 Result := False;
22887 end;
22889 procedure AddRule( Rule : TSortDirRules );
22890 begin
22891 if J > High( SortDirData.Rules ) then exit;
22892 if RulePresent( Rule ) then exit;
22893 SortDirData.Rules[ J ] := Rule;
22894 Inc( J );
22895 end;
22896 begin
22897 if fList = nil then Exit;
22898 J := 0;
22899 for I := 0 to High(Rules) do
22900 AddRule( Rules[ I ] );
22901 for I := 0 to High(DefSortDirRules) do
22902 AddRule( DefSortDirRules[ I ] );
22903 while J < High( SortDirData.Rules ) do
22904 begin
22905 SortDirData.Rules[ J ] := sdrNone;
22906 Inc( J );
22907 end;
22909 SortDirData.Dir := @Self;
22910 SortDirData.FoldersFirst := RulePresent( sdrFoldersFirst );
22911 SortDirData.CaseSensitive := RulePresent( sdrCaseSensitive );
22912 SortData( Pointer( @SortDirData ), fList.fCount, @CompareDirItems, @SwapDirItems );
22913 end;
22914 {$ENDIF ASM_VERSION}
22917 //[function TDirList.FileList]
22918 function TDirList.FileList(const Separator: String; Dirs,
22919 FullPaths: Boolean): String;
22920 var I: Integer;
22921 begin
22922 Result := '';
22923 for I := 0 to Count-1 do
22924 begin
22925 if not Dirs and IsDirectory[ I ] then Continue;
22926 if FullPaths then
22927 Result := Result + Path;
22928 Result := Result + Names[ I ] + Separator;
22929 end;
22930 end;
22936 ////////////////////////////////////////////////////////////////////////
22939 // R E G I S T R Y
22942 ////////////////////////////////////////////////////////////////////////
22946 {++}(*
22947 function RegSetValueEx; external advapi32 name 'RegSetValueExA';
22948 *){--}
22951 { -- registry -- }
22953 //[function RegKeyOpenRead]
22954 function RegKeyOpenRead( Key: HKey; const SubKey: String ): HKey;
22955 begin
22956 if RegOpenKeyEx( Key, PChar( SubKey ), 0, KEY_READ, Result ) <> ERROR_SUCCESS then
22957 Result := 0;
22958 end;
22960 //[function RegKeyOpenWrite]
22961 function RegKeyOpenWrite( Key: HKey; const SubKey: String ): HKey;
22962 begin
22963 if RegOpenKeyEx( Key, PChar( SubKey ), 0, KEY_READ or KEY_WRITE, Result ) <> ERROR_SUCCESS then
22964 Result := 0;
22965 end;
22967 //[function RegKeyOpenCreate]
22968 function RegKeyOpenCreate( Key: HKey; const SubKey: String ): HKey;
22969 var dwDisp: DWORD;
22970 begin
22971 if RegCreateKeyEx( Key, PChar( SubKey ), 0, nil, 0, KEY_ALL_ACCESS, nil, Result,
22972 @dwDisp ) <> ERROR_SUCCESS then
22973 Result := 0;
22974 end;
22976 //[function RegKeyGetDw]
22977 function RegKeyGetDw( Key: HKey; const ValueName: String ): DWORD;
22978 var dwType, dwSize: DWORD;
22979 begin
22980 dwSize := sizeof( DWORD );
22981 Result := 0;
22982 if (Key = 0) or
22983 (RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType, PByte( @Result ), @dwSize ) <> ERROR_SUCCESS)
22984 or (dwType <> REG_DWORD) then Result := 0;
22985 end;
22987 //[function RegKeyGetStr]
22988 function RegKeyGetStr( Key: HKey; const ValueName: String ): String;
22989 var dwType, dwSize: DWORD;
22990 Buffer: PChar;
22992 function Query: Boolean;
22993 begin
22994 Result := RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType,
22995 Pointer( Buffer ), @dwSize ) = ERROR_SUCCESS;
22996 end;
22997 begin
22998 Result := '';
22999 if Key = 0 then Exit;
23000 dwSize := 0;
23001 Buffer := nil;
23002 if not Query or (dwType <> REG_SZ) then Exit;
23003 GetMem( Buffer, dwSize );
23004 if Query then
23005 Result := Buffer;
23006 FreeMem( Buffer );
23007 end;
23009 //[function RegKeyGetStrEx]
23010 function RegKeyGetStrEx( Key: HKey; const ValueName: String ): String;
23011 var dwType, dwSize: DWORD;
23012 Buffer, Buffer2: PChar;
23013 Sz: Integer;
23014 function Query: Boolean;
23015 begin
23016 Result := RegQueryValueEx( Key, PChar( ValueName ), nil, @dwType,
23017 Pointer( Buffer ), @dwSize ) = ERROR_SUCCESS;
23018 end;
23019 begin
23020 Result := '';
23021 if Key = 0 then Exit;
23022 dwSize := 0;
23023 Buffer := nil;
23024 if not Query or ((dwType <> REG_SZ) and (dwtype <> REG_EXPAND_SZ)) then Exit;
23025 GetMem( Buffer, dwSize );
23026 if Query then
23027 begin
23028 if dwtype = REG_EXPAND_SZ then
23029 begin
23030 //------------------------------------------------------ by Dmitry Zharov
23031 // Sz := ExpandEnvironmentStrings(Buffer,nil,0); 18-Aug-2004
23032 // SetLength( Result, Sz );
23033 // ExpandEnvironmentStrings(Buffer, PChar(Result), Sz);
23034 //---------------------------------------------//
23035 Sz := ExpandEnvironmentStrings(Buffer,nil,0); // bug in size detection! sometimes we get an additional 2 bytes at the end...
23036 GetMem(Buffer2,Sz); //
23037 ExpandEnvironmentStrings(Buffer, Buffer2, Sz); //
23038 Result:=Buffer2; //
23039 FreeMem(Buffer2); //
23040 //---------------------------------------------//
23042 else
23043 Result := Buffer;
23044 end;
23045 FreeMem( Buffer );
23046 end;
23048 //[function RegKeySetDw]
23049 function RegKeySetDw( Key: HKey; const ValueName: String; Value: DWORD ): Boolean;
23050 begin
23051 Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0, REG_DWORD, @Value, sizeof( DWORD ) )
23052 = ERROR_SUCCESS);
23053 end;
23055 //[function RegKeySetStr]
23056 function RegKeySetStr( Key: HKey; const ValueName: String; const Value: String ): Boolean;
23057 begin
23058 Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0,
23059 REG_SZ, PChar(Value),
23060 Length( Value ) + 1 ) = ERROR_SUCCESS);
23061 end;
23063 //[function RegKeySetStrEx]
23064 function RegKeySetStrEx( Key: HKey; const ValueName: string; const Value: string;
23065 expand: boolean): Boolean;
23066 var dwType: DWORD;
23067 begin
23068 dwType := REG_SZ;
23069 if expand then
23070 dwType := REG_EXPAND_SZ;
23071 Result := (Key <> 0) and (RegSetValueEx(Key, PChar(ValueName), 0, dwType,
23072 PChar(Value), Length(Value) + 1) = ERROR_SUCCESS);
23073 end;
23075 //[procedure RegKeyClose]
23076 procedure RegKeyClose( Key: HKey );
23077 begin
23078 if Key <> 0 then
23079 RegCloseKey( Key );
23080 end;
23082 //[function RegKeyDelete]
23083 function RegKeyDelete( Key: HKey; const SubKey: String ): Boolean;
23084 begin
23085 Result := FALSE;
23086 if Key <> 0 then
23087 Result := RegDeleteKey( Key, PChar( SubKey ) ) = ERROR_SUCCESS;
23088 end;
23090 //[function RegKeyDeleteValue]
23091 function RegKeyDeleteValue( Key: HKey; const SubKey: String ): Boolean;
23092 begin
23093 Result := FALSE;
23094 if Key <> 0 then
23095 Result := RegDeleteValue( Key, PChar( SubKey ) ) = ERROR_SUCCESS;
23096 end;
23098 //[function RegKeyExists]
23099 function RegKeyExists( Key: HKey; const SubKey: String ): Boolean;
23100 var K: Integer;
23101 begin
23102 if Key = 0 then
23103 begin
23104 Result := FALSE;
23105 Exit;
23106 end;
23107 K := RegKeyOpenRead( Key, SubKey );
23108 Result := K <> 0;
23109 if K <> 0 then
23110 RegKeyClose( K );
23111 end;
23113 //[function RegKeyValExists]
23114 function RegKeyValExists( Key: HKey; const ValueName: String ): Boolean;
23115 var dwType, dwSize: DWORD;
23116 begin
23117 Result := (Key <> 0) and
23118 (RegQueryValueEx( Key, PChar( ValueName ), nil,
23119 @dwType, nil, @dwSize ) = ERROR_SUCCESS);
23120 end;
23122 //[function RegKeyValueSize]
23123 function RegKeyValueSize( Key: HKey; const ValueName: String ): Integer;
23124 begin
23125 Result := 0;
23126 if Key = 0 then Exit;
23127 RegQueryValueEx( Key, PChar( ValueName ), nil, nil, nil, @ DWORD( Result ) );
23128 end;
23130 //[function RegKeyGetBinary]
23131 function RegKeyGetBinary( Key: HKey; const ValueName: String; var Buffer; Count: Integer ): Integer;
23132 begin
23133 Result := 0;
23134 if Key = 0 then Exit;
23135 Result := Count;
23136 RegQueryValueEx( Key, PChar( ValueName ), nil, nil, @ Buffer, @ Result );
23137 end;
23139 //[function RegKeySetBinary]
23140 function RegKeySetBinary( Key: HKey; const ValueName: String; const Buffer; Count: Integer ): Boolean;
23141 begin
23142 Result := (Key <> 0) and (RegSetValueEx( Key, PChar( ValueName ), 0,
23143 REG_BINARY, @ Buffer, Count ) = ERROR_SUCCESS);
23144 end;
23146 //[function RegKeyGetDateTime]
23147 function RegKeyGetDateTime(Key: HKey; const ValueName: String): TDateTime;
23148 begin
23149 RegKeyGetBinary( Key, ValueName, Result, Sizeof( Result ) );
23150 end;
23152 //[function RegKeySetDateTime]
23153 function RegKeySetDateTime(Key: HKey; const ValueName: String; DateTime: TDateTime): Boolean;
23154 begin
23155 Result := RegKeySetBinary( Key, ValueName, DateTime, Sizeof( DateTime ) );
23156 end;
23158 //-----------------------------------------------
23159 // functions by Valerian Luft <luft@valerian.de>
23160 //-----------------------------------------------
23161 //[function RegKeyGetSubKeys]
23162 function RegKeyGetSubKeys( const Key: HKEY; List: PStrList) : Boolean;
23164 I, Size, NumSubKeys, MaxSubKeyLen : DWORD;
23165 KeyName: String;
23166 begin
23167 Result := False;
23168 List.Clear ;
23169 if RegQueryInfoKey(Key, nil, nil, nil, @NumSubKeys, @MaxSubKeyLen, nil, nil, nil, nil,
23170 nil, nil) = ERROR_SUCCESS then
23171 begin
23172 if NumSubKeys > 0 then begin
23173 for I := 0 to NumSubKeys-1 do
23174 begin
23175 Size := MaxSubKeyLen+1;
23176 SetLength(KeyName, Size);
23177 //FillChar(KeyName[1],Size,#0);
23178 RegEnumKeyEx(Key, I, @KeyName[1], Size, nil, nil, nil, nil);
23179 SetLength(KeyName, lstrlen(@KeyName[1]));
23180 List.Add(KeyName);
23181 end;
23182 end;
23183 Result:= True;
23184 end;
23185 end;
23188 //[function RegKeyGetValueNames]
23189 function RegKeyGetValueNames(const Key: HKEY; List: PStrList): Boolean;
23191 I, Size, NumSubKeys, NumValueNames, MaxValueNameLen: DWORD;
23192 ValueName: String;
23193 begin
23194 List.Clear ;
23195 Result:=False;
23196 if RegQueryInfoKey(Key, nil, nil, nil, @NumSubKeys, nil, nil, @NumValueNames,
23197 @MaxValueNameLen, nil, nil, nil) = ERROR_SUCCESS then
23198 begin
23199 if NumValueNames > 0 then
23200 for I := 0 to NumValueNames - 1 do begin
23201 Size := MaxValueNameLen + 1;
23202 SetLength(ValueName, Size);
23203 //FillChar(ValueName[1],Size,#0);
23204 RegEnumValue(Key, I, @ValueName[1], Size, nil, nil, nil, nil);
23205 SetLength(ValueName, lstrlen(@ValueName[1]));
23206 List.Add(ValueName);
23207 end;
23208 Result := True;
23209 end ;
23210 end;
23213 //[function RegKeyGetValueTyp]
23214 function RegKeyGetValueTyp (const Key:HKEY; const ValueName: String) : DWORD;
23215 begin
23216 Result:= Key ;
23217 if Key <> 0 then
23218 RegQueryValueEx (Key,@ValueName[1],NIL,@Result,NIL,NIL)
23219 end;
23245 //////////////////////////////////////////////////////////////////////
23248 // D A T E A N D T I M E
23251 //////////////////////////////////////////////////////////////////////
23263 { -- date and time utilities -- }
23265 {* This part of the unit contains date-time routines. It is not a simple compilation
23266 of Delphi VCL date-time. E.g., TDateTime type is not based on 31-Dec-1899,
23267 but it is based on 31-Dec-0000 instead, allowing easy manipulating of dates
23268 at all Christian era, and all other historical era too. }
23270 //[procedure DivMod]
23271 procedure DivMod(Dividend: Integer; Divisor: Word;
23272 var Result, Remainder: Word);
23273 {$IFDEF F_P}
23274 begin
23275 Result := Dividend div Divisor;
23276 Remainder := Dividend mod Divisor;
23277 end;
23278 {$ELSE DELPHI}
23280 PUSH EBX
23281 MOV EBX,EDX
23282 MOV EDX,EAX
23283 SHR EDX,16
23284 DIV BX
23285 MOV EBX,Remainder
23286 MOV [ECX],AX
23287 MOV [EBX],DX
23288 POP EBX
23289 end;
23290 {$ENDIF}
23292 {++}(*
23293 //[API GetLocalTime, GetSystemTime]
23294 procedure GetLocalTime; external kernel32 name 'GetLocalTime';
23295 procedure GetSystemTime; external kernel32 name 'GetSystemTime';
23296 *){--}
23299 //[function Now]
23300 function Now : TDateTime;
23301 var SystemTime : TSystemTime;
23302 begin
23303 GetLocalTime( SystemTime );
23304 SystemTime2DateTime( SystemTime, Result );
23305 end;
23307 //[function Date]
23308 function Date: TDateTime;
23309 begin
23310 Result := Trunc( Now );
23311 end;
23313 //[procedure DecodeDateFully]
23314 procedure DecodeDateFully( DateTime: TDateTime; var Year, Month, Day, DayOfWeek: WORD );
23315 var ST: TSystemTime;
23316 begin
23317 DateTime2SystemTime( DateTime, ST );
23318 Year := ST.wYear;
23319 Month := ST.wMonth;
23320 Day := ST.wDay;
23321 DayOfWeek := ST.wDayOfWeek;
23322 end;
23324 //[procedure DecodeDate]
23325 procedure DecodeDate( DateTime: TDateTime; var Year, Month, Day: WORD );
23326 var Dummy: Word;
23327 begin
23328 DecodeDateFully( DateTime, Year, Month, Day, Dummy );
23329 end;
23331 //[function EncodeDate]
23332 function EncodeDate( Year, Month, Day: WORD; var DateTime: TDateTime ): Boolean;
23333 var ST: TSystemTime;
23334 begin
23335 FillChar( ST, Sizeof( ST ), 0 );
23336 ST.wYear := Year;
23337 ST.wMonth := Month;
23338 ST.wDay := Day;
23339 Result := SystemTime2DateTime( ST, DateTime );
23340 end;
23342 //[FUNCTION CompareSystemTime]
23343 {$IFDEF ASM_VERSION}
23344 function CompareSystemTime( const D1, D2 : TSystemTime) : Integer; assembler;
23346 PUSH ESI
23347 PUSH EBX
23348 MOV ESI, EAX
23349 XOR EAX, EAX
23350 XOR ECX, ECX
23351 MOV CL, 8 // 8 words: wYear, wMonth,..., wMilliseconds
23352 @@loo:
23353 LODSW
23354 MOV BX, [EDX]
23355 INC EDX
23356 INC EDX
23358 CMP CL, 6
23359 JE @@cont // skip compare DayOfWeek
23361 SUB AX, BX
23362 JNE @@calc
23364 @@cont:
23365 LOOP @@loo
23366 JMP @@exit
23368 @@calc:
23369 SBB EAX, EAX
23370 {$IFDEF PARANOIA}
23371 DB $0C, 1
23372 {$ELSE}
23373 OR AL, 1
23374 {$ENDIF}
23376 @@exit:
23377 POP EBX
23378 POP ESI
23379 end;
23380 {$ELSE ASM_VERSION} //Pascal
23381 function CompareSystemTime(const D1, D2 : TSystemTime) : Integer;
23382 var R: Integer;
23383 procedure CompareFields(const F1, F2 : Integer);
23384 begin
23385 if R <> 0 then Exit;
23386 if F1 = F2 then Exit;
23387 if F1 < F2 then
23388 R := -1
23389 else
23390 R := 1;
23391 end;
23392 begin
23393 R := 0;
23394 CompareFields( D1.wYear, D2.wYear );
23395 CompareFields( D1.wMonth, D2.wMonth );
23396 CompareFields( D1.wDay, D2.wDay );
23397 CompareFields( D1.wHour, D2.wHour );
23398 CompareFields( D1.wMinute, D2.wMinute );
23399 CompareFields( D1.wSecond, D2.wSecond );
23400 CompareFields( D1.wMilliseconds, D2.wMilliseconds );
23401 Result := R;
23402 end;
23403 {$ENDIF ASM_VERSION}
23404 //[END CompareSystemTime]
23407 //[procedure IncDays]
23408 procedure IncDays( var SystemTime : TSystemTime; DaysNum : Integer );
23409 var DateTime : TDateTime;
23410 begin
23411 SystemTime2DateTime( SystemTime, DateTime );
23412 DateTime := DateTime + DaysNum;
23413 DateTime2SystemTime( DateTime, SystemTime );
23414 end;
23417 //[procedure IncMonths]
23418 procedure IncMonths( var SystemTime : TSystemTime; MonthsNum : Integer );
23419 var M : Integer;
23420 DateTime : TDateTime;
23421 begin
23422 M := SystemTime.wMonth + MonthsNum - 1;
23423 Inc( SystemTime.wYear, M div 12 );
23424 SystemTime.wMonth := M mod 12 + 1;
23426 // Normalize wDayOfWeek field:
23427 SystemTime2DateTime( SystemTime, DateTime );
23428 DateTime2SystemTime( DateTime, SystemTime );
23429 end;
23432 //[function IsLeapYear]
23433 function IsLeapYear(Year: Word): Boolean;
23434 begin
23435 Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 0));
23436 end;
23439 //[function SystemTime2DateTime]
23440 function SystemTime2DateTime(const SystemTime : TSystemTime; var DateTime : TDateTime ) : Boolean;
23441 var I : Integer;
23442 Day : Integer;
23443 DayTable: PDayTable;
23444 begin
23445 Result := False;
23446 DateTime := 0.0;
23447 DayTable := @MonthDays[IsLeapYear(SystemTime.wYear)];
23448 with SystemTime do
23449 //-------- by Vadim Petrov ----------------------------------------------------------------
23450 //if (wYear >= 1) and (wYear <= 9999) and (wMonth >= 1) and (wMonth <= 12) and
23451 // (wDay >= 1) and (wDay <= DayTable^[wMonth]) and
23452 // (wHour < 24) and (wMinute < 60) and (wSecond < 60) and (wMilliSeconds < 1000) then
23453 //---------------------------------------------------------------------------------------//
23454 if {(wYear >= 0) !always true! and} (wYear <= 9999) and
23455 {(wMonth >= 0) !always true! and} (wMonth <= 12) and
23456 {(wDay >= 0) !always true! and} (wDay <= DayTable^[wMonth]) and //
23457 (wHour < 24) and (wMinute < 60) and (wSecond < 60) and (wMilliSeconds < 1000) then //
23458 //---------------------------------------------------------------------------------------//
23459 begin
23460 Day := wDay;
23461 for I := 1 to wMonth - 1 do
23462 Inc(Day, DayTable^[I]);
23463 I := wYear - 1;
23464 //--------------- by Vadim Petrov ------++
23465 if I<0 then i := 0; //
23466 //--------------------------------------++
23467 DateTime := I * 365 + I div 4 - I div 100 + I div 400 + Day
23468 + (wHour * 3600000 + wMinute * 60000 + wSecond * 1000 + wMilliSeconds) / MSecsPerDay;
23469 Result := True;
23470 end;
23471 end;
23474 //[function DayOfWeek]
23475 function DayOfWeek(Date: TDateTime): Integer;
23476 begin
23477 Result := (Trunc( Date ) + 6) mod 7 + 1;
23478 end;
23481 //[function DateTime2SystemTime]
23482 function DateTime2SystemTime(const DateTime : TDateTime; var SystemTime : TSystemTime ) : Boolean;
23483 const
23484 D1 = 365;
23485 D4 = D1 * 4 + 1;
23486 D100 = D4 * 25 - 1;
23487 D400 = D100 * 4 + 1;
23488 var Days : Integer;
23489 Y, M, D, I: Word;
23490 MSec : Integer;
23491 DayTable: PDayTable;
23492 MinCount, MSecCount: Word;
23493 begin
23494 Days := Trunc( DateTime );
23495 MSec := Round((DateTime - Days) * MSecsPerDay);
23496 Result := False;
23497 with SystemTime do
23498 if Days > 0 then
23499 begin
23500 Dec(Days);
23501 Y := 1;
23502 while Days >= D400 do
23503 begin
23504 Dec(Days, D400);
23505 Inc(Y, 400);
23506 end;
23507 DivMod(Days, D100, I, D);
23508 if I = 4 then
23509 begin
23510 Dec(I);
23511 Inc(D, D100);
23512 end;
23513 Inc(Y, I * 100);
23514 DivMod(D, D4, I, D);
23515 Inc(Y, I * 4);
23516 DivMod(D, D1, I, D);
23517 if I = 4 then
23518 begin
23519 Dec(I);
23520 Inc(D, D1);
23521 end;
23522 Inc(Y, I);
23523 DayTable := @MonthDays[IsLeapYear(Y)];
23524 M := 1;
23525 while True do
23526 begin
23527 I := DayTable^[M];
23528 if D < I then Break;
23529 Dec(D, I);
23530 Inc(M);
23531 end;
23532 wYear := Y;
23533 wMonth := M;
23534 wDay := D + 1;
23535 wDayOfWeek := DayOfWeek( DateTime );
23536 DivMod(MSec, 60000, MinCount, MSecCount);
23537 DivMod(MinCount, 60, wHour, wMinute);
23538 DivMod(MSecCount, 1000, wSecond, wMilliSeconds);
23539 Result := True;
23540 end;
23541 end;
23543 function DateTime_DiffSysLoc: TDateTime;
23544 var ST, LT: TSystemTime;
23545 FT, FT1: TFileTime;
23546 D1, D2: TDateTime;
23547 begin
23548 GetSystemTime( ST );
23549 SystemTimeToFileTime( ST, FT );
23550 FileTimeToLocalFileTime( FT, FT1 );
23551 FileTimeToSystemTime( FT1, LT );
23552 SystemTime2DateTime( ST, D1 );
23553 SystemTime2DateTime( LT, D2 );
23554 Result := D2 - D1;
23555 end;
23557 //[function DateTime_System2Local]
23558 function DateTime_System2Local( DTSys: TDateTime ): TDateTime;
23559 begin
23560 Result := DTSys + DateTime_DiffSysLoc;
23561 end;
23563 //[function DateTime_Local2System]
23564 function DateTime_Local2System( DTLoc: TDateTime ): TDateTime;
23565 begin
23566 Result := DTLoc - DateTime_DiffSysLoc;
23567 end;
23570 //[function CatholicEaster]
23571 function CatholicEaster( nYear: Integer ): TDateTime;
23573 nMoon, nEpact, nSunday, nGold, nCent, nCorx, nCorz: Integer;
23574 SystemTime : TSystemTime;
23575 begin
23576 FillChar( SystemTime, Sizeof( SystemTime ), 0 );
23577 with SystemTime do
23578 begin
23580 wYear := nYear;
23582 { The Golden Number of the year in the 19 year Metonic Cycle }
23583 nGold := ( ( wYear mod 19 ) + 1 );
23585 { Calculate the Century }
23586 nCent := ( ( wYear div 100 ) + 1 );
23588 { No. of Years in which leap year was dropped in order to keep in step
23589 with the sun }
23590 nCorx := ( ( 3 * nCent ) div 4 - 12 );
23592 { Special Correction to Syncronize Easter with the moon's orbit }
23593 nCorz := ( ( 8 * nCent + 5 ) div 25 - 5 );
23595 { Find Sunday }
23596 nSunday := ( ( 5 * wYear ) div 4 - nCorx - 10 );
23598 { Set Epact (specifies occurance of full moon }
23599 nEpact := ( ( 11 * nGold + 20 + nCorz - nCorx ) mod 30 );
23601 if ( nEpact < 0 ) then
23602 nEpact := nEpact + 30;
23604 if ( ( nEpact = 25 ) and ( nGold > 11 ) ) or ( nEpact = 24 ) then
23605 nEpact := nEpact + 1;
23607 { Find Full Moon }
23608 nMoon := 44 - nEpact;
23610 if ( nMoon < 21 ) then
23611 nMoon := nMoon + 30;
23613 { Advance to Sunday }
23614 nMoon := ( nMoon + 7 - ( ( nSunday + nMoon ) mod 7 ) );
23616 if ( nMoon > 31 ) then
23617 begin
23618 wMonth := 4;
23619 wDay := ( nMoon - 31 );
23621 else
23622 begin
23623 wMonth := 3;
23624 wDay := nMoon;
23625 end;
23626 end;
23627 SystemTime2DateTime( SystemTime, Result );
23628 end;
23631 //[function SystemDate2Str]
23632 function SystemDate2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
23633 const DfltDateFormat : TDateFormat; const DateFormat : PChar ) : String;
23634 var Buf : PChar;
23635 Sz : Integer;
23636 Flags : DWORD;
23637 begin
23638 Sz := 100;
23639 Buf := nil;
23640 Result := '';
23641 Flags := 0;
23642 if DateFormat = nil then
23643 if DfltDateFormat = dfShortDate then
23644 Flags := DATE_SHORTDATE
23645 else
23646 Flags := DATE_LONGDATE;
23647 while True do
23648 begin
23649 if Buf <> nil then
23650 FreeMem( Buf );
23651 GetMem( Buf, Sz );
23652 if Buf = nil then Exit;
23653 if GetDateFormat( LocaleID, Flags, @SystemTime, DateFormat, Buf, Sz )
23654 = 0 then
23655 begin
23656 if GetLastError = ERROR_INSUFFICIENT_BUFFER then
23657 Sz := Sz * 2
23658 else
23659 break;
23661 else
23662 begin
23663 Result := Buf;
23664 break;
23665 end;
23666 end;
23667 if Buf <> nil then
23668 FreeMem( Buf );
23669 end;
23672 //[function SystemTime2Str]
23673 function SystemTime2Str( const SystemTime : TSystemTime; const LocaleID : DWORD;
23674 const Flags : TTimeFormatFlags; const TimeFormat : PChar ) : String;
23675 var Buf : PChar;
23676 Sz : Integer;
23677 Flg : DWORD;
23678 begin
23679 Sz := 100;
23680 Buf := nil;
23681 Result := '';
23682 Flg := 0;
23683 if tffNoMinutes in Flags then
23684 Flg := TIME_NOMINUTESORSECONDS
23685 else
23686 if tffNoSeconds in Flags then
23687 Flg := TIME_NOSECONDS;
23688 if tffNoMarker in Flags then
23689 Flg := Flg or TIME_NOTIMEMARKER;
23690 if tffForce24 in Flags then
23691 Flg := Flg or TIME_FORCE24HOURFORMAT;
23692 while True do
23693 begin
23694 if Buf <> nil then
23695 FreeMem( Buf );
23696 GetMem( Buf, Sz );
23697 if Buf = nil then Exit;
23698 if GetTimeFormat( LocaleID, Flg, @SystemTime, TimeFormat, Buf, Sz )
23699 = 0 then
23700 begin
23701 if GetLastError = ERROR_INSUFFICIENT_BUFFER then
23702 Sz := Sz * 2
23703 else
23704 break;
23706 else
23707 begin
23708 Result := Buf;
23709 break;
23710 end;
23711 end;
23712 if Buf <> nil then
23713 FreeMem( Buf );
23714 end;
23716 //[function Date2StrFmt]
23717 function Date2StrFmt( const Fmt: String; D: TDateTime ): String;
23718 var ST: TSystemTime;
23719 lpFmt: PChar;
23720 begin
23721 DateTime2SystemTime( D, ST );
23722 lpFmt := nil;
23723 if Fmt <> '' then lpFmt := PChar( Fmt );
23724 Result := SystemDate2Str( ST, LOCALE_USER_DEFAULT, dfShortDate, lpFmt );
23725 end;
23727 //[function Time2StrFmt]
23728 function Time2StrFmt( const Fmt: String; D: TDateTime ): String;
23729 var ST: TSystemTime;
23730 lpFmt: PChar;
23731 begin
23732 if D < 1 then D := D + 1;
23733 DateTime2SystemTime( D, ST );
23734 lpFmt := nil;
23735 if Fmt <> '' then lpFmt := PChar( Fmt );
23736 Result := SystemTime2Str( ST, LOCALE_USER_DEFAULT, [], lpFmt );
23737 end;
23739 //[function DateTime2StrShort]
23740 function DateTime2StrShort( D: TDateTime ): String;
23741 var ST: TSystemTime;
23742 begin
23743 //--------- by Vadim Petrov --------++
23744 if D < 1 then D := D + 1; //
23745 //----------------------------------++
23746 DateTime2SystemTime( D, ST );
23747 Result := SystemDate2Str( ST, LOCALE_USER_DEFAULT {GetUserDefaultLCID}, dfShortDate, nil ) + ' ' +
23748 SystemTime2Str( ST, LOCALE_USER_DEFAULT {GetUserDefaultLCID}, [], nil );
23749 end;
23751 //[function Str2DateTimeFmt]
23752 function Str2DateTimeFmt( const sFmtStr, sS: String ): TDateTime;
23753 var h12, hAM: Boolean;
23754 FmtStr, S: PChar;
23756 function GetNum( var S: PChar; NChars: Integer ): Integer;
23757 begin
23758 Result := 0;
23759 while (S^ <> #0) and (NChars <> 0) do
23760 begin
23761 Dec( NChars );
23762 if S^ in ['0'..'9'] then
23763 begin
23764 Result := Result * 10 + Ord(S^) - Ord('0');
23765 Inc( S );
23767 else
23768 break;
23769 end;
23770 end;
23772 function GetYear( var S: PChar; NChars: Integer ): Integer;
23773 var STNow: TSystemTime;
23774 OldDate: Boolean;
23775 begin
23776 Result := GetNum( S, NChars );
23777 GetSystemTime( STNow );
23778 OldDate := Result < 50;
23779 Result := Result + STNow.wYear - STNow.wYear mod 100;
23780 if OldDate then Dec( Result, 100 );
23781 end;
23783 function GetMonth( const fmt: String; var S: PChar ): Integer;
23784 var SD: TSystemTime;
23785 M: Integer;
23786 C, MonthStr: String;
23787 begin
23788 GetSystemTime( SD );
23789 for M := 1 to 12 do
23790 begin
23791 SD.wMonth := M;
23792 C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/dd/yyyy/' ) );
23793 MonthStr := Parse( C, '/' );
23794 if AnsiCompareStrNoCase( MonthStr, Copy( S, 1, Length( MonthStr ) ) ) = 0 then
23795 begin
23796 Result := M;
23797 Inc( S, Length( MonthStr ) );
23798 Exit;
23799 end;
23800 end;
23801 Result := 1;
23802 end;
23804 procedure SkipDayOfWeek( const fmt: String; var S: PChar );
23805 var SD: TSystemTime;
23806 Dt: TDateTime;
23807 D: Integer;
23808 C, DayWeekStr: String;
23809 begin
23810 GetSystemTime( SD );
23811 SystemTime2DateTime( SD, Dt );
23812 Dt := Dt - SD.wDayOfWeek;
23813 for D := 0 to 6 do
23814 begin
23815 DateTime2SystemTime( Dt, SD );
23816 C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/MM/yyyy/' ) );
23817 DayWeekStr := Parse( C, '/' );
23818 if AnsiCompareStrNoCase( DayWeekStr, Copy( S, 1, Length( DayWeekStr ) ) ) = 0 then
23819 begin
23820 Inc( S, Length( DayWeekStr ) );
23821 Exit;
23822 end;
23823 Dt := Dt + 1.0;
23824 end;
23825 end;
23827 procedure GetTimeMark( const fmt: String; var S: PChar );
23828 var SD: TSystemTime;
23829 AM: Boolean;
23830 C, TimeMarkStr: String;
23831 begin
23832 GetSystemTime( SD );
23833 SD.wHour := 0;
23834 for AM := FALSE to TRUE do
23835 begin
23836 C := SystemDate2Str( SD, LOCALE_USER_DEFAULT, dfLongDate, PChar( fmt + '/HH/mm' ) );
23837 TimeMarkStr := Parse( C, '/' );
23838 if AnsiCompareStrNoCase( TimeMarkStr, Copy( S, 1, Length( TimeMarkStr ) ) ) = 0 then
23839 begin
23840 Inc( S, Length( TimeMarkStr ) );
23841 hAM := AM;
23842 Exit;
23843 end;
23844 SD.wHour := 13;
23845 end;
23846 Result := 1;
23847 end;
23849 function FmtIs1( S: PChar ): Boolean;
23850 begin
23851 if StrIsStartingFrom( FmtStr, S ) then
23852 begin
23853 Inc( FmtStr, StrLen( S ) );
23854 Result := TRUE;
23856 else
23857 Result := FALSE;
23858 end;
23860 function FmtIs( S1, S2: PChar ): Boolean;
23861 begin
23862 Result := FmtIs1( S1 ) or FmtIs1( S2 );
23863 end;
23865 var ST: TSystemTime;
23866 begin
23867 FmtStr := PChar( sFmtStr);
23868 S := PChar( sS );
23869 FillChar( ST, Sizeof( ST ), 0 );
23870 h12 := FALSE;
23871 hAM := FALSE;
23872 while (FmtStr^ <> #0) and (S^ <> #0) do
23873 begin
23874 if (FmtStr^ in ['a'..'z','A'..'Z']) and (S^ in ['0'..'9']) then
23875 begin
23876 if FmtIs1( 'yyyy' ) then ST.wYear := GetNum( S, 4 )
23877 else if FmtIs1( 'yy' ) then ST.wYear := GetYear( S, 2 )
23878 else if FmtIs1( 'y' ) then ST.wYear := GetYear( S, -1 )
23879 else if FmtIs( 'dd', 'd' ) then ST.wDay := GetNum( S, 2 )
23880 else if FmtIs( 'MM', 'M' ) then ST.wMonth := GetNum( S, 2 )
23881 else if FmtIs( 'HH', 'H' ) then ST.wHour := GetNum( S, 2 )
23882 else if FmtIs( 'hh', 'h' ) then begin ST.wHour := GetNum( S, 2 ); h12 := TRUE end
23883 else if FmtIs( 'mm', 'm' ) then ST.wMinute := GetNum( S, 2 )
23884 else if FmtIs( 'ss', 's' ) then ST.wSecond := GetNum( S, 2 )
23885 else break; // + ECM
23887 else
23888 if (FmtStr^ in [ 'M', 'd', 'g' ]) then
23889 begin
23890 if FmtIs1( 'MMMM' ) then ST.wMonth := GetMonth( 'MMMM', S )
23891 else if FmtIs1( 'MMM' ) then ST.wMonth := GetMonth( 'MMM', S )
23892 else if FmtIs1( 'dddd' ) then SkipDayOfWeek( 'dddd', S )
23893 else if FmtIs1( 'ddd' ) then SkipDayOfWeek( 'ddd', S )
23894 else if FmtIs1( 'tt' ) then GetTimeMark( 'tt', S )
23895 else if FmtIs1( 't' ) then GetTimeMark( 't', S )
23896 else break; // + ECM
23898 else
23899 begin
23900 if FmtStr^ = S^ then
23901 Inc( FmtStr );
23902 Inc( S );
23903 end;
23904 end;
23906 if h12 then
23907 if hAM then
23908 Inc( ST.wHour, 12 );
23910 SystemTime2DateTime( ST, Result );
23911 end;
23913 var FmtBuf: PChar;
23914 DateSeparator : Char = #0; // + ECM
23916 //[function Str2DateTimeShort]
23917 function Str2DateTimeShort( const S: String ): TDateTime;
23918 var FmtStr, FmtStr2: String;
23920 function EnumDateFmt( lpstrFmt: PChar ): Boolean; stdcall;
23921 begin
23922 GetMem( FmtBuf, StrLen( lpstrFmt ) + 1 );
23923 StrCopy( FmtBuf, lpstrFmt );
23924 Result := FALSE;
23925 end;
23927 begin
23928 FmtStr := 'dd.MM.yyyy';
23929 FmtBuf := nil;
23930 EnumDateFormats( @ EnumDateFmt, LOCALE_USER_DEFAULT, DATE_SHORTDATE );
23931 if FmtBuf <> nil then
23932 begin
23933 FmtStr := FmtBuf;
23934 FreeMem( FmtBuf );
23935 end;
23937 FmtStr2 := 'H:mm:ss';
23938 FmtBuf := nil;
23939 EnumTimeFormats( @ EnumDateFmt, LOCALE_USER_DEFAULT, 0 );
23940 if FmtBuf <> nil then
23941 begin
23942 FmtStr2 := FmtBuf;
23943 FreeMem( FmtBuf );
23944 end;
23946 Result := Str2DateTimeFmt( FmtStr + ' ' + FmtStr2, S );
23947 end;
23949 // + ECM
23950 //[function Str2DateTimeShortEx]
23951 function Str2DateTimeShortEx( const S: String ): TDateTime;
23952 var St: String;
23953 Buff: Array[0..1] of Char;
23954 begin
23955 if DateSeparator = #0 then
23956 begin
23957 if GetLocaleInfo(GetThreadLocale,LOCALE_SDATE,Buff,2) > 0 then
23958 DateSeparator := Buff[0];
23959 end;
23960 St := S;
23961 if Pos(DateSeparator,S) = 0 then
23962 St := '0.0.0 '+S;
23963 Result := Str2DateTimeShort(St);
23964 end;
23983 ///////////////////////////////////////////////////////////////////////
23986 // T H R E A D S
23989 ///////////////////////////////////////////////////////////////////////
23998 { -- Thread -- }
24000 //[function ThreadFunc]
24001 function ThreadFunc(Thread: PThread): integer; stdcall;
24002 begin
24003 Result := Thread.Execute;
24004 end;
24006 {$IFDEF USE_CONSTRUCTORS}
24007 //[function NewThread]
24008 function NewThread: PThread;
24009 begin
24010 new( Result, ThreadCreate );
24011 end;
24012 //[END NewThread]
24013 {$ELSE not_USE_CONSTRUCTORS}
24015 //[function NewThread]
24016 function NewThread: PThread;
24017 begin
24018 {$IFNDEF FPC105ORBELOW}
24019 IsMultiThread := True;
24020 {$ENDIF}
24022 New( Result, Create );
24024 {++}(*Result := PThread.Create;*){--}
24025 Result.FSuspended := True;
24026 Result.FHandle := CreateThread( nil, // no security
24027 0, // the same stack size
24028 @ThreadFunc, // thread entry point
24029 Result, // parameter to pass to ThreadFunc
24030 CREATE_SUSPENDED, // always SUSPENDED
24031 Result.FThreadID ); // receive thread ID
24032 end;
24033 //[END NewThread]
24034 {$ENDIF USE_CONSTRUCTORS}
24036 {$IFDEF USE_CONSTRUCTORS}
24037 //[function NewThreadEx]
24038 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
24039 begin
24040 new( Result, ThreadCreateEx( Proc ) );
24041 end;
24042 {$ELSE not_USE_CONSTRUCTORS}
24044 //[FUNCTION NewThreadEx]
24045 {$IFDEF ASM_VERSION}
24046 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
24048 CALL NewThread
24049 POP EBP
24050 POP ECX
24051 POP EDX
24052 MOV [EAX].TThread.fOnExecute.TMethod.Code, EDX
24053 POP EDX
24054 MOV [EAX].TThread.fOnExecute.TMethod.Data, EDX
24055 PUSH ECX
24056 PUSH EAX
24057 CALL TThread.Resume
24058 POP EAX
24060 end;
24061 {$ELSE ASM_VERSION} //Pascal
24062 function NewThreadEx( const Proc: TOnThreadExecute ): PThread;
24063 begin
24064 Result := NewThread;
24065 Result.OnExecute := {++}(*{$IFDEF F_P} @ {$ENDIF}*){--}Proc;
24066 Result.Resume;
24067 end;
24068 {$ENDIF ASM_VERSION}
24069 //[END NewThreadEx]
24071 {$ENDIF USE_CONSTRUCTORS}
24073 //[function NewThreadAutoFree]
24074 function NewThreadAutoFree( const Proc: TOnThreadExecute ): PThread;
24075 begin
24076 Result := NewThread;
24077 Result.OnExecute := {++}(*{$IFDEF F_P} @ {$ENDIF}*){--}Proc;
24078 Result.F_AutoFree := TRUE;
24079 if Assigned( Proc ) then
24080 Result.Resume;
24081 end;
24083 { TThread }
24085 {$IFDEF ASM_VERSION}
24086 //[destructor TThread.Destroy]
24087 destructor TThread.Destroy;
24089 PUSH EBX
24090 MOV EBX, EAX
24091 CMP [EAX].FTerminated, 0
24092 JNZ @@1
24093 CALL Terminate
24094 MOV EAX, EBX
24095 CALL WaitFor
24096 @@1: MOV ECX, [EBX].FHandle
24097 JECXZ @@2
24098 PUSH ECX
24099 CALL CloseHandle
24100 @@2: POP EAX
24101 XCHG EBX, EAX
24102 JMP TObj.Destroy
24103 end;
24104 {$ELSE ASM_VERSION} //Pascal
24105 destructor TThread.Destroy;
24106 begin
24107 if not FTerminated then
24108 begin
24109 Terminate;
24110 WaitFor;
24111 end;
24112 if (FHandle <> 0) then
24113 CloseHandle(FHandle);
24114 inherited;
24115 end;
24116 {$ENDIF ASM_VERSION}
24119 //[function TThread.Execute]
24120 function TThread.Execute: integer;
24121 begin
24122 Result := 0;
24123 if Assigned( FOnExecute ) then
24124 Result := FOnExecute( @Self );
24125 if F_AutoFree then
24126 begin
24127 FTerminated := TRUE; // fake thread object (to prevent terminating while freeing)
24128 Free;
24129 end;
24130 end;
24133 //[function TThread.GetPriorityCls]
24134 function TThread.GetPriorityCls: Integer;
24135 begin
24136 Result := GetPriorityClass(FHandle);
24137 end;
24140 //[function TThread.GetThrdPriority]
24141 function TThread.GetThrdPriority: Integer;
24142 begin
24143 Result := GetThreadPriority(FHandle);
24144 end;
24147 //[procedure TThread.Resume]
24148 procedure TThread.Resume;
24149 begin
24150 FSuspended := False;
24151 if (ResumeThread(FHandle) > 1) then
24152 FSuspended := True
24153 else
24154 if Assigned(FOnResume) then
24155 FOnResume(@Self);
24156 end;
24159 //[procedure TThread.SetPriorityCls]
24160 procedure TThread.SetPriorityCls(Value: Integer);
24161 begin
24162 {$IFDEF DEBUG}
24163 if not SetPriorityClass(GetCurrentProcess, Value) then
24164 begin
24165 ShowMessage( SysErrorMessage( GetLastError ) );
24166 end;
24167 {$ELSE}
24168 SetPriorityClass(GetCurrentProcess, Value);
24169 {$ENDIF}
24170 end;
24173 //[procedure TThread.SetThrdPriority]
24174 procedure TThread.SetThrdPriority(Value: Integer);
24175 begin
24176 SetThreadPriority(FHandle, Value);
24177 end;
24180 //[procedure TThread.Suspend]
24181 procedure TThread.Suspend;
24182 begin
24183 FSuspended := TRUE;
24184 if Assigned(FOnSuspend) then
24185 Synchronize( FOnSuspend );
24186 SuspendThread(FHandle);
24187 end;
24190 //[procedure CallSynchronized]
24191 procedure CallSynchronized( Sender: PObj; Param: Pointer );
24192 var Thread: PThread;
24193 begin
24194 Thread := PThread( Sender );
24195 if Param <> nil then
24196 Thread.FMethodEx( Thread, Param )
24197 else
24198 Thread.FMethod( );
24199 end;
24202 //[procedure TThread.Synchronize]
24203 procedure TThread.Synchronize(Method: TThreadMethod);
24204 begin
24205 Global_Synchronized := CallSynchronized;
24206 FMethod := Method;
24207 if Applet <> nil then
24208 SendMessage( Applet.fHandle, CM_EXECPROC, 0, Integer( @Self ) );
24209 end;
24211 //[procedure TThread.SynchronizeEx]
24212 procedure TThread.SynchronizeEx( Method: TThreadMethodEx; Param: Pointer );
24213 begin
24214 Assert( Param <> nil, 'Parameter must not be NIL' );
24215 Global_Synchronized := CallSynchronized;
24216 FMethodEx := Method;
24217 SendMessage( Applet.fHandle, CM_EXECPROC, Integer( Param ), Integer( @Self ) );
24218 end;
24221 //[procedure TThread.Terminate]
24222 procedure TThread.Terminate;
24223 begin
24224 TerminateThread(FHandle,0);
24225 FTerminated := True;
24226 end;
24229 //[function TThread.WaitFor]
24230 function TThread.WaitFor: Integer;
24231 begin
24232 RefInc;
24233 Result := -1;
24234 if FHandle = 0 then Exit;
24235 WaitForSingleObject(FHandle, INFINITE);
24236 GetExitCodeThread(FHandle, DWORD(Result));
24237 RefDec;
24238 end;
24242 { TStream }
24244 {* This part of the unit contains implementation of streams for KOL. Please note,
24245 that both stream types (file stream and memory stream) are incapsulated
24246 by a single object type TStream. To avoid including unnedeed code,
24247 use constructing functions NewReadFileStream and NewWriteFileStream
24248 to work with file streams, which do not require both types of operation. }
24250 {* To create new type of stream, define your own methods, and in your
24251 constructing function, pass it to _NewStream function (through
24252 TStreamMethods record). In a field Custom, You can store a reference to
24253 your own data of any type (but do not forget to define correct releasing
24254 of such data in your fClose procedure). }
24256 //[function TStream.GetPosition]
24257 function TStream.GetPosition: DWord;
24258 begin
24259 Result := Seek( 0, spCurrent );
24260 end;
24262 //[procedure TStream.SetPosition]
24263 procedure TStream.SetPosition(Value: DWord);
24264 begin
24265 Seek( Value, spBegin );
24266 end;
24268 {$IFDEF ASM_VERSION}
24269 //[function TStream.GetSize]
24270 function TStream.GetSize: DWord;
24272 CALL [EAX].fMethods.fGetSiz
24273 end;
24274 {$ELSE ASM_VERSION} //Pascal
24275 function TStream.GetSize: DWord;
24276 begin
24277 Result := fMethods.fGetSiz( @Self );
24278 end;
24279 {$ENDIF ASM_VERSION}
24281 {$IFDEF ASM_VERSION}
24282 //[procedure TStream.SetSize]
24283 procedure TStream.SetSize(NewSize: DWord);
24285 CALL [EAX].fMethods.fSetSiz
24286 end;
24287 {$ELSE ASM_VERSION} //Pascal
24288 procedure TStream.SetSize(NewSize: DWord);
24289 begin
24290 fMethods.fSetSiz( @Self, NewSize );
24291 end;
24292 {$ENDIF ASM_VERSION}
24294 //[function TStream.GetFileStreamHandle]
24295 function TStream.GetFileStreamHandle: THandle;
24296 begin
24297 Result := fData.fHandle;
24298 end;
24300 {$IFDEF ASM_VERSION}
24301 //[function TStream.Read]
24302 function TStream.Read(var Buffer; Count: DWord): DWord;
24304 CALL [EAX].fMethods.fRead
24305 end;
24306 {$ELSE ASM_VERSION} //Pascal
24307 function TStream.Read(var Buffer; Count: DWord): DWord;
24308 begin
24309 Result := fMethods.fRead( @Self, Buffer, Count );
24310 end;
24311 {$ENDIF ASM_VERSION}
24313 //[function TStream.GetCapacity]
24314 function TStream.GetCapacity: DWORD;
24315 begin
24316 Result := fData.fCapacity;
24317 end;
24319 //[procedure TStream.SetCapacity]
24320 procedure TStream.SetCapacity(const Value: DWORD);
24321 var OldSize: DWORD;
24322 begin
24323 if fData.fCapacity >= Value then Exit;
24324 OldSize := Size;
24325 Size := Value;
24326 Size := OldSize;
24327 end;
24329 //[function TStream.Busy]
24330 function TStream.Busy: Boolean;
24331 begin
24332 Result := Assigned( fData.fThread );
24333 end;
24335 //[function TStream.DoAsyncRead]
24336 function TStream.DoAsyncRead( Sender: PThread ): Integer;
24337 begin
24338 Read( Pointer( fParam1 )^, fParam2 );
24339 fData.fThread := nil;
24340 Result := 0;
24341 end;
24343 //[procedure TStream.ReadAsync]
24344 procedure TStream.ReadAsync(var Buffer; Count: DWord);
24345 begin
24346 if Busy then Wait;
24347 fData.fThread := NewThreadAutoFree( nil );
24348 fData.fThread.OnExecute := DoAsyncRead;
24349 fParam1 := DWORD( @ Buffer );
24350 fParam2 := Count;
24351 fData.fThread.Resume;
24352 end;
24354 //[function TStream.DoAsyncSeek]
24355 function TStream.DoAsyncSeek( Sender: PThread ): Integer;
24356 begin
24357 Seek( fParam1, TMoveMethod( fParam2 ) );
24358 fData.fThread := nil;
24359 Result := 0;
24360 end;
24362 //[procedure TStream.SeekAsync]
24363 procedure TStream.SeekAsync(MoveTo: Integer; MoveMethod: TMoveMethod);
24364 begin
24365 if Busy then Wait;
24366 fData.fThread := NewThreadAutoFree( nil );
24367 fData.fThread.OnExecute := DoAsyncSeek;
24368 fParam1 := MoveTo;
24369 fParam2 := Ord( MoveMethod );
24370 fData.fThread.Resume;
24371 end;
24373 //[function TStream.DoAsyncWrite]
24374 function TStream.DoAsyncWrite( Sender: PThread ): Integer;
24375 begin
24376 Write( Pointer( fParam1 )^, fParam2 );
24377 fData.fThread := nil;
24378 Result := 0;
24379 end;
24381 //[procedure TStream.WriteAsync]
24382 procedure TStream.WriteAsync(var Buffer; Count: DWord);
24383 begin
24384 if Busy then Wait;
24385 fData.fThread := NewThreadAutoFree( nil );
24386 fData.fThread.OnExecute := DoAsyncWrite;
24387 fParam1 := DWORD( @ Buffer );
24388 fParam2 := Count;
24389 fData.fThread.Resume;
24390 end;
24392 //[procedure TStream.Wait]
24393 procedure TStream.Wait;
24394 begin
24395 if not Assigned( fData.fThread ) then Exit;
24396 if Assigned( fMethods.fWait ) then
24397 fMethods.fWait( @Self )
24398 else
24399 fData.fThread.WaitFor;
24400 end;
24402 {$IFDEF ASM_VERSION}
24403 //[function TStream.Write]
24404 function TStream.Write(var Buffer; Count: DWord): DWord;
24406 CALL [EAX].fMethods.fWrite
24407 end;
24408 {$ELSE ASM_VERSION} //Pascal
24409 function TStream.Write(var Buffer; Count: DWord): DWord;
24410 begin
24411 Result := fMethods.fWrite( @Self, Buffer, Count );
24412 end;
24413 {$ENDIF ASM_VERSION}
24415 //[function TStream.WriteStr]
24416 function TStream.WriteStr(S: String): DWORD;
24417 begin
24418 if S <> '' then
24419 Result := fMethods.fWrite( @Self, S[1], Length( S ) )
24420 else
24421 Result := 0;
24422 end;
24424 //[function TStream.ReadStrZ]
24425 function TStream.ReadStrZ: String;
24426 var C: Char;
24427 begin
24428 Result := '';
24429 REPEAT
24430 C := #0;
24431 Read( C, 1 );
24432 if C <> #0 then Result := Result + C;
24433 UNTIL C = #0;
24434 end;
24436 //[function TStream.ReadStr]
24437 function TStream.ReadStr: String;
24438 var C: Char;
24439 begin
24440 Result := '';
24441 REPEAT
24442 C := #0;
24443 Read( C, 1 );
24444 if C <> #0 then
24445 begin
24446 if C = #13 then
24447 begin
24448 C := #0;
24449 Read( C, 1 );
24450 if C <> #10 then Position := Position - 1;
24451 C := #13;
24453 else
24454 if C = #10 then
24455 C := #13;
24456 if C <> #13 then
24457 Result := Result + C;
24458 end;
24459 UNTIL C in [ #13, #0 ];
24460 end;
24462 //[function TStream.WriteStrZ]
24463 function TStream.WriteStrZ(S: String): DWORD;
24464 var C: Char;
24465 begin
24466 if S = '' then
24467 begin
24468 C := #0;
24469 Result := Write( C, 1 );
24471 else
24472 Result := Write( S[ 1 ], Length( S ) + 1 );
24473 end;
24475 //[function TStream.WriteStrEx]
24476 function TStream.WriteStrEx(S: String): DWord;
24477 var L: DWORD;
24478 begin
24479 L := length(s);
24480 result:=fmethods.fwrite(@self,L,Sizeof(DWORD));
24481 if result = Sizeof(DWORD) then
24482 Inc( result, fmethods.fwrite(@self,s[1],L) );
24483 end;
24485 //[function TStream.ReadStrExVar]
24486 function TStream.ReadStrExVar(var S: String): DWord;
24487 begin
24488 fmethods.fread(@self,result,Sizeof(DWORD));
24489 setlength(s,result);
24490 if result<>0 then result:=fmethods.fread(@self,s[1],result);
24491 end;
24493 //[function TStream.ReadStrEx]
24494 function TStream.ReadStrEx: String;
24495 begin
24496 readstrexvar(result);
24497 end;
24499 //[function TStream.WriteStrPas]
24500 function TStream.WriteStrPas( S: String ): DWORD;
24501 var L: Integer;
24502 begin
24503 Result := 0;
24504 L := Length( S );
24505 if L > 255 then L := 255;
24506 if Write( L, 1 ) < 1 then Exit;
24507 Result := 1;
24508 if L > 0 then
24509 Result := Write( S[ 1 ], L ) + 1;
24510 end;
24512 //[function TStream.ReadStrPas]
24513 function TStream.ReadStrPas: String;
24514 var L: Byte;
24515 begin
24516 Result := '';
24517 if Read( L, 1 ) < 1 then Exit;
24518 SetLength( Result, L );
24519 L := Read( Result[ 1 ], L );
24520 Result := Copy( Result, 1, L );
24521 end;
24524 {$IFDEF ASM_VERSION}
24525 //[function TStream.Seek]
24526 function TStream.Seek(MoveTo: integer; MoveMethod: TMoveMethod): DWord;
24528 CALL [EAX].fMethods.fSeek
24529 end;
24530 {$ELSE ASM_VERSION} //Pascal
24531 function TStream.Seek(MoveTo: integer; MoveMethod: TMoveMethod): DWord;
24532 begin
24533 Result := fMethods.fSeek( @Self, MoveTo, MoveMethod );
24534 end;
24535 {$ENDIF ASM_VERSION}
24537 {$IFDEF ASM_VERSION}
24538 //[destructor TStream.Destroy]
24539 destructor TStream.Destroy;
24541 PUSH EAX
24542 PUSH [EAX].fData.fThread
24543 CALL [EAX].fMethods.fClose
24544 POP EAX
24545 CALL TObj.Free
24546 POP EAX
24547 CALL TObj.Destroy
24548 end;
24549 {$ELSE ASM_VERSION} //Pascal
24550 destructor TStream.Destroy;
24551 begin
24552 fMethods.fClose( @Self );
24553 fData.fThread.Free;
24554 inherited;
24555 end;
24556 {$ENDIF ASM_VERSION}
24558 //+-
24559 //[function _NewStream]
24560 function _NewStream( const StreamMethods: TStreamMethods ): PStream;
24561 begin
24563 New( Result, Create );
24564 {+}{++}(*Result := PStream.Create;*){--}
24565 Move( StreamMethods, Result.fMethods, Sizeof( TStreamMethods ) );
24566 Result.fPMethods := @Result.fMethods;
24567 end;
24570 //[function SeekFileStream]
24571 function SeekFileStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
24572 begin
24573 Result := FileSeek( Strm.fData.fHandle, MoveTo, MoveFrom );
24574 end;
24577 //[function GetSizeFileStream]
24578 function GetSizeFileStream( Strm: PStream ): DWORD;
24579 begin
24580 Result := GetFileSize( Strm.fData.fHandle, nil );
24581 if Result = DWORD( -1 ) then Result := 0;
24582 end;
24584 //[procedure DummySetSize]
24585 procedure DummySetSize( Strm: PStream; Value: DWORD );
24586 begin
24587 end;
24589 //[procedure DummyStreamProc]
24590 procedure DummyStreamProc(Strm: PStream);
24591 begin
24592 end;
24594 //[function DummyReadWrite]
24595 function DummyReadWrite( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
24597 XOR EAX, EAX
24598 end;
24600 //[function ReadFileStream]
24601 function ReadFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
24602 begin
24603 Result := FileRead( Strm.fData.fHandle, Buffer, Count );
24604 end;
24606 //[function WriteFileStream]
24607 function WriteFileStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
24608 begin
24609 Result := FileWrite( Strm.fData.fHandle, Buffer, Count );
24610 end;
24612 //[FUNCTION WriteFileStreamEOF]
24613 {$IFDEF ASM_VERSION}
24614 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
24616 PUSH EBX
24617 PUSH [EAX].TStream.fData.fHandle
24618 CALL WriteFileStream
24619 XCHG EBX, EAX
24620 CALL SetEndOfFile
24621 XCHG EAX, EBX
24622 POP EBX
24623 end;
24624 {$ELSE ASM_VERSION} //Pascal
24625 function WriteFileStreamEOF( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
24626 begin
24627 Result := WriteFileStream( Strm, Buffer, Count );
24628 SetEndOfFile( Strm.fData.fHandle );
24629 end;
24630 {$ENDIF ASM_VERSION}
24631 //[END WriteFileStreamEOF]
24633 //[procedure CloseFileStream]
24634 procedure CloseFileStream( Strm: PStream );
24635 begin
24636 FileClose( Strm.fData.fHandle );
24637 end;
24639 //[FUNCTION SeekMemStream]
24640 {$IFDEF ASM_VERSION}
24641 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
24643 PUSH EBX
24644 MOV EBX, EDX
24645 AND ECX, $FF
24646 LOOP @@not_from_cur
24647 ADD EBX, [EAX].TStream.fData.fPosition
24648 @@not_from_cur:
24649 LOOP @@not_from_end
24650 ADD EBX, [EAX].TStream.fData.fSize
24651 @@not_from_end:
24652 CMP EBX, [EAX].TStream.fData.fSize
24653 JLE @@space_ok
24654 PUSH EAX
24655 MOV EDX, EBX
24656 CALL TStream.SetSize
24657 POP EAX
24658 @@space_ok:
24659 XCHG EAX, EBX
24660 MOV [EBX].TStream.fData.fPosition, EAX
24661 POP EBX
24662 end;
24663 {$ELSE ASM_VERSION} //Pascal
24664 function SeekMemStream( Strm: PStream; MoveTo: Integer; MoveFrom: TMoveMethod ): DWORD;
24665 var NewPos: DWORD;
24666 begin
24667 case MoveFrom of
24668 spBegin: NewPos := MoveTo;
24669 spCurrent: NewPos := Strm.fData.fPosition + DWORD( MoveTo );
24670 else //spEnd:
24671 NewPos := Strm.fData.fSize + DWORD( MoveTo );
24672 end;
24673 if NewPos > Strm.fData.fSize then
24674 Strm.SetSize( NewPos );
24675 Strm.fData.fPosition := NewPos;
24676 Result := NewPos;
24677 end;
24678 {$ENDIF ASM_VERSION}
24679 //[END SeekMemStream]
24681 //[function GetSizeMemStream]
24682 function GetSizeMemStream( Strm: PStream ): DWORD;
24683 begin
24684 Result := Strm.fData.fSize;
24685 end;
24687 //[PROCEDURE SetSizeMemStream]
24688 {$IFDEF ASM_VERSION}
24689 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );
24691 CMP [EAX].TStream.fData.fCapacity, EDX
24692 JGE @@cap_ok
24693 PUSH EDX
24694 PUSH EAX
24695 MOV ECX, [EAX].TStream.fMemory
24696 JECXZ @@get_mem
24697 TEST EDX, EDX
24698 JZ @@free_mem
24699 LEA EAX, [EAX].TStream.fMemory
24700 CALL System.@ReallocMem
24701 JMP @@1
24702 @@get_mem:
24703 XCHG EAX, EDX
24704 CALL System.@GetMem
24705 XCHG EDX, EAX
24706 POP EAX
24707 MOV [EAX].TStream.fMemory, EDX
24708 JMP @@2
24709 @@free_mem:
24710 XCHG EDX, [EAX].TStream.fMemory
24711 XCHG EAX, EDX
24712 CALL System.@FreeMem
24713 @@1:
24714 POP EAX
24715 @@2:
24716 POP EDX
24718 @@cap_ok:
24719 MOV [EAX].TStream.fData.fSize, EDX
24720 CMP [EAX].TStream.fData.fPosition, EDX
24721 JLE @@exit
24722 MOV [EAX].TStream.fData.fPosition, EDX
24723 @@exit:
24724 end;
24725 {$ELSE ASM_VERSION} //Pascal
24726 procedure SetSizeMemStream( Strm: PStream; NewSize: DWORD );
24727 var S: PStream;
24728 begin
24729 S := Strm;
24730 if S.fData.fCapacity < NewSize then
24731 begin
24732 if S.fMemory = nil then
24733 begin
24734 if NewSize <> 0 then
24735 GetMem( S.fMemory, NewSize );
24737 else
24738 if NewSize = 0 then
24739 begin
24740 FreeMem( S.fMemory );
24741 S.fMemory := nil;
24743 else
24744 ReallocMem( S.fMemory, NewSize );
24745 S.fData.fCapacity := NewSize;
24746 end;
24747 S.fData.fSize := NewSize;
24748 if S.fData.fPosition > S.fData.fSize then
24749 S.fData.fPosition := S.fData.fSize;
24750 end;
24751 {$ENDIF ASM_VERSION}
24752 //[END SetSizeMemStream]
24754 //[FUNCTION ReadMemStream]
24755 {$IFDEF ASM_VERSION}
24756 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
24758 PUSH EBX
24759 XCHG EBX, EAX
24760 MOV EAX, [EBX].TStream.fData.fPosition
24761 ADD EAX, ECX
24762 CMP EAX, [EBX].TStream.fData.fSize
24763 JLE @@count_ok
24764 MOV ECX, [EBX].TStream.fData.fSize
24765 SUB ECX, [EBX].TStream.fData.fPosition
24766 @@count_ok:
24767 PUSH ECX
24768 MOV EAX, [EBX].TStream.fMemory
24769 ADD EAX, [EBX].TStream.fData.fPosition
24770 CALL System.Move
24771 POP EAX
24772 ADD [EBX].TStream.fData.fPosition, EAX
24773 POP EBX
24774 end;
24775 {$ELSE ASM_VERSION} //Pascal
24776 function ReadMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
24777 var S: PStream;
24778 begin
24779 S := Strm;
24780 if Count + S.fData.fPosition > S.fData.fSize then
24781 Count := S.fData.fSize - S.fData.fPosition;
24782 Result := Count;
24783 Move( Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Buffer, Result );
24784 Inc( S.fData.fPosition, Result );
24785 end;
24786 {$ENDIF ASM_VERSION}
24787 //[END ReadMemStream]
24789 //[FUNCTION WriteMemStream]
24790 {$IFDEF ASM_VERSION}
24791 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
24793 PUSH EBX
24794 XCHG EBX, EAX
24795 MOV EAX, [EBX].TStream.fData.fPosition
24796 ADD EAX, ECX
24797 CMP EAX, [EBX].TStream.fData.fSize
24798 PUSH EDX
24799 PUSH ECX
24800 JLE @@count_ok
24801 XCHG EDX, EAX
24802 MOV EAX, EBX
24803 CALL TStream.SetSize
24804 @@count_ok:
24805 POP ECX
24806 POP EAX
24807 MOV EDX, [EBX].TStream.fMemory
24808 ADD EDX, [EBX].TStream.fData.fPosition
24809 PUSH ECX
24810 CALL System.Move
24811 POP EAX
24812 ADD [EBX].TStream.fData.fPosition, EAX
24813 POP EBX
24814 end;
24815 {$ELSE ASM_VERSION} //Pascal
24816 function WriteMemStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
24817 var S: PStream;
24818 begin
24819 S := Strm;
24820 if Count + S.fData.fPosition > S.fData.fSize then
24821 S.SetSize( S.fData.fPosition + Count );
24822 Result := Count;
24823 Move( Buffer, Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Result );
24824 Inc( S.fData.fPosition, Result );
24825 end;
24826 {$ENDIF ASM_VERSION}
24827 //[END WriteMemStream]
24829 //[PROCEDURE CloseMemStream]
24830 {$IFDEF ASM_VERSION}
24831 procedure CloseMemStream( Strm: PStream );
24833 MOV ECX, [EAX].TStream.fMemory
24834 JECXZ @@exit
24835 XCHG EAX, ECX
24836 CALL System.@FreeMem
24837 @@exit:
24838 end;
24839 {$ELSE ASM_VERSION} //Pascal
24840 procedure CloseMemStream( Strm: PStream );
24841 var S: PStream;
24842 begin
24843 S := Strm;
24844 if S.fMemory <> nil then
24845 FreeMem( S.fMemory );
24846 end;
24847 {$ENDIF ASM_VERSION}
24848 //[END CloseMemStream]
24850 const
24851 BaseFileMethods: TStreamMethods = (
24852 fSeek: SeekFileStream;
24853 fGetSiz: GetSizeFileStream;
24854 fSetSiz: DummySetSize;
24855 fRead: DummyReadWrite;
24856 fWrite: DummyReadWrite;
24857 fClose: CloseFileStream;
24858 fCustom: nil;
24861 MemoryMethods: TStreamMethods = (
24862 fSeek: SeekMemStream;
24863 fGetSiz: GetSizeMemStream;
24864 fSetSiz: SetSizeMemStream;
24865 fRead: ReadMemStream;
24866 fWrite: WriteMemStream;
24867 fClose: CloseMemStream;
24868 fCustom: nil;
24871 // by Roman Vorobets:
24872 //[procedure SetSizeFileStream]
24873 procedure SetSizeFileStream( Strm: PStream; NewSize: DWORD );
24875 P: DWORD;
24876 begin
24877 P:=Strm.Position;
24878 Strm.Position:=NewSize;
24879 SetEndOfFile(Strm.Handle);
24880 if P < NewSize then
24881 Strm.Position:=P;
24882 end;
24884 //[function NewFileStream]
24885 function NewFileStream( const FileName: String; Options: DWORD ): PStream;
24886 begin
24887 Result := _NewStream( BaseFileMethods );
24888 Result.fMethods.fRead := ReadFileStream;
24889 Result.fMethods.fWrite := WriteFileStream; // not WriteStreamEOF, Àëåêñåé Øóâàëîâ
24890 Result.fMethods.fSetSiz := SetSizeFileStream;
24891 Result.fData.fHandle := FileCreate( FileName, Options );
24892 end;
24894 //[FUNCTION NewReadFileStream]
24895 {$IFDEF ASM_VERSION}
24896 function NewReadFileStream( const FileName: String ): PStream;
24898 PUSH EBX
24899 XCHG EBX, EAX
24900 MOV EAX, offset[BaseFileMethods]
24901 CALL _NewStream
24902 MOV [EAX].TStream.fMethods.fRead, offset[ReadFileStream]
24903 XCHG EBX, EAX
24904 MOV EDX, ofOpenRead or ofOpenExisting or ofShareDenyWrite
24905 CALL FileCreate
24906 MOV [EBX].TStream.fData.fHandle, EAX
24907 XCHG EAX, EBX
24908 POP EBX
24909 end;
24910 {$ELSE ASM_VERSION} //Pascal
24911 function NewReadFileStream( const FileName: String ): PStream;
24912 begin
24913 Result := _NewStream( BaseFileMethods );
24914 Result.fMethods.fRead := ReadFileStream;
24915 Result.fData.fHandle := FileCreate( FileName,
24916 ofOpenRead or ofShareDenyWrite or ofOpenExisting );
24917 end;
24918 {$ENDIF ASM_VERSION}
24919 //[END NewReadFileStream]
24921 //[FUNCTION NewWriteFileStream]
24922 {$IFDEF ASM_VERSION}
24923 function NewWriteFileStream( const FileName: String ): PStream;
24925 PUSH EBX
24926 XCHG EBX, EAX
24927 MOV EAX, offset[BaseFileMethods]
24928 CALL _NewStream
24929 MOV [EAX].TStream.fMethods.fWrite, offset[WriteFileStreamEOF]
24930 MOV [EAX].TStream.fMethods.fSetSiz, offset[SetSizeFileStream]
24931 XCHG EBX, EAX
24932 MOV EDX, ofOpenWrite or ofCreateAlways or ofShareDenyWrite
24933 CALL FileCreate
24934 MOV [EBX].TStream.fData.fHandle, EAX
24935 XCHG EAX, EBX
24936 POP EBX
24937 end;
24938 {$ELSE ASM_VERSION} //Pascal
24939 function NewWriteFileStream( const FileName: String ): PStream;
24940 begin
24941 Result := _NewStream( BaseFileMethods );
24942 Result.fMethods.fWrite := WriteFileStreamEOF;
24943 Result.fMethods.fSetSiz := SetSizeFileStream;
24944 Result.fData.fHandle := FileCreate( FileName,
24945 ofOpenWrite or ofCreateAlways or ofShareDenyWrite );
24946 end;
24947 {$ENDIF ASM_VERSION}
24948 //[END NewWriteFileStream]
24950 //[FUNCTION NewReadWriteFileStream]
24951 {$IFDEF ASM_noVERSION}
24952 function NewReadWriteFileStream( const FileName: String ): PStream;
24954 PUSH EBX
24955 XCHG EBX, EAX
24956 MOV EAX, offset[BaseFileMethods]
24957 CALL _NewStream
24958 MOV [EAX].TStream.fMethods.fRead, offset[ReadFileStream]
24959 MOV [EAX].TStream.fMethods.fWrite, offset[WriteFileStream]
24960 MOV [EAX].TStream.fMethods.fSetSiz, offset[SetSizeFileStream]
24961 XCHG EBX, EAX
24963 PUSH EAX
24964 CALL FileExists
24965 MOV EDX, ofOpenReadWrite or ofCreateAlways or ofShareDenyWrite
24966 ADD DH, AL // $200 (ofCreateAlways) -> $300 (ofCreateExisting)
24967 POP EAX
24969 CALL FileCreate
24970 MOV [EBX].TStream.fData.fHandle, EAX
24971 XCHG EAX, EBX
24972 POP EBX
24973 end;
24974 {$ELSE ASM_VERSION} //Pascal
24975 function NewReadWriteFileStream( const FileName: String ): PStream;
24976 var Creation: DWORD;
24977 begin
24978 Result := _NewStream( BaseFileMethods );
24979 Result.fMethods.fRead := ReadFileStream;
24980 Result.fMethods.fWrite := WriteFileStream;
24981 Result.fMethods.fSetSiz := SetSizeFileStream;
24982 Creation := ofCreateAlways;
24983 if FileExists( FileName ) then Creation := ofOpenExisting;
24984 Result.fData.fHandle := FileCreate( FileName,
24985 ofOpenReadWrite or Creation or ofShareDenyWrite );
24986 end;
24987 {$ENDIF ASM_VERSION}
24988 //[END NewReadWriteFileStream]
24990 //[function NewMemoryStream]
24991 function NewMemoryStream: PStream;
24992 begin
24993 Result := _NewStream( MemoryMethods );
24994 end;
24996 //[FUNCTION WriteExMemoryStream]
24997 {$IFDEF ASM_VERSION}
24998 function WriteExMemoryStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25000 PUSH EBX
25001 XCHG EBX, EAX
25002 MOV EAX, [EBX].TStream.fData.fSize
25003 SUB EAX, [EBX].TStream.fData.fPosition
25004 CMP EAX, ECX
25005 JGE @@1
25006 XCHG ECX, EAX
25007 @@1:
25008 PUSH EDX
25009 PUSH ECX
25010 JLE @@count_ok
25011 XCHG EDX, EAX
25012 MOV EAX, EBX
25013 CALL TStream.SetSize
25014 @@count_ok:
25015 POP ECX
25016 POP EAX
25017 MOV EDX, [EBX].TStream.fMemory
25018 ADD EDX, [EBX].TStream.fData.fPosition
25019 PUSH ECX
25020 CALL System.Move
25021 POP EAX
25022 ADD [EBX].TStream.fData.fPosition, EAX
25023 POP EBX
25024 end;
25025 {$ELSE ASM_VERSION}
25026 function WriteExMemoryStream( Strm: PStream; var Buffer; Count: DWORD ): DWORD;
25027 var S: PStream;
25028 begin
25029 S := Strm;
25030 if Count + S.fData.fPosition > S.fData.fSize then
25031 Count := S.fData.fSize - S.fData.fPosition;
25032 Result := Count;
25033 Move( Buffer, Pointer( DWORD(S.fMemory) + S.fData.fPosition )^, Result );
25034 Inc( S.fData.fPosition, Result );
25035 end;
25036 {$ENDIF ASM_VERSION}
25037 //[END WriteExMemoryStream]
25039 //[procedure DummyClose_ExMemStream]
25040 procedure DummyClose_ExMemStream( Strm: PStream );
25041 begin
25042 // nothing to do - ignore call (memory is not released by any way)
25043 end;
25045 //[function NewExMemoryStream]
25046 function NewExMemoryStream( ExistingMem: Pointer; Size: DWORD ): PStream;
25047 begin
25048 Result := NewMemoryStream;
25049 Result.fMemory := ExistingMem;
25050 Result.fData.fCapacity := Size;
25051 Result.fData.fSize := Size;
25052 Result.fMethods.fWrite := WriteExMemoryStream;
25053 Result.fMethods.fSetSiz := DummySetSize;
25054 Result.fMethods.fClose := DummyClose_ExMemStream;
25055 end;
25058 //[function Stream2Stream]
25059 function Stream2Stream( Dst, Src: PStream; Count: DWORD ): DWORD;
25060 var Buf: Pointer;
25061 begin
25062 if Src.fMemory <> nil then
25063 begin
25064 if Src.fData.fPosition + Count > Src.fData.fSize then
25065 Count := Src.fData.fSize - Src.fData.fPosition;
25066 Result := Dst.Write( Pointer(DWORD(Src.fMemory)+Src.fData.fPosition)^,
25067 Count );
25068 Inc( Src.fData.fPosition, Result );
25070 else
25071 if Dst.fMemory <> nil then
25072 begin
25073 if Dst.fData.fPosition + Count > Dst.fData.fSize then
25074 Dst.SetSize( Dst.fData.fPosition + Count );
25075 Result := Src.Read( Pointer( DWORD( Dst.fMemory ) + Dst.fData.fPosition )^,
25076 Count );
25077 Inc( Dst.fData.fPosition, Result );
25079 else
25080 begin
25081 GetMem( Buf, Count );
25082 Count := Src.Read( Buf^, Count );
25083 Result := Dst.Write( Buf^, Count );
25084 FreeMem( Buf );
25085 end;
25086 end;
25088 //[function Stream2StreamEx]
25089 function Stream2StreamEx( Dst, Src: PStream; Count: DWORD ): DWORD;
25090 begin
25091 Result := Stream2StreamExBufSz( Dst, Src, Count, 65536 );
25092 end;
25094 //[function Stream2StreamExBufSz]
25095 function Stream2StreamExBufSz( Dst, Src: PStream; Count, BufSz: DWORD ): DWORD;
25097 buf:pointer;
25098 rd, wr:dword;
25099 begin
25100 if count=0 then result:=0 else
25101 begin
25102 result:=0;
25103 BufSz := Min( BufSz, Count );
25104 if BufSz = 0 then BufSz := Count;
25105 getmem(buf,BufSz);
25106 repeat
25107 if count<BufSz then rd:=count else rd:=BufSz;
25108 rd:=src.read(buf^,rd);
25109 wr := dst.write(buf^,rd);
25110 inc(result,wr);
25111 dec(Count, rd);
25112 until (rd<>BufSz) or (Count=0);
25113 freemem(buf);
25114 end;
25115 end;
25117 //[FUNCTION Resource2Stream]
25118 {$IFDEF ASM_VERSION}
25119 function Resource2Stream( DestStrm : PStream; Inst : HInst;
25120 ResName : PChar; ResType : PChar ): Integer;
25122 PUSH EBX
25123 PUSH ESI
25124 MOV EBX, EDX // EBX = Inst
25125 PUSH EAX // DestStrm
25126 PUSH ResType
25127 PUSH ECX
25128 PUSH EDX
25129 CALL FindResource
25130 TEST EAX, EAX
25131 JZ @@exit0
25133 PUSH EAX
25134 PUSH EBX
25135 PUSH EAX
25136 PUSH EBX
25137 CALL SizeofResource
25138 XCHG EBX, EAX
25139 CALL LoadResource
25140 TEST EAX, EAX
25141 JZ @@exit0
25142 XCHG ESI, EAX
25144 PUSH ESI
25145 CALL GlobalLock
25146 TEST EAX, EAX
25147 JNZ @@P_ok
25149 CALL GetLastError
25150 CMP EAX, ERROR_INVALID_HANDLE
25151 JNZ @@exit_00
25152 MOV EAX, ESI
25154 @@P_ok:
25155 XCHG EDX, EAX
25156 POP EAX // DestStrm
25157 PUSH EDX
25158 MOV ECX, EBX
25159 CALL TStream.Write
25161 //EAX = Result (length of written data)
25162 XCHG EBX, EAX
25163 POP EAX
25164 CMP ESI, EAX
25165 JE @@not_unlock
25167 PUSH ESI
25168 CALL GlobalUnlock
25169 @@not_unlock:
25170 XCHG EAX, EBX
25171 JMP @@exit
25173 @@exit_00:
25174 XOR EAX, EAX
25175 @@exit0:
25176 POP ECX
25177 @@exit:
25178 POP ESI
25179 POP EBX
25180 end;
25181 {$ELSE ASM_VERSION} //Pascal
25182 function Resource2Stream( DestStrm : PStream; Inst : HInst;
25183 ResName : PChar; ResType : PChar ): Integer;
25184 var R : HRSRC;
25185 G : HGlobal;
25186 P : PChar;
25187 Sz : DWORD;
25188 E : Integer;
25189 begin
25190 Result := 0;
25191 R := FindResource( Inst, ResName, ResType );
25192 if R <> 0 then
25193 begin
25194 Sz := SizeofResource( Inst, R );
25195 G := LoadResource( Inst, R );
25196 if G <> 0 then
25197 begin
25198 P := GlobalLock( G );
25199 if P = nil then
25200 begin
25201 E := GetLastError;
25202 if E = ERROR_INVALID_HANDLE then
25203 P := Pointer( G )
25204 else
25205 Exit;
25206 end;
25207 Result := DestStrm.Write( P^, Sz );
25208 if P <> Pointer( G ) then
25209 GlobalUnlock( G );
25210 //FreeResource( G );
25211 { from Win32.hlp: "You do not need to call the FreeResource
25212 function to free a resource loaded by using the LoadResource
25213 function." }
25214 end;
25215 end;
25216 end;
25217 {$ENDIF ASM_VERSION}
25218 //[END Resource2Stream]
25231 ///////////////////////////////////////////////////////////////////////////
25234 // I N I - F I L E S
25237 ///////////////////////////////////////////////////////////////////////////
25240 { TIniFile }
25242 {$IFDEF ASM_VERSION}
25243 //[destructor TIniFile.Destroy]
25244 destructor TIniFile.Destroy;
25245 asm //cmd //opd
25246 PUSH EAX
25247 LEA EDX, [EAX].fFileName
25248 PUSH EDX
25249 LEA EAX, [EAX].fSection
25250 CALL System.@LStrClr
25251 POP EAX
25252 CALL System.@LStrClr
25253 POP EAX
25254 CALL TObj.Destroy
25255 end;
25256 {$ELSE ASM_VERSION} //Pascal
25257 destructor TIniFile.Destroy;
25258 begin
25259 fFileName := '';
25260 fSection := '';
25261 inherited;
25262 end;
25263 {$ENDIF ASM_VERSION}
25265 {$IFNDEF _D5orHigher}
25266 // Place here correct definition for WritePrivateProfileStruct
25267 // and GetPrivateProfileStruct (a bug in Delphi2, Delphi3 and Delphi4)
25268 //[API WritePrivateProfileStruct]
25269 function WritePrivateProfileStruct(lpszSection, lpszKey: PChar;
25270 lpStruct: Pointer; uSizeStruct: UINT; szFile: PChar): BOOL; stdcall;
25271 external kernel32 name 'WritePrivateProfileStructA';
25272 //[API GetPrivateProfileStruct]
25273 function GetPrivateProfileStruct(lpszSection, lpszKey: PAnsiChar;
25274 lpStruct: Pointer; uSizeStruct: UINT; szFile: PAnsiChar): BOOL; stdcall;
25275 external kernel32 name 'GetPrivateProfileStructA';
25277 // + by Slava A. Gavrik:
25278 ////////////////////////////////////////////////////////////////////////////
25279 //[function WritePrivateProfileSection]
25280 function WritePrivateProfileSection(lpAppName, lpString,
25281 lpFileName: PChar): BOOL; stdcall;
25282 external kernel32 name 'WritePrivateProfileSectionA';
25283 //[function GetPrivateProfileSection]
25284 function GetPrivateProfileSection(lpAppName: PChar; lpReturnedString: PChar;
25285 nSize: DWORD; lpFileName: PChar): DWORD; stdcall;
25286 external kernel32 name 'GetPrivateProfileSectionA';
25288 //[function GetPrivateProfileSectionNames]
25289 function GetPrivateProfileSectionNames(lpszReturnBuffer: PChar; nSize:
25290 DWORD;
25291 lpFileName: PChar): DWORD; stdcall;
25292 external kernel32 name 'GetPrivateProfileSectionNamesA';
25293 ////////////////////////////////////////////////////////////////////////////
25294 {$ENDIF}
25297 //[procedure TIniFile.ClearAll]
25298 procedure TIniFile.ClearAll;
25299 begin
25300 WritePrivateProfileString( nil, nil, nil,
25301 PChar( fFileName ) );
25302 end;
25304 //[procedure TIniFile.ClearKey]
25305 procedure TIniFile.ClearKey(const Key: String);
25306 begin
25307 WritePrivateProfileString( PChar( fSection ), PChar( Key ), nil,
25308 PChar( fFileName ) );
25309 end;
25311 //[procedure TIniFile.ClearSection]
25312 procedure TIniFile.ClearSection;
25313 begin
25314 WritePrivateProfileString( PChar( fSection ), nil, nil,
25315 PChar( fFileName ) );
25316 end;
25318 //[function TIniFile.ValueBoolean]
25319 function TIniFile.ValueBoolean(const Key: String; Value: Boolean): Boolean;
25320 begin
25321 if fMode = ifmRead then
25322 Result := GetPrivateProfileInt( PChar( fSection ), PChar( Key ),
25323 Integer( Value ), PChar( fFileName ) ) <> 0
25324 else
25325 begin
25326 WritePrivateProfileString( PChar( fSection ), PChar( Key ),
25327 PChar( Int2Str( Integer( Value ) ) ), PChar( fFileName ) );
25328 Result := Value;
25329 end;
25330 end;
25332 //[function TIniFile.ValueData]
25333 function TIniFile.ValueData(const Key: String; Value: Pointer;
25334 Count: Integer): Boolean;
25335 begin
25336 if fMode = ifmRead then
25337 Result := GetPrivateProfileStruct( PChar( fSection ), PChar( Key ),
25338 Value, Count, PChar( fFileName ) )
25339 else
25340 Result := WritePrivateProfileStruct( PChar( fSection ), PChar( Key ),
25341 Value, Count, PChar( fFileName ) );
25342 end;
25344 //[function TIniFile.ValueInteger]
25345 function TIniFile.ValueInteger(const Key: String; Value: Integer): Integer;
25346 begin
25347 if fMode = ifmRead then
25348 Result := GetPrivateProfileInt( PChar( fSection ), PChar( Key ),
25349 Integer( Value ), PChar( fFileName ) )
25350 else
25351 begin
25352 Result := Value;
25353 WritePrivateProfileString( PChar( fSection ), PChar( Key ),
25354 PChar( Int2Str( Value ) ), PChar( fFileName ) );
25355 end;
25356 end;
25358 //[function TIniFile.ValueString]
25359 function TIniFile.ValueString(const Key, Value: String): String;
25361 Buffer: array[0..2047] of Char;
25362 begin
25363 if fMode = ifmRead then
25364 begin
25365 Buffer[ 0 ] := #0;
25366 GetPrivateProfileString(PChar(fSection),
25367 PChar(Key), PChar(Value), Buffer, SizeOf(Buffer), PChar(fFileName));
25368 Result := Buffer;
25370 else
25371 begin
25372 Result := Value;
25373 WritePrivateProfileString( PChar( fSection ), PChar( Key ),
25374 PChar( Value ), PChar( fFileName ) );
25375 end;
25376 end;
25378 //[function OpenIniFile]
25379 function OpenIniFile( const FileName: String ): PIniFile;
25380 begin
25382 New( Result, Create );
25383 {+}{++}(*Result := PIniFile.Create;*){--}
25384 Result.fFileName := FileName;
25385 end;
25387 /////////////////////////////////////////////////// GetSectionNames, SectionData
25388 // - by Vyacheslav A. Gavrik :
25390 const
25391 IniBufferSize = 32767;
25392 IniBufferStrSize = IniBufferSize+4; /// äëÿ ìàõèíàöèé :)
25394 {$IFDEF ASM_VERSION}
25395 //[procedure _FillStrList]
25396 procedure _FillStrList; // Ýòà ÷àñòü êîäà îáùàÿ äëÿ äâóõ ñëåäóþùèõ ïðîöåäóð
25398 ///////////////////////////////
25399 OR EAX,0
25400 JE @@EXIT //ERROR
25401 // LEA EAX,[EAX-IniBufferSize]
25402 // JE @@EXIT
25403 // âîçìîæíà íåõâàòêà Áóôåðà... â ïðèíöèïå íå îøèáêà :)
25404 // âîçâðàùàåì ÷òî âëåçëî...
25405 //////////////////////////////
25406 @@LOOP:
25407 LEA EAX,[ESI+4]
25408 CALL StrLen
25409 MOV [ESI],EAX
25410 LEA EDX,[ESI+4]
25411 INC EAX
25412 ADD ESI,EAX
25414 MOV EAX,EDI
25416 CALL TStrList.ADD
25418 CMP byte ptr [ESI+4],0
25419 JNE @@LOOP
25421 @@EXIT:
25422 POP EAX
25423 CALL System.@FreeMem
25426 POP ECX
25427 POP EBX
25428 POP EDI
25429 POP ESI
25430 end;
25433 //[procedure TIniFile.GetSectionNames]
25434 procedure TIniFile.GetSectionNames(Names: PStrList);
25436 PUSH ESI
25437 PUSH EDI
25438 PUSH EBX
25439 PUSH ECX
25441 MOV EBX,EAX
25442 MOV EAX, IniBufferStrSize
25443 MOV EDI,EDX
25445 CALL System.@GetMem
25446 MOV ESI,EAX
25447 PUSH EAX
25449 PUSH [EBX].fFileName
25450 MOV EAX,IniBufferSize
25451 PUSH EAX
25453 LEA EAX,[ESI+4]
25454 PUSH EAX
25456 CALL GetPrivateProfileSectionNames
25457 JMP _FillStrList
25458 end;
25460 //[procedure TIniFile.SectionData]
25461 procedure TIniFile.SectionData(Names: PStrList);
25463 PUSH ESI
25464 PUSH EDI
25465 PUSH EBX
25466 PUSH ECX
25468 MOV EBX,EAX
25469 MOV EAX, IniBufferStrSize
25470 MOV EDI,EDX
25472 CALL System.@GetMem
25473 MOV ESI,EAX
25474 PUSH EAX
25476 OR [EBX].fMode,0
25477 JNE @@DOWrite
25479 PUSH [EBX].fFileName
25480 MOV EAX,IniBufferSize
25481 PUSH EAX
25483 LEA EAX,[ESI+4]
25484 PUSH EAX
25485 PUSH [EBX].fSection
25487 CALL GetPrivateProfileSection
25488 JMP _FillStrList
25490 @@DOWrite:
25492 PUSH EBX
25493 PUSH ESI
25494 PUSH EDX
25495 PUSH EBP
25497 MOV EDX,0
25498 MOV EBP,[EDI].TStrList.fCount
25499 MOV EBX,IniBufferSize-2 // îñòàâèì ìåñòî äëÿ #0#0
25501 {ECM+++>} OR EBP,EBP // otherwise GetPChars when StrList.Count = 0 crashed
25503 @@LOOP:
25504 JE @@ENDLOOP
25506 OR EBX,EBX
25507 JE @@ENDLOOP
25509 PUSH EDX
25510 MOV EAX,EDI
25511 CALL TStrList.GetPChars
25513 PUSH EAX
25514 CALL StrLen
25515 POP EAX
25517 XOR ECX,-1
25518 MOV EDX,ESI
25520 SUB EBX,ECX
25521 JA @@L1
25522 ADD ECX,EBX
25523 XOR EBX,EBX
25524 @@L1:
25526 ADD ESI,ECX
25528 CALL MOVE
25529 @@L2:
25530 POP EDX
25531 INC EDX
25532 DEC EBP
25533 JMP @@LOOP
25534 @@ENDLOOP:
25535 MOV WORD PTR [ESI],0
25537 POP EBP
25538 POP EDX
25539 POP ESI
25540 POP EBX
25541 ///////////////////////////////////
25542 MOV EAX,EBX // íîäî î÷èùàòü
25543 CALL ClearSection
25544 //////////////////////////////////
25546 PUSH [EBX].fFileName
25547 PUSH ESI
25548 PUSH [EBX].fSection
25550 CALL WritePrivateProfileSection
25552 POP EAX
25553 CALL System.@FreeMem
25555 POP ECX
25556 POP EBX
25557 POP EDI
25558 POP ESI
25560 end;
25561 {$ELSE ASM_VERSION} //Pascal
25563 //[procedure TIniFile.GetSectionNames]
25564 procedure TIniFile.GetSectionNames(Names: PStrList);
25566 i:integer;
25567 Pc:PChar;
25568 PcEnd:PChar;
25569 Buffer:Pointer;
25570 begin
25571 GetMem(Buffer,IniBufferSize);
25572 Pc:=Buffer;
25573 i := GetPrivateProfileSectionNames(Buffer, IniBufferSize, PChar(fFileName));
25574 PcEnd:=Pc+i;
25575 repeat
25576 Names.Add(Pc);
25577 Pc:=PC+Length(PC)+1;
25578 until PC>=PcEnd;
25579 FreeMem(Buffer);
25580 end;
25582 //[procedure TIniFile.SectionData]
25583 procedure TIniFile.SectionData(Names: PStrList);
25585 i:integer;
25586 Pc:PChar;
25587 PcEnd:PChar;
25588 Buffer:Pointer;
25589 begin
25590 GetMem(Buffer,IniBufferSize);
25591 Pc:=Buffer;
25592 if fMode = ifmRead then
25593 begin
25594 i:=GetPrivateProfileSection(PChar(fSection), Buffer, IniBufferSize, PChar(fFileName));
25595 PcEnd:=Pc+i;
25596 while PC < PcEnd do // Chg by ECM from REPEAT-UNTIL: i=0 (empty section) => Names.Count=1
25597 begin
25598 Names.Add(Pc);
25599 Pc:=PC+Length(PC)+1;
25600 end;
25601 end else
25602 begin
25603 for i:= 0 to Names.Count-1 do
25604 begin
25605 StrCopy(Pc,Names.ItemPtrs[i]);
25606 Pc:=PC+Length(PC)+1;
25607 end;
25608 Pc[0]:=#0;
25609 ClearSection;
25610 WritePrivateProfileSection(PChar(fSection), Buffer, PChar(fFileName));
25612 end;
25613 FreeMem(Buffer);
25614 end;
25615 {$ENDIF ASM_VERSION}
25617 //////////////////////////////////////////////////////////////////////
25629 /////////////////////////////////////////////////////////////////////////
25632 // M E N U
25635 /////////////////////////////////////////////////////////////////////////
25637 { -- Menu implementation -- }
25639 //[FUNCTION MakeAccelerator]
25640 {$IFDEF ASM_VERSION}
25641 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;
25643 MOVZX EAX, AL
25644 PUSH EAX
25645 MOV [ESP+1], DX
25646 POP EAX
25647 end;
25648 {$ELSE ASM_VERSION} //Pascal
25649 function MakeAccelerator( fVirt: Byte; Key: Word ): TMenuAccelerator;
25650 begin
25651 Result.fVirt := fVirt;
25652 Result.Key := Key;
25653 end;
25654 {$ENDIF ASM_VERSION}
25655 //[END MakeAccelerator]
25657 //[FUNCTION GetAcceleratorText]
25658 function GetAcceleratorText( const Accelerator: TMenuAccelerator ): string;
25660 KeyName: array[0..255] of Char;
25662 procedure AddKeyName( Code: Integer );
25663 begin
25664 Code := MapVirtualKey(Code, 0);
25665 if Code = 0 then exit;
25666 if GetKeyNameText(Code shl 16, KeyName, SizeOf(KeyName)) > 0 then begin
25667 if Result <> '' then
25668 Result := Result + '+';
25669 Result := Result + KeyName;
25670 end;
25671 end;
25673 begin
25674 Result := '';
25675 with Accelerator do begin
25676 if fVirt and FCONTROL <> 0 then
25677 AddKeyName(VK_CONTROL);
25678 if fVirt and FSHIFT <> 0 then
25679 AddKeyName(VK_SHIFT);
25680 if fVirt and FALT <> 0 then
25681 AddKeyName(VK_ALT);
25682 if fVirt and $20 <> 0 then
25683 AddKeyName(VK_LWIN);
25684 if fVirt and $40 <> 0 then
25685 AddKeyName(VK_RWIN);
25687 AddKeyName(Key);
25688 end;
25689 end;
25690 //[END GetAcceleratorText]
25693 const
25694 MIDATA_CHECKITEM = $40000000;
25695 MIDATA_RADIOITEM = $80000000;
25697 //[function WndProcMenu]
25698 {$IFNDEF NEW_MENU_ACCELL}
25699 function WndProcMenu( Sender: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
25700 var M, M1: PMenu;
25701 Idx: Integer;
25702 Id: Integer;
25703 begin
25704 Result := False;
25705 if Msg.message = WM_COMMAND then
25706 begin
25707 if (Msg.lParam = 0) and (HIWORD( Msg.wParam ) <= 1) then
25708 begin
25709 M := PMenu( Sender.fMenuObj );
25710 while M <> nil do
25711 begin
25712 Id := LoWord( Msg.wParam );
25713 M1 := M.Items[ Id ];
25714 if M1 <> nil then
25715 begin
25716 Result := True;
25717 Rslt := 0;
25718 Idx := M.IndexOf( M1 );
25719 M.fByAccel := HiWord( Msg.wParam ) <> 0;
25720 if M1.FRadioGroup <> 0 then
25721 M1.RadioCheckItem
25722 else
25723 if M1.FIsCheckItem then
25724 M1.Checked := not M1.Checked;
25725 if Assigned(M1.FOnMenuItem) then
25726 M1.FOnMenuItem( M, Idx )
25727 else if Assigned( M.FOnMenuItem ) then
25728 M.FOnMenuItem( M, Idx );
25729 //M.FProcessed := True;
25730 break;
25731 end;
25732 M := M.fNextMenu;
25733 end;
25734 end;
25735 end;
25736 end;
25738 {$ELSE}
25740 function WndProcMenu( Sender: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
25742 function ProcessMenuItem(M: PMenu; Id: Integer): Boolean;
25744 M1: PMenu;
25745 Idx: Integer;
25746 begin
25747 M1 := M.Items[ Id ];
25748 Result := (M1 <> nil);
25749 if Result then
25750 begin
25751 Idx := M.IndexOf( M1 );
25752 M.fByAccel := HiWord( Msg.wParam ) <> 0;
25753 if M1.FRadioGroup <> 0 then
25754 M1.RadioCheckItem
25755 else
25756 if M1.FIsCheckItem then
25757 M1.Checked := not M1.Checked;
25758 if Assigned(M1.FOnMenuItem) then begin
25759 {$IFDEF USE_MENU_CURCTL} // fixed
25760 M.fCurCtl := Sender; // fixed
25761 {$ENDIF} // fixed
25762 M1.FOnMenuItem( M, Idx )
25764 else if Assigned( M.FOnMenuItem ) then
25765 M.FOnMenuItem( M, Idx );
25766 end;
25767 end;
25770 M: PMenu;
25771 Id: Integer;
25772 begin
25773 Result := False;
25774 if Msg.message = WM_COMMAND then
25775 if (Msg.lParam = 0) and (HIWORD( Msg.wParam ) <= 1) then begin
25776 Id := LoWord(Msg.wParam);
25777 M := PMenu(Sender.fAutoPopupMenu);
25778 if (M <> nil) and ProcessMenuItem(M, Id) then begin
25779 Result := True;
25780 Rslt := 0;
25782 else begin
25783 M := PMenu(Sender.fMenuObj);
25784 while M <> nil do begin
25785 if ProcessMenuItem(M, Id) then begin
25786 Result := True;
25787 Rslt := 0;
25788 Break;
25789 end;
25790 M := M.fNextMenu;
25791 end;
25792 end;
25793 end;
25794 end;
25795 {$ENDIF}
25798 var FDynamicMenuID: DWORD = $1000;
25800 //[function NewMenu]
25801 function NewMenu( AParent : PControl; MaxCmdReserve : DWORD; const Template : array of PChar;
25802 aOnMenuItem: TOnMenuItem ): PMenu;
25803 var M: PMenu;
25804 {$IFDEF INITIALFORMSIZE_FIXMENU}
25805 R: TRect;
25806 {$ENDIF}
25807 begin
25809 New( Result, Create );
25810 {+}{++}(*Result := PMenu.Create;*){--}
25811 Result.FVisible := TRUE;
25812 Result.FPopupFlags := TPM_LEFTALIGN or TPM_LEFTBUTTON;
25813 Result.FItems := NewList;
25814 Result.FOnMenuItem := aOnMenuItem;
25815 if (High(Template)>=0) and (Template[0] <> nil) then
25816 begin
25817 if (AParent <> nil) and (AParent.fMenuObj = nil) and not AParent.fIsControl then
25818 Result.FHandle := CreateMenu
25819 else
25820 Result.FHandle := CreatePopupMenu;
25821 Result.FillMenuItems( Result.FHandle, 0, Template );
25822 end;
25823 if assigned( AParent ) then
25824 begin
25825 Result.FControl := AParent;
25826 if AParent.fMenuObj <> nil then
25827 begin
25828 // add popup menu to the end of menu chain
25829 M := PMenu( AParent.fMenuObj );
25830 while M.fNextMenu <> nil do
25831 M := M.fNextMenu;
25832 M.fNextMenu := Result;
25834 else
25835 begin
25836 if not AParent.fIsControl then
25837 begin
25838 {$IFDEF INITIALFORMSIZE_FIXMENU}
25839 R := AParent.ClientRect;
25840 {$ENDIF}
25841 AParent.Menu := Result.FHandle;
25842 {$IFDEF INITIALFORMSIZE_FIXMENU}
25843 AParent.SetClientSize( R.Right, R.Bottom );
25844 {$ENDIF}
25845 end;
25846 AParent.fMenuObj := Result;
25847 AParent.AttachProc( WndProcMenu );
25848 end;
25849 end;
25850 end;
25851 //[END NewMenu]
25853 //[function NewMenuEx]
25854 function NewMenuEx( AParent : PControl; FirstCmd : Integer; const Template : array of PChar;
25855 aOnMenuItems: array of TOnMenuItem ): PMenu;
25856 begin
25857 Result := NewMenu( AParent, FirstCmd, Template, nil );
25858 Result.AssignEvents( 0, aOnMenuItems );
25859 end;
25860 //[END NewMenuEx]
25862 { TMenu }
25864 const
25865 Breaks: array[ TMenuBreak ] of DWORD = ( 0, MFT_MENUBREAK, MFT_MENUBARBREAK );
25867 { + by AK - Andrzej Kubaszek }
25868 //[function MenuStructSize]
25869 function MenuStructSize: Integer;
25870 begin
25871 Result := 44;
25872 if not( WinVer in [wv31, wv95, wvNT] ) then
25873 Result := {48=} Sizeof( TMenuItemInfo );
25874 end;
25876 //[destructor TMenu.Destroy]
25877 destructor TMenu.Destroy;
25878 var Next, Prnt: PMenu;
25879 begin
25880 if Count > 0 then
25881 begin
25882 FItems.ReleaseObjects;
25883 FItems := NewList;
25884 end;
25885 if FParent <> nil then
25886 begin
25887 Prnt := FParent;
25888 FParent := nil;
25889 Next := Prnt.RemoveSubMenu( FId );
25890 Prnt.FItems.Remove( @ Self );
25891 if Next = nil then Exit;
25892 end;
25893 if (FControl <> nil) and (FControl.fMenu = FHandle) and (FHandle <> 0) then
25894 begin
25895 //if FControl.fHandle <> 0 then
25896 begin
25897 Windows.SetMenu( FControl.fHandle, 0 );
25898 // this removes main menu from window, but does not destroy it
25899 end;
25900 FControl.fMenu := 0;
25901 Next := PMenu( FControl.fMenuObj );
25902 while Next <> nil do
25903 begin
25904 if Next.fNextMenu = @Self then
25905 begin
25906 Next.fNextMenu := fNextMenu;
25907 break;
25908 end;
25909 Next := Next.fNextMenu;
25910 end;
25911 end;
25912 Next := fNextMenu;
25913 if FBitmap <> 0 then
25914 Bitmap := 0;
25915 if FHandle <> 0 then
25916 DestroyMenu( FHandle );
25917 FCaption := '';
25918 FItems.Free;
25919 inherited;
25920 Next.Free;
25921 // all later created (popup) menus (of the same control)
25922 // are destroyed too
25923 end;
25925 //[function TMenu.GetInfo]
25926 function TMenu.GetInfo( var MII: TMenuItemInfo ): Boolean;
25927 begin
25928 MII.cbSize := MenuStructSize;
25929 Result := GetMenuItemInfo( Parent.FHandle, FId, FALSE,
25930 Windows.PMenuitemInfo( @ MII )^ );
25931 end;
25933 //[procedure TMenu.RedrawFormMenuBar]
25934 procedure TMenu.RedrawFormMenuBar;
25935 var C: PControl;
25936 begin
25937 C := TopParent.FControl;
25938 if not AppletTerminated then
25939 if (C <> nil) and (Pointer( C.fMenuObj ) = Pointer( TopParent )) then
25940 DrawMenuBar( C.FHandle );
25941 end;
25943 //[function TMenu.SetInfo]
25944 function TMenu.SetInfo( var MII: TMenuItemInfo ): Boolean;
25945 var H: THandle;
25946 begin
25947 MII.cbSize := MenuStructSize;
25948 H := FHandle;
25949 if FParent <> nil then
25950 H := FParent.FHandle;
25951 Result := SetMenuItemInfo( H, FId, FALSE, Windows.PMenuitemInfo( @ MII )^ );
25952 if Result and ((FParent = nil) or (FParent.FParent = nil)) then {YS}
25953 RedrawFormMenuBar;
25954 end;
25956 //[function TMenu.SetTypeInfo]
25957 function TMenu.SetTypeInfo( var MII: TMenuItemInfo ): Boolean;
25958 begin
25959 if not FIsSeparator then
25960 begin
25961 if FBmpItem = 0 then
25962 MII.dwTypeData := PChar( FCaption )
25963 else
25964 MII.dwTypeData := Pointer( FBmpItem );
25965 MII.cch := Length( FCaption );
25966 end;
25967 Result := SetInfo( MII );
25968 end;
25970 //[function TMenu.GetTopParent]
25971 function TMenu.GetTopParent: PMenu;
25972 begin
25973 Result := @ Self;
25974 while Result.FParent <> nil do
25975 Result := Result.FParent;
25976 end;
25978 //[function TMenu.GetControl]
25979 function TMenu.GetControl: PControl;
25980 begin
25981 Result := TopParent.FControl;
25982 end;
25984 //[function TMenu.GetItems]
25985 function TMenu.GetItems( Id: HMenu ): PMenu;
25986 function SearchItems( ParentMenu: PMenu; var FromIdx: Integer ): PMenu;
25987 var I: Integer;
25988 begin
25989 Result := ParentMenu;
25990 if Id = HMenu( FromIdx ) then Exit;
25991 if (Id >= 4096) and (DWORD( ParentMenu.FId ) = Id) then Exit;
25992 if ParentMenu.FItems = nil then Exit;
25993 for I := 0 to ParentMenu.FItems.FCount-1 do
25994 begin
25995 Inc( FromIdx );
25996 Result := SearchItems( ParentMenu.FItems.Items[ I ], FromIdx );
25997 if Result <> nil then Exit;
25998 end;
25999 Result := nil;
26000 end;
26001 var I: Integer;
26002 begin
26003 I := -1;
26004 Result := SearchItems( @ Self, I );
26005 end;
26007 //[function TMenu.GetCount]
26008 function TMenu.GetCount: Integer;
26009 var I: Integer;
26010 SubM: PMenu;
26011 begin
26012 Result := FItems.FCount;
26013 for I := 0 to Result-1 do
26014 begin
26015 SubM := FItems.Items[ I ];
26016 Result := Result + SubM.Count;
26017 end;
26018 end;
26020 //[function TMenu.IndexOf]
26021 function TMenu.IndexOf( Item: PMenu ): Integer;
26022 function SearchMenu( ParentMenu: PMenu; var FromIdx: Integer ): PMenu;
26023 var I: Integer;
26024 begin
26025 Result := ParentMenu;
26026 if Result = Item then Exit;
26027 for I := 0 to ParentMenu.FItems.FCount-1 do
26028 begin
26029 Inc( FromIdx );
26030 Result := SearchMenu( ParentMenu.FItems.Items[ I ], FromIdx );
26031 if Result <> nil then Exit;
26032 end;
26033 Result := nil;
26034 end;
26035 begin
26036 Result := -1;
26037 if SearchMenu( @ Self, Result ) = nil then
26038 Result := -2;
26039 end;
26041 //[function TMenu.GetState]
26042 function TMenu.GetState( const Index: Integer ): Boolean;
26043 var MII: TMenuItemInfo;
26044 begin
26045 if FVisible then
26046 begin
26047 MII.fMask := MIIM_STATE;
26048 if GetInfo( MII ) then
26049 FSavedState := MII.fState;
26050 end;
26051 Result := LongBool( FSavedState and Index );
26052 if Index < 0 then
26053 Result := not Result;
26054 end;
26056 //[procedure TMenu.SetState]
26057 procedure TMenu.SetState( const Index: Integer; Value: Boolean );
26058 var MII: TMenuItemInfo;
26059 begin
26060 GetState( 0 );
26061 if Value xor (Index < 0) then
26062 FSavedState := FSavedState or DWORD( Index and $7FFFFFFF )
26063 else
26064 FSavedState := FSavedState and not DWORD( Index );
26065 if FVisible then
26066 begin
26067 MII.fMask := MIIM_STATE;
26068 if GetInfo( MII ) then
26069 begin
26070 MII.fState := FSavedState;
26071 SetInfo( MII );
26072 end;
26073 end;
26074 end;
26076 //[procedure TMenu.SetData]
26077 procedure TMenu.SetData( Value: Pointer );
26078 var MII: TMenuItemInfo;
26079 begin
26080 MII.fMask := MIIM_DATA;
26081 MII.dwItemData := DWORD( Value );
26082 SetInfo( MII );
26083 FData := Value;
26084 end;
26086 //[procedure TMenu.ClearBitmaps]
26087 procedure TMenu.ClearBitmaps;
26088 begin
26089 if FBitmap <> 0 then
26090 DeleteObject( FBitmap );
26091 if FBmpChecked <> 0 then
26092 DeleteObject( FBmpChecked );
26093 if FBmpItem <> 0 then
26094 DeleteObject( FBmpItem );
26095 end;
26097 //[procedure TMenu.SetBitmap]
26098 procedure TMenu.SetBitmap( Value: HBitmap );
26099 var MII: TMenuItemInfo;
26100 begin
26101 if not FClearBitmaps then
26102 begin
26103 FClearBitmaps := TRUE;
26104 Add2AutoFreeEx( ClearBitmaps );
26105 end;
26106 if Value = FBitmap then Exit;
26107 if FBitmap <> 0 then
26108 DeleteObject( FBitmap ); // seems not necessary.
26109 FBitmap := Value;
26110 MII.fMask := MIIM_CHECKMARKS;
26111 MII.hbmpChecked := FBmpChecked;
26112 MII.hbmpUnchecked := FBitmap;
26113 SetInfo( MII );
26114 end;
26116 //[procedure TMenu.SetBmpChecked]
26117 procedure TMenu.SetBmpChecked( Value: HBitmap );
26118 var MII: TMenuItemInfo;
26119 begin
26120 if not FClearBitmaps then
26121 begin
26122 FClearBitmaps := TRUE;
26123 Add2AutoFreeEx( ClearBitmaps );
26124 end;
26125 if Value = FBmpChecked then Exit;
26126 if FBmpChecked <> 0 then
26127 DeleteObject( FBmpChecked );
26128 FBmpChecked := Value;
26129 MII.fMask := MIIM_CHECKMARKS;
26130 MII.hbmpChecked := FBmpChecked;
26131 MII.hbmpUnchecked := FBitmap;
26132 SetInfo( MII );
26133 end;
26135 //[procedure TMenu.SetBmpItem]
26136 procedure TMenu.SetBmpItem( Value: HBitmap );
26137 var MII: TMenuItemInfo;
26138 begin
26139 if not FClearBitmaps then
26140 begin
26141 FClearBitmaps := TRUE;
26142 Add2AutoFreeEx( ClearBitmaps );
26143 end;
26144 if Value = FBmpItem then Exit;
26145 if FBmpItem <> 0 then
26146 DeleteObject( FBmpItem );
26147 FBmpItem := Value;
26148 if WinVer >= wv98 then {AK}
26149 begin {AK}
26150 MII.fMask := $80 {MIIM_BITMAP} ; {AK}
26151 MII.hbmpItem:=Value; {AK}
26152 end {AK}
26153 else {AK}
26154 begin//I haven't possibility to test it in Win95 {AK}
26155 MII.fType := MFT_BITMAP;
26156 MII.dwItemData := Value;
26157 end; {AK}
26158 SetInfo( MII );
26159 end;
26161 //[procedure TMenu.SetAccelerator]
26162 {$IFNDEF NEW_MENU_ACCELL}
26163 procedure TMenu.SetAccelerator(const Value: TMenuAccelerator);
26164 const MaxAccel = 1000;
26165 type TAccTab = array[0..10000] of TAccel;
26166 PAccTab = ^TAccTab;
26167 //TSetAcceleratorProc = procedure( Self_: PMenu; Idx: Integer; const Value: TMenuAccelerator );
26168 var AccTab: PAccTab;
26169 I, N : Integer;
26170 M, SubM: PMenu;
26171 C: PControl;
26172 Main: Boolean;
26173 begin
26174 //SetAcceleratorProc := TSetAcceleratorProc( MakeMethod( nil, @TMenu.SetAccelerator ).Code );
26175 if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then Exit;
26176 FAccelerator := Value;
26177 C := TopParent.FControl;
26178 if C = nil then Exit;
26179 if C.fAccelTable <> 0 then
26180 DestroyAcceleratorTable( C.fAccelTable );
26181 C.fAccelTable := 0;
26182 GetMem( AccTab, sizeof( TAccel ) * MaxAccel );
26183 N := 0;
26184 M := PMenu( C.fMenuObj );
26185 Main := TRUE;
26186 while M <> nil do
26187 begin
26188 if Main or M.Visible then
26189 begin
26190 for I := 0 to MaxInt-1 do
26191 begin
26192 SubM := M.Items[ I ];
26193 if SubM = nil then break;
26194 if SubM.FVisible then
26195 if (SubM.FAccelerator.Key <> 0) or (SubM.FAccelerator.fVirt <> 0) then
26196 begin
26197 AccTab[ N ].fVirt := SubM.FAccelerator.fVirt;
26198 AccTab[ N ].key := SubM.FAccelerator.Key;
26199 AccTab[ N ].cmd := WORD( SubM.FId );
26200 Inc( N );
26201 if N > MaxAccel then break;
26202 end;
26203 end;
26204 end;
26205 if N > MaxAccel then break;
26206 M := M.fNextMenu;
26207 end;
26208 if N > 0 then
26209 begin
26210 C.fAccelTable := CreateAcceleratorTable( AccTab[ 0 ], N );
26211 C := C.ParentForm;
26212 if C <> nil then
26213 C.SupportMnemonics;
26214 end;
26215 FreeMem( AccTab );
26216 end;
26218 {$ELSE NEW_MENU_ACCELL}
26220 procedure TMenu.SetAccelerator(const Value: TMenuAccelerator);
26222 C: PControl;
26223 M: PMenu;
26224 begin
26225 if (FAccelerator.fVirt = Value.fVirt) and (FAccelerator.Key = Value.Key) then Exit;
26226 FAccelerator := Value;
26227 C := FControl;
26228 M := @Self;
26229 while (C = nil) and (M <> nil) do begin
26230 M := M.Parent;
26231 if (M <> nil) then
26232 C := M.FControl;
26233 end;
26234 if (C <> nil) then
26235 C.SupportMnemonics;
26236 end;
26238 {$ENDIF NEW_MENU_ACCELL}
26240 //[procedure TMenu.SetMenuItemCaption]
26241 procedure TMenu.SetMenuItemCaption( const Value: String );
26242 var MII: TMenuItemInfo;
26243 begin
26244 FCaption := Value;
26245 {AK}if not (WinVer in [wv95,wvNT]) then
26246 {AK} MII.fMask := $40 {MIIM_STRING}
26247 {AK}else begin
26248 MII.fMask := MIIM_TYPE;
26249 MII.fType := MFT_STRING;
26250 {AK}end;
26251 //+++++++++++++++++++ to fix turning radio mark to check mark in NT4
26252 MII.cch := 0;
26253 GetInfo( MII );
26254 //------------------------------------------------------------------
26255 MII.dwTypeData := PChar( Value );
26256 MII.cch := Length( Value );
26257 SetInfo( MII );
26258 end;
26260 //[procedure TMenu.SetMenuBreak]
26261 procedure TMenu.SetMenuBreak( Value: TMenuBreak );
26262 var MII: TMenuItemInfo;
26263 begin
26264 if FId = 0 then Exit;
26265 if FMenuBreak = Value then Exit;
26266 FMenuBreak := Value;
26267 FillChar( MII, Sizeof( MII ), 0 );
26268 MII.fMask := MIIM_TYPE;
26269 MII.dwTypeData := nil;
26270 if GetInfo( MII ) then
26271 begin
26272 MII.fType := MII.fType and not( MFT_MENUBREAK or MFT_MENUBARBREAK ) or
26273 Breaks[ Value ];
26274 SetTypeInfo( MII );
26275 end;
26276 end;
26278 //[procedure TMenu.SetVisible]
26279 procedure TMenu.SetVisible( Value: Boolean );
26280 var I, J: Integer;
26281 M: PMenu;
26282 Before: Integer;
26283 ByPosition: Boolean;
26284 MII: TMenuItemInfo;
26285 begin
26286 if Value then
26287 if FParent <> nil then
26288 FParent.Visible := TRUE;
26289 if Value = FVisible then Exit;
26290 FVisible := Value;
26291 if (FControl <> nil) and (FControl.fMenuObj = @ Self) then
26292 begin
26293 FControl.GetWindowHandle;
26294 if Value then
26295 SetMenu( FControl.fHandle, FHandle )
26296 else
26297 SetMenu( FControl.fHandle, 0 );
26298 Exit;
26299 end;
26300 if FId = 0 then Exit;
26301 if FParent = nil then Exit;
26302 if Value then
26303 begin // show menu item inserting it again into appropriate position
26304 Before := -1;
26305 ByPosition := TRUE;
26306 I := FParent.FItems.IndexOf( @ Self );
26307 for J := I + 1 to FParent.FItems.FCount-1 do
26308 begin
26309 M := FParent.FItems.Items[ J ];
26310 if M.FVisible then
26311 begin
26312 Before := M.FId;
26313 ByPosition := FALSE;
26314 break;
26315 end;
26316 end;
26318 FillChar( MII, Sizeof( MII ), 0 );
26319 MII.cbSize := MenuStructSize;
26320 MII.fMask := MIIM_CHECKMARKS or MIIM_ID or MIIM_STATE or
26321 MIIM_TYPE;
26322 MII.fType := Breaks[ FMenuBreak ];
26323 MII.fState := FSavedState;
26324 MII.wID := FId;
26325 MII.dwItemData := DWORD( FData );
26327 if not FIsSeparator then
26328 begin
26329 MII.fType := MII.fType or MFT_STRING;
26330 MII.dwTypeData := PChar( FCaption );
26331 MII.cch := Length( FCaption );
26333 else
26334 MII.fType := MII.fType or MFT_SEPARATOR;
26336 if FRadioGroup <> 0 then
26337 MII.fType := MII.fType or MFT_RADIOCHECK;
26339 if FOwnerDraw then
26340 MII.fType := MII.fType or MFT_OWNERDRAW;
26342 if FBitmap <> 0 then
26343 begin
26344 MII.fMask := MII.fMask or MIIM_CHECKMARKS;
26345 MII.hbmpUnchecked := FBitmap;
26346 end;
26348 if FHandle <> 0 then
26349 begin
26350 MII.fMask := MII.fMask or MIIM_SUBMENU;
26351 MII.hSubMenu := FHandle;
26352 end;
26354 InsertMenuItem( FParent.FHandle, Before, ByPosition,
26355 Windows.PMenuitemInfo( @ MII )^ );
26357 else
26358 begin // hide menu item removing it
26359 GetState( 0 ); // store menu item state in FSavedState to allow
26360 // changing its state while it is not attached to
26361 // a menu
26362 RemoveMenu( TopParent.FHandle, FId, MF_BYCOMMAND );
26363 end;
26364 if (FControl <> nil) or (FParent <> nil) and (FParent.FControl <> nil) then
26365 RedrawFormMenuBar;
26366 end;
26368 //[procedure TMenu.RadioCheckItem]
26369 procedure TMenu.RadioCheckItem;
26370 var I, J: Integer;
26371 M, First, Last: PMenu;
26372 begin
26373 if (FParent <> nil) and (FRadioGroup <> 0) then
26374 begin
26375 I := FParent.FItems.IndexOf( @ Self );
26376 if I >= 0 then
26377 begin
26378 First := @ Self;
26379 Last := @ Self;
26380 for J := I-1 downto 0 do
26381 begin
26382 M := FParent.FItems.Items[ J ];
26383 if M.FRadioGroup <> FRadioGroup then break;
26384 if M.FVisible then
26385 First := M;
26386 end;
26387 for J := I+1 to FParent.FItems.FCount-1 do
26388 begin
26389 M := FParent.FItems.Items[ J ];
26390 if M.FRadioGroup <> FRadioGroup then break;
26391 if M.FVisible then
26392 Last := M;
26393 end;
26394 if First <> Last then
26395 begin
26396 CheckMenuRadioItem( FParent.FHandle, First.FId, Last.FId,
26397 FId, MF_BYCOMMAND {or MF_CHECKED} );
26398 Exit;
26399 end;
26400 end;
26401 end;
26402 Checked := TRUE;
26403 end;
26405 //[function TMenu.FillMenuItems]
26406 function TMenu.FillMenuItems(AHandle: HMenu; StartIdx: Integer;
26407 const Template: array of PChar): Integer;
26408 var S, S1: PChar;
26409 I: Integer;
26410 MII: TMenuItemInfo;
26411 Item, PrevItem: PMenu;
26412 begin
26413 PrevItem := nil;
26414 I := StartIdx;
26415 while I <= High( Template ) do
26416 begin
26417 S := Template[ I ];
26418 if (S = nil) or (S^ = #0) then break;
26419 if S = {$IFDEF F_P}'' +{$ENDIF} ')' then
26420 begin
26421 Result := I + 1;
26422 Exit;
26423 end;
26426 new( Item, Create );
26427 {+}{++}(*Item := PMenu.Create;*){--}
26428 Item.FVisible := TRUE;
26429 Item.FParent := @ Self;
26430 Item.FItems := NewList;
26431 FItems.Add( Item );
26433 FillChar( MII, Sizeof( MII ), 0 );
26434 MII.cbSize := MenuStructSize;
26435 MII.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE or MIIM_SUBMENU or MIIM_TYPE;
26436 if S <> {$IFDEF F_P}'' +{$ENDIF} '-' then
26437 begin
26438 if (S^ = {$IFDEF F_P}'' +{$ENDIF} '-') or
26439 (S^ = {$IFDEF F_P}'' +{$ENDIF} '+') then
26440 begin
26441 Item.FIsCheckItem := TRUE;
26442 MII.dwItemData := MIDATA_CHECKITEM;
26443 if S^ <> {$IFDEF F_P}'' +{$ENDIF} '-' then
26444 MII.fState := MII.fState or MFS_CHECKED;
26445 Inc( S );
26446 if S^ = {$IFDEF F_P}'' +{$ENDIF} '!' then
26447 begin
26448 MII.fType := MII.fType or MFT_RADIOCHECK;
26449 MII.dwItemData := MII.dwItemData or MIDATA_RADIOITEM;
26450 Inc( S );
26451 if PrevItem <> nil then
26452 begin
26453 if PrevItem.FRadioGroup <> 0 then
26454 Item.FRadioGroup := PrevItem.FRadioGroup;
26455 end;
26456 if Item.FRadioGroup = 0 then
26457 Inc( Item.FRadioGroup );
26458 if S^ = {$IFDEF F_P}'' +{$ENDIF} '!' then
26459 begin
26460 Inc( S );
26461 Inc( Item.FRadioGroup );
26462 end;
26463 end;
26464 end;
26465 Item.FCaption := S;
26467 else
26468 begin
26469 Item.FIsSeparator := TRUE;
26470 MII.fType := MFT_SEPARATOR;
26471 MII.fState := MFS_GRAYED;
26472 MII.wID := 0;
26473 end;
26474 Item.FId := FDynamicMenuID;
26475 Inc( FDynamicMenuID );
26476 MII.wID := Item.FId;
26477 if I <> High( Template ) then //YS
26478 begin //YS
26479 S1 := Template[ I + 1 ];
26480 if S1 = {$IFDEF F_P}'' +{$ENDIF} '(' then Item.FHandle := CreatePopupMenu;
26481 end; //YS
26482 MII.hSubMenu := Item.FHandle;
26483 MII.dwTypeData := PChar( S );
26484 MII.cch := StrLen( S );
26485 InsertMenuItem( AHandle, DWORD(-1), True, Windows.PMenuitemInfo( @ MII )^ );
26486 if Item.FHandle <> 0 then
26487 I := Item.FillMenuItems( Item.FHandle, I + 2, Template )
26488 else
26489 Inc( I );
26490 PrevItem := Item;
26491 end;
26492 Result := I;
26493 end;
26495 //[procedure TMenu.AssignEvents]
26496 procedure TMenu.AssignEvents(StartIdx: Integer;
26497 Events: array of TOnMenuItem);
26498 var I: Integer;
26499 M: PMenu;
26500 begin
26501 for I := 0 to High(Events) do
26502 begin
26503 M := Items[ StartIdx ];
26504 if M = nil then break;
26505 M.FOnMenuItem := Events[ I ];
26506 Inc( StartIdx );
26507 end;
26508 end;
26510 //[procedure TMenu.Popup]
26511 function TMenu.Popup(X, Y: Integer): Integer;
26512 begin
26513 if Assigned( fOnPopup ) then fOnPopup( @Self );
26514 if not FNotPopup then
26515 Result := Integer( TrackPopupMenu( FHandle, FPopupFlags, {*ecm}
26516 X, Y, 0, FControl.Handle, nil ) ) {*ecm}
26517 else Result := 0; {*ecm}
26518 end;
26520 //[procedure TMenu.PopupEx]
26521 function TMenu.PopupEx( X, Y: Integer ): Integer;
26522 var OldBounds: TRect;
26523 WasVisible: Boolean;
26524 begin
26525 WasVisible := TRUE;
26526 if FControl <> nil then
26527 begin
26528 OldBounds := FControl.BoundsRect;
26529 if not FControl.fIsControl then
26530 begin
26531 WasVisible := FControl.Visible;
26532 if not WasVisible then
26533 FControl.Top := ScreenHeight + 50;
26534 FControl.Show;
26535 end;
26536 end;
26538 // -- by Martin Larsen: -----------------------\
26539 FControl.ProcessMessage; // specific for Win9x |
26540 //---------------------------------------------/
26542 Result := Popup( X, Y ); {*ecm}
26543 if FControl <> nil then
26544 begin
26545 if FControl.Top = ScreenHeight + 50 then
26546 begin
26547 if not WasVisible then
26548 FControl.Visible := FALSE;
26549 FControl.BoundsRect := OldBounds;
26550 end;
26551 end;
26552 end;
26554 //[function TMenu.GetItemChecked]
26555 function TMenu.GetItemChecked( Item : Integer ) : Boolean;
26556 begin
26557 Result := Items[ Item ].Checked;
26558 end;
26560 //[procedure TMenu.SetItemChecked]
26561 procedure TMenu.SetItemChecked( Item : Integer; Value : Boolean );
26562 begin
26563 Items[ Item ].Checked := Value;
26564 end;
26566 //[function TMenu.GetMenuItemHandle]
26567 function TMenu.GetMenuItemHandle( Idx : Integer ): DWORD;
26568 begin
26569 Result := Items[ Idx ].FId;
26570 end;
26572 //[procedure TMenu.RadioCheck]
26573 procedure TMenu.RadioCheck( Idx : Integer );
26574 begin
26575 Items[ Idx ].RadioCheckItem;
26576 end;
26578 //[function TMenu.GetItemBitmap]
26579 function TMenu.GetItemBitmap(Idx: Integer): HBitmap;
26580 begin
26581 Result := Items[ Idx ].Bitmap;
26582 end;
26584 //[procedure TMenu.SetItemBitmap]
26585 procedure TMenu.SetItemBitmap(Idx: Integer; const Value: HBitmap);
26586 begin
26587 Items[ Idx ].Bitmap := Value;
26588 end;
26590 //[procedure TMenu.AssignBitmaps]
26591 procedure TMenu.AssignBitmaps(StartIdx: Integer; Bitmaps: array of HBitmap);
26592 var I: Integer;
26593 begin
26594 for I := 0 to High(Bitmaps) do
26595 ItemBitmap[ I + StartIdx ] := Bitmaps[ I ];
26596 end;
26598 //[function TMenu.GetItemText]
26599 function TMenu.GetItemText(Idx: Integer): String;
26600 begin
26601 Result := Items[ Idx ].FCaption;
26602 end;
26604 //[procedure TMenu.SetItemText]
26605 procedure TMenu.SetItemText(Idx: Integer; const Value: String);
26606 begin
26607 Items[ Idx ].Caption := Value;
26608 end;
26610 //[function TMenu.GetItemEnabled]
26611 function TMenu.GetItemEnabled(Idx: Integer): Boolean;
26612 begin
26613 Result := Items[ Idx ].Enabled;
26614 end;
26616 //[procedure TMenu.SetItemEnabled]
26617 procedure TMenu.SetItemEnabled(Idx: Integer; const Value: Boolean);
26618 begin
26619 Items[ Idx ].Enabled := Value;
26620 end;
26622 //[function TMenu.GetItemVisible]
26623 function TMenu.GetItemVisible(Idx: Integer): Boolean;
26624 begin
26625 Result := Items[ Idx ].Visible;
26626 end;
26628 //[procedure TMenu.SetItemVisible]
26629 procedure TMenu.SetItemVisible(Idx: Integer; const Value: Boolean);
26630 begin
26631 Items[ Idx ].Visible := Value;
26632 end;
26634 //[function TMenu.ParentItem]
26635 function TMenu.ParentItem( Idx: Integer ): Integer;
26636 begin
26637 Result := TopParent.IndexOf( Items[ Idx ].FParent );
26638 end;
26640 //[function TMenu.GetItemAccelerator]
26641 function TMenu.GetItemAccelerator(Idx: Integer): TMenuAccelerator;
26642 begin
26643 Result := Items[ Idx ].Accelerator;
26644 end;
26646 //[procedure TMenu.SetItemAccelerator]
26647 procedure TMenu.SetItemAccelerator(Idx: Integer; const Value: TMenuAccelerator);
26648 begin
26649 Items[ Idx ].Accelerator := Value;
26650 end;
26652 //[function TMenu.GetItemSubMenu]
26653 function TMenu.GetItemSubMenu( Idx: Integer ): HMenu;
26654 begin
26655 Result := Items[ Idx ].SubMenu;
26656 end;
26658 //[function WndProcHelp FORWARD DECLARATION]
26659 function WndProcHelp( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
26660 forward;
26662 //[procedure TMenu.SetHelpContext]
26663 procedure TMenu.SetHelpContext( Value: Integer );
26664 var Form, C: PControl;
26665 begin
26666 if TopParent <> @ Self then Exit;
26667 // Help context can not be associated with individual menu items
26668 FHelpContext := Value;
26669 C := FControl;
26670 if C = nil then Exit;
26671 Form := C.ParentForm;
26672 Form.AttachProc( WndProcHelp );
26673 SetMenuContextHelpID( FHandle, Value );
26674 end;
26676 //[procedure TMenu.SetSubmenu]
26677 procedure TMenu.SetSubmenu( Value: HMenu );
26678 var MII: TMenuItemInfo;
26679 begin
26680 MII.fMask := MIIM_SUBMENU;
26681 MII.hSubMenu := Value;
26682 SetInfo( MII );
26683 FHandle := Value;
26684 end;
26686 //[function WndProcMeasureItem]
26687 function WndProcMeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
26688 var MIS: PMeasureItemStruct;
26689 M, SM: PMenu;
26690 H, I: Integer;
26691 begin
26692 Result := FALSE;
26693 if (Msg.message = WM_MEASUREITEM) and (Msg.wParam = 0) then
26694 begin
26695 MIS := Pointer( Msg.lParam );
26696 if MIS.CtlType = ODT_MENU then
26697 begin
26698 M := Pointer( Sender.fMenuObj );
26699 while M <> nil do
26700 begin
26701 SM := M.Items[ MIS.itemID ];
26702 if SM <> nil then
26703 begin
26704 Sender.CallDefWndProc( Msg );
26705 I := M.IndexOf( SM );
26706 if Assigned( SM.OnMeasureItem ) then
26707 M := SM;
26708 if not Assigned( M.OnMeasureItem ) then
26709 Exit;
26710 H := M.OnMeasureItem( M, I );
26711 if HiWord( H ) <> 0 then
26712 MIS.itemWidth := HiWord( H );
26713 if LoWord( H ) <> 0 then
26714 MIS.itemHeight := LoWord( H );
26715 Rslt := 1;
26716 Result := TRUE;
26717 break;
26718 end;
26719 M := M.fNextMenu;
26720 end;
26721 end;
26722 end;
26723 end;
26725 //[procedure TMenu.SetOnMeasureItem]
26726 procedure TMenu.SetOnMeasureItem( const Value: TOnMeasureItem );
26727 var C: PControl;
26728 begin
26729 FOnMeasureItem := Value;
26730 C := TopParent.FControl;
26731 if C <> nil then
26732 C.AttachProc( WndProcMeasureItem );
26733 end;
26735 //[function WndProcDrawItem]
26736 function WndProcDrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
26737 type PDrawAction = ^TDrawAction;
26738 PDrawState = ^TDrawState;
26739 var DIS: PDrawItemStruct;
26740 M, SM: PMenu;
26741 I: Integer;
26742 begin
26743 Result := FALSE;
26744 if (Msg.message = WM_DRAWITEM) and (Msg.wParam = 0) then
26745 begin
26746 DIS := Pointer( Msg.lParam );
26747 if DIS.CtlType = ODT_MENU then
26748 begin
26749 M := Pointer( Sender.fMenuObj );
26750 while M <> nil do
26751 begin
26752 SM := M.Items[ DIS.itemID ];
26753 if SM <> nil then
26754 begin
26755 I := M.IndexOf( SM );
26756 if Assigned( SM.OnDrawItem ) then
26757 M := SM;
26758 if Assigned( M.OnDrawItem ) then
26759 begin
26760 if not M.OnDrawItem( M, DIS.hDC, DIS.rcItem, I,
26761 PDrawAction( @ DIS.itemAction )^,
26762 PDrawState( @ DIS.itemState )^ ) then Exit;
26764 else Exit;
26765 Rslt := 1;
26766 Result := TRUE;
26767 break;
26768 end;
26769 M := M.fNextMenu;
26770 end;
26771 end;
26772 end;
26773 end;
26775 //[procedure TMenu.SetOnDrawItem]
26776 procedure TMenu.SetOnDrawItem( const Value: TOnDrawItem );
26777 var C: PControl;
26778 begin
26779 FOnDrawItem := Value;
26780 C := TopParent.FControl;
26781 if C <> nil then
26782 C.AttachProc( WndProcDrawItem );
26783 end;
26785 //[procedure TMenu.SetOwnerDraw]
26786 procedure TMenu.SetOwnerDraw( Value: Boolean );
26787 const Masks: array[ Boolean ] of DWORD = ( 0, $FFFFFFFF );
26788 var MII: TMenuItemInfo;
26789 begin
26790 FOwnerDraw := Value;
26791 FillChar( MII, Sizeof( MII ), 0 );
26792 MII.fMask := MIIM_TYPE;
26793 MII.dwTypeData := nil;
26794 if GetInfo( MII ) then
26795 begin
26796 MII.fType := MII.fType and not MFT_OWNERDRAW or
26797 (MFT_OWNERDRAW and Masks[ Value ]);
26798 SetTypeInfo( MII );
26799 end;
26800 end;
26802 //[function TMenu.Insert]
26803 function TMenu.Insert(InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;
26804 Options: TMenuOptions): PMenu;
26805 const
26806 MenuStateFlags: array[TMenuOption] of Integer = (MFS_DEFAULT, MFS_DISABLED, MFS_CHECKED, 0, 0,
26807 MFS_DISABLED, 0, 0, 0, 0);
26808 MenuTypeFlags: array[TMenuOption] of Integer = (0, 0, 0, 0, MFT_RADIOCHECK, MFT_SEPARATOR, MFT_BITMAP, 0,
26809 MFT_MENUBREAK, MFT_MENUBARBREAK);
26810 var M: PMenu;
26811 MII: TMenuItemInfo;
26812 begin
26814 new( Result, Create );
26815 {+}{++}(*Result := PMenu.Create;*){--}
26816 Result.FVisible := TRUE;
26817 Result.FParent := @ Self;
26818 Result.FItems := NewList;
26819 Result.FIsSeparator := moSeparator in Options;
26820 if FHandle = 0 then
26821 SetSubMenu( CreatePopupMenu );
26822 M := nil;
26823 if (InsertBefore >= 0) and (InsertBefore < 4096) then
26824 begin
26825 M := Items[ InsertBefore ];
26826 if M <> nil then
26827 begin
26828 InsertBefore := M.FId;
26829 M.Parent.FItems.Insert( M.Parent.FItems.IndexOf( M ), Result );
26830 end;
26831 end;
26832 if M = nil then
26833 begin
26834 InsertBefore := -1;
26835 FItems.Add( Result );
26836 end;
26837 Result.FOnMenuItem := Event;
26839 FillChar( MII, Sizeof( MII ), 0 );
26840 MII.cbSize := MenuStructSize;
26841 MII.fMask := MIIM_DATA or MIIM_ID or MIIM_STATE or MIIM_SUBMENU or MIIM_TYPE;
26843 MII.fState := MakeFlags( Pointer( @Options ), MenuStateFlags);
26844 MII.fType := MakeFlags( Pointer( @Options ), MenuTypeFlags);
26845 Result.FId := FDynamicMenuID;
26846 Inc( FDynamicMenuID );
26847 MII.wID := Result.FId;
26848 if moSubMenu in Options
26849 then begin
26850 Result.FHandle := CreatePopupMenu;
26851 MII.hSubMenu := Result.FHandle;
26852 end;
26853 MII.dwTypeData := ACaption;
26854 if not (moBitmap in Options) then MII.cch := StrLen( ACaption );
26855 InsertMenuItem( FHandle, InsertBefore, InsertBefore = -1,
26856 Windows.PMenuItemInfo( @ MII )^ );
26857 if moBitmap in Options then
26858 begin
26859 Result.BitmapItem := DWORD( ACaption );
26861 else
26862 Result.FCaption := ACaption;
26863 RedrawFormMenuBar;
26864 end;
26866 //[function TMenu.AddItem]
26867 function TMenu.AddItem(ACaption: PChar; Event: TOnMenuItem; Options: TMenuOptions): Integer;
26868 begin
26869 Result := InsertItem( -1, ACaption, Event, Options );
26870 end;
26872 //[function TMenu.InsertItem]
26873 function TMenu.InsertItem( InsertBefore: Integer; ACaption: PChar; Event: TOnMenuItem;
26874 Options: TMenuOptions): Integer;
26875 begin
26876 Result := InsertItemEx( InsertBefore, ACaption, Event, Options, FALSE );
26877 end;
26879 //[function TMenu.InsertItemEx]
26880 function TMenu.InsertItemEx(InsertBefore: Integer; ACaption: PChar;
26881 Event: TOnMenuItem; Options: TMenuOptions; ByPosition: Boolean): Integer;
26882 var M: PMenu;
26883 begin
26884 M := Insert( InsertBefore, ACaption, Event, Options );
26885 Result := M.FId;
26886 end;
26888 //[procedure TMenu.InsertSubMenu]
26889 procedure TMenu.InsertSubMenu( SubMenuToInsert: PMenu; InsertBefore: Integer );
26890 var AFlags: DWORD;
26891 M: PMenu;
26892 MII: TMenuItemInfo;
26893 begin
26894 if SubMenuToInsert.FParent <> nil then
26895 SubMenuToInsert := SubMenuToInsert.FParent.RemoveSubMenu( SubMenuToInsert.FId );
26896 if SubMenuToInsert = nil then Exit;
26898 AFlags := MF_BYPOSITION;
26899 M := nil;
26900 if (InsertBefore >= 0) and (InsertBefore < 4096) then
26901 begin
26902 M := Items[ InsertBefore ];
26903 if M = nil then
26904 InsertBefore := -1
26905 else
26906 InsertBefore := M.FId;
26907 end;
26908 if M = nil then
26909 begin
26910 FItems.Add( SubMenuToInsert );
26911 SubMenuToInsert.FParent := @ Self;
26913 else
26914 begin
26915 M.FParent.FItems.Insert( M.FParent.FItems.IndexOf( M ), SubMenuToInsert );
26916 SubMenuToInsert.FParent := M.FParent;
26917 end;
26919 if InsertBefore > 0 then
26920 AFlags := MF_BYCOMMAND;
26921 if SubMenuToInsert.FBmpItem <> 0 then
26922 InsertMenu( FHandle, InsertBefore, AFlags or MF_BITMAP or MF_POPUP, SubMenuToInsert.FHandle,
26923 PChar( SubMenuToInsert.FBmpItem ) )
26924 else
26925 InsertMenu( FHandle, InsertBefore, AFlags or MF_STRING or MF_POPUP, SubMenuToInsert.FHandle,
26926 PChar( SubMenuToInsert.Caption ) );
26927 if SubMenuToInsert.FId = 0 then
26928 begin
26929 SubMenuToInsert.FId := FDynamicMenuID;
26930 Inc( FDynamicMenuID );
26931 MII.cbSize := MenuStructSize;
26932 MII.fMask := MIIM_ID;
26933 MII.wID := SubMenuToInsert.FId;
26934 SetMenuItemInfo( SubMenuToInsert.FParent.FHandle, SubMenuToInsert.FParent.FItems.IndexOf( SubMenuToInsert ),
26935 TRUE, Windows.PMenuItemInfo( @ MII )^ );
26936 end;
26937 RedrawFormMenuBar;
26938 end;
26940 //[function TMenu.RemoveSubMenu]
26941 function TMenu.RemoveSubMenu( ItemToRemove: Integer ): PMenu;
26942 {$IFDEF DEBUG_MENU}var OK: Boolean; {$ENDIF}
26943 begin
26944 Result := Items[ ItemToRemove ];
26945 if Result = nil then Exit;
26946 if Result.FParent <> nil then
26947 {$IFDEF DEBUG_MENU} OK := {$ENDIF}
26948 RemoveMenu( Result.FParent.FHandle, Result.FId, MF_BYCOMMAND )
26949 else
26950 {$IFDEF DEBUG_MENU} OK := {$ENDIF}
26951 RemoveMenu( FHandle, Result.FId, MF_BYCOMMAND );
26952 {$IFDEF DEBUG_MENU}
26953 if not OK then
26954 ShowMessage( 'Error removing menu: ' + Int2Str( GetLastError ) + ' - ' +
26955 SysErrorMessage( GetLastError ) );
26956 {$ENDIF}
26957 if Count = 0 then
26958 begin
26959 Result.Free;
26960 Result := nil;
26961 end;
26962 RedrawFormMenuBar;
26963 end;
26965 //[procedure ClearText]
26966 procedure ClearText( Sender: PControl );
26967 begin
26968 Sender.Caption := '';
26969 end;
26971 //[procedure ClearListbox]
26972 procedure ClearListbox( Sender: PControl );
26973 begin
26974 Sender.Perform( LB_RESETCONTENT, 0, 0 );
26975 end;
26977 //[procedure ClearCombobox]
26978 procedure ClearCombobox( Sender: PControl );
26979 begin
26980 Sender.Perform( CB_RESETCONTENT, 0, 0 );
26981 end;
26983 //[procedure ClearListView]
26984 procedure ClearListView( Sender: PControl );
26985 begin
26986 Sender.Perform( LVM_DELETEALLITEMS, 0, 0 );
26987 end;
26989 //[procedure ClearToolbar]
26990 procedure ClearToolbar( Sender: PControl );
26991 begin
26992 while Sender.TBButtonCount > 0 do
26993 Sender.TBDeleteButton( Sender.TBIndex2Item( 0 ) );
26994 Sender.Perform( TB_SETBITMAPSIZE, 0, 0 );
26995 end;
26997 { -- Constructor of canvas -- }
26998 //[function NewCanvas]
26999 function NewCanvas( DC: HDC ): PCanvas;
27000 begin
27002 New( Result, Create );
27004 {++}(*
27005 Result := PCanvas.Create;
27006 *){--}
27007 Result.ModeCopy := cmSrcCopy;
27008 if DC <> 0 then
27009 begin
27010 Result.SetHandle( DC );
27011 //Result.fIsPaintDC := True; // If Canvas will be destroyed, DC will not be deleted
27012 end;
27013 end;
27014 //[END NewCanvas]
27016 { -- Contructors of controls -- }
27018 {$IFDEF ASM_VERSION}
27019 //[FUNCTION _NewTControl]
27020 function _NewTControl( AParent: PControl ): PControl;
27021 begin
27022 New( Result, CreateParented( AParent ) );
27023 end;
27024 //[END _NewTControl]
27026 //[function _NewWindowed]
27027 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;
27029 PUSH EBX
27030 PUSH ESI
27031 PUSH EDI
27033 PUSH ECX // Ctl3D
27034 PUSH EDX // ControlClassName
27036 MOV ESI, EAX // ESI = AParent
27037 CALL _NewTControl
27038 XCHG EBX, EAX // EBX = Result
27039 POP [EBX].TControl.fControlClassName
27040 INC [EBX].TControl.fWindowed
27042 INC EAX
27043 POP EDX // DL = parameter Ctl3D
27044 TEST ESI, ESI
27045 JZ @@no_parent
27047 LEA ESI, [ESI].TControl.fWndProcResizeFlicks
27048 LEA EDI, [EBX].TControl.fWndProcResizeFlicks
27049 MOVSD // fWndProcResizeFlicks
27050 MOVSD // fGotoControl
27051 //MOVSW // fDoubleBuffered, fTransparent
27052 LODSB // fCtl3Dchild
27053 STOSB
27054 DEC AL
27055 LODSB // fCtl3D
27056 JZ @@passed3D
27057 XOR EDX, EDX
27058 @@passed3D:
27059 XCHG EAX, EDX
27060 STOSB // fCtl3D
27062 MOVSD // fTextColor
27063 LODSD
27064 XCHG EDX, EAX
27065 XOR EAX, EAX
27066 PUSH EDX
27067 CALL TGraphicTool.Assign
27068 STOSD // fFont
27069 POP EDX
27070 XCHG ECX, EAX
27071 JECXZ @@no_font
27072 MOV [ECX].TGraphicTool.fParentGDITool, EDX
27073 MOV [ECX].TGraphicTool.fOnChange.TMethod.Code, offset[TControl.FontChanged]
27074 MOV [ECX].TGraphicTool.fOnChange.TMethod.Data, EBX
27075 MOV EAX, EBX
27076 MOV EDX, ECX
27077 CALL TControl.FontChanged
27078 @@no_font:
27080 MOVSD // fColor
27081 LODSD
27082 XCHG EDX, EAX
27083 XOR EAX, EAX
27084 PUSH EDX
27085 CALL TGraphicTool.Assign
27086 STOSD // fBrush
27087 POP EDX
27088 XCHG ECX, EAX
27089 JECXZ @@no_brush
27090 MOV [ECX].TGraphicTool.fParentGDITool, EDX
27091 MOV [ECX].TGraphicTool.fOnChange.TMethod.Code, offset[TControl.BrushChanged]
27092 MOV [ECX].TGraphicTool.fOnChange.TMethod.Data, EBX
27093 MOV EAX, EBX
27094 MOV EDX, ECX
27095 CALL TControl.BrushChanged
27096 @@no_brush:
27098 LODSD
27099 STOSD // fMargin
27100 STOSD // fBoundsRect.Left
27101 PUSH EAX
27102 ADD EAX, [ESI+16] // AParent.fClientTop
27103 STOSD // fBoundsRect.Top
27104 POP EAX
27105 ADD EAX, 64
27106 STOSD // fBoundsRect.Right
27107 STOSD // fBoundsRect.Bottom
27109 @@no_parent:
27110 XCHG EAX, EBX
27111 //DEC byte ptr [EAX].TControl.fAlphaBlend
27112 //INC byte ptr [EAX].TControl.fEraseUpdRgn
27113 POP EDI
27114 POP ESI
27115 POP EBX
27116 end;
27117 {$ELSE ASM_VERSION} //Pascal
27118 function _NewWindowed( AParent: PControl; ControlClassName: PChar; Ctl3D: Boolean ): PControl;
27119 begin
27121 New( Result, CreateParented( AParent ) );
27122 {+}{++}(*Result := PControl.CreateParented( AParent );*){--}
27123 Result.fControlClassName := ControlClassName;
27124 if AParent <> nil then
27125 begin
27126 Result.fWndProcResizeFlicks := AParent.fWndProcResizeFlicks;
27127 Result.fGotoControl := AParent.fGotoControl;
27128 //Result.fDoubleBuffered := AParent.fDoubleBuffered;
27129 //Result.fTransparent := AParent.fTransparent;
27130 Result.fCtl3Dchild := AParent.fCtl3Dchild;
27131 if AParent.fCtl3Dchild then
27132 Result.fCtl3D := Ctl3D
27133 else
27134 Result.fCtl3D := False;
27135 Result.fMargin := AParent.fMargin;
27136 with Result.fBoundsRect do
27137 begin
27138 Left := AParent.fMargin + AParent.fClientLeft;
27139 Top := AParent.fMargin + AParent.fClientTop;
27140 Right := Left + 64;
27141 Bottom := Top + 64;
27142 end;
27143 Result.fTextColor := AParent.fTextColor;
27144 Result.fFont := Result.fFont.Assign( AParent.fFont );
27145 if Result.fFont <> nil then
27146 begin
27147 Result.fFont.fParentGDITool := AParent.fFont;
27148 Result.fFont.fOnChange := Result.FontChanged;
27149 Result.FontChanged( Result.fFont );
27150 end;
27151 Result.fColor := AParent.fColor;
27152 Result.fBrush := Result.fBrush.Assign( AParent.fBrush );
27153 if Result.fBrush <> nil then
27154 begin
27155 Result.fBrush.fParentGDITool := AParent.fBrush;
27156 Result.fBrush.fOnChange := Result.BrushChanged;
27157 Result.BrushChanged( Result.fBrush );
27158 end;
27159 end;
27160 //Result.fAlphaBlend := 255;
27161 //Result.fEraseUpdRgn := TRUE;
27162 end;
27163 //[END _NewWindowed]
27164 {$ENDIF ASM_VERSION}
27166 //===================== Form ========================//
27168 {$IFDEF USE_CONSTRUCTORS}
27169 //[function NewForm]
27170 function NewForm( AParent: PControl; const Caption: String ): PControl;
27171 begin
27172 new( Result, CreateForm( AParent, Caption ) );
27173 end;
27174 //[END NewForm]
27175 {$ELSE not_USE_CONSTRUCTORS}
27177 //[FUNCTION NewForm]
27178 {$IFDEF ASM_VERSION}
27179 function NewForm( AParent: PControl; const Caption: String ): PControl;
27180 const FormClass: array[ 0..4 ] of Char = ( 'F', 'o', 'r', 'm', #0 );
27182 PUSH EBX
27183 PUSH EDX
27184 MOV EDX, offset[FormClass]
27185 MOV CL, 1
27186 CALL _NewWindowed
27187 MOV EBX, EAX
27188 INC [EBX].TControl.fSizeGrip
27189 OR byte ptr [EBX].TControl.fClsStyle, CS_DBLCLKS
27190 MOV EDX, offset[WndProcForm]
27191 CALL TControl.AttachProc
27192 MOV EDX, offset[WndProcDoEraseBkgnd]
27193 MOV EAX, EBX
27194 CALL TControl.AttachProc
27195 POP EDX
27196 MOV EAX, EBX
27197 CALL TControl.SetCaption
27198 INC [EBX].TControl.fSizeGrip
27199 INC [EBX].TControl.fIsForm
27200 XCHG EAX, EBX
27201 POP EBX
27202 end;
27203 {$ELSE ASM_VERSION} //Pascal
27204 function NewForm( AParent: PControl; const Caption: String ): PControl;
27205 begin
27206 Result := _NewWindowed( AParent, 'Form', True );
27207 Result.fClsStyle := Result.fClsStyle or CS_DBLCLKS;
27208 Result.AttachProc( WndProcForm );
27209 Result.AttachProc( WndProcDoEraseBkgnd );
27210 Result.Caption := Caption;
27211 Result.fSizeGrip := TRUE;
27212 Result.fIsForm := TRUE;
27213 end;
27214 {$ENDIF ASM_VERSION}
27215 //[END NewForm]
27217 {$ENDIF USE_CONSTRUCTORS}
27219 //===================== Applet button ========================//
27221 //{$DEFINE WNDPROCAPP_USED}
27222 {$IFDEF WNDPROCAPP_USED}
27224 //[FUNCTION WndProcApp]
27225 {$IFDEF ASM_VERSION}
27226 {$IFDEF WNDPROCAPP_ASM_USED}
27227 function WndProcApp(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
27229 CMP word ptr [EDX].TMsg.message, WM_SETFOCUS
27230 JNZ @@chk_CLOSE
27231 MOV ECX, [EAX].TControl.FCurrentControl
27232 JECXZ @@ret_false
27233 XCHG EAX, ECX
27234 PUSH EAX
27235 CALL CallTControlCreateWindow
27236 TEST AL, AL
27237 POP EAX
27238 JZ @@1
27239 PUSH [EAX].TControl.fHandle
27240 CALL SetFocus
27241 @@1: MOV AL, 1
27243 @@chk_CLOSE:
27244 CMP word ptr [EDX].TMsg.message, WM_SYSCOMMAND
27245 JNZ @@ret_false
27246 MOV EDX, dword ptr [EDX].TMsg.wParam
27247 AND DX, $FFF0
27248 CMP DX, SC_CLOSE
27249 JNZ @@ret_false
27250 PUSH ECX
27251 MOV ECX, [EAX].TControl.fChildren
27252 JECXZ @@ret_false1
27253 XCHG EAX, ECX
27254 MOV ECX, [EAX].TList.fCount
27255 JECXZ @@ret_false1
27256 MOV EAX, [EAX].TList.fItems
27257 MOV ECX, dword ptr [EAX]
27258 JECXZ @@ret_false1
27259 XCHG EAX, ECX
27260 PUSH EAX
27261 CALL TControl.IsMainWindow
27262 TEST EAX, EAX
27263 POP EAX
27264 JZ @@ret_false1
27265 CALL TControl.Close
27266 POP ECX
27267 XOR EAX, EAX
27268 MOV dword ptr [ECX], EAX
27269 INC EAX
27270 JMP @@exit
27271 @@ret_false1:
27272 POP ECX
27273 @@ret_false:
27274 XOR EAX, EAX
27275 @@exit:
27276 end;
27277 {$ENDIF}
27278 {$ELSE ASM_VERSION} //Pascal
27279 function WndProcApp(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
27280 begin
27281 Result := False;
27282 case Msg.message of
27283 WM_SETFOCUS:
27284 {$IFDEF NEW_MODAL}
27285 if Self_.fModalForm <> nil then
27286 SetFocus( Self_.fModalForm.fHandle )
27287 else if ( Self_.FCurrentControl <> nil ) and not
27288 ( Self_.fCurrentControl.IsForm xor Self_.fIsApplet ) then
27289 {$ELSE not_NEW_MODAL}
27290 if Self_.FCurrentControl <> nil then
27291 {$ENDIF NEW_MODAL}
27292 begin
27293 if Self_.FCurrentControl.CreateWindow then
27294 SetFocus( Self_.FCurrentControl.fHandle );
27295 Result := True;
27296 end;
27297 WM_SYSCOMMAND:
27298 if Msg.wParam and $FFF0 = SC_CLOSE then
27299 if (Self_.fChildren <> nil) and (Self_.fChildren.fCount > 0) and
27300 PControl( Self_.fChildren.fItems[ 0 ] ).IsMainWindow then
27301 begin
27302 PControl( Self_.fChildren.fItems[ 0 ] ).Close;
27303 Rslt := 0;
27304 Result := TRUE;
27305 end;
27306 end;
27307 end;
27308 {$ENDIF ASM_VERSION}
27309 //[END WndProcApp]
27311 {$ENDIF WNDPROCAPP_USED}
27313 {$IFDEF USE_CONSTRUCTORS}
27314 {$DEFINE CREATEAPPBUTTON_USED}
27315 //[function NewApplet]
27316 function NewApplet( const Caption: String ): PControl;
27317 begin
27318 new( Result, CreateApplet( Caption ) );
27319 end;
27320 //[END NewApplet]
27321 {$ELSE not_USE_CONSTRUCTORS}
27323 //[FUNCTION NewApplet]
27324 {$IFDEF ASM_VERSION}
27325 function NewApplet( const Caption: String ): PControl;
27326 const AppClass: array[ 0..3 ] of Char = ( 'A', 'p', 'p', #0 );
27328 XOR ECX, ECX
27329 INC ECX
27330 MOV [AppButtonUsed], CL
27331 PUSH EAX
27332 MOV EDX, offset[AppClass]
27333 XOR EAX, EAX
27334 CALL _NewWindowed
27335 INC [EAX].TControl.FIsApplet
27336 MOV word ptr [EAX].TControl.fStyle + 2, $90CA //WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX or WS_CAPTION
27337 MOV byte ptr [EAX].TControl.fExStyle + 2, WS_EX_APPWINDOW shr 16 // WS_EX_APPWINDOW = $40000
27338 CALL @@newapp1
27340 // BODY of CreateAppButton here:
27341 PUSH ESI
27342 PUSH 0
27343 PUSH [EAX].TControl.fHandle
27344 CALL GetSystemMenu
27345 MOV ESI, offset[DeleteMenu]
27347 XCHG ECX, EAX
27348 MOV EAX, SC_MAXIMIZE
27351 PUSH EDX
27352 PUSH EAX
27353 PUSH ECX
27355 PUSH EDX
27356 {$IFDEF PARANOIA}
27357 DB $2C, $20
27358 {$ELSE}
27359 SUB AL, $20 // SC_MOVE
27360 {$ENDIF}
27361 PUSH EAX
27362 PUSH ECX
27364 PUSH EDX
27365 {$IFDEF PARANOIA}
27366 DB $2C, $10
27367 {$ELSE}
27368 SUB AL, $10 // SC_SIZE
27369 {$ENDIF}
27370 PUSH EAX
27371 PUSH ECX
27373 PUSH 1 // MF_GRAYED or MF_BYCOMMAND
27374 MOV AX, SC_RESTORE
27375 PUSH EAX
27376 PUSH ECX
27378 CALL EnableMenuItem
27379 CALL ESI
27380 CALL ESI
27381 CALL ESI
27382 POP ESI
27383 @@ret_false:
27384 XOR EAX, EAX
27387 @@chk_CLOSE:
27388 CMP word ptr [EDX].TMsg.message, WM_SYSCOMMAND
27389 JNZ @@ret_false
27390 MOV EDX, dword ptr [EDX].TMsg.wParam
27391 AND DX, $FFF0
27392 CMP DX, SC_CLOSE
27393 JNZ @@ret_false
27394 PUSH ECX
27395 MOV ECX, [EAX].TControl.fChildren
27396 JECXZ @@ret_false1
27397 XCHG EAX, ECX
27398 MOV ECX, [EAX].TList.fCount
27399 JECXZ @@ret_false1
27400 MOV EAX, [EAX].TList.fItems
27401 MOV ECX, dword ptr [EAX]
27402 JECXZ @@ret_false1
27403 XCHG EAX, ECX
27404 PUSH EAX
27405 CALL TControl.IsMainWindow
27406 TEST EAX, EAX
27407 POP EAX
27408 JZ @@ret_false1
27409 CALL TControl.Close
27410 POP ECX
27411 XOR EAX, EAX
27412 MOV dword ptr [ECX], EAX
27413 INC EAX
27415 @@ret_false1:
27416 POP ECX
27417 JMP @@ret_false
27419 @@newapp1:
27420 //MOV [EAX].TControl.FCreateWndExt, offset[CreateAppButton]
27421 POP [EAX].TControl.FCreateWndExt
27422 PUSH EAX
27423 CALL @@newapp2
27425 // BODY of WndProcApp here:
27426 CMP word ptr [EDX].TMsg.message, WM_SETFOCUS
27427 JNZ @@chk_CLOSE
27428 MOV ECX, [EAX].TControl.FCurrentControl
27429 JECXZ @@ret_false
27430 XCHG EAX, ECX
27432 PUSH EAX
27433 CALL CallTControlCreateWindow
27434 POP EAX
27435 PUSH [EAX].TControl.fHandle
27437 CALL SetFocus
27438 MOV AL, 1
27441 @@newapp2:
27442 POP EDX
27443 CALL TControl.AttachProc
27444 POP EAX
27445 POP EDX
27446 PUSH EAX
27447 CALL TControl.SetCaption
27448 POP EAX
27449 end;
27451 {$ELSE ASM_VERSION} //Pascal
27453 //[procedure CreateAppButton]
27454 procedure CreateAppButton( App: PControl );
27455 var M: HMenu;
27456 begin
27457 M := GetSystemMenu( App.fHandle, False );
27458 DeleteMenu( M, SC_MAXIMIZE, MF_BYCOMMAND );
27459 DeleteMenu( M, SC_MOVE, MF_BYCOMMAND );
27460 DeleteMenu( M, SC_SIZE, MF_BYCOMMAND );
27461 EnableMenuItem( M, SC_RESTORE, MF_GRAYED or MF_BYCOMMAND );
27462 end;
27464 //[function NewApplet]
27465 function NewApplet( const Caption: String ): PControl;
27466 begin
27467 AppButtonUsed := True;
27468 Result := _NewWindowed( nil, 'App', True );
27469 Result.FIsApplet := TRUE;
27470 Result.fStyle := WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX or WS_CAPTION;
27471 Result.fExStyle := WS_EX_APPWINDOW;
27472 Result.FCreateWndExt := CreateAppButton;
27473 Result.AttachProc( WndProcApp );
27474 Result.Caption := Caption;
27475 end;
27476 {$ENDIF ASM_VERSION}
27477 //[END NewApplet]
27478 {$ENDIF USE_CONSTRUCTORS}
27480 {$IFDEF CREATEAPPBUTTON_USED}
27481 procedure CreateAppButton( App: PControl );
27483 {$IFDEF F_P}
27484 MOV EAX, [App]
27485 {$ENDIF F_P}
27486 PUSH ESI
27487 PUSH 0
27488 PUSH [EAX].TControl.fHandle
27489 CALL GetSystemMenu
27490 MOV ESI, offset[DeleteMenu]
27492 XCHG ECX, EAX
27493 MOV EAX, SC_MAXIMIZE
27496 PUSH EDX
27497 PUSH EAX
27498 PUSH ECX
27500 PUSH EDX
27501 {$IFDEF PARANOIA}
27502 DB $2C, $20
27503 {$ELSE}
27504 SUB AL, $20 // SC_MOVE
27505 {$ENDIF}
27506 PUSH EAX
27507 PUSH ECX
27509 PUSH EDX
27510 {$IFDEF PARANOIA}
27511 DB $2C, $10
27512 {$ELSE}
27513 SUB AL, $10 // SC_SIZE
27514 {$ENDIF}
27515 PUSH EAX
27516 PUSH ECX
27518 PUSH 1 // MF_GRAYED or MF_BYCOMMAND
27519 MOV AX, SC_RESTORE
27520 PUSH EAX
27521 PUSH ECX
27523 CALL EnableMenuItem
27524 CALL ESI
27525 CALL ESI
27526 CALL ESI
27527 POP ESI
27528 end {$IFDEF F_P} [ 'EAX', 'EDX', 'ECX' ] {$ENDIF};
27529 {$ENDIF CREATEAPPBUTTON_USED}
27531 var CtlIdCount: WORD = $8000;
27534 {$IFNDEF ASM_VERSION}
27535 //{$DEFINE CREATEPARAMS2_USED}
27536 {$ENDIF}
27537 {$IFDEF USE_CONSTRUCTORS}
27538 //{$DEFINE CREATEPARAMS2_USED}
27539 {$ENDIF}
27542 {$IFDEF CREATEPARAMS2_USED} // seems not needed more
27543 //[procedure CreateParams2]
27544 procedure CreateParams2( Self_: PControl; var Params: TCreateParams);
27545 begin
27546 Self_.CreateSubclass( Params, Self_.fControlClassName );
27547 end;
27548 {$ENDIF}
27550 //[FUNCTION _NewControl]
27551 {$IFDEF ASM_VERSION}
27552 function _NewControl( AParent: PControl; ControlClassName: PChar;
27553 Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;
27554 const szActions = sizeof(TCommandActions);
27556 PUSH EBX
27557 PUSH EAX // push AParent
27558 PUSH ECX // push Style
27559 MOVZX ECX, Ctl3D
27560 CALL _NewWindowed
27561 XCHG EBX, EAX
27562 INC [EBX].TControl.fIsControl
27563 INC [EBX].TControl.fVerticalAlign
27564 MOV EAX, Actions
27565 TEST EAX, EAX
27566 JZ @@noActions
27567 LEA EDX, [EBX].TControl.fCommandActions
27568 XOR ECX, ECX
27569 MOV CL, szActions
27570 CALL System.Move
27571 @@noActions:
27572 POP EDX // pop Style
27573 OR EDX, WS_CLIPSIBLINGS or WS_CLIPCHILDREN
27574 MOV byte ptr [EBX].TControl.fLookTabKeys, $0F
27575 CMP [EBX].TControl.fCtl3D, 0
27576 JZ @@noCtl3D
27577 AND EDX, not WS_BORDER
27578 OR byte ptr [EBX].TControl.fExStyle + 1, WS_EX_CLIENTEDGE shr 8
27579 @@noCtl3D:
27580 MOV [EBX].TControl.fStyle, EDX
27581 TEST EDX, WS_VISIBLE
27582 SETNZ AL
27583 MOV [EBX].TControl.fVisible, AL
27584 TEST EDX, WS_TABSTOP
27585 POP ECX // pop AParent
27586 PUSHFD
27587 JECXZ @@noParent
27588 MOV EAX, [ECX].TControl.fCursor
27589 MOV [EBX].TControl.fCursor, EAX
27590 XCHG EAX, ECX
27591 CALL TControl.ParentForm
27592 XCHG ECX, EAX
27593 JECXZ @@noParent
27594 INC [ECX].TControl.fTabOrder
27595 MOV EDX, [ECX].TControl.fTabOrder
27596 MOV [EBX].TControl.fTabOrder, EDX
27597 @@noParent:
27598 POPFD
27599 JZ @@noTabStop
27600 INC [EBX].TControl.fTabstop
27601 JECXZ @@noTabstop
27602 XCHG EAX, ECX
27603 MOV ECX, [EAX].TControl.FCurrentControl
27604 INC ECX
27605 LOOP @@noTabStop
27606 MOV [EAX].TControl.FCurrentControl, EBX
27607 @@noTabStop:
27608 MOVZX EDX, [CtlIdCount]
27609 INC [CtlIdCount]
27610 MOV [EBX].TControl.fMenu, EDX
27611 MOV EDX, offset[WndProcCtrl]
27612 MOV EAX, EBX
27613 CALL TControl.AttachProc
27614 XCHG EAX, EBX
27615 POP EBX
27616 end;
27617 {$ELSE ASM_VERSION} //Pascal
27618 function _NewControl( AParent: PControl; ControlClassName: PChar;
27619 Style: DWORD; Ctl3D: Boolean; Actions: PCommandActions ): PControl;
27620 var Form: PControl;
27621 begin
27622 Result := _NewWindowed( AParent, ControlClassName, Ctl3D );
27623 if Actions <> nil then
27624 Result.fCommandActions := Actions^;
27625 Result.fIsControl := True;
27626 Result.fStyle := Style or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
27627 Result.fVerticalAlign := vaTop;
27628 Result.fVisible := (Style and WS_VISIBLE) <> 0;
27629 Result.fTabstop := (Style and WS_TABSTOP) <> 0;
27630 if (AParent <> nil) then
27631 begin
27632 Inc( AParent.ParentForm.fTabOrder );
27633 Result.fTabOrder := AParent.ParentForm.fTabOrder;
27634 Result.fCursor := AParent.fCursor;
27635 end;
27636 Result.fLookTabKeys := [ tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn ];
27637 if Result.fCtl3D then
27638 begin
27639 Result.fStyle := Result.fStyle and not WS_BORDER;
27640 Result.fExStyle := Result.fExStyle or WS_EX_CLIENTEDGE;
27641 end;
27642 if (Style and WS_TABSTOP) <> 0 then
27643 begin
27644 Form := Result.ParentForm;
27645 if Form <> nil then
27646 if Form.FCurrentControl = nil then
27647 Form.FCurrentControl := Result;
27648 end;
27649 //Result.fCreateParamsExt := CreateParams2;
27650 Result.fMenu := CtlIdCount;
27651 Inc( CtlIdCount );
27652 Result.AttachProc( WndProcCtrl );
27653 end;
27654 {$ENDIF ASM_VERSION}
27655 //[END _NewControl]
27657 //===================== Button ========================//
27659 //[function TControl.SetButtonIcon]
27660 function TControl.SetButtonIcon(aIcon: HIcon): PControl;
27661 var PrevImg: THandle;
27662 begin
27663 Style := Style or BS_ICON;
27664 fButtonIcon := aIcon;
27665 PrevImg := Perform( BM_SETIMAGE, IMAGE_ICON, aIcon );
27666 if PrevImg <> 0 then
27667 DeleteObject( PrevImg );
27668 Result := @ Self;
27669 end;
27671 //[function TControl.SetButtonBitmap]
27672 function TControl.SetButtonBitmap(aBmp: HBitmap): PControl;
27673 var PrevImg: THandle;
27674 begin
27675 Style := Style or BS_BITMAP;
27676 PrevImg := Perform( BM_SETIMAGE, IMAGE_BITMAP, aBmp );
27677 if PrevImg <> 0 then
27678 DeleteObject( PrevImg );
27679 Result := @ Self;
27680 end;
27682 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
27683 //[function WndProcBtnReturnClick]
27684 function WndProcBtnReturnClick( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
27685 begin
27686 Result := FALSE;
27687 if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_KEYUP) or
27688 (Msg.message = WM_CHAR)) and (Msg.wParam = 13) then
27689 Msg.wParam := 32;
27690 end;
27691 {$ENDIF}
27693 //[function AutoMinimizeApplet]
27694 function AutoMinimizeApplet(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
27695 begin
27696 if (msg.Message=WM_SYSCOMMAND) and (msg.wParam=SC_MINIMIZE) then begin
27697 AppletMinimize;
27698 Result := True;
27699 end else
27700 Result := False;
27701 end;
27703 {$IFDEF USE_CONSTRUCTORS}
27704 //[function NewButton]
27705 function NewButton( AParent: PControl; const Caption: String ): PControl;
27706 begin
27707 new( Result, CreateButton( AParent, Caption ) );
27708 end;
27709 {$ELSE USE_CONSTRUCTORS}
27711 {$IFDEF ASM_VERSION}
27712 const ButtonClass: array[ 0..6 ] of Char = ( 'B','U','T','T','O','N',#0 );
27713 {$ENDIF ASM_VERSION}
27715 //[FUNCTION NewButton]
27716 {$IFDEF ASM_VERSION}
27717 function NewButton( AParent: PControl; const Caption: String ): PControl;
27718 const szActions = sizeof(TCommandActions);
27720 PUSH EDX
27722 PUSH 0
27723 PUSH offset[ButtonActions]
27725 MOV EDX, offset[ButtonClass]
27726 MOV ECX, WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or WS_TABSTOP
27727 CALL _NewControl
27728 INC [EAX].TControl.fIgnoreDefault
27729 MOV EDX, [EAX].TControl.fBoundsRect.Top
27730 ADD EDX, 22
27731 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
27732 MOV [EAX].TControl.fTextAlign, taCenter
27733 INC [EAX].TControl.fIsButton
27735 POP EDX
27736 PUSH EAX
27737 CALL TControl.SetCaption
27738 POP EAX
27739 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
27740 PUSH EAX
27741 MOV EDX, offset[WndProcBtnReturnClick]
27742 CALL TControl.AttachProc
27743 POP EAX
27744 {$ENDIF}
27745 end;
27746 {$ELSE ASM_VERSION} //Pascal
27747 function NewButton( AParent: PControl; const Caption: String ): PControl;
27748 begin
27749 Result := _NewControl( AParent, 'BUTTON',
27750 WS_VISIBLE or WS_CHILD or
27751 BS_PUSHLIKE or WS_TABSTOP, False, @ButtonActions );
27752 Result.fIgnoreDefault := TRUE;
27753 Result.fCtl3D := TRUE;
27754 with Result.fBoundsRect do
27755 Bottom := Top + 22;
27756 Result.fTextAlign := taCenter;
27757 Result.Caption := Caption;
27758 Result.fIsButton := TRUE;
27759 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
27760 Result.AttachProc( WndProcBtnReturnClick );
27761 {$ENDIF}
27762 end;
27763 {$ENDIF ASM_VERSION}
27764 //[END NewButton]
27766 {$ENDIF USE_CONSTRUCTORS}
27768 //----------------- BitBtn -----------------------
27770 //[FUNCTION WndProc_DrawItem]
27771 {$IFDEF ASM_VERSION}
27772 function WndProc_DrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
27773 : Boolean;
27774 asm //cmd //opd
27775 CMP word ptr [EDX].TMsg.message, WM_DRAWITEM
27776 JNZ @@ret_false
27777 MOV EAX, [EDX].TMsg.lParam
27778 MOV ECX, [EAX].TDrawItemStruct.hwndItem
27779 JECXZ @@ret_false
27780 PUSH EDX
27781 PUSH offset[ID_SELF]
27782 PUSH ECX
27783 CALL GetProp
27784 POP EDX
27785 TEST EAX, EAX
27786 JZ @@ret_false
27787 PUSH [EDX].TMsg.lParam
27788 PUSH [EDX].TMsg.wParam
27789 PUSH CN_DRAWITEM
27790 PUSH EAX
27791 CALL TControl.Perform
27792 MOV AL, 1
27794 @@ret_false:
27795 XOR EAX, EAX
27796 end;
27797 {$ELSE ASM_VERSION} //Pascal
27798 function WndProc_DrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
27799 : Boolean;
27800 var DI: PDrawItemStruct;
27801 Control: PControl;
27802 begin
27803 Result := FALSE;
27804 if Msg.message = WM_DRAWITEM then
27805 begin
27806 DI := Pointer( Msg.lParam );
27807 Control := Pointer( GetProp( DI.hwndItem, ID_SELF ) );
27808 if Control <> nil then
27809 begin
27810 {Rslt := Integer(
27811 Control.OnDrawItem( Control, DI.hDC, DI.rcItem, DI.itemID,
27812 TDrawAction( Byte( DI.itemAction ) ),
27813 TDrawState( Word( DI.itemState ) ) ) );}
27814 Rslt := Control.Perform( CN_DRAWITEM, Msg.wParam, Msg.lParam );
27815 Result := TRUE;
27816 end;
27817 //else Rslt := 0;
27818 end;
27819 end;
27820 {$ENDIF ASM_VERSION}
27821 //[END WndProc_DrawItem]
27823 //[function ExcludeAmpersands]
27824 function ExcludeAmpersands( Self_: PControl; const S: String ): String;
27825 var I: Integer;
27826 begin
27827 Result := S;
27828 if not Self_.FBitBtnDrawMnemonic then Exit;
27829 for I := Length( Result ) downto 1 do
27830 begin
27831 if Result[ I ] = '&' then
27832 Delete( Result, I, 1 );
27833 end;
27834 end;
27836 //[procedure BitBtnExtDraw]
27837 procedure BitBtnExtDraw( Self_: PControl; DC: HDC; X, Y: Integer; const R: TRect;
27838 const CapText, CapTxtOrig: String; Color: TColor );
27839 var I, J, W, H: Integer;
27840 Sz: TSize;
27841 Pen, OldPen: HPen;
27842 begin
27843 if not Self_.FBitBtnDrawMnemonic then Exit;
27844 J := 0;
27845 for I := 1 to Length( CapTxtOrig ) do
27846 begin
27847 if CapTxtOrig[ I ] <> '&' then
27848 Inc( J )
27849 else
27850 begin
27851 Windows.GetTextExtentPoint32( DC, PChar( CapText ), J, Sz );
27852 W := Sz.cx;
27853 Windows.GetTextExtentPoint32( DC, '_', 1, Sz );
27854 H := Sz.cy - 1;
27855 Windows.GetTextExtentPoint32( DC, @ CapTxtOrig[ I + 1 ], 1, Sz );
27856 Windows.MoveToEx( DC, X + W, Y + H, nil );
27858 Pen := CreatePen( PS_SOLID, 0, Color2RGB( Color ) );
27859 OldPen := SelectObject( DC, Pen );
27861 Windows.LineTo( DC, X + W + Sz.cx, Y + H );
27863 SelectObject( DC, OldPen );
27864 DeleteObject( Pen );
27865 end;
27866 end;
27867 end;
27869 //[procedure TControl.SetBitBtnDrawMnemonic]
27870 procedure TControl.SetBitBtnDrawMnemonic(const Value: Boolean);
27871 begin
27872 FBitBtnDrawMnemonic := Value;
27873 FBitBtnGetCaption := ExcludeAmpersands;
27874 FBitBtnExtDraw := BitBtnExtDraw;
27875 Invalidate;
27876 end;
27878 //[function TControl.GetBitBtnImgIdx]
27879 function TControl.GetBitBtnImgIdx: Integer;
27880 begin
27881 Result := LoWord( fGlyphCount );
27882 end;
27884 //[procedure TControl.SetBitBtnImgIdx]
27885 procedure TControl.SetBitBtnImgIdx(const Value: Integer);
27886 begin
27887 if not( bboImageList in fBitBtnOptions ) then Exit;
27888 fGlyphCount := HiWord( fGlyphCount ) or (Value and $FFFF);
27889 Invalidate;
27890 end;
27892 //[function TControl.GetBitBtnImageList]
27893 function TControl.GetBitBtnImageList: THandle;
27894 begin
27895 Result := 0;
27896 if bboImageList in fBitBtnOptions then
27897 Result := fGlyphBitmap;
27898 end;
27900 //[procedure TControl.SetBitBtnImageList]
27901 procedure TControl.SetBitBtnImageList(const Value: THandle);
27902 begin
27903 fGlyphBitmap := Value;
27904 if Value <> 0 then
27905 begin
27906 fBitBtnOptions := fBitBtnOptions + [ bboImageList ];
27907 ImageList_GetIconSize( Value, fGlyphWidth, fGlyphHeight );
27909 else
27910 fBitBtnOptions := fBitBtnOptions - [ bboImageList ];
27911 Invalidate;
27912 end;
27914 //[FUNCTION WndProcBitBtn]
27915 {$IFDEF ASM_noVERSION} // remove &-s from view //+ TextShift & if Y < 0 then Y := 0; // + glyph + TextShift if not glyphOver
27916 function WndProcBitBtn( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
27917 const szBitmapInfo = sizeof(TBitmapInfo);
27919 CMP word ptr [EDX].TMsg.message, WM_LBUTTONDBLCLK
27920 JNZ @@noWM_LBUTTONDBLCLK
27921 PUSH ECX
27922 PUSH [EDX].TMsg.wParam
27923 PUSH [EDX].TMsg.lParam
27924 PUSH WM_LBUTTONDOWN
27925 PUSH EAX
27926 CALL TControl.Perform
27927 POP ECX
27928 MOV [ECX], EAX
27929 MOV AL, 1
27931 @@noWM_LBUTTONDBLCLK:
27932 PUSH EBX
27933 CMP [EDX].TMsg.message, CN_DRAWITEM
27934 JNZ @@noCN_DRAWITEM
27935 PUSH EDI
27936 PUSH ESI
27937 XCHG EDI, EAX // EDI = @Self
27938 MOV dword ptr [ECX], 1
27939 MOV ESI, [EDX].TMsg.lParam // ESI = DIS
27940 XOR EBX, EBX // G = 0
27941 MOV EAX, [ESI].TDrawItemStruct.itemState
27942 TEST byte ptr [EDI].TControl.fBitBtnOptions, 8 //1 shl Ord(bboFixed)
27943 JNZ @@fixed_in_options
27944 {$IFDEF PARANOIA}
27945 DB $A8, ODS_SELECTED
27946 {$ELSE}
27947 TEST AL, ODS_SELECTED
27948 {$ENDIF}
27949 JZ @@not1
27950 JMP @@1
27951 @@fixed_in_options:
27952 TEST byte ptr [EDI].TControl.fChecked, 1
27953 JZ @@not1
27954 @@1: INC EBX
27955 @@not1:
27956 {$IFDEF PARANOIA}
27957 DB $A8, ODS_DISABLED
27958 {$ELSE}
27959 TEST AL, ODS_DISABLED
27960 {$ENDIF}
27961 JZ @@not2
27962 MOV BL, 2
27963 @@not2: TEST EBX, EBX
27964 JNZ @@not3
27965 {$IFDEF PARANOIA}
27966 DB $A8, ODS_FOCUS
27967 {$ELSE}
27968 TEST AL, ODS_FOCUS
27969 {$ENDIF}
27970 JZ @@not3
27971 MOV BL, 3
27972 @@not3: CMP [EDI].TControl.fMouseInControl, BH
27973 JZ @@not4
27974 TEST EBX, EBX
27975 JZ @@4
27976 CMP BL, 3
27977 JNZ @@not4
27978 @@4: MOV BL, 4
27979 @@not4: MOV ECX, [EDI].TControl.fOnBitBtnDraw.TMethod.Code
27980 TEST ECX, ECX
27981 JZ @@noOnBitBtnDraw
27982 //JECXZ @@noOnBitBtnDraw
27983 MOV EAX, [EDI].TControl.fCanvas
27984 PUSH EAX
27985 TEST EAX, EAX
27986 JZ @@noCanvas
27987 MOV EDX, [ESI].TDrawItemStruct.hDC
27988 CALL TCanvas.SetHandle
27989 @@noCanvas:
27990 MOV EAX, [EDI].TControl.fOnBitBtnDraw.TMethod.Data
27991 MOV EDX, EDI
27992 PUSH EBX
27993 XCHG ECX, EBX
27994 CALL EBX
27995 POP EBX
27996 POP ECX // Canvas
27997 PUSH EAX
27998 JECXZ @@noCanvas2
27999 XCHG EAX, ECX
28000 XOR EDX, EDX
28001 CALL TCanvas.SetHandle
28002 @@noCanvas2:
28003 POP EAX
28004 TEST AL, AL
28005 JNZ @@exit_draw
28006 @@noOnBitBtnDraw:
28007 TEST byte ptr [EDI].TControl.fBitBtnOptions, 2 //1 shl Ord(bboNoBorder)
28008 JNZ @@noborder
28009 TEST byte ptr [ESI].TDrawItemStruct.itemState, ODS_FOCUS
28010 JZ @@noDefaultBorder
28011 PUSH BLACK_BRUSH
28012 CALL GetStockObject
28013 LEA EDX, [ESI].TDrawItemStruct.rcItem
28014 OR ECX, -1
28015 PUSH ECX
28016 PUSH ECX
28017 PUSH EDX
28018 PUSH EAX
28019 PUSH EDX
28020 PUSH [ESI].TDrawItemStruct.hDC
28021 CALL Windows.FrameRect
28022 CALL InflateRect
28023 XOR ECX, ECX
28024 JMP @@noFlat
28025 @@noDefaultBorder:
28026 MOVZX ECX, [EDI].TControl.fFlat
28027 JECXZ @@noFlat
28028 AND CL, [EDI].TControl.fMouseInControl
28029 JZ @@noborder
28030 @@noFlat:
28031 TEST byte ptr [ESI].TDrawItemStruct.itemState, ODS_SELECTED
28032 MOV CL, BDR_SUNKENOUTER or BDR_SUNKENINNER
28033 JNZ @@border_sunken
28034 MOV CL, BDR_RAISEDOUTER or BDR_RAISEDINNER
28035 @@border_sunken:
28036 LEA EDX, [ESI].TDrawItemStruct.rcItem
28037 OR EAX, -1
28038 PUSH EAX
28039 PUSH EAX
28040 PUSH EDX
28041 PUSH BF_ADJUST or BF_RECT
28042 PUSH ECX
28043 PUSH EDX
28044 PUSH [ESI].TDrawItemStruct.hDC
28045 CALL DrawEdge
28046 CALL InflateRect
28047 @@noborder:
28048 PUSH [ESI].TDrawItemStruct.rcItem.Bottom
28049 PUSH [ESI].TDrawItemStruct.rcItem.Right
28050 PUSH [ESI].TDrawItemStruct.rcItem.Top
28051 PUSH [ESI].TDrawItemStruct.rcItem.Left
28052 MOV EAX, [EDI].TControl.fGlyphWidth
28053 MOV EDX, [EDI].TControl.fGlyphHeight
28054 TEST EAX, EAX
28055 JLE @@noglyph
28056 TEST EDX, EDX
28057 JLE @@noglyph
28058 PUSH EBP
28059 MOV EBP, ESP
28060 // [EBP+4] = TxRect
28062 PUSH EDX // ImgH -> [EBP-4]
28063 PUSH EAX // ImgW -> [EBP-8]
28064 PUSH EDX // OutH -> [EBP-12]
28065 PUSH EAX // OutW -> [EBP-16]
28066 MOV EAX, [ESI].TDrawItemStruct.rcItem.Left // X = DIS.rcItem.Left
28067 MOV EDX, [ESI].TDrawItemStruct.rcItem.Top // Y = DIS.rcItem.Top
28068 MOV ECX, [ESI].TDrawItemStruct.rcItem.Bottom
28069 SUB ECX, EDX
28070 PUSH ECX // H -> [EBP-20]
28071 MOV ECX, [ESI].TDrawItemStruct.rcItem.Right
28072 SUB ECX, EAX
28073 PUSH ECX // W -> [EBP-24]
28074 MOVZX ECX, [EDI].TControl.fGlyphLayout
28075 PUSH EBX
28076 INC ECX
28077 LOOP @@noGlyphLeft
28078 MOV EBX, EAX // X
28079 ADD EBX, [EBP-16] // +OutW
28080 MOV [EBP+4].TRect.Left, EBX // TxRect.Left = X+OutW
28081 JMP @@centerY
28082 @@noGlyphLeft:
28083 LOOP @@noGlyphTop
28084 MOV EBX, EDX // Y
28085 ADD EBX, [EBP-12] // +OutH
28086 MOV [EBP+4].TRect.Top, EBX // TxRect.Top = Y+OutH
28087 LOOP @@centerX // always JMP, ECX := -1
28088 @@noGlyphTop:
28089 LOOP @@noGlyphRight
28090 MOV EAX, [ESI].TDrawItemStruct.rcItem.Right
28091 SUB EAX, [EBP-16] // -OutW -> X
28092 MOV [EBP+4].TRect.Right, EAX
28093 @@centerY:
28094 MOV EBX, [EBP-20] // H
28095 SUB EBX, [EBP-12] // -OutH
28096 JLE @@noGlyphRight
28097 SAR EBX, 1
28098 ADD EDX, EBX // Y = Y + (H-OutH)/2
28099 @@noGlyphRight:
28100 LOOP @@noGlyphBottom
28101 MOV EDX, [ESI].TDrawItemStruct.rcItem.Bottom
28102 SUB EDX, [EBP-12] // -OutH -> Y
28103 MOV [EBP+4].TRect.Bottom, EDX
28104 LOOP @@centerX // always JMP, ECX := -1
28105 @@noGlyphBottom:
28106 LOOP @@noGlyphOver
28107 @@centerX:
28108 MOV EBX, [EBP-24] // W
28109 SUB EBX, [EBP-16] // -OutW
28110 SHR EBX, 1 // /2
28111 ADD EAX, EBX // +EAX, X = X + (W-OutW)/2
28112 JECXZ @@centerY
28113 @@noGlyphOver:
28114 MOV ECX, [ESI].TDrawItemStruct.rcItem.Left
28115 CMP EAX, ECX
28116 JGE @@ok1
28117 XCHG EAX, ECX
28118 @@ok1: CMP EDX, [ESI].TDrawItemStruct.rcItem.Top
28119 {$IFDEF USE_CMOV}
28120 CMOVL EDX, [ESI].TDrawItemStruct.rcItem.Top
28121 {$ELSE}
28122 JGE @@ok2
28123 MOV EDX, [ESI].TDrawItemStruct.rcItem.Top
28124 @@ok2: {$ENDIF}
28126 MOV ECX, [ESI].TDrawItemStruct.rcItem.Right
28127 SUB ECX, EAX
28128 CMP [EBP-16], ECX
28129 JLE @@ok3
28130 MOV [EBP-16], ECX // OutW := rcItem.Right - X;
28131 @@ok3: MOV ECX, [ESI].TDrawItemStruct.rcItem.Bottom
28132 SUB ECX, EDX
28133 CMP ECX, [EBP-12]
28134 JGE @@ok4
28135 MOV [EBP-12], ECX // OutH := rcItem.Bottom - Y;
28136 @@ok4:
28137 POP EBX // EBX = G
28138 TEST byte ptr [EDI].TControl.fBitBtnOptions, 1 //1 shl Ord(bboImageList)
28139 JZ @@draw_bitmap
28140 MOVZX ECX, word ptr [EDI].TControl.fGlyphCount
28141 CMP word ptr [EDI].TControl.fGlyphCount + 2, BX
28142 JLE @@no_add_glyphIdx
28143 ADD ECX, EBX
28144 @@no_add_glyphIdx:
28145 XOR EBX, EBX
28146 PUSH ILD_TRANSPARENT // Flags = 1 (ILD_TRANSPARENT)
28147 PUSH EBX // Blend = 0
28148 PUSH -1 // Bk = CLR_NONE
28149 PUSH EBX // 0
28150 PUSH EBX // 0
28151 PUSH EDX
28152 PUSH EAX
28153 PUSH [ESI].TDrawItemStruct.hDC
28154 PUSH ECX
28155 PUSH [EDI].TControl.fGlyphBitmap
28156 CMP [EDI].TControl.fTransparent, BL
28157 JNZ @@imgl_transp
28158 MOV EAX, [EDI].TControl.fColor
28159 CALL Color2RGB
28160 MOV [ESP+32], EAX // Bk = Color2RGB(fColor)
28161 MOV [ESP+40], EBX // Flags = 0
28162 @@imgl_transp:
28163 INC EBX
28164 CMP word ptr [EDI].TControl.fGlyphCount + 2, BX
28165 JNZ @@draw_imagelist
28166 DEC byte ptr [ESP+36+3] // $FF, CLR_DEFAULT = $FF000000
28167 TEST byte ptr [ESI].TDrawItemStruct.itemState, ODS_FOCUS
28168 JZ @@draw_imagelist
28169 OR byte ptr [ESP+40], ILD_BLEND25 // Flags != 2
28170 @@draw_imagelist:
28171 CALL ImageList_DrawEx
28172 JMP @@glyph_drawn
28174 @@draw_bitmap:
28175 PUSH EAX // PlaceHold for DC
28176 PUSH EAX // PlaceHold for OldBmp
28177 PUSH SRCCOPY
28178 PUSH dword ptr [EBP-4] // ImgH
28179 PUSH dword ptr [EBP-8] // ImgW
28180 PUSH 0
28181 PUSH EAX // PlaceHold for I
28182 PUSH EAX // PlaceHold for DC
28183 PUSH dword ptr [EBP-12] // OutH
28184 PUSH dword ptr [EBP-16] // OutW
28185 PUSH EDX // Y
28186 PUSH EAX // X
28187 PUSH [ESI].TDrawItemStruct.hDC
28189 PUSH 0
28190 CALL CreateCompatibleDC
28191 MOV [ESP+48], EAX // save DC
28192 MOV [ESP+20], EAX // place DC
28193 PUSH [EDI].TControl.fGlyphBitmap
28194 PUSH EAX
28195 CALL SelectObject
28196 MOV [ESP+44], EAX // save OldBitmap
28197 XOR EAX, EAX
28198 CMP [EDI].TControl.fGlyphCount, EBX
28199 JLE @@no_incGlyIdx
28200 MOV EAX, [EBP-8] // ImgW
28201 IMUL EBX
28202 @@no_incGlyIdx:
28203 MOV [ESP+24], EAX // place I
28204 CALL StretchBlt
28205 CALL FinishDC
28207 @@glyph_drawn:
28208 MOV ESP, EBP
28209 POP EBP
28211 @@noglyph:
28212 TEST byte ptr[EDI].TControl.fBitBtnOptions, 4 //1 shl Ord(bboNoCaption)
28213 JNZ @@noCaption
28216 POP EAX
28217 PUSH EAX
28218 MOV EDX, [ESP].TRect.Right
28219 CMP EDX, EAX
28220 JLE @@noCaption
28221 MOV EDX, [ESP].TRect.Bottom
28222 CMP EDX, [ESP].TRect.Top
28223 JLE @@noCaption
28225 XOR EBX, EBX
28226 PUSH EBX // > CapText
28227 MOV EDX, ESP
28228 MOV EAX, EDI
28229 CALL TControl.GetCaption
28230 PUSH EBX // > Bk
28231 PUSH EBX // > Blend
28232 CMP [EDI].TControl.fTransparent, BL
28233 MOV BL, ETO_CLIPPED
28234 JNZ @@drwTxTransparent
28235 CMP [EDI].TControl.fGlyphLayout, glyphOver
28236 JNZ @@drwTxOpaque
28237 @@drwTxTransparent:
28238 PUSH TRANSPARENT
28239 PUSH [ESI].TDrawItemStruct.hDC
28240 CALL SetBkMode
28241 MOV [ESP+4], EAX // Bk := SetBkMode( DIS.hDC, TRANSPARENT )
28242 JMP @@drwTx1
28243 @@drwTxOpaque:
28244 MOV BL, ETO_CLIPPED or ETO_OPAQUE
28245 MOV EAX, [EDI].TControl.fColor
28246 CALL Color2RGB
28247 PUSH EAX
28248 PUSH [ESI].TDrawItemStruct.hDC
28249 CALL SetBkColor
28250 POP ECX
28251 PUSH EAX // Blend := SetBkColor(DIS.hDC,fColor)
28252 @@drwTx1:
28253 PUSH 0 // > OldFont
28254 PUSH 0 // > OldTextColor
28256 PUSH 0 // push <nil>
28257 MOV EDX, [ESP+20] // CapText
28258 CALL EDX2PChar
28259 PUSH dword ptr [EDX-4] // push Length(CapText)
28260 PUSH EDX // push PChar(CapText)
28261 LEA EAX, [ESP+32]
28262 PUSH EAX // push @TxRect
28263 PUSH EBX // push Flags
28265 MOV EBX, [ESI].TDrawItemStruct.hDC
28267 MOV ECX, [EDI].TControl.fFont
28268 JECXZ @@drwTx_noFont
28269 XCHG EAX, ECX
28270 CALL TGraphicTool.GetHandle
28271 PUSH EAX
28272 PUSH EBX
28273 CALL SelectObject
28274 MOV [ESP+24], EAX // OldFont := SelectObject...
28275 @@drwTx_noFont:
28276 MOV EAX, [EDI].TControl.fTextColor
28277 CALL Color2RGB
28278 PUSH EAX
28279 PUSH EBX
28280 CALL SetTextColor
28281 MOV [ESP+20], EAX // OldTextColor := SetTextColor...
28283 PUSH EAX
28284 PUSH EAX
28285 PUSH ESP
28286 MOV ECX, [ESP+48] // ECX = CapText
28287 XOR EAX, EAX
28288 JECXZ @@drwTx0
28289 MOV EAX, [ECX-4] // EAX = Length(CapText)
28290 @@drwTx0:
28291 PUSH EAX
28292 PUSH ECX
28293 PUSH EBX
28294 CALL GetTextExtentPoint32
28295 POP ECX // ECX = TextSz.cx
28296 POP EDX // EDX = TextSz.cy
28297 MOV EAX, [ESP+40].TRect.Bottom
28298 SUB EAX, [ESP+40].TRect.Top
28299 SUB EAX, EDX
28300 JGE @@yOk
28301 XOR EAX, EAX
28302 @@yOk: SHR EAX, 1
28303 ADD EAX, [ESP+40].TRect.Top
28304 PUSH EAX // push Y
28305 MOV EDX, [ESP+44].TRect.Right
28306 MOV EAX, [ESP+44].TRect.Left // EAX = TxRect.Left
28307 SUB EDX, EAX // EDX = W
28308 PUSH EAX
28309 CMP [EDI].TControl.fTextAlign, taRight
28310 JL @@chk_X
28311 JE @@alignR
28312 SUB ECX, EDX
28313 SAR ECX, 1
28314 JMP @@alignC
28315 @@alignR:
28316 ADD EAX, EDX
28317 @@alignC:
28318 SUB EAX, ECX
28319 @@chk_X:POP EDX
28320 CMP EAX, EDX
28321 JGE @@xOk
28322 XCHG EAX, EDX
28323 @@xOk: PUSH EAX // push X
28324 PUSH EBX // push hDC
28325 CALL ExtTextOut
28327 PUSH EBX
28328 CALL SetTextColor
28329 POP ECX
28330 JECXZ @@noRestoreFont
28331 PUSH ECX
28332 PUSH EBX
28333 CALL SelectObject
28334 @@noRestoreFont:
28335 POP ECX // Blend
28336 JECXZ @@restoreBk
28337 PUSH ECX
28338 PUSH EBX
28339 CALL SetBkColor
28340 POP ECX
28341 JMP @@delCaption
28342 @@restoreBk:
28343 PUSH EBX
28344 CALL SetBkMode
28345 @@delCaption:
28346 CALL RemoveStr
28348 @@noCaption:
28349 ADD ESP, 16
28351 @@exit_draw:
28352 POP ESI
28353 POP EDI
28354 POP EBX
28355 MOV AL, 1
28358 @@noCN_DRAWITEM:
28359 CMP word ptr [EDX].TMsg.message, WM_LBUTTONDOWN
28360 JZ @@doDown
28361 CMP word ptr [EDX].TMsg.message, WM_KEYDOWN
28362 JNZ @@noWM_LBUTTONDOWN
28363 CMP [EDX].TMsg.wParam, 32
28364 JNZ @@noWM_LBUTTONDOWN
28365 @@doDown:
28366 PUSH EDX
28367 XCHG EBX, EAX
28369 CALL @@fixed_proc
28370 MOV ECX, [EBX].TControl.fRepeatInterval
28371 JECXZ @@exit_LBUTTONDOWN
28372 //MOV EAX, EBX
28373 //CALL TControl.DoClick
28374 POP EDX
28375 PUSH EDX
28376 CMP word ptr [EDX].TMsg.message, WM_KEYDOWN
28377 JZ @@not_SetTimer
28378 PUSH 0
28379 PUSH [EBX].TControl.fRepeatInterval
28380 PUSH 1
28381 PUSH [EBX].TControl.fHandle
28382 CALL SetTimer
28383 @@exit_LBUTTONDOWN:
28384 @@not_SetTimer:
28385 POP EDX
28386 JMP @@invalidate
28388 @@noWM_LBUTTONDOWN:
28389 CMP word ptr [EDX].TMsg.message, WM_TIMER
28390 JNZ @@noWM_TIMER
28392 XCHG EBX, EAX
28393 PUSH 0
28394 PUSH 0
28395 PUSH BM_GETSTATE
28396 PUSH EBX
28397 CALL TControl.Perform
28398 {$IFDEF PARANOIA}
28399 DB $A8, 4
28400 {$ELSE}
28401 TEST AL, BST_PUSHED
28402 {$ENDIF}
28403 JNZ @@pushed
28404 PUSH 1
28405 PUSH [EBX].TControl.fHandle
28406 CALL KillTimer
28407 CALL ReleaseCapture
28408 JMP @@noWM_TIMER
28409 @@fixed_proc:
28410 TEST byte ptr [EBX].TControl.fBitBtnOptions, 8 // bboFixed
28411 JZ @@not_fixed
28412 XOR [EBX].TControl.fChecked, 1
28413 MOV ECX, [EBX].TControl.fOnChange.TMethod.Code
28414 JECXZ @@not_fixed
28415 MOV EAX, [EBX].TControl.fOnChange.TMethod.Data
28416 MOV EDX, EBX
28417 JMP ECX
28418 @@pushed:
28419 CALL @@fixed_proc
28420 MOV EAX, EBX
28421 CALL TControl.DoClick
28422 @@invalidate:
28423 XCHG EAX, EBX
28424 CALL TControl.Invalidate
28425 @@noWM_TIMER:
28426 XOR EAX, EAX
28427 POP EBX
28428 @@not_fixed:
28429 end;
28430 {$ELSE ASM_VERSION} //Pascal
28431 function WndProcBitBtn( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
28432 var DIS: PDrawItemStruct;
28433 IsDown, IsDefault, IsDisabled: Boolean;
28434 Flags: Integer;
28435 X, Y, W, H, ImgW, ImgH, OutW, OutH, I, G, Bk, Blend: Integer;
28436 //BI: TBitmapInfo;
28437 //Dib: TDibSection;
28438 TxRect: TRect;
28439 OldFont: HFont;
28440 OldTextColor: TColor;
28441 CapText, CapTxtOrig: String;
28442 TextSz: TSize;
28443 DC: HDC;
28444 OldBmp: HBitmap;
28445 Handled: Boolean;
28446 //Br: HBrush;
28447 begin
28448 Result := False;
28449 if (Msg.message = WM_LBUTTONDBLCLK) then
28450 begin
28451 Rslt := Self_.Perform( WM_LBUTTONDOWN, Msg.wParam, Msg.lParam );
28452 Result := True;
28453 Exit;
28454 end;
28455 if (Msg.message = CN_DRAWITEM) then
28456 begin
28457 Result := True;
28458 Rslt := 1;
28459 DIS := Pointer( Msg.lParam );
28460 //IsDown := DIS.itemState and ODS_SELECTED <> 0;
28461 IsDown := (DIS.itemState and ODS_SELECTED <> 0) or
28462 ({(bboFixed in Self_.fBitBtnOptions) and} Self_.fChecked);
28463 IsDefault := DIS.itemState and ODS_FOCUS <> 0;
28464 IsDisabled := DIS.itemState and ODS_DISABLED <> 0;
28465 G := 0;
28466 if IsDown {and not(bboFixed in Self_.fBitBtnOptions)
28467 or (bboFixed in Self_.fBitBtnOptions) and Self_.fChecked} then
28468 G := 1;
28469 if IsDisabled then
28470 G := 2;
28471 if (G = 0) and IsDefault then
28472 G := 3;
28473 if ((G = 0) or (G = 3)) and Self_.MouseInControl then
28474 G := 4;
28475 if Assigned( Self_.fOnBitBtnDraw ) then
28476 begin
28477 if Assigned( Self_.fCanvas ) then
28478 Self_.fCanvas.SetHandle( DIS.hDC );
28479 Handled := Self_.fOnBitBtnDraw( Self_, G );
28480 if Assigned( Self_.fCanvas ) then
28481 Self_.fCanvas.SetHandle( 0 );
28482 if Handled then Exit;
28483 end;
28484 if not ( bboNoBorder in Self_.fBitBtnOptions ) then
28485 begin
28486 if IsDefault then
28487 begin
28488 Windows.FrameRect( DIS.hDC, DIS.rcItem, GetStockObject( BLACK_BRUSH ) );
28489 InflateRect( DIS.rcItem, -1, -1 );
28490 end;
28491 if not Self_.fFlat or Self_.fMouseInControl or IsDefault then
28492 begin
28493 if IsDown then
28494 Flags := BDR_SUNKENOUTER or BDR_SUNKENINNER
28495 else
28496 Flags := BDR_RAISEDOUTER or BDR_RAISEDINNER;
28497 DrawEdge( DIS.hDC, DIS.rcItem, Flags, BF_ADJUST or BF_RECT );
28498 InflateRect( DIS.rcItem, -1, -1 );
28499 end;
28500 end;
28501 TxRect := DIS.rcItem;
28502 if Self_.fGlyphBitmap <> 0 then
28503 begin
28504 ImgW := Self_.fGlyphWidth;
28505 ImgH := Self_.fGlyphHeight;
28506 if (ImgW > 0) and (ImgH > 0) then
28507 begin
28508 OutW := ImgW;
28509 OutH := ImgH;
28510 W := DIS.rcItem.Right - DIS.rcItem.Left;
28511 H := DIS.rcItem.Bottom - DIS.rcItem.Top;
28512 X := DIS.rcItem.Left;
28513 Y := DIS.rcItem.Top;
28514 if isDown and (Self_.fGlyphLayout <> glyphOver) then
28515 begin
28516 Inc( X, Self_.TextShiftX );
28517 Inc( Y, Self_.TextShiftY );
28518 end;
28519 case Self_.fGlyphLayout of
28520 glyphLeft:
28521 begin
28522 Y := Y + (H - OutH) div 2;
28523 TxRect.Left := X + OutW;
28524 end;
28525 glyphTop:
28526 begin
28527 X := X + (W - OutW) div 2;
28528 TxRect.Top := Y + OutH;
28529 end;
28530 glyphRight:
28531 begin
28532 X := DIS.rcItem.Right - OutW;
28533 TxRect.Right := X;
28534 Y := Y + (H - OutH) div 2;
28535 end;
28536 glyphBottom:
28537 begin
28538 Y := DIS.rcItem.Bottom - OutH;
28539 TxRect.Bottom := Y;
28540 X := X + (W - OutW) div 2;
28541 end;
28542 glyphOver:
28543 begin
28544 X := X + (W - OutW) div 2;
28545 Y := Y + (H - OutH) div 2;
28546 end;
28547 end;
28548 if X < DIS.rcItem.Left then
28549 X := DIS.rcItem.Left;
28550 if Y < DIS.rcItem.Top then
28551 Y := DIS.rcItem.Top;
28552 if X + OutW > DIS.rcItem.Right then
28553 OutW := DIS.rcItem.Right - X;
28554 if Y + OutH > DIS.rcItem.Bottom then
28555 OutH := DIS.rcItem.Bottom - Y;
28557 //Br := CreateSolidBrush( Color2RGB( Self_.fColor ) );
28558 //Windows.FillRect( DIS.hDC, MakeRect( X, DIS.rcItem.Top, X + OutW, DIS.rcItem.Bottom ), Br );
28559 //DeleteObject( Br );
28561 if bboImageList in Self_.fBitBtnOptions then
28562 begin
28563 I := LoWord( Self_.fGlyphCount );
28564 if //(HiWord( Self_.fGlyphCount ) > 1) and
28565 (HiWord( Self_.fGlyphCount ) > G) then
28566 I := I + G;
28567 Flags := 0; // ILD_NORMAL
28568 Blend := 0;
28569 if not Self_.fTransparent then
28570 Bk := Color2RGB( Self_.fColor )
28571 else
28572 begin
28573 Bk := Integer(CLR_NONE);
28574 Flags := ILD_TRANSPARENT;
28575 end;
28576 if HiWord( Self_.fGlyphCount ) = 1 then
28577 begin
28578 Blend := Integer(CLR_DEFAULT);
28579 if IsDefault then
28580 Flags := Flags or ILD_BLEND25;
28581 end;
28582 ImageList_DrawEx( Self_.fGlyphBitmap, I, DIS.hDC, X, Y, 0, 0,
28583 Bk, Blend, Flags );
28585 else
28586 begin
28587 DC := CreateCompatibleDC( 0 );
28588 OldBmp := SelectObject( DC, Self_.fGlyphBitmap );
28590 I := 0;
28591 if Self_.fGlyphCount > G then
28592 I := I + G * ImgW;
28593 StretchBlt( DIS.hDC, X, Y, OutW, OutH, DC, I, 0, ImgW, ImgH, SRCCOPY );
28595 SelectObject( DC, OldBmp );
28596 DeleteDC( DC );
28597 end;
28598 end;
28599 end;
28600 if not (bboNoCaption in Self_.fBitBtnOptions) then
28601 //if (Self_.Text <> '') then
28602 if (TxRect.Right > TxRect.Left) and (TxRect.Bottom > TxRect.Top) then
28603 begin
28604 CapText := Self_.Caption;
28605 ///////////////////////////////////////////// added 19 Nov 2001
28606 CapTxtOrig := CapText;
28607 if Assigned( Self_.FBitBtnGetCaption ) then
28608 CapText := Self_.FBitBtnGetCaption( Self_, CapText );
28609 /////////////////////////////////////////////
28611 Bk := 0;
28612 Blend := 0;
28613 Flags := ETO_CLIPPED;
28614 if Self_.fTransparent or (Self_.fGlyphLayout = glyphOver) then
28615 Bk := SetBkMode( DIS.hDC, TRANSPARENT )
28616 else
28617 begin
28618 Flags := Flags or ETO_OPAQUE;
28619 Blend := SetBkColor( DIS.hDC, Color2RGB( Self_.fColor ) );
28620 end;
28621 // Returned previous BkMode is either OPAQUE=1 or TRANSPARENT=2
28623 OldFont := 0;
28624 if assigned( Self_.fFont ) then
28625 OldFont := SelectObject( DIS.hDC, Self_.fFont.Handle );
28626 OldTextColor := SetTextColor( DIS.hDC, Color2RGB( Self_.fTextColor ) );
28628 Windows.GetTextExtentPoint32( DIS.hDC, PChar( CapText ), Length( CapText ),
28629 TextSz );
28630 W := TxRect.Right - TxRect.Left;
28631 H := TxRect.Bottom - TxRect.Top;
28632 Y := TxRect.Top + (H - TextSz.cy) div 2;
28633 case Self_.fTextAlign of
28634 taLeft: X := TxRect.Left;
28635 taCenter: X := TxRect.Left + (W - TextSz.cx) div 2;
28636 else {taRight:} X := TxRect.Right - TextSz.cx;
28637 end;
28638 if isDown then
28639 begin
28640 Inc( X, Self_.TextShiftX );
28641 Inc( Y, Self_.TextShiftY );
28642 end;
28643 if Y < 0 then
28644 Y := 0;
28645 if X < TxRect.Left then
28646 X := TxRect.Left;
28648 Windows.ExtTextOut( DIS.hDC, X, Y, Flags, @TxRect,
28649 PChar( CapText ), Length( CapText ), nil );
28651 //////////////////////////////////////////////////////////////////////////
28652 // added 19 Nov 2001 to provide underlying mnemonic characters
28653 if Assigned( Self_.FBitBtnExtDraw ) then
28654 Self_.FBitBtnExtDraw( Self_, DIS.hDC, X, Y, TxRect, CapText, CapTxtOrig,
28655 OldTextColor );
28656 //////////////////////////////////////////////////////////////////////////
28658 SetTextColor( DIS.hDC, OldTextColor );
28659 if OldFont <> 0 then
28660 SelectObject( DIS.hDC, OldFont );
28662 if Blend = 0 then
28663 SetBkMode( DIS.hDC, Bk )
28664 else
28665 SetBkColor( DIS.hDC, Blend );
28666 end;
28667 end;
28668 if (Msg.message = WM_LBUTTONDOWN) or (Msg.message = WM_KEYDOWN) and (Msg.wParam = 32) then
28669 begin
28670 if bboFixed in Self_.fBitBtnOptions then
28671 begin
28672 Self_.fChecked := not Self_.fChecked;
28673 if Assigned( Self_.fOnChange ) then
28674 Self_.fOnChange( Self_ );
28675 end;
28676 if Self_.fRepeatInterval > 0 then
28677 begin
28678 if Msg.message <> WM_KEYDOWN then
28679 SetTimer( Self_.fHandle, 1, Self_.fRepeatInterval, nil );
28680 Self_.Invalidate;
28681 end;
28682 end;
28684 // added 15 Aug 2002 to repaint when focus lost:
28685 if Msg.message = WM_KILLFOCUS then
28686 Self_.Invalidate;
28688 if Msg.message = WM_TIMER then
28689 begin
28690 if Self_.Perform( BM_GETSTATE, 0, 0 ) and BST_PUSHED = 0 then
28691 begin
28692 KillTimer( Self_.fHandle, 1 );
28693 ReleaseCapture;
28695 else
28696 begin
28697 if bboFixed in Self_.fBitBtnOptions then
28698 begin
28699 Self_.fChecked := not Self_.fChecked;
28700 if Assigned( Self_.fOnChange ) then
28701 Self_.fOnChange( Self_ );
28702 end;
28703 Self_.DoClick;
28704 Self_.Invalidate;
28705 end;
28706 end;
28707 end;
28708 {$ENDIF ASM_VERSION}
28709 //[END WndProcBitBtn]
28711 {$IFDEF USE_CONSTRUCTORS}
28712 //[function NewBitBtn]
28713 function NewBitBtn( AParent: PControl; const Caption: String;
28714 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap;
28715 GlyphCount: Integer ): PControl;
28716 begin
28717 new( Result, CreateBitBtn( AParent, Caption, Options, Layout, GlyphBitmap, GlyphCount ) );
28718 end;
28719 //[END NewBitBtn]
28720 {$ELSE not_USE_CONSTRUCTORS}
28722 //[FUNCTION NewBitBtn]
28723 {$IFDEF ASM_VERSION}
28724 function NewBitBtn( AParent: PControl; const Caption: String;
28725 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap; GlyphCount: Integer ): PControl;
28726 const szBitmapInfo = sizeof(TBitmapInfo);
28728 PUSH EBX
28729 PUSH EDX
28730 PUSH ECX
28732 PUSH 0
28733 PUSH offset[ButtonActions]
28734 MOV EDX, offset[ButtonClass]
28735 MOV ECX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or BS_OWNERDRAW
28736 CALL _NewControl
28737 XCHG EBX, EAX
28738 INC [EBX].TControl.fIgnoreDefault
28739 INC [EBX].TControl.fIsButton
28740 MOV byte ptr [EBX].TControl.fCommandActions.aAutoSzX, 8
28741 MOV byte ptr [EBX].TControl.fCommandActions.aAutoSzY, 8
28742 POP EAX
28743 MOV [EBX].TControl.fBitBtnOptions, AL
28744 MOVZX EDX, Layout
28745 MOV [EBX].TControl.fGlyphLayout, DL
28746 MOV ECX, GlyphBitmap
28747 MOV [EBX].TControl.fGlyphBitmap, ECX
28748 MOV EDX, [EBX].TControl.fBoundsRect.Top
28749 ADD EDX, 22
28750 MOV [EBX].TControl.fBoundsRect.Bottom, EDX
28751 TEST ECX, ECX
28752 JZ @@noGlyphWH
28753 {$IFDEF PARANOIA}
28754 DB $A8, 01
28755 {$ELSE}
28756 TEST AL, bboImageList
28757 {$ENDIF}
28758 JZ @@getBmpWH
28759 PUSH EAX
28760 MOV EAX, ESP
28761 PUSH EAX
28762 MOV EDX, ESP
28763 PUSH EAX
28764 PUSH EDX
28765 PUSH ECX
28766 CALL ImageList_GetIconSize
28767 POP EAX
28768 POP EDX
28769 MOV ECX, GlyphCount
28770 JMP @@WHready
28771 @@getBmpWH:
28772 ADD ESP, -szBitmapInfo
28773 PUSH ESP
28774 PUSH szBitmapInfo
28775 PUSH ECX
28776 CALL GetObject
28777 XCHG ECX, EAX
28778 POP EAX
28779 POP EAX
28780 POP EDX
28781 ADD ESP, szBitmapInfo-12
28782 TEST ECX, ECX
28783 JZ @@noGlyphWH
28784 MOV ECX, GlyphCount
28785 INC ECX
28786 LOOP @@GlyphCountOK
28787 PUSH EAX
28788 PUSH EDX
28789 XCHG EDX, ECX
28790 DIV ECX
28791 XCHG ECX, EAX
28792 POP EDX
28793 POP EAX
28794 @@GlyphCountOK:
28795 CMP ECX, 1
28796 JLE @@WHReady
28797 PUSH EDX
28799 IDIV ECX
28800 POP EDX
28801 @@WHReady:
28802 MOV [EBX].TControl.fGlyphWidth, EAX
28803 MOV [EBX].TControl.fGlyphHeight, EDX
28804 MOV [EBX].TControl.fGlyphCount, ECX
28805 POP ECX // ECX = @ Caption[ 1 ]
28806 PUSH ECX
28807 PUSH EDX
28808 PUSH EAX
28809 TEST EAX, EAX
28810 JLE @@noWidthResize
28811 JECXZ @@addWLeft
28812 CMP [Layout], glyphOver
28813 JE @@addWLeft
28814 MOVZX ECX, byte ptr[ECX]
28815 JECXZ @@addWLeft
28816 // else
28817 CMP [Layout], glyphLeft
28818 JZ @@addWRight
28819 CMP [Layout], glyphRight
28820 JNZ @@noWidthResize
28821 @@addWRight:
28822 ADD [EBX].TControl.fBoundsRect.Right, EAX
28823 ADD [EBX].TControl.fCommandActions.aAutoSzX, AX
28824 JMP @@noWidthResize
28825 @@addWLeft:
28826 // then
28827 ADD EAX, [EBX].TControl.fBoundsRect.Left
28828 MOV [EBX].TControl.fBoundsRect.Right, EAX
28829 MOV byte ptr [EBX].TControl.fCommandActions.aAutoSzX, 0
28830 @@noWidthResize:
28831 TEST EDX, EDX
28832 JLE @@noHeightResize
28833 CMP [Layout], glyphTop
28834 JE @@addHBottom
28835 CMP [Layout], glyphBottom
28836 JNE @@addHTop
28837 @@addHBottom:
28838 ADD [EBX].TControl.fBoundsRect.Bottom, EDX
28839 ADD [EBX].TControl.fCommandActions.aAutoSzY, DX
28840 JMP @@noHeightResize
28841 @@addHTop:
28842 ADD EDX, [EBX].TControl.fBoundsRect.Top
28843 MOV [EBX].TControl.fBoundsRect.Bottom, EDX
28844 MOV [EBX].TControl.fCommandActions.aAutoSzY, 0
28845 @@noHeightResize:
28846 POP ECX
28847 POP EAX
28849 MOV DL, 4
28850 TEST [EBX].TControl.fBitBtnOptions, 2 //1 shl bboNoBorder
28851 JNZ @@noBorderResize
28852 JECXZ @@noBorderWinc
28853 ADD [EBX].TControl.fBoundsRect.Right, EDX
28854 CMP [EBX].TControl.fCommandActions.aAutoSzX, 0
28855 JZ @@noBorderWinc
28856 ADD [EBX].TControl.fCommandActions.aAutoSzX, DX
28857 @@noBorderWinc:
28858 TEST EAX, EAX
28859 JLE @@noBorderResize
28860 ADD [EBX].TControl.fBoundsRect.Bottom, EDX
28861 CMP [EBX].TControl.fCommandActions.aAutoSzY, 0
28862 JZ @@noBorderResize
28863 ADD [EBX].TControl.fCommandActions.aAutoSzY, DX
28864 @@noBorderResize:
28865 @@noGlyphWH:
28866 MOV ECX, [EBX].TControl.fParent
28867 JECXZ @@notAttach2Parent
28868 XCHG EAX, ECX
28869 MOV EDX, offset[WndProc_DrawItem]
28870 CALL TControl.AttachProc
28871 @@notAttach2Parent:
28872 MOV EAX, EBX
28873 MOV EDX, offset[WndProcBitBtn]
28874 CALL TControl.AttachProc
28875 MOV EAX, EBX
28876 POP EDX
28877 CALL TControl.SetCaption
28878 MOV [EBX].TControl.fTextAlign, taCenter
28879 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
28880 MOV EAX, EBX
28881 MOV EDX, offset[WndProcBtnReturnClick]
28882 CALL TControl.AttachProc
28883 {$ENDIF}
28884 XCHG EAX, EBX
28885 POP EBX
28886 end;
28887 {$ELSE ASM_VERSION} //Pascal
28888 function NewBitBtn( AParent: PControl; const Caption: String;
28889 Options: TBitBtnOptions; Layout: TGlyphLayout; GlyphBitmap: HBitmap;
28890 GlyphCount: Integer ): PControl;
28892 B: TBitmapInfo;
28893 W, H: Integer;
28894 begin
28895 Result := _NewControl( AParent, 'BUTTON', WS_VISIBLE or WS_CHILD or
28896 WS_TABSTOP or BS_OWNERDRAW, False, @ButtonActions );
28897 Result.fIgnoreDefault := TRUE;
28898 Result.fIsButton := TRUE;
28899 Result.fCommandActions.aAutoSzX := 8;
28900 Result.fCommandActions.aAutoSzY := 8;
28901 //Result.fExStyle := Result.fExStyle and not WS_EX_CONTROLPARENT;
28902 Result.fBitBtnOptions := Options;
28903 Result.fGlyphLayout := Layout;
28904 Result.fGlyphBitmap := GlyphBitmap;
28905 with Result.fBoundsRect do
28906 begin
28907 Bottom := Top + 22;
28908 W := 0; H := 0;
28909 if GlyphBitmap <> 0 then
28910 begin
28911 if bboImageList in Options then
28912 ImageList_GetIconSize( GlyphBitmap, W, H )
28913 else
28914 begin
28915 if GetObject( GlyphBitmap, Sizeof(B), @B ) > 0 then
28916 begin
28917 W := B.bmiHeader.biWidth;
28918 H := B.bmiHeader.biHeight;
28919 if GlyphCount = 0 then
28920 GlyphCount := W div H;
28921 if GlyphCount > 1 then
28922 W := W div GlyphCount;
28923 end;
28924 end;
28925 if W > 0 then
28926 begin
28927 if (Caption = '') or (Layout = glyphOver) then
28928 begin
28929 Right := Left + W;
28930 Result.fCommandActions.aAutoSzX := 0;
28932 else
28933 if Layout in [ glyphLeft, glyphRight ] then
28934 begin
28935 Right := Right + W;
28936 Inc( Result.fCommandActions.aAutoSzX, W );
28937 end;
28938 end;
28939 if H > 0 then
28940 begin
28941 if Layout in [ glyphTop, glyphBottom ] then
28942 begin
28943 Bottom := Bottom + H;
28944 Inc( Result.fCommandActions.aAutoSzY, H );
28946 else
28947 begin
28948 Bottom := Top + H;
28949 Result.fCommandActions.aAutoSzY := 0;
28950 end;
28951 end;
28952 if not ( bboNoBorder in Options ) then
28953 begin
28954 if W > 0 then
28955 begin
28956 Inc( Right, 4 );
28957 if Result.fCommandActions.aAutoSzX > 0 then
28958 Inc( Result.fCommandActions.aAutoSzX, 4 );
28959 end;
28960 if H > 0 then
28961 begin
28962 Inc( Bottom, 4 );
28963 if Result.fCommandActions.aAutoSzY > 0 then
28964 Inc( Result.fCommandActions.aAutoSzY, 4 );
28965 end;
28966 end;
28967 end;
28968 Result.fGlyphWidth := W;
28969 Result.fGlyphHeight := H;
28970 end;
28971 Result.fGlyphCount := GlyphCount;
28972 if AParent <> nil then
28973 AParent.AttachProc( WndProc_DrawItem );
28974 Result.AttachProc( WndProcBitBtn );
28975 //Result.AttachProc( WndProcDoEraseBkgnd );
28976 Result.fTextAlign := taCenter;
28977 Result.Caption := Caption;
28978 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
28979 Result.AttachProc( WndProcBtnReturnClick );
28980 {$ENDIF}
28981 end;
28982 {$ENDIF ASM_VERSION}
28983 //[END NewBitBtn]
28985 {$ENDIF USE_CONSTRUCTORS}
28987 //===================== Check box ========================//
28989 {$IFDEF USE_CONSTRUCTORS}
28990 //[function NewCheckbox]
28991 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
28992 begin
28993 new( Result, CreateCheckbox( AParent, Caption ) );
28994 end;
28995 //[END NewCheckbox]
28996 {$ELSE not_USE_CONSTRUCTORS}
28998 //[FUNCTION NewCheckbox]
28999 {$IFDEF ASM_VERSION}
29000 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
29002 CALL NewButton
29003 MOV EDX, [EAX].TControl.fBoundsRect.Left
29004 ADD EDX, 72
29005 MOV [EAX].TControl.fBoundsRect.Right, EDX
29006 MOV [EAX].TControl.fStyle, WS_VISIBLE or WS_CHILD or BS_AUTOCHECKBOX or WS_TABSTOP
29007 MOV [EAX].TControl.fCommandActions.aAutoSzX, 24
29008 end;
29009 {$ELSE ASM_VERSION} //Pascal
29010 function NewCheckbox( AParent: PControl; const Caption: String ): PControl;
29011 begin
29012 Result := NewButton( AParent, Caption );
29013 with Result.fBoundsRect do
29014 begin
29015 Right := Left + 72;
29016 end;
29017 Result.fStyle := WS_VISIBLE or WS_CHILD or
29018 BS_AUTOCHECKBOX or WS_TABSTOP;
29019 Result.fCommandActions.aAutoSzX := 24;
29020 end;
29021 {$ENDIF ASM_VERSION}
29022 //[END NewCheckbox]
29024 {$ENDIF USE_CONSTRUCTORS}
29026 //[function NewCheckBox3State]
29027 function NewCheckBox3State( AParent: PControl; const Caption: String ): PControl;
29028 begin
29029 Result := NewCheckbox( AParent, Caption );
29030 Result.fStyle := Result.fStyle and not BS_AUTOCHECKBOX or BS_AUTO3STATE;
29031 end;
29033 //===================== Radiobox ========================//
29035 //[FUNCTION ClickRadio]
29036 {$IFDEF ASM_VERSION}
29037 procedure ClickRadio( Sender:PObj );
29039 MOV ECX, [EAX].TControl.fParent
29040 JECXZ @@exit
29041 PUSH [EAX].TControl.fMenu
29042 PUSH [ECX].TControl.fRadioLast
29043 PUSH [ECX].TControl.fRadio1st
29044 PUSH [ECX].TControl.fHandle
29045 CALL CheckRadioButton
29046 @@exit:
29047 end;
29048 {$ELSE ASM_VERSION} //Pascal
29049 procedure ClickRadio( Sender:PObj );
29050 var Self_:PControl;
29051 begin
29052 Self_ := PControl( Sender );
29053 if Self_.FParent <> nil then
29054 CheckRadioButton( Self_.fParent.fHandle,
29055 Self_.fParent.fRadio1st,
29056 Self_.fParent.fRadioLast,
29057 Self_.fMenu );
29058 end;
29059 {$ENDIF ASM_VERSION}
29060 //[END ClickRadio]
29062 {$IFDEF USE_CONSTRUCTORS}
29063 //[function NewRadiobox]
29064 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
29065 begin
29066 new( Result, CreateRadiobox( AParent, Caption ) );
29067 end;
29068 //[END NewRadiobox]
29069 {$ELSE not_USE_CONSTRUCTORS}
29071 //[FUNCTION NewRadiobox]
29072 {$IFDEF ASM_VERSION}
29073 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
29074 const
29075 RadioboxStyles = WS_VISIBLE or WS_CHILD or BS_RADIOBUTTON or
29076 WS_TABSTOP or WS_GROUP or BS_NOTIFY;
29078 PUSH EBX
29079 PUSH EAX
29080 CALL NewCheckbox
29081 XCHG EBX, EAX
29082 MOV [EBX].TControl.fStyle, RadioboxStyles
29083 MOV [EBX].TControl.fControlClick, offset[ClickRadio]
29084 POP ECX
29085 JECXZ @@exit
29086 MOV EDX, [EBX].TControl.fMenu
29087 MOV [ECX].TControl.fRadioLast, EDX
29088 MOV EAX, [ECX].TControl.fRadio1st
29089 TEST EAX, EAX
29090 JNZ @@exit
29091 MOV [ECX].TControl.fRadio1st, EDX
29092 MOV EAX, EBX
29093 CALL TControl.SetRadioChecked
29094 @@exit: XCHG EAX, EBX
29095 POP EBX
29096 end;
29097 {$ELSE ASM_VERSION} //Pascal
29098 function NewRadiobox( AParent: PControl; const Caption: String ): PControl;
29099 begin
29100 Result := NewCheckbox( AParent, Caption );
29101 Result.fStyle := WS_VISIBLE or WS_CHILD or
29102 BS_RADIOBUTTON or WS_TABSTOP or WS_GROUP or BS_NOTIFY;
29103 Result.fControlClick := ClickRadio;
29104 if AParent <> nil then
29105 begin
29106 AParent.fRadioLast := Result.fMenu;
29107 if AParent.fRadio1st = 0 then
29108 begin
29109 AParent.fRadio1st := Result.fMenu;
29110 Result.SetRadioChecked;
29111 end;
29112 end;
29113 end;
29114 {$ENDIF ASM_VERSION}
29115 //[END NewRadiobox]
29117 {$ENDIF USE_CONSTRUCTORS}
29119 //===================== Label ========================//
29121 {$IFNDEF USE_CONSTRUCTORS}
29122 {$IFDEF ASM_VERSION}
29123 const StaticClass: array[0..6]of Char=('S','T','A','T','I','C',#0);
29124 {$ENDIF ASM_VERSION}
29125 {$ENDIF USE_CONSTRUCTORS}
29127 {$IFDEF USE_CONSTRUCTORS}
29128 //[function NewLabel]
29129 function NewLabel( AParent: PControl; const Caption: String ): PControl;
29130 begin
29131 new( Result, CreateLabel( AParent, Caption ) );
29132 end;
29133 //[END NewLabel]
29134 {$ELSE not_USE_CONSTRUCTORS}
29136 //[FUNCTION NewLabel]
29137 {$IFDEF ASM_VERSION}
29138 function NewLabel( AParent: PControl; const Caption: String ): PControl;
29140 PUSH EDX
29142 PUSH 0
29143 PUSH offset[LabelActions]
29144 MOV ECX, WS_VISIBLE or WS_CHILD or SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY
29145 MOV EDX, offset[StaticClass]
29146 CALL _NewControl
29147 INC [EAX].TControl.fIsStaticControl
29148 INC [EAX].TControl.fSizeRedraw
29149 MOV EDX, [EAX].TControl.fBoundsRect.Top
29150 ADD EDX, 22
29151 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
29152 POP EDX
29153 PUSH EAX
29154 CALL TControl.SetCaption
29155 POP EAX
29156 end;
29157 {$ELSE ASM_VERSION} //Pascal
29158 function NewLabel( AParent: PControl; const Caption: String ): PControl;
29159 begin
29160 Result := _NewControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or
29161 SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY,
29162 False, @LabelActions );
29163 Inc( Result.fIsStaticControl );
29164 Result.fSizeRedraw := True;
29165 with Result.fBoundsRect do
29166 begin
29167 //Right := Left + 64;
29168 Bottom := Top + 22;
29169 end;
29170 Result.Caption := Caption;
29171 end;
29172 {$ENDIF ASM_VERSION}
29173 //[END NewLabel]
29175 {$ENDIF USE_CONSTRUCTORS}
29177 //===================== word wrap Label ========================//
29179 {$IFDEF USE_CONSTRUCTORS}
29180 //[function NewWordWrapLabel]
29181 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
29182 begin
29183 new( Result, CreateWordWrapLabel( AParent, Caption ) );
29184 end;
29185 //[END NewWordWrapLabel]
29186 {$ELSE not_USE_CONSTRUCTORS}
29188 //[FUNCTION NewWordWrapLabel]
29189 {$IFDEF ASM_VERSION}
29190 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
29192 CALL NewLabel
29193 MOV EDX, [EAX].TControl.fBoundsRect.Top
29194 ADD EDX, 44
29195 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
29196 INC [EAX].TControl.fWordWrap
29197 AND byte ptr [EAX].TControl.fStyle, not SS_LEFTNOWORDWRAP
29198 end;
29199 {$ELSE ASM_VERSION} //Pascal
29200 function NewWordWrapLabel( AParent: PControl; const Caption: String ): PControl;
29201 begin
29202 Result := NewLabel( AParent, Caption );
29203 Result.fWordWrap := TRUE;
29204 with Result.fBoundsRect do
29205 begin
29206 Bottom := Top + 44;
29207 end;
29208 Result.fStyle := Result.fStyle and not SS_LEFTNOWORDWRAP;
29209 end;
29210 {$ENDIF ASM_VERSION}
29211 //[END NewWordWrapLabel]
29213 {$ENDIF USE_CONSTRUCTORS}
29215 //===================== Label Effect ========================//
29217 {$IFDEF USE_CONSTRUCTORS}
29218 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
29219 begin
29220 new( Result, CreateLabelEffect( AParent, Caption, ShadowDeep ) );
29221 end;
29222 {$ELSE not_USE_CONSTRUCTORS}
29224 //[FUNCTION NewLabelEffect]
29225 {$IFDEF ASM_VERSION}
29226 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
29228 PUSH EBX
29230 PUSH ECX
29231 PUSH EDX
29232 XOR EDX, EDX
29233 CALL NewLabel
29234 MOV EBX, EAX
29235 DEC [EBX].TControl.fIsStaticControl // ñíîâà 0 !
29236 MOV EDX, offset[WndProcLabelEffect]
29237 CALL TControl.AttachProc
29239 //MOV EAX, EBX
29240 //CALL TControl.GetWindowHandle
29242 POP EDX
29243 MOV EAX, EBX
29244 CALL TControl.SetCaption
29246 MOV EDX, offset[WndProcDoEraseBkgnd]
29247 MOV EAX,EBX
29248 CALL TControl.AttachProc
29249 MOV [EBX].TControl.fTextAlign, taCenter
29250 MOV [EBX].TControl.fTextColor, clWindowText
29251 POP [EBX].TControl.fShadowDeep
29252 INC [EBX].TControl.fIgnoreWndCaption
29253 ADD [EBX].TControl.fBoundsRect.Bottom, 40 - 22
29254 MOV [EBX].TControl.fColor2, clNone
29256 XCHG EAX, EBX
29257 POP EBX
29258 end;
29259 {$ELSE ASM_VERSION} //Pascal
29260 function NewLabelEffect( AParent: PControl; const Caption: String; ShadowDeep: Integer ): PControl;
29261 begin
29262 Result := NewLabel( AParent, '' );
29263 Dec( Result.fIsStaticControl ); // ñíîâà 0 !
29264 Result.AttachProc( WndProcLabelEffect );
29265 //Result.GetWindowHandle;
29266 Result.Caption := Caption;
29267 Result.AttachProc( WndProcDoEraseBkgnd );
29268 Result.fTextAlign := taCenter;
29269 Result.fTextColor := clWindowText;
29270 Result.fShadowDeep := ShadowDeep;
29271 Result.fIgnoreWndCaption := True;
29272 with Result.fBoundsRect do
29273 begin
29274 Bottom := Top + 40;
29275 end;
29276 Result.fColor2 := clNone;
29277 end;
29278 {$ENDIF ASM_VERSION}
29279 //[END NewLabelEffect]
29281 {$ENDIF USE_CONSTRUCTORS}
29283 //===================== Paint box ========================//
29285 {$IFDEF USE_CONSTRUCTORS}
29286 //[function NewPaintbox]
29287 function NewPaintbox( AParent: PControl ): PControl;
29288 begin
29289 new( Result, CreatePaintBox( AParent ) );
29290 end;
29291 {$ELSE not_USE_CONSTRUCTORS}
29293 //[FUNCTION NewPaintbox]
29294 {$IFDEF ASM_VERSION}
29295 function NewPaintbox( AParent: PControl ): PControl;
29297 XOR EDX, EDX
29298 CALL NewLabel
29299 //PUSH EAX
29300 //MOV EDX, offset[WndProcPaintBox]
29301 //CALL TControl.AttachProc
29302 //POP EAX
29303 ADD [EAX].TControl.fBoundsRect.Right, 40-64
29304 ADD [EAX].TControl.fBoundsRect.Bottom, 40-22
29305 end;
29306 {$ELSE ASM_VERSION} //Pascal
29307 function NewPaintbox( AParent: PControl ): PControl;
29308 begin
29309 Result := NewLabel( AParent, '' );
29310 //Result.AttachProc( WndProcPaintBox );
29311 with Result.fBoundsRect do
29312 begin
29313 Right := Left + 40;
29314 Bottom := Top + 40;
29315 end;
29316 end;
29317 {$ENDIF ASM_VERSION}
29318 //[END NewPaintbox]
29320 {$ENDIF USE_CONSTRUCTORS}
29322 {$IFDEF _D2}
29323 //[API SetBrushOrgEx]
29324 function SetBrushOrgEx(DC: HDC; X, Y: Integer; PrevPt: PPoint): BOOL; stdcall;
29325 external gdi32 name 'SetBrushOrgEx';
29326 {$ENDIF}
29328 //[FUNCTION WndProcDoEraseBkgnd]
29329 {$IFDEF ASM_VERSION}
29330 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29331 asm // //
29332 CMP word ptr [EDX].TMsg.message, WM_ERASEBKGND
29333 JNE @@ret_false
29334 MOV byte ptr [ECX], 1
29335 PUSH EBX
29336 PUSH EDI
29337 MOV EBX, EAX
29338 MOV EDI, [EDX].TMsg.wParam
29340 CALL TControl.CreateChildWindows
29341 CMP [EBX].TControl.fTransparent, 0
29342 JNE @@exit
29344 PUSH OPAQUE
29345 PUSH EDI
29346 CALL SetBkMode
29347 MOV EAX, [EBX].TControl.fColor
29348 CALL Color2RGB
29349 PUSH EAX
29350 PUSH EDI
29351 CALL SetBkColor
29352 XOR EAX, EAX
29353 PUSH EAX
29354 PUSH EAX
29355 PUSH EAX
29356 PUSH EDI
29357 CALL SetBrushOrgEx
29358 SUB ESP, 16
29359 PUSH ESP
29360 PUSH [EBX].TControl.fHandle
29361 CALL GetClientRect
29362 MOV EAX, EBX
29363 CALL dword ptr[Global_GetCtlBrushHandle]
29364 MOV EDX, ESP
29365 PUSH EAX
29366 PUSH EDX
29367 PUSH EDI
29368 CALL Windows.FillRect
29369 ADD ESP, 16
29370 @@exit: POP EDI
29371 POP EBX
29372 @@ret_false:
29373 XOR EAX, EAX
29374 end;
29375 {$ELSE ASM_VERSION PAS_VERSION}
29376 function WndProcDoEraseBkgnd( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29377 var DC: HDC;
29378 R: TRect;
29379 begin
29380 Result := FALSE;
29381 if Msg.message = WM_ERASEBKGND then
29382 begin
29383 Self_.CreateChildWindows;
29384 if Self_.Transparent then Exit;
29385 DC := Msg.wParam;
29386 SetBkMode( DC, OPAQUE );
29387 SetBkColor( DC, Color2RGB( Self_.fColor ) );
29388 SetBrushOrgEx( DC, 0, 0, nil );
29389 GetClientRect( Self_.fHandle, R );
29390 Windows.FillRect( DC, R, Global_GetCtlBrushHandle( Self_ ) );
29391 Rslt := 1;
29392 end;
29393 end;
29394 {$ENDIF ASM_VERSION}
29395 //[END WndProcDoEraseBkgnd]
29397 //[function WndProcImageShow]
29398 function WndProcImageShow( Sender: PControl; var Msg: TMsg;
29399 var Rslt: Integer ): Boolean;
29400 var PaintStruct: TPaintStruct;
29401 IL: PImageList;
29402 OldPaintDC: HDC;
29403 begin
29404 Result := FALSE;
29405 if (Msg.message = WM_PAINT) or (Msg.message = WM_PRINT) then
29406 begin
29407 OldPaintDC := Sender.fPaintDC;
29408 Sender.fPaintDC := Msg.wParam;
29409 if Sender.fPaintDC = 0 then
29410 Sender.fPaintDC := BeginPaint( Sender.fHandle, PaintStruct );
29411 //fOnPaint( Self_, fPaintDC );
29412 IL := Sender.ImageListNormal;
29413 if IL <> nil then
29414 begin
29415 IL.Draw( Sender.fCurIndex, Sender.fPaintDC, 0, 0 );
29416 Result := TRUE;
29417 end;
29418 if Msg.wParam = 0 then
29419 EndPaint( Sender.fHandle, PaintStruct );
29420 Sender.fPaintDC := OldPaintDC;
29421 Rslt := 0;
29422 //Result := True;
29423 Exit;
29424 end;
29425 end;
29427 //[function NewImageShow]
29428 function NewImageShow( AParent: PControl; AImgList: PImageList;
29429 ImgIdx: Integer ): PControl;
29430 var W, H: Integer;
29431 begin
29432 Result := NewLabel( AParent, '' );
29433 Result.ImageListNormal := AImgList;
29434 Result.AttachProc( WndProcImageShow );
29435 Result.AttachProc( WndProcDoEraseBkgnd );
29436 W := 32; H := 32;
29437 if AImgList <> nil then
29438 begin
29439 W := AImgList.ImgWidth;
29440 H := AImgList.ImgHeight;
29441 end;
29442 with Result.fBoundsRect do
29443 begin
29444 Right := Left + W;
29445 Bottom := Top + H;
29446 end;
29447 end;
29448 //[END NewImageShow]
29450 //===================== Scrollbar ========================//
29451 const
29452 KSB_INITIALIZE = WM_USER + 10000;
29453 KSB_KEY = $3232;
29455 //[function WndProcScrollBar]
29456 function WndProcScrollBar( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29457 begin
29458 Result := False;
29459 case Msg.message of
29460 WM_CREATE:
29461 PostMessage(Sender.Handle, KSB_INITIALIZE, KSB_KEY, KSB_KEY);
29463 KSB_INITIALIZE:
29464 if (Msg.wParam = Msg.lParam) and (Msg.wParam = KSB_KEY) then
29465 begin
29466 Sender.SBPageSize := Sender.fSBPageSize;
29467 Sender.SBMinMax := Sender.fSBMinMax;
29468 Sender.SBPosition := Sender.fSBPosition;
29469 end;
29470 end;
29471 end;
29472 //[END WndProcScrollBar]
29474 //[function WndProcScrollBarParent]
29475 function WndProcScrollBarParent( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29477 Bar: PControl;
29478 SI: TScrollInfo;
29479 NewPos: Integer;
29480 AllowChange: Boolean;
29481 Cmd: Word;
29483 begin
29484 Result := False;
29485 case Msg.message of
29486 WM_HSCROLL, WM_VSCROLL:
29487 if (Msg.lParam <> 0) then begin
29488 Bar := Pointer(GetProp(Msg.lParam, ID_SELF));
29489 if (Bar <> nil) then begin
29490 FillChar(SI, SizeOf(SI), 0);
29491 SI.cbSize := SizeOf(SI);
29492 SI.fMask := SIF_RANGE or SIF_POS or SIF_TRACKPOS or SIF_PAGE;
29493 Bar.SBGetScrollInfo(SI);
29495 Cmd := Msg.wParam and $0000FFFF;
29496 case Cmd of
29497 SB_BOTTOM: NewPos := SI.nMax;
29498 SB_TOP: NewPos := SI.nMin;
29499 SB_LINEDOWN: NewPos := SI.nPos + 1;
29500 SB_LINEUP: NewPos := SI.nPos - 1;
29501 SB_PAGEDOWN: NewPos := SI.nPos + Integer(SI.nPage);
29502 SB_PAGEUP: NewPos := SI.nPos - Integer(SI.nPage);
29503 SB_THUMBTRACK: NewPos := SI.nTrackPos;
29504 else
29505 Exit;
29506 end;
29508 if (NewPos > SI.nMax - Integer(SI.nPage) + 1) then
29509 NewPos := SI.nMax - Integer(SI.nPage) + 1;
29510 if (NewPos < SI.nMin) then
29511 NewPos := SI.nMin;
29513 AllowChange := True;
29514 if Assigned(Bar.OnSBBeforeScroll) then
29515 Bar.OnSBBeforeScroll(Bar, SI.nPos, NewPos, Cmd, AllowChange);
29516 if AllowChange then
29517 SI.nPos := NewPos
29518 else
29519 SI.nTrackPos := SI.nPos;
29520 Bar.fSBPosition := SI.nPos;
29521 Bar.fSBPosition := Bar.SBSetScrollInfo(SI);
29522 if AllowChange and Assigned(Bar.OnSBScroll) then
29523 Bar.OnSBScroll(Bar, Cmd);
29524 end;
29525 end;
29526 end;
29527 end;
29528 //[END WndProcScrollBarParent]
29530 //[function NewScrollBar]
29531 function NewScrollBar( AParent: PControl; BarSide: TScrollerBar ): PControl;
29532 const SBS_Directions: array[ TScrollerBar ] of DWORD = ( SBS_HORZ or SBS_BOTTOMALIGN,
29533 SBS_VERT or SBS_RIGHTALIGN );
29534 begin
29535 Result := _NewCommonControl(
29536 AParent,
29537 'SCROLLBAR',
29538 WS_VISIBLE or WS_CHILD or SBS_Directions[ BarSide ],
29539 False,
29542 Result.DetachProc(WndProcCtrl);
29543 Result.fLookTabKeys := [tkTab];
29544 Result.AttachProc(WndProcScrollBar);
29545 AParent.AttachProc(WndProcScrollBarParent);
29546 end;
29547 //[END NewScrollBar]
29549 //===================== Scrollbox ========================//
29550 //[function WndProcScrollBox]
29551 function WndProcScrollBox( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29552 var Bar: DWORD;
29553 SI: TScrollInfo;
29554 OldNotifyProc: pointer;
29555 begin
29557 case Msg.message of
29558 WM_HSCROLL: Bar := SB_HORZ;
29559 WM_VSCROLL: Bar := SB_VERT;
29560 WM_SIZE: begin
29561 if Assigned( Sender.fNotifyChild ) then
29562 Sender.fNotifyChild( Sender, nil );
29563 Result := FALSE;
29564 Exit;
29565 end;
29566 else begin
29567 Result := FALSE;
29568 Exit;
29569 end;
29570 end;
29572 SI.cbSize := Sizeof( SI );
29573 SI.fMask := SIF_RANGE or SIF_POS or SIF_PAGE or
29574 {$IFDEF F_P}$10{$ELSE}SIF_TRACKPOS{$ENDIF};
29575 {$IFDEF _D2}
29576 GetScrollInfo( Sender.fHandle, Bar, SI );
29577 {$ELSE}
29578 GetScrollInfo( Sender.fHandle, Bar, SI );
29579 {$ENDIF}
29580 SI.fMask := SIF_POS;
29581 case LoWord( Msg.wParam ) of
29582 SB_BOTTOM: SI.nPos := SI.nMax;
29583 SB_TOP: SI.nPos := SI.nMin;
29584 SB_LINEDOWN: Inc( SI.nPos, Sender.FScrollLineDist[ Bar ] );
29585 SB_LINEUP: Dec( SI.nPos, Sender.FScrollLineDist[ Bar ] );
29586 SB_PAGEDOWN: Inc( SI.nPos, Max( SI.nPage, 1 ) );
29587 SB_PAGEUP: Dec( SI.nPos, Max( SI.nPage, 1 ) );
29588 SB_THUMBTRACK:SI.nPos := SI.nTrackPos;
29589 end;
29590 if SI.nPos > SI.nMax { - Integer( SI.nPage ) } then
29591 SI.nPos := SI.nMax { - Integer( SI.nPage ) };
29592 if SI.nPos < SI.nMin then
29593 SI.nPos := SI.nMin;
29594 SetScrollInfo( Sender.fHandle, Bar, SI, TRUE );
29596 if Assigned( Sender.fScrollChildren ) then
29597 begin
29598 OldNotifyProc := @ Sender.fNotifyChild;
29599 Sender.fNotifyChild := nil;
29600 Sender.fScrollChildren( Sender );
29601 Sender.fNotifyChild := OldNotifyProc;
29602 end;
29604 SetScrollInfo( Sender.fHandle, Bar, SI, TRUE );
29605 Result := FALSE;
29606 end;
29607 //[END WndProcScrollBox]
29609 //[function NewScrollBox]
29610 function NewScrollBox( AParent: PControl; EdgeStyle: TEdgeStyle;
29611 Bars: TScrollerBars ): PControl;
29612 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 );
29613 var SBFlag: Integer;
29614 begin
29615 SBFlag := EdgeStyles[ EdgeStyle ];
29616 if sbHorizontal in Bars then
29617 SBFlag := SBFlag or WS_HSCROLL;
29618 if sbVertical in Bars then
29619 SBFlag := SBFlag or WS_VSCROLL;
29621 Result := _NewControl( AParent, 'ScrollBox', WS_VISIBLE or WS_CHILD or
29622 SBFlag, EdgeStyle = esLowered, nil );
29623 Result.AttachProc( WndProcForm ); //!!!
29624 Result.AttachProc( WndProcScrollBox );
29625 Result.AttachProc( WndProcDoEraseBkgnd );
29626 Result.fIsControl := TRUE;
29627 end;
29628 //[END NewScrollBox]
29630 //[function WndProcNotifyParentAboutResize]
29631 function WndProcNotifyParentAboutResize( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29632 var P: PControl;
29633 begin
29634 if (Msg.message = WM_SIZE) or (Msg.message = WM_MOVE) or (Msg.message = CM_SHOW) then
29635 begin
29636 P := Sender.Parent;
29637 if P <> nil then
29638 if Assigned( P.fNotifyChild ) then
29639 P.fNotifyChild( P, nil );
29641 else
29642 if Msg.message = WM_SHOWWINDOW then
29643 PostMessage( Sender.fHandle, CM_SHOW, 0, 0 );
29644 Result := FALSE;
29645 end;
29647 //[procedure CalcMinMaxChildren]
29648 procedure CalcMinMaxChildren( Self_: PControl; var SzR: TRect );
29649 var I: Integer;
29650 C: PControl;
29651 R: TRect;
29652 begin
29653 Szr := MakeRect( 0, 0, 0, 0 );
29654 for I := 0 to Self_.fChildren.fCount - 1 do
29655 begin
29656 C := Self_.fChildren.fItems[ I ];
29657 if C.ToBeVisible then
29658 begin
29659 R := C.BoundsRect;
29660 if (SzR.Left = SzR.Right) or (R.Left < SzR.Left) or (R.Right > SzR.Right) then
29661 begin
29662 if SzR.Left = SzR.Right then
29663 begin
29664 SzR.Left := R.Left;
29665 SzR.Right := R.Right;
29667 else
29668 begin
29669 if R.Left < SzR.Left then SzR.Left := R.Left;
29670 if R.Right > SzR.Right then SzR.Right := R.Right;
29671 end;
29672 end;
29673 if (SzR.Top = SzR.Bottom) or (R.Top < SzR.Top) or (R.Bottom > SzR.Bottom) then
29674 begin
29675 if SzR.Top = SzR.Bottom then
29676 begin
29677 SzR.Top := R.Top;
29678 SzR.Bottom := R.Bottom;
29680 else
29681 begin
29682 if R.Top < SzR.Top then SzR.Top := R.Top;
29683 if R.Bottom > SzR.Bottom then SzR.Bottom := R.Bottom;
29684 end;
29685 end;
29686 end;
29687 end;
29688 Dec( SzR.Left, Self_.Border );
29689 Inc( SzR.Right, Self_.Border - 1 );
29690 Dec( SzR.Top, Self_.Border );
29691 Inc( SzR.Bottom, Self_.Border - 1 );
29692 end;
29694 //[procedure NotifyScrollBox]
29695 procedure NotifyScrollBox( Self_, Child: PControl );
29696 var SI: TScrollInfo;
29698 procedure GetSetScrollInfo( SBar: DWORD; WH, R_RightBottom, SzR_LeftTop, SzR_RightBottom: Integer );
29699 var OldPos: Double;
29700 begin
29701 OldPos := 0;
29702 if not GetScrollInfo( Self_.fHandle, SBar, SI ) then
29703 begin
29704 SI.nMin := 0;
29705 SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );
29707 else
29708 begin
29709 if SI.nMax > SI.nMin then
29710 begin
29711 OldPos := (SI.nPos - SI.nMin) / (SI.nMax - SI.nMin);
29712 SI.nMin := 0;
29713 SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );
29714 if SzR_LeftTop < 0 then
29715 SI.nMax := Max( R_RightBottom - SzR_LeftTop - 1, WH - 1 );
29717 else
29718 begin
29719 SI.nMin := 0;
29720 SI.nMax := Max( R_RightBottom - 1, SzR_RightBottom - 1 );
29721 end;
29722 end;
29723 SI.nPos := SI.nMin + Round( (SI.nMax - SI.nMin) * OldPos );
29724 SI.nPage := R_RightBottom;
29725 SetScrollInfo( Self_.fHandle, SBar, SI, TRUE );
29726 end;
29728 var W, H: Integer;
29729 SzR: TRect;
29730 R: TRect;
29731 begin
29732 if Assigned( Child ) then
29733 begin
29734 Child.AttachProc( WndProcNotifyParentAboutResize );
29735 Exit;
29736 end;
29737 CalcMinMaxChildren( Self_, SzR );
29738 W := SzR.Right - SzR.Left;
29739 H := SzR.Bottom - SzR.Top;
29741 R := Self_.ClientRect;
29742 if (R.Right = 0) or (R.Bottom = 0) then Exit; // for case when form is minimized
29743 SI.cbSize := sizeof( SI );
29744 SI.fMask := SIF_RANGE or SIF_PAGE or SIF_POS;
29746 GetSetScrollInfo( SB_HORZ, W, R.Right, SzR.Left, SzR.Right );
29747 GetSetScrollInfo( SB_VERT, H, R.Bottom, SzR.Top, SzR.Bottom );
29749 end;
29751 //[procedure ScrollChildren]
29752 procedure ScrollChildren( _Self_: PControl );
29753 var SzR, R: TRect;
29754 I, Xpos, Ypos: Integer;
29755 OldNotifyProc: Pointer;
29756 C: PControl;
29757 DeltaX, DeltaY: Integer;
29759 begin
29761 CalcMinMaxChildren( _Self_, SzR );
29762 Xpos := GetScrollPos( _Self_.fHandle, SB_HORZ );
29763 Ypos := GetScrollPos( _Self_.fHandle, SB_VERT );
29765 DeltaX := -Xpos - SzR.Left;
29766 DeltaY := -Ypos - SzR.Top;
29768 if (DeltaX <> 0) or (DeltaY <> 0) then
29769 begin
29771 OldNotifyProc := @ _Self_.fNotifyChild;
29772 _Self_.fNotifyChild := nil;
29774 for I := 0 to _Self_.fChildren.fCount - 1 do
29775 begin
29776 C := _Self_.fChildren.fItems[ I ];
29777 R := C.BoundsRect;
29778 OffsetRect( R, DeltaX, DeltaY );
29779 C.BoundsRect := R;
29780 end;
29782 _Self_.fNotifyChild := OldNotifyProc;
29783 CalcMinMaxChildren( _Self_, R );
29784 if //(SzR.Left <> R.Left) or (SzR.Top <> R.Top) or
29785 //(Szr.Right <> R.Right) or (SzR.Bottom <> R.Bottom)
29786 ((SzR.Right - SzR.Left) <> (R.Right - R.Left)) or
29787 ((SzR.Bottom - SzR.Top) <> (R.Bottom - R.Top))
29788 then
29789 if Assigned( _Self_.fNotifyChild ) then
29790 _Self_.fNotifyChild( _Self_, nil );
29792 end;
29794 end;
29796 //[function NewScrollBoxEx]
29797 function NewScrollBoxEx( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
29798 begin
29799 Result := NewScrollBox( AParent, EdgeStyle, [ ] );
29800 Result.fNotifyChild := NotifyScrollBox;
29801 Result.fScrollChildren := ScrollChildren;
29802 Result.FScrollLineDist[ 0 ] := 16;
29803 Result.FScrollLineDist[ 1 ] := 16;
29804 end;
29806 //[function WndProcOnScroll]
29807 function WndProcOnScroll( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
29808 var Bar: TScrollerBar;
29809 begin
29810 Bar := sbHorizontal; //0
29811 if Msg.message = WM_VSCROLL then
29812 Bar := sbVertical
29813 else
29814 if Msg.message <> WM_HSCROLL then
29815 begin
29816 Result := FALSE;
29817 Exit;
29818 end;
29820 if Assigned( Sender.OnScroll ) then
29821 Sender.OnScroll( Sender, Bar, LoWord( Msg.wParam ), HiWord( Msg.wParam ) );
29822 Result := FALSE;
29823 end;
29825 //[procedure TControl.SetOnScroll]
29826 procedure TControl.SetOnScroll(const Value: TOnScroll);
29827 begin
29828 FOnScroll := Value;
29829 AttachProc( @ WndProcOnScroll );
29830 end;
29832 //===================== Groupbox ========================//
29834 {$IFDEF USE_CONSTRUCTORS}
29835 //[function NewGroupbox]
29836 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
29837 begin
29838 new( Result, CreateGroupbox( AParent, Caption ) );
29839 end;
29840 //[END NewGroupbox]
29841 {$ELSE not_USE_CONSTRUCTORS}
29843 //[FUNCTION NewGroupbox]
29844 {$IFDEF ASM_VERSION}
29845 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
29847 PUSH EDX
29848 PUSH 0
29849 PUSH offset[ButtonActions]
29850 MOV EDX, offset[ButtonClass]
29851 MOV ECX, WS_VISIBLE or WS_CHILD or BS_GROUPBOX or WS_CLIPCHILDREN or WS_CLIPSIBLINGS
29852 CALL _NewControl
29853 OR [EAX].TControl.fExStyle, WS_EX_CONTROLPARENT
29854 MOV EDX, [EAX].TControl.fBoundsRect.Left
29855 ADD EDX, 100
29856 MOV [EAX].TControl.fBoundsRect.Right, EDX
29857 MOV EDX, [EAX].TControl.fBoundsRect.Top
29858 ADD EDX, 100
29859 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
29860 MOV [EAX].TControl.fClientTop, 22
29861 XOR EDX, EDX
29862 MOV [EAX].TControl.fTabstop, DL
29863 MOV DL, 2
29864 ADD [EAX].TControl.fClientBottom, EDX
29865 ADD [EAX].TControl.fClientLeft, EDX
29866 ADD [EAX].TControl.fClientRight, EDX
29867 POP EDX
29868 PUSH EAX
29869 CALL TControl.SetCaption
29870 POP EAX
29871 PUSH EAX
29872 INC [EAX].TControl.fIsGroupBox
29873 MOV EDX, offset[WndProcDoEraseBkgnd]
29874 CALL TControl.AttachProc
29875 POP EAX
29876 end;
29877 {$ELSE ASM_VERSION} //Pascal
29878 function NewGroupbox( AParent: PControl; const Caption: String ): PControl;
29879 begin
29880 Result := _NewControl( AParent, 'BUTTON',
29881 WS_CHILD
29882 or WS_CLIPSIBLINGS
29883 or WS_CLIPCHILDREN
29884 or WS_VISIBLE
29885 or BS_GROUPBOX
29886 //or WS_TABSTOP
29887 //or BS_NOTIFY
29888 //or WS_GROUP
29890 FALSE, @ ButtonActions );
29891 Result.fExStyle := Result.fExStyle or WS_EX_CONTROLPARENT;
29892 Result.Caption := Caption;
29893 with Result.fBoundsRect do
29894 begin
29895 Right := Left + 100;
29896 Bottom := Top + 100;
29897 end;
29898 Result.fClientTop := 22;
29899 Result.fClientBottom := 2;
29900 Result.fClientLeft := 2;
29901 Result.fClientRight := 2;
29902 Result.fTabstop := False;
29903 Result.fIsGroupBox := TRUE;
29904 Result.AttachProc( WndProcDoEraseBkgnd );
29905 end;
29906 {$ENDIF ASM_VERSION}
29907 //[END NewGroupbox]
29909 {$ENDIF USE_CONSTRUCTORS}
29911 //===================== Panel ========================//
29913 {$IFDEF USE_CONSTRUCTORS}
29914 //[function NewPanel]
29915 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
29916 begin
29917 new( Result, CreatePanel( AParent, EdgeStyle ) );
29918 end;
29919 //[END NewPanel]
29920 {$ELSE not_USE_CONSTRUCTORS}
29922 //[FUNCTION NewPanel]
29923 {$IFDEF ASM_VERSION}
29924 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
29926 PUSH EDX
29927 MOV EDX, offset[StaticClass]
29928 MOV ECX, WS_VISIBLE or WS_CHILD or SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY
29929 PUSH 0
29930 PUSH offset[LabelActions]
29931 CALL _NewControl
29932 ADD [EAX].TControl.fBoundsRect.Right, 100-64
29933 ADD [EAX].TControl.fBoundsRect.Bottom, 100-64
29934 OR byte ptr [EAX].TControl.fExStyle+2, 1
29935 POP ECX
29936 CMP CL, 1
29937 JG @@exit
29938 JE @@sunken
29939 OR byte ptr [EAX].TControl.fStyle+2, $40
29941 @@sunken:
29942 OR byte ptr [EAX].TControl.fStyle+1, $10
29943 @@exit:
29944 end;
29945 {$ELSE ASM_VERSION} //Pascal
29946 function NewPanel( AParent: PControl; EdgeStyle: TEdgeStyle ): PControl;
29947 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 );
29948 begin
29949 Result := _NewControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or SS_NOTIFY or
29950 SS_LEFTNOWORDWRAP or SS_NOPREFIX, False, @LabelActions );
29951 with Result.fBoundsRect do
29952 begin
29953 Right := Left + 100;
29954 Bottom := Top + 100;
29955 end;
29956 Result.Style := Result.Style or Edgestyles[ EdgeStyle ];
29957 Result.ExStyle := Result.fExStyle or WS_EX_CONTROLPARENT;
29958 Result.fVerticalAlign := vaTop;
29959 end;
29960 {$ENDIF ASM_VERSION}
29961 //[END NewPanel]
29963 {$ENDIF USE_CONSTRUCTORS}
29965 //===================== Splitter ==============================//
29967 //{$DEFINE USE_ASM_DODRAG}
29969 {$IFNDEF USE_ASM_DODRAG}
29970 {$DEFINE USE_PAS_DODRAG}
29971 {$ENDIF}
29972 {$IFNDEF ASM_VERSION}
29973 {$DEFINE USE_PAS_DODRAG}
29974 {$ENDIF}
29975 {$IFDEF USE_PAS_DODRAG}
29976 //[procedure DoDrag]
29977 procedure DoDrag( Self_: PControl; Cancel: Boolean );
29978 var NewSize1, NewSize2: Integer;
29979 MousePos: TPoint;
29980 R: TRect;
29981 Prev: PControl;
29982 I, M : Integer;
29983 begin
29984 if Self_.fDragging then
29985 begin
29986 I := Self_.fParent.fChildren.IndexOf( Self_ );
29987 Prev := Self_;
29988 if I > 0 then
29989 Prev := Self_.FParent.fChildren.fItems[ I - 1 ];
29990 GetCursorPos( MousePos );
29991 if Cancel then
29992 MousePos := Self_.fSplitStartPos;
29993 M := 1;
29994 if Self_.FAlign in [ caRight, caBottom ] then
29995 M := -1;
29996 if Self_.FAlign in [ caTop, caBottom ] then
29997 begin
29998 NewSize1 := (MousePos.y - Self_.fSplitStartPos.y)* M
29999 + Self_.fSplitStartSize;
30000 NewSize2 := Self_.fParent.ClientHeight - NewSize1
30001 - Self_.fBoundsRect.Bottom + Self_.fBoundsRect.Top
30002 - Self_.fParent.fMargin * 4;
30003 if Self_.fSecondControl <> nil then
30004 begin
30005 NewSize2 := Self_.fSecondControl.fBoundsRect.Bottom
30006 - Self_.fSecondControl.fBoundsRect.Top;
30007 if Self_.fSecondControl.FAlign = caClient then
30008 NewSize2 := Self_.fSplitStartPos2.y
30009 - (MousePos.y - Self_.fSplitStartPos.y)* M
30010 - Self_.fParent.fMargin * 4;
30011 end;
30013 else
30014 begin
30015 NewSize1 := (MousePos.x - Self_.fSplitStartPos.x)* M
30016 + Self_.fSplitStartSize;
30017 NewSize2 := Self_.fParent.ClientWidth - NewSize1
30018 - Self_.fBoundsRect.Right + Self_.fBoundsRect.Left
30019 - Self_.fParent.fMargin * 4;
30020 if Self_.fSecondControl <> nil then
30021 begin
30022 NewSize2 := Self_.fSecondControl.fBoundsRect.Right
30023 - Self_.fSecondControl.fBoundsRect.Left;
30024 if Self_.fSecondControl.FAlign = caClient then
30025 NewSize2 := Self_.fSplitStartPos2.x
30026 - (MousePos.x - Self_.fSplitStartPos.x)* M
30027 - Self_.fParent.Margin * 4;
30028 end;
30029 end;
30030 if {(Self_.fSplitMinSize1 <> 0) and} (NewSize1 < Self_.fSplitMinSize1) then
30031 begin
30032 Dec( NewSize2, Self_.fSplitMinSize1 - NewSize1 );
30033 NewSize1 := Self_.fSplitMinSize1;
30034 end;
30035 if {(Self_.fSplitMinSize2 <> 0) and} (NewSize2 < Self_.fSplitMinSize2) then
30036 begin
30037 Dec( NewSize1, Self_.fSplitMinSize2 - NewSize2 );
30038 NewSize2 := Self_.fSplitMinSize2;
30039 end;
30040 //if Self_.fSplitMinSize1 <> 0 then
30041 if NewSize1 < Self_.fSplitMinSize1 then Exit;
30042 //if Self_.fSplitMinSize2 <> 0 then
30043 if NewSize2 < Self_.fSplitMinSize2 then Exit;
30044 if assigned( Self_.fOnSplit ) then
30045 if not Self_.fOnSplit( Self_, NewSize1, NewSize2 ) then Exit;
30046 R := Prev.BoundsRect;
30047 case Self_.FAlign of
30048 caTop: R.Bottom := R.Top + NewSize1;
30049 caBottom: R.Top := R.Bottom - NewSize1;
30050 caRight: R.Left := R.Right - NewSize1;
30051 else R.Right := R.Left + NewSize1;
30052 end;
30053 Prev.BoundsRect := R;
30054 Global_Align( Self_.fParent );
30055 end;
30056 end;
30057 {$ENDIF}
30059 const
30060 chkLeft=2;
30061 chkTop=4;
30062 chkRight=8;
30063 chkBott=16;
30065 {$DEFINE USE!_ASM_DODRAG}
30067 //[FUNCTION WndProcSplitter]
30068 {$IFDEF ASM_VERSION}
30069 function WndProcSplitter( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30071 CMP word ptr [EDX].TMsg.message, WM_NCHITTEST
30072 JNE @@noWM_NCHITTEST
30073 PUSH ECX
30074 PUSH [EDX].TMsg.lParam
30075 PUSH [EDX].TMsg.wParam
30076 PUSH [EDX].TMsg.message
30077 PUSH [EAX].TControl.fHandle
30078 CALL DefWindowProc
30079 TEST EAX, EAX
30080 JLE @@htReady
30081 XOR EAX, EAX
30082 INC EAX
30083 @@htReady:
30084 POP ECX
30085 MOV [ECX], EAX
30086 MOV AL, 1
30089 @@noWM_NCHITTEST:
30090 PUSH EBX
30091 XCHG EBX, EAX
30092 CMP word ptr [EDX].TMsg.message, WM_MOUSEMOVE
30093 JNE @@noWM_MOUSEMOVE
30095 PUSH [EBX].TControl.fCursor
30096 CALL Windows.SetCursor
30098 XOR EDX, EDX
30100 {$IFDEF USE_ASM_DODRAG}
30101 CALL @@DoDrag
30102 {$ELSE}
30103 MOV EAX, EBX
30104 CALL DoDrag
30105 {$ENDIF}
30107 POP EBX
30110 {$IFDEF USE_ASM_DODRAG}
30111 @@DoDrag:
30112 PUSHAD
30113 MOVZX EDI, DL // EDI = 1 if Cancel, 0 otherwise
30114 CMP [EBX].TControl.fDragging, 0
30115 JZ @@e_DoDrag
30116 MOV EAX, [EBX].TControl.fParent
30117 MOV EAX, [EAX].TControl.fChildren
30118 PUSH EAX
30119 MOV EDX, EBX
30120 CALL TList.IndexOf
30121 POP EDX // EDX = Self_.fParent.fChildren:PList
30122 MOV EBP, EBX // Prev := Self_;
30123 TEST EAX, EAX
30124 JLE @@noPrev
30125 MOV EDX, [EDX].TList.fItems
30126 MOV EBP, [EDX+EAX*4-4] // Prev = Self_.fParent.fChildren.fItems[I-1]
30127 PUSH EBP // push Prev
30128 @@noPrev:
30129 PUSH EDX
30130 PUSH EDX
30131 PUSH ESP
30132 CALL GetCursorPos
30133 DEC EDI
30134 JNZ @@noCancel
30135 POP EDX
30136 POP EDX
30137 PUSH [EBX].TControl.fSplitStartPos.y
30138 PUSH [EBX].TControl.fSplitStartPos.x
30139 @@noCancel:
30140 OR EDI, -1
30141 MOV CL, [EBX].TControl.fAlign
30142 MOV AL, 1
30143 SHL EAX, CL
30144 {$IFDEF PARANOIA}
30145 DB $A8, chkRight or chkBott
30146 {$ELSE}
30147 TEST AL, chkRight or chkBott //fAlign in [ caRight, caBottom ] ?
30148 {$ENDIF}
30149 JNZ @@mReady
30150 INC EDI
30151 INC EDI
30152 @@mReady:
30153 MOV EDX, [EBX].TControl.fParent
30154 MOV EBP, [EDX].TControl.fMargin
30155 NEG EBP
30156 {$IFDEF PARANOIA}
30157 DB $A8, chkTop or chkBott
30158 {$ELSE}
30159 TEST AL, chkTop or chkBott // fAlign in [ caTop, caBottom ] ?
30160 {$ENDIF}
30161 XCHG EAX, EDX
30162 JZ @@noTopBottom
30164 CALL TControl.GetClientHeight
30165 XCHG EDX, EAX
30167 POP EAX
30168 POP ESI // MousePos.y
30169 MOV EAX, ESI
30170 PUSH EDX // Self_.fParent.ClientHeight
30171 SUB EAX, [EBX].TControl.fSplitStartPos.y
30172 IMUL EAX, EDI
30173 ADD EAX, [EBX].TControl.fSplitStartSize // EAX = NewSize1
30175 POP EDX
30176 SUB EDX, EAX
30177 SUB EDX, [EBX].TControl.fBoundsRect.Bottom
30178 ADD EDX, [EBX].TControl.fBoundsRect.Top
30179 LEA EDX, [EDX+EBP*4]
30181 MOV ECX, [EBX].TControl.fSecondControl
30182 JECXZ @@noSecondControl
30183 MOV EDX, [ECX].TControl.fBoundsRect.Bottom
30184 SUB EDX, [ECX].TControl.fBoundsRect.Top
30185 CMP [ECX].TControl.fAlign, caClient
30186 JNZ @@noSecondControl
30188 PUSH EAX
30189 MOV EAX, [EBX].TControl.fSplitStartPos.y
30190 SUB EAX, ESI
30191 IMUL EAX, EDI
30192 ADD EAX, [EBX].TControl.fSplitStartPos2.y
30193 LEA EDX, [EAX+EBP*4]
30194 POP EAX
30196 @@noSecondControl:
30197 JMP @@newSizesReady
30199 @@noTopBottom:
30200 CALL TControl.GetClientWidth
30201 XCHG EDX, EAX
30203 POP ESI // MousePos.x
30204 POP ECX
30205 MOV EAX, ESI
30206 PUSH EDX // Self_.fParent.ClientWidth
30207 SUB EAX, [EBX].TControl.fSplitStartPos.x
30208 IMUL EAX, EDI
30209 ADD EAX, [EBX].TControl.fSplitStartSize // EAX = NewSize1
30211 POP EDX
30212 SUB EDX, EAX
30213 SUB EDX, [EBX].TControl.fBoundsRect.Right
30214 ADD EDX, [EBX].TControl.fBoundsRect.Left
30215 LEA EDX, [EDX+EBP*4]
30217 MOV ECX, [EBX].TControl.fSecondControl
30218 JECXZ @@newSizesReady
30219 MOV EDX, [ECX].TControl.fBoundsRect.Right
30220 SUB EDX, [ECX].TControl.fBoundsRect.Left
30221 CMP [ECX].TControl.fAlign, caClient
30222 JNZ @@noSecondControl
30224 PUSH EAX
30225 MOV EAX, [EBX].TControl.fSplitStartPos.x
30226 SUB EAX, ESI
30227 IMUL EAX, EDI
30228 ADD EAX, [EBX].TControl.fSplitStartPos2.x
30229 LEA EDX, [EAX+EBP*4]
30230 POP EAX
30232 @@newSizesReady:
30233 MOV ECX, [EBX].TControl.fSplitMinSize1
30234 //JECXZ @@noCheckMinSize1
30235 SUB ECX, EAX
30236 JLE @@noCheckMinSize1
30237 SUB EDX, ECX
30238 ADD EAX, ECX
30240 @@noCheckMinSize1:
30241 MOV ECX, [EBX].TControl.fSplitMinSize2
30242 //JECXZ @@noCheckMinSize2
30243 SUB ECX, EDX
30244 JLE @@noCheckMinSize2
30245 SUB EAX, ECX
30246 ADD EDX, ECX
30248 @@noCheckMinSize2:
30249 MOV ECX, [EBX].TControl.fOnSplit.TMethod.Code
30250 JECXZ @@noOnSplit
30251 PUSHAD
30252 PUSH EDX
30253 MOV ESI, ECX
30254 XCHG ECX, EAX
30255 MOV EDX, EBX
30256 MOV EAX, [EBX].TControl.fOnSplit.TMethod.Data
30257 CALL ESI
30258 TEST AL, AL
30259 POPAD
30260 JZ @@e_DoDrag
30262 @@noOnSplit:
30263 XCHG ESI, EAX // NewSize1 -> ESI
30264 //MOV EDI, EDX // NewSize2 -> EDI
30265 POP EBP
30266 ADD ESP, -16
30267 MOV EAX, EBP
30268 MOV EDX, ESP
30269 CALL TControl.GetBoundsRect
30270 MOVZX ECX, [EBX].TControl.fAlign
30271 LOOP @@noPrev_caLeft
30272 ADD ESI, [ESP].TRect.Left
30273 MOV [ESP].TRect.Right, ESI
30274 @@noPrev_caLeft:
30275 LOOP @@noPrev_caTop
30276 ADD ESI, [ESP].TRect.Top
30277 MOV [ESP].TRect.Bottom, ESI
30278 @@noPrev_caTop:
30279 LOOP @@noPrev_caRight
30280 MOV EAX, [ESP].TRect.Right
30281 SUB EAX, ESI
30282 MOV [ESP].TRect.Left, EAX
30283 @@noPrev_caRight:
30284 LOOP @@noPrev_caBottom
30285 MOV EAX, [ESP].TRect.Bottom
30286 SUB EAX, ESI
30287 MOV [ESP].TRect.Top, EAX
30288 @@noPrev_caBottom:
30289 MOV EAX, EBP
30290 MOV EDX, ESP
30291 CALL TControl.SetBoundsRect
30292 ADD ESP, 16
30293 MOV EAX, [EBX].TControl.fParent
30294 //PUSH EAX
30295 CALL dword ptr[Global_Align]
30296 //POP EAX
30297 //CALL TControl.Update
30299 @@e_DoDrag:
30300 POPAD
30302 {$ENDIF USE_ASM_DODRAG}
30304 @@noWM_MOUSEMOVE:
30305 CMP word ptr [EDX].TMsg.message, WM_LBUTTONDOWN
30306 JNE @@noWM_LBUTTONDOWN
30307 MOV ECX, [EBX].TControl.fParent
30308 TEST ECX, ECX
30309 JZ @@noWM_LBUTTONDOWN
30310 //JECXZ @@noWM_LBUTTONDOWN
30312 MOV EAX, [ECX].TControl.fChildren
30313 PUSH EAX
30314 MOV EDX, EBX
30315 CALL TList.IndexOf
30316 POP ECX
30317 MOV EDX, EBX
30318 TEST EAX, EAX
30319 JLE @@noParent1
30320 MOV ECX, [ECX].TList.fItems
30321 MOV EDX, [ECX+EAX*4-4]
30322 @@noParent1:
30324 MOV CL, [EBX].TControl.fAlign
30325 MOV AL, 1
30326 SHL EAX, CL
30327 {$IFDEF PARANOIA}
30328 DB $A8, chkTop or chkBott
30329 {$ELSE}
30330 TEST AL, chkTop or chkBott // fAlign in [caTop,caBottom] ?
30331 {$ENDIF}
30332 XCHG EAX, EDX
30333 JZ @@no_caTop_caBottom
30334 CALL TControl.GetHeight
30335 JMP @@caTop_caBottom
30336 @@no_caTop_caBottom:
30337 CALL TControl.GetWidth
30338 @@caTop_caBottom:
30339 MOV [EBX].TControl.fSplitStartSize, EAX
30340 MOV ECX, [EBX].TControl.fSecondControl
30341 JECXZ @@noSecondControl1
30342 XCHG EAX, ECX
30343 PUSH EAX
30344 CALL TControl.GetWidth
30345 MOV [EBX].TControl.fSplitStartPos2.x, EAX
30346 POP EAX
30347 CALL TControl.GetHeight
30348 MOV [EBX].TControl.fSplitStartPos2.y, EAX
30349 @@noSecondControl1:
30350 PUSH [EBX].TControl.fHandle
30351 CALL SetCapture
30352 OR [EBX].TControl.fDragging, 1
30353 PUSH 0
30354 PUSH 100
30355 PUSH $7B
30356 PUSH [EBX].TControl.fHandle
30357 CALL SetTimer
30358 LEA EAX, [EBX].TControl.fSplitStartPos
30359 PUSH EAX
30360 CALL GetCursorPos
30361 JMP @@exit
30363 @@noWM_LBUTTONDOWN:
30364 CMP word ptr [EDX].TMsg.message, WM_LBUTTONUP
30365 JNE @@noWM_LBUTTONUP
30366 XOR EDX, EDX
30368 {$IFDEF USE_ASM_DODRAG}
30369 CALL @@DoDrag
30370 {$ELSE}
30371 MOV EAX, EBX
30372 CALL DoDrag
30373 {$ENDIF}
30375 JMP @@killtimer
30377 @@noWM_LBUTTONUP:
30378 CMP word ptr[EDX].TMsg.message, WM_TIMER
30379 JNE @@exit
30380 CMP [EBX].TControl.fDragging, 0
30381 JE @@exit
30382 PUSH VK_ESCAPE
30383 CALL GetAsyncKeyState
30384 TEST EAX, EAX
30385 JGE @@exit
30387 MOV DL, 1
30389 {$IFDEF USE_ASM_DODRAG}
30390 CALL @@DoDrag
30391 {$ELSE}
30392 MOV EAX, EBX
30393 CALL DoDrag
30394 {$ENDIF}
30396 @@killtimer:
30397 MOV [EBX].TControl.fDragging, 0
30398 PUSH $7B
30399 PUSH [EBX].TControl.fHandle
30400 CALL KillTimer
30401 CALL ReleaseCapture
30403 @@exit:
30404 POP EBX
30405 XOR EAX, EAX
30406 end;
30407 {$ELSE ASM_VERSION} //Pascal
30408 function WndProcSplitter( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30409 var I: Integer;
30410 Prev: PControl;
30412 procedure FinDrag;
30413 begin
30414 KillTimer( Self_.fHandle, $7B );
30415 Self_.fDragging := False;
30416 ReleaseCapture;
30417 end;
30418 begin
30419 case Msg.message of
30420 WM_NCHITTEST:
30421 begin
30422 Rslt := DefWindowProc( Self_.fHandle, Msg.message, Msg.wParam, Msg.lParam );
30423 if Rslt > 0 then
30424 Rslt := HTCLIENT;
30425 Result := True;
30426 Exit;
30427 end;
30428 WM_MOUSEMOVE:
30429 begin
30430 Windows.SetCursor( Self_.fCursor );
30431 DoDrag( Self_, False );
30432 end;
30433 WM_LBUTTONDOWN:
30434 begin
30435 if Self_.fParent <> nil then
30436 begin
30437 I := Self_.fParent.fChildren.IndexOf( Self_ );
30438 Prev := Self_;
30439 if I > 0 then
30440 Prev := Self_.FParent.fChildren.fItems[ I - 1 ];
30441 if Self_.fAlign in [ caTop, caBottom ] then
30442 Self_.fSplitStartSize := Prev.Height
30443 else
30444 Self_.fSplitStartSize := Prev.Width;
30445 if Self_.fSecondControl <> nil then
30446 Self_.fSplitStartPos2 :=
30447 MakePoint( Self_.fSecondControl.Width, Self_.fSecondControl.Height );
30448 SetCapture( Self_.fHandle );
30449 Self_.fDragging := True;
30450 SetTimer( Self_.fHandle, $7B, 100, nil );
30451 GetCursorPos( Self_.fSplitStartPos );
30452 end;
30453 end;
30454 WM_LBUTTONUP:
30455 begin
30456 DoDrag( Self_, False );
30457 FinDrag;
30458 end;
30459 WM_TIMER:
30460 if Self_.fDragging and (GetAsyncKeyState( VK_ESCAPE ) < 0) then
30461 begin
30462 DoDrag( Self_, True );
30463 FinDrag;
30464 end;
30465 end;
30466 Result := False;
30467 end;
30468 {$ENDIF ASM_VERSION}
30469 //[END WndProcSplitter]
30471 //[function NewSplitter]
30472 function NewSplitter( AParent: PControl; MinSizePrev, MinSizeNext: Integer ): PControl;
30473 begin
30474 Result := NewSplitterEx( AParent, MinSizePrev, MinSizeNext, esLowered );
30475 end;
30476 //[END NewSplitter]
30478 {$IFDEF USE_CONSTRUCTORS}
30479 //[function NewSplitterEx]
30480 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
30481 EdgeStyle: TEdgeStyle ): PControl;
30482 begin
30483 new( Result, CreateSplitter( AParent, MinSizePrev, MinSizeNext, EdgeStyle ) );
30484 end;
30485 //[END NewSplitterEx]
30486 {$ELSE not_USE_CONSTRUCTORS}
30488 //[FUNCTION NewSplitterEx]
30489 {$IFDEF ASM_VERSION}
30490 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
30491 EdgeStyle: TEdgeStyle ): PControl;
30492 const int_IDC_SIZEWE = integer( IDC_SIZEWE );
30494 PUSH EBX
30495 PUSH EAX // AParent
30496 PUSH ECX // MinSizePrev
30497 PUSH EDX // MinSizeNext
30498 MOV DL, EdgeStyle
30499 CALL NewPanel
30500 XCHG EBX, EAX
30501 POP [EBX].TControl.fSplitMinSize1
30502 POP [EBX].TControl.fSplitMinSize2
30503 XOR EDX, EDX
30504 MOV DL, 4
30505 MOV EAX, [EBX].TControl.fBoundsRect.Left
30506 ADD EAX, EDX
30507 MOV [EBX].TControl.fBoundsRect.Right, EAX
30508 ADD EDX, [EBX].TControl.fBoundsRect.Top
30509 MOV [EBX].TControl.fBoundsRect.Bottom, EDX
30511 POP ECX // ECX = AParent
30512 JECXZ @@noParent2
30513 MOV EAX, [ECX].TControl.fChildren
30514 MOV ECX, [EAX].TList.fCount
30515 CMP ECX, 1
30516 JLE @@noParent2
30518 MOV EAX, [EAX].TList.fItems
30519 MOV EAX, [EAX+ECX*4-8]
30520 MOV CL, [EAX].TControl.fAlign
30521 PUSH ECX
30522 MOV AL, 1
30523 SHL EAX, CL
30524 {$IFDEF PARANOIA}
30525 DB $A8, chkTop or chkBott
30526 {$ELSE}
30527 TEST AL, chkTop or chkBott
30528 {$ENDIF}
30529 MOV EAX, int_IDC_SIZEWE
30530 JZ @@TopBottom
30531 INC EAX
30532 @@TopBottom:
30533 PUSH EAX
30534 PUSH 0
30535 CALL LoadCursor
30536 MOV [EBX].TControl.fCursor, EAX
30537 POP EDX
30538 MOV EAX, EBX
30539 CALL TControl.SetAlign
30541 @@noParent2:
30542 MOV EAX, EBX
30543 MOV EDX, offset[WndProcSplitter]
30544 CALL TControl.AttachProc
30545 XCHG EAX, EBX
30546 POP EBX
30547 end;
30548 {$ELSE ASM_VERSION} //Pascal
30549 function NewSplitterEx( AParent: PControl; MinSizePrev, MinSizeNext: Integer;
30550 EdgeStyle: TEdgeStyle ): PControl;
30551 var PrevCtrl: PControl;
30552 Sz0: Integer;
30553 begin
30554 Result := NewPanel( AParent, EdgeStyle );
30555 Result.fSplitMinSize1 := MinSizePrev;
30556 Result.fSplitMinSize2 := MinSizeNext;
30557 Sz0 := 4;
30558 with Result.fBoundsRect do
30559 begin
30560 Right := Left + Sz0;
30561 Bottom := Top + Sz0;
30562 end;
30563 if AParent <> nil then
30564 begin
30565 if AParent.fChildren.fCount > 1 then
30566 begin
30567 PrevCtrl := AParent.fChildren.fItems[ AParent.fChildren.fCount - 2 ];
30568 case PrevCtrl.FAlign of
30569 caLeft, caRight:
30570 begin
30571 Result.fCursor := LoadCursor( 0, IDC_SIZEWE );
30572 end;
30573 caTop, caBottom:
30574 begin
30575 Result.fCursor := LoadCursor( 0, IDC_SIZENS );
30576 end;
30577 end;
30578 Result.Align := PrevCtrl.FAlign;
30579 end;
30580 end;
30581 Result.AttachProc( WndProcSplitter );
30582 end;
30583 {$ENDIF ASM_VERSION}
30584 //[END NewSplitterEx]
30586 {$ENDIF USE_CONSTRUCTORS}
30588 //===================== MDI client window control =============//
30590 //[procedure DestroyMDIChildren]
30591 procedure DestroyMDIChildren( Form: PControl );
30592 var MDIClient: PControl;
30593 I: Integer;
30594 Ch: PControl;
30595 begin
30596 //Form.fDefWndProc := nil;
30597 MDIClient := Form.fMDIClient;
30598 MDIClient.fMDIDestroying := TRUE;
30599 if MDIClient = nil then Exit;
30600 if MDIClient.fMDIChildren <> nil then
30601 for I := MDIClient.fMDIChildren.Count - 1 downto 0 do
30602 begin
30603 Ch := MDIClient.fMDIChildren.fItems[ I ];
30604 if Ch.fHandle <> 0 then
30605 MDIClient.Perform( WM_MDIDESTROY, Ch.fHandle, 0 );
30606 end;
30607 MDIClient.fMDIChildren.Free;
30608 MDIClient.fMDIChildren := nil;
30609 if Form.fMenu <> 0 then
30610 begin
30611 MDIClient.Perform( WM_MDISETMENU, 0, 0 );
30612 MDIClient.Perform( WM_MDIREFRESHMENU, 0, 0 );
30613 DrawMenuBar( Form.fHandle );
30614 Form.fMenuObj.Free;
30615 Form.fMenuObj := nil;
30616 end;
30617 Form.fMDIClient := nil;
30618 MDIClient.Free;
30619 end;
30621 //[function ProcMDIAccel]
30622 function ProcMDIAccel( Applet: PControl; var Msg: TMsg ): Boolean;
30623 var Form: PControl;
30624 begin
30625 Result := FALSE;
30626 if (Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST) then
30627 begin
30628 Form := Applet.ActiveControl;
30629 if Form <> nil then
30630 begin
30631 if Form.IsMDIChild then
30632 Form := Form.Parent;
30633 Form := Form.ParentForm;
30634 if (Form <> nil) and (Form.MDIClient <> nil) then
30635 Result := TranslateMDISysAccel( Form.MDIClient.fHandle, Msg );
30636 end;
30637 end;
30638 end;
30640 //[function CallDefFrameProc]
30641 function CallDefFrameProc( Wnd: HWnd; Msg: Integer; wParam, lParam: Integer ): Integer;
30642 stdcall;
30643 var Form: PControl;
30644 begin
30645 Form := Pointer( GetProp( Wnd, ID_SELF ) );
30646 if Form <> nil then
30647 Form := Form.ParentForm;
30648 if (Form <> nil) and (Form.fMDIClient <> nil) then
30649 Result := DefFrameProc( Wnd, Form.fMDIClient.fHandle, Msg, wParam, lParam )
30650 else
30651 Result := DefWindowProc( Wnd, Msg, wParam, lParam );
30652 end;
30654 //[function WndFuncMDIClient]
30655 function WndFuncMDIClient( Wnd: HWnd; Msg, wParam, lParam: Integer ): Integer;
30656 stdcall;
30657 var C: PControl;
30658 M: TMsg;
30659 begin
30660 C := Pointer( GetProp( Wnd, ID_SELF ) );
30661 if C <> nil then
30662 begin
30663 M.hwnd := Wnd;
30664 M.message := Msg;
30665 M.wParam := wParam;
30666 M.lParam := lParam;
30667 Result := C.WndProc( M );
30669 else
30670 Result := DefWindowProc( Wnd, Msg, wParam, lParam );
30671 end;
30673 //[function ShowMDIClientEdge]
30674 function ShowMDIClientEdge( MDIClient: PControl ): Boolean;
30675 var ShowEdge: Boolean;
30676 I: Integer;
30677 Ch: PControl;
30678 ExStyle: Integer;
30679 begin
30680 Result := FALSE;
30681 ShowEdge := TRUE;
30682 if MDIClient.fMDIChildren.Count > 0 then
30683 for I := 0 to MDIClient.fMDIChildren.Count-1 do
30684 begin
30685 Ch := MDIClient.fMDIChildren.fItems[ I ];
30686 if IsZoomed( Ch.fHandle ) then
30687 begin
30688 ShowEdge := FALSE;
30689 break;
30690 end;
30691 end;
30692 ExStyle := MDIClient.ExStyle;
30693 if ShowEdge then
30694 if ExStyle and WS_EX_CLIENTEDGE = 0 then
30695 ExStyle := ExStyle or WS_EX_CLIENTEDGE
30696 else
30697 Exit
30698 else if ExStyle and WS_EX_CLIENTEDGE <> 0 then
30699 ExStyle := ExStyle and not WS_EX_CLIENTEDGE
30700 else
30701 Exit;
30702 MDIClient.ExStyle := ExStyle;
30703 Result := TRUE;
30704 end;
30706 //[function WndProcMDIClient]
30707 function WndProcMDIClient( MDIClient: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30708 {var I: Integer;
30709 Ch: PControl;}
30710 begin
30711 if not MDIClient.fMDIDestroying then
30712 case Msg.message of
30713 $3f:
30714 begin
30715 PostMessage( MDIClient.fHandle, CM_MDIClientShowEdge, 0, 0 );
30716 end;
30717 CM_MDIClientShowEdge:
30718 begin
30719 ShowMDIClientEdge( MDIClient );
30720 end;
30721 WM_NCHITTEST: // not necessary though
30722 begin
30723 Rslt := DefWindowProc( MDIClient.fHandle, WM_NCHITTEST, Msg.wParam, Msg.lParam );
30724 if Rslt = HTCLIENT then Rslt := HTTRANSPARENT;
30725 end;
30726 WM_WINDOWPOSCHANGING:
30727 begin
30728 MDIClient.Perform( WM_SETREDRAW, 0, 0 );
30729 end;
30730 WM_WINDOWPOSCHANGED:
30731 begin
30732 Global_Align( MDIClient.Parent );
30733 MDIClient.Invalidate;
30734 MDIClient.Parent.Invalidate;
30735 MDIClient.Perform( WM_SETREDRAW, 1, 0 );
30736 PostMessage( MDIClient.fHandle, CM_INVALIDATE, 0, 0 );
30737 end;
30738 CM_INVALIDATE:
30739 begin
30740 MDIClient.InvalidateNC( TRUE );
30741 MDIClient.InvalidateEx;
30742 {for I := 0 to MDIClient.fMDIChildren.Count-1 do
30743 begin
30744 Ch := MDIClient.fMDIChildren.fItems[ I ];
30745 Ch.InvalidateEx;
30746 Ch.Perform( WM_NCPAINT, 1, 0 );
30747 end;}
30748 end;
30749 end;
30750 Result := FALSE;
30751 end;
30753 // function added by Thaddy de Koning to fix MDI behaviour
30754 //[function WndProcParentNotifyMouseLDown]
30755 function WndProcParentNotifyMouseLDown( Sender: PControl; var Msg: TMsg;
30756 var Rslt: Integer ): Boolean;
30757 begin
30758 Result := FALSE;
30759 if (Sender.IsMDIChild) and (Msg.message = WM_PARENTNOTIFY) and
30760 (LOWORD(msg.wparam)=WM_LBUTTONDOWN) then
30761 BringWindowToTop( Sender.Handle );
30762 end;
30764 //[function NewMDIClient]
30765 function NewMDIClient( AParent: PControl; WindowMenu: THandle ): PControl;
30766 var F: PControl;
30767 CCS: TClientCreateStruct;
30768 PrntWin: HWnd;
30769 begin
30770 F := nil;
30771 PrntWin := 0;
30772 if AParent <> nil then
30773 begin
30774 F := AParent.ParentForm;
30775 if F <> nil then
30776 begin
30777 F.Add2AutoFreeEx( TObjectMethod( MakeMethod( F, @ DestroyMDIChildren ) ) );
30778 F.GetWindowHandle; // must be created before MDI client creation
30779 F.fDefWndProc := @CallDefFrameProc;
30780 end;
30781 PrntWin := AParent.GetWindowHandle;
30782 end;
30783 Applet.fExMsgProc := ProcMDIAccel;
30784 Result := _NewControl( AParent, 'MDICLIENT',
30785 WS_CHILD or WS_CLIPCHILDREN or WS_VSCROLL or WS_HSCROLL or
30786 WS_VISIBLE or WS_TABSTOP or MDIS_ALLCHILDSTYLES, TRUE, nil );
30787 {Result.fBoundsRect.Right := Result.fBoundsRect.Left + 300;
30788 Result.fBoundsRect.Bottom := Result.fBoundsRect.Top + 200;}
30789 Result.fMDIChildren := NewList;
30790 Result.fExStyle := WS_EX_CLIENTEDGE;
30792 CCS.hWindowMenu := WindowMenu;
30793 CCS.idFirstChild := $FF00;
30794 Result.fHandle := CreateWindowEx( WS_EX_CLIENTEDGE, 'MDICLIENT', nil,
30795 WS_CHILD or WS_CLIPCHILDREN or WS_VSCROLL or WS_HSCROLL or
30796 WS_VISIBLE or WS_TABSTOP,
30797 //or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX,
30798 0, 0, 0, 0, PrntWin, 0, hInstance, @ CCS );
30799 Result.fDefWndProc := Pointer( GetWindowLong( Result.fHandle, GWL_WNDPROC ) );
30800 SetWindowLong( Result.fHandle, GWL_WNDPROC, Integer( @WndFuncMDIClient ) );
30801 SetProp( Result.fHandle, ID_SELF, Integer( Result ) );
30802 if F <> nil then
30803 F.fMDIClient := Result;
30804 Result.AttachProc( WndProcMDIClient );
30805 Result.GetWindowHandle;
30807 Applet.AttachProc( WndProcParentNotifyMouseLDown );
30808 end;
30810 //===================== MDI child window object ==============//
30811 //[function MDIChildFunc]
30812 function MDIChildFunc( Wnd: HWnd; Msg: DWord; wParam, lParam: Integer ): Integer;
30813 stdcall;
30814 var C: PControl;
30815 M: TMsg;
30816 begin
30817 C := Pointer( GetProp( Wnd, ID_SELF ) );
30818 if C <> nil then
30819 begin
30820 M.hwnd := Wnd;
30821 M.message := Msg;
30822 M.wParam := wParam;
30823 M.lParam := lParam;
30824 Result := C.WndProc( M );
30826 else
30827 Result := DefMDIChildProc( Wnd, Msg, wParam, lParam );
30828 end;
30830 //[function Pass2DefMDIChildProc]
30831 function Pass2DefMDIChildProc( Sender_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30832 begin
30833 Result := FALSE;
30834 if Sender_ = nil then Exit;
30835 if Sender_.Parent = nil then Exit;
30836 if Sender_.Parent.fDestroying then Exit;
30837 if (Msg.message = WM_SYSCOMMAND) or (Msg.message = WM_CHILDACTIVATE) or
30838 (Msg.message = WM_SETFOCUS) or (Msg.message = WM_SIZE) or
30839 (Msg.message = WM_MOVE) or (Msg.message = WM_MENUCHAR) or
30840 (Msg.message = WM_GETMINMAXINFO) {and IsZoomed( Sender_.fHandle ) {and (Msg.hwnd = Sender_.fHandle) { -- doesn't work -- } then
30841 begin
30842 {if Msg.message = WM_GETMINMAXINFO then
30843 Rslt := DefWindowProc( Msg.hwnd, Msg.message, Msg.lParam, Msg.wParam )
30844 else}
30845 Rslt := DefMDIChildProc( Msg.hwnd, Msg.message, Msg.lParam, Msg.wParam );
30846 Result := TRUE;
30847 end;
30848 end;
30850 //[function WndProcMDIChild]
30851 function WndProcMDIChild( MDIChild: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
30852 var ClientWnd: HWnd;
30853 MDIClient: PControl;
30854 MDIForm: PControl;
30855 begin
30856 Result := FALSE;
30857 MDIClient := MDIChild.Parent;
30858 if MDIClient = nil then Exit;
30859 ClientWnd := MDIClient.fHandle;
30860 if ClientWnd = 0 then Exit;
30861 case Msg.message of
30862 WM_DESTROY:
30863 begin
30864 MDIClient.fMDIChildren.Remove( MDIChild );
30865 MDIForm := MDIClient.ParentForm;
30866 if MDIForm <> nil then
30867 if MDIForm.fHandle <> 0 then
30868 DrawMenuBar( MDIForm.fHandle );
30869 MDIChild.Free;
30870 Result := TRUE;
30871 Exit;
30872 end;
30873 end;
30874 if MDIChild.fNotAvailable then
30875 begin
30876 MDIChild.fNotAvailable := FALSE;
30877 MDIChild.Invalidate;
30878 end;
30879 end;
30881 //[procedure CreateMDIChildExt]
30882 procedure CreateMDIChildExt( Sender: PControl );
30883 var F: PControl;
30884 begin
30885 F := Sender.Parent;
30886 if F <> nil then
30887 F := F.ParentForm;
30888 if F <> nil then
30889 DrawMenuBar( F.fHandle );
30890 end;
30892 //[function NewMDIChild]
30893 function NewMDIChild( AParent: PControl; const ACaption: String ): PControl;
30894 var MDIClient: PControl;
30895 begin
30896 Assert( (AParent <> nil) and (AParent.ParentForm <> nil) and
30897 (AParent.ParentForm.fMDIClient <> nil), 'Error creating MDI child' );
30898 MDIClient := AParent.ParentForm.fMDIClient;
30899 Result := NewForm( MDIClient, ACaption );
30900 Result.fIsMDIChild := TRUE;
30901 Result.fMenu := CtlIdCount;
30902 Inc( CtlIdCount );
30903 MDIClient.fMDIChildren.Add( Result );
30904 Result.fExStyle := Result.fExStyle or WS_EX_MDICHILD;
30905 Result.fWndFunc := @ MDIChildFunc;
30906 Result.fDefWndProc := @DefMDIChildProc;
30907 Result.fPass2DefProc := Pass2DefMDIChildProc;
30908 Result.AttachProc( WndProcMDIChild );
30910 Result.SubClassName := 'MDI_chld';
30911 Result.fNotAvailable := TRUE;
30912 Result.fCreateWndExt := CreateMDIChildExt;
30914 end;
30916 //===================== Gradient panel ========================//
30918 {$IFDEF USE_CONSTRUCTORS}
30919 //[function NewGradientPanel]
30920 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
30921 begin
30922 new( Result, CreateGradientPanel( AParent, Color1, Color2 ) );
30923 end;
30924 //[END NewGradientPanel]
30925 {$ELSE not_USE_CONSTRUCTORS}
30927 //[FUNCTION NewGradientPanel]
30928 {$IFDEF ASM_VERSION}
30929 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
30931 PUSH ECX
30932 PUSH EDX
30933 XOR EDX, EDX
30934 CALL NewLabel
30935 PUSH EAX
30936 MOV EDX, offset[WndProcGradient]
30937 CALL TControl.AttachProc
30938 POP EAX
30939 POP [EAX].TControl.fColor1
30940 POP [EAX].TControl.fColor2
30941 ADD [EAX].TControl.fBoundsRect.Right, 40-64
30942 ADD [EAX].TControl.fBoundsRect.Bottom, 40 - 22
30943 end;
30944 {$ELSE ASM_VERSION} //Pascal
30945 function NewGradientPanel( AParent: PControl; Color1, Color2: TColor ): PControl;
30946 begin
30947 Result := NewLabel( AParent, '' );
30948 Result.AttachProc( WndProcGradient );
30949 Result.fColor2 := Color2;
30950 Result.fColor1 := Color1;
30951 with Result.fBoundsRect do
30952 begin
30953 Right := Left + 40;
30954 Bottom := Top + 40;
30955 end;
30956 end;
30957 {$ENDIF ASM_VERSION}
30958 //[END NewGradientPanel]
30960 {$ENDIF USE_CONSTRUCTORS}
30962 {$IFDEF USE_CONSTRUCTORS}
30963 //[function NewGradientPanelEx]
30964 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
30965 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
30966 begin
30967 new( Result, CreateGradientPanelEx( AParent, Color1, Color2,
30968 Style, Layout ) );
30969 end;
30970 //[END NewGradientPanelEx]
30971 {$ELSE not_USE_CONSTRUCTORS}
30973 //[FUNCTION NewGradientPanelEx]
30974 {$IFDEF ASM_VERSION}
30975 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
30976 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
30978 PUSH ECX
30979 PUSH EDX
30980 XOR EDX, EDX
30981 CALL NewLabel
30982 PUSH EAX
30983 MOV EDX, offset[WndProcGradientEx]
30984 CALL TControl.AttachProc
30985 POP EAX
30986 POP [EAX].TControl.fColor1
30987 POP [EAX].TControl.fColor2
30988 ADD [EAX].TControl.fBoundsRect.Right, 40-100
30989 ADD [EAX].TControl.fBoundsRect.Bottom, 40 - 22
30990 MOV DL, Style
30991 MOV [EAX].TControl.fGradientStyle, DL
30992 MOV DL, Layout
30993 MOV [EAX].TControl.fGradientLayout, DL
30994 end;
30995 {$ELSE ASM_VERSION} //Pascal
30996 function NewGradientPanelEx( AParent: PControl; Color1, Color2: TColor;
30997 Style: TGradientStyle; Layout: TGradientLayout ): PControl;
30998 begin
30999 Result := NewLabel( AParent, '' );
31000 Result.AttachProc( WndProcGradientEx );
31001 Result.fColor2 := Color2;
31002 Result.fColor1 := Color1;
31003 Result.fGradientStyle := Style;
31004 Result.fGradientLayout := Layout;
31005 with Result.fBoundsRect do
31006 begin
31007 Right := Left + 40;
31008 Bottom := Top + 40;
31009 end;
31010 end;
31011 {$ENDIF ASM_VERSION}
31012 //[END NewGradientPanelEx]
31014 {$ENDIF USE_CONSTRUCTORS}
31016 //===================== Edit box ========================//
31018 const Editflags: array [ TEditOption ] of Integer = (
31019 not (ES_AUTOHSCROLL or WS_HSCROLL),
31020 not (es_AutoVScroll or WS_VSCROLL),
31021 es_Lowercase, es_Multiline,
31022 es_NoHideSel, es_OemConvert, es_Password, es_Readonly,
31023 es_UpperCase, es_WantReturn, 0, es_Number );
31025 {$IFDEF USE_CONSTRUCTORS}
31026 //[function NewEditbox]
31027 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;
31028 begin
31029 new( Result, CreateEditbox( AParent, Options ) );
31030 end;
31031 //[END NewEditbox]
31032 {$ELSE not_USE_CONSTRUCTORS}
31034 //[FUNCTION NewEditBox]
31035 {$IFDEF ASM_VERSION}
31036 const EditClass: array[0..4] of Char = ( 'E','D','I','T',#0 );
31037 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;
31038 const int_IDC_IBEAM = integer( IDC_IBEAM );
31039 const WS_flags = integer( WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER );
31040 const WS_clear = integer( not(WS_VSCROLL or WS_HSCROLL) );
31042 PUSH EBX
31043 XCHG EBX, EAX // EBX=AParent
31044 PUSH EDX
31045 MOV EAX, ESP
31046 XOR ECX, ECX
31047 MOV CL, 11
31048 MOV EDX, offset [EditFlags]
31049 CALL MakeFlags
31050 XCHG ECX, EAX // ECX = Flags
31051 POP EAX // Options
31052 PUSH EAX
31053 {$IFDEF PARANOIA}
31054 DB $A8, 8
31055 {$ELSE}
31056 TEST AL, 8
31057 {$ENDIF}
31058 JNZ @@1
31059 AND ECX, WS_clear
31060 @@1: OR ECX, WS_flags
31061 PUSH 1
31062 PUSH offset [EditActions]
31063 MOV EDX, offset [EditClass]
31064 XCHG EAX, EBX
31065 CALL _NewControl
31066 XCHG EBX, EAX
31067 { //YS
31068 PUSH int_IDC_IBEAM
31069 PUSH 0
31070 CALL LoadCursor
31071 MOV [EBX].TControl.fCursor, EAX
31073 LEA ECX, [EBX].TControl.fBoundsRect
31074 MOV EDX, [ECX].TRect.Left
31075 ADD EDX, 100
31076 MOV [ECX].TRect.Right, EDX
31077 MOV EDX, [ECX].TRect.Top
31078 ADD EDX, 22
31079 MOV [ECX].TRect.Bottom, EDX
31080 POP EAX // Options
31081 {$IFDEF PARANOIA}
31082 DB $A8, 8
31083 {$ELSE}
31084 TEST AL, 8
31085 {$ENDIF}
31086 MOV DL, $0D
31087 JZ @@2
31088 ADD [ECX].TRect.Right, 100
31089 ADD [ECX].TRect.Bottom, 200 - 22
31090 MOV DL, 1
31091 INC [EBX].TControl.fIgnoreDefault
31092 @@2: //MOV [EBX].TControl.fColor, clWindow
31093 TEST AH, 4
31094 JZ @@3
31095 AND DL, $FE
31096 @@3: MOV [EBX].TControl.fLookTabKeys, DL
31097 XCHG EAX, EBX
31098 POP EBX
31099 end;
31100 {$ELSE ASM_VERSION} //Pascal
31101 function NewEditbox( AParent: PControl; Options: TEditOptions ) : PControl;
31102 var Flags: Integer;
31103 begin
31104 Flags := MakeFlags( @Options, EditFlags );
31105 if not(eoMultiline in Options) then
31106 Flags := Flags and not(WS_HSCROLL or WS_VSCROLL);
31107 Result := _NewControl( AParent, 'EDIT', WS_VISIBLE or WS_CHILD or WS_TABSTOP
31108 or WS_BORDER or Flags, True, @EditActions );
31109 // Result.fCursor := LoadCursor( 0, IDC_IBEAM ); {YS}
31110 with Result.fBoundsRect do
31111 begin
31112 Right := Left + 100;
31113 Bottom := Top + 22;
31114 if eoMultiline in Options then
31115 begin
31116 Right := Right + 100;
31117 Bottom := Top + 200;
31118 Result.fIgnoreDefault := TRUE;
31119 end;
31120 end;
31121 Result.fLookTabKeys := [ tkTab, tkUpDown, tkPageUpPageDn ];
31122 if eoMultiline in Options then
31123 Result.fLookTabKeys := [ tkTab ];
31124 if eoWantTab in Options then
31125 Result.fLookTabKeys := Result.fLookTabKeys - [ tkTab ];
31126 end;
31127 {$ENDIF ASM_VERSION}
31128 //[END NewEditBox]
31130 {$ENDIF USE_CONSTRUCTORS}
31132 //===================== List box ========================//
31134 const ListFlags: array[TListOption] of Integer = (
31135 LBS_DISABLENOScroll, not LBS_ExtendedSel,
31136 LBS_MultiColumn or WS_HSCROLL,
31137 LBS_MultiPLESel,
31138 LBS_NoIntegralHeight, LBS_NoSel, LBS_Sort, LBS_USETabstops,
31139 not LBS_HASSTRINGS, LBS_NODATA, LBS_OWNERDRAWFIXED, LBS_OWNERDRAWVARIABLE );
31141 {$IFDEF USE_CONSTRUCTORS}
31142 //[function NewListbox]
31143 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
31144 begin
31145 new( Result, CreateListbox( AParent, Options ) );
31146 end;
31147 //[END NewListbox]
31148 {$ELSE not_USE_CONSTRUCTORS}
31150 //[FUNCTION NewListbox]
31151 {$IFDEF ASM_VERSION}
31152 const ListBoxClass : array[ 0..7 ] of Char = ( 'L','I','S','T','B','O','X',#0 );
31153 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
31155 PUSH EAX
31156 PUSH EDX
31157 MOV EAX, ESP
31158 MOV EDX, offset[ListFlags]
31159 XOR ECX, ECX
31160 MOV CL, 11
31161 CALL MakeFlags
31162 POP EDX
31163 OR EAX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER or WS_VSCROLL or LBS_NOTIFY
31164 XCHG ECX, EAX
31165 POP EAX
31166 PUSH 1
31167 PUSH offset[ListActions]
31168 MOV EDX, offset[ListBoxClass]
31169 CALL _NewControl
31170 ADD [EAX].TControl.fBoundsRect.Right, 100
31171 ADD [EAX].TControl.fBoundsRect.Bottom, 200-64
31172 MOV [EAX].TControl.fColor, clWindow
31173 MOV [EAX].TControl.fLookTabKeys, 3
31174 end;
31175 {$ELSE ASM_VERSION} //Pascal
31176 function NewListbox( AParent: PControl; Options: TListOptions ): PControl;
31177 var Flags: Integer;
31178 begin
31179 Flags := MakeFlags( @Options, ListFlags );
31180 Result := _NewControl( AParent, 'LISTBOX', WS_VISIBLE or WS_CHILD or WS_TABSTOP
31181 or WS_BORDER or WS_VSCROLL
31182 or LBS_NOTIFY or Flags, True, @ListActions );
31183 with Result.fBoundsRect do
31184 begin
31185 Right := Right + 100;
31186 Bottom := Top + 200;
31187 end;
31188 Result.fColor := clWindow;
31189 Result.fLookTabKeys := [ tkTab, tkLeftRight ];
31190 end;
31191 {$ENDIF ASM_VERSION}
31192 //[END NewListbox]
31194 {$ENDIF USE_CONSTRUCTORS}
31196 //===================== Combo box ========================//
31198 //[FUNCTION ComboboxDropDown]
31199 {$IFNDEF USE_DROPDOWNCOUNT}
31200 {$IFDEF ASM_VERSION}
31201 procedure ComboboxDropDown( Sender: PObj );
31203 PUSH EBX
31204 PUSH ESI
31205 MOV EBX, EAX
31206 CALL TControl.GetItemsCount
31207 CMP EAX, 1
31208 JGE @@1
31209 XOR EAX, EAX
31210 INC EAX
31211 @@1: CMP EAX, 8
31212 JLE @@2
31213 XOR EAX, EAX
31214 MOV AL, 8
31215 @@2: XOR ESI, ESI
31216 PUSH SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_SHOWWINDOW
31217 PUSH ESI
31218 PUSH ESI
31219 PUSH SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_HIDEWINDOW
31220 PUSH EAX
31221 MOV EAX, EBX
31222 CALL TControl.GetHeight
31223 POP ECX
31224 INC ECX
31225 IMUL ECX
31226 INC EAX
31227 INC EAX
31228 PUSH EAX
31229 MOV EAX, EBX
31230 CALL TControl.GetWidth
31231 PUSH EAX
31232 INC ESI
31233 @@3: XOR EDX, EDX
31234 PUSH EDX
31235 PUSH EDX
31236 PUSH EDX
31237 PUSH [EBX].TControl.fHandle
31238 CALL SetWindowPos
31239 DEC ESI
31240 JZ @@3
31241 MOV ECX, [EBX].TControl.fOnDropDown.TMethod.Code
31242 JECXZ @@exit
31243 MOV EAX, [EBX].TControl.fOnDropDown.TMethod.Data
31244 MOV EDX, EBX
31245 CALL ECX
31246 @@exit: POP ESI
31247 POP EBX
31248 end;
31249 {$ELSE ASM_VERSION} //Pascal
31250 procedure ComboboxDropDown( Sender: PObj );
31252 CB: PControl;
31253 IC: Integer;
31254 begin
31255 CB := PControl( Sender );
31256 IC := CB.Count;
31257 if IC > 8 then IC := 8;
31258 if IC < 1 then IC := 1;
31260 SetWindowPos( CB.Handle, 0, 0, 0, CB.Width, CB.Height * (IC + 1) + 2,
31261 SWP_NOMOVE + SWP_NOZORDER + SWP_NOACTIVATE + SWP_NOREDRAW +
31262 SWP_HIDEWINDOW);
31264 SetWindowPos( CB.Handle, 0, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE
31265 + SWP_NOZORDER + SWP_NOACTIVATE
31266 + SWP_NOREDRAW + SWP_SHOWWINDOW);
31268 if assigned( CB.fOnDropDown ) then
31269 CB.fOnDropDown( CB );
31271 end;
31272 {$ENDIF ASM_VERSION}
31273 {$ELSE newcode}
31274 procedure ComboboxDropDown( Sender: PObj );
31276 CB: PControl;
31277 Count: Integer;
31278 DropDownCount: Integer;
31279 ItemHeight: Integer;
31280 begin
31281 CB := PControl(Sender);
31283 Count := CB.Count;
31284 DropDownCount := CB.DropDownCount;
31285 DropDownCount := 8;
31286 if (Count > DropDownCount) then
31287 Count := DropDownCount;
31288 if (Count < 1) then
31289 Count := 1;
31290 ItemHeight := CB.Perform(CB_GETITEMHEIGHT, 0, 0);
31291 SetWindowPos(
31292 CB.Handle, 0, 0, 0, CB.Width, ItemHeight * Count + CB.Height + 2,
31293 SWP_NOMOVE or SWP_NOZORDER or SWP_NOACTIVATE or SWP_NOREDRAW or SWP_HIDEWINDOW);
31294 SetWindowPos(
31295 CB.Handle, 0, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOZORDER or
31296 SWP_NOACTIVATE or SWP_NOREDRAW or SWP_SHOWWINDOW);
31298 if Assigned(CB.fOnDropDown) then
31299 CB.fOnDropDown(CB);
31300 end;
31301 {$ENDIF USE_DROPDOWNCOUNT}
31302 //[END ComboboxDropDown]
31304 //[function WndFuncCombo]
31305 function WndFuncCombo( W: HWnd; Msg: Cardinal; wParam, lParam: Integer )
31306 : Integer; stdcall;
31307 var Combo, Form: PControl;
31308 ParentWnd : HWnd;
31309 MsgStruct: TMsg;
31310 //********************************************************** Added By M.Gerasimov
31312 PrevProc:Pointer;
31314 //********************************************************** Added By M.Gerasimov
31315 begin
31316 Combo := nil;
31318 ParentWnd := GetParent( W );
31319 if ParentWnd <> 0 then
31320 Combo := Pointer( GetProp( ParentWnd, ID_SELF ) );
31322 if Combo <> nil then
31323 begin
31324 MsgStruct.hwnd := Combo.fHandle;
31325 MsgStruct.message := Msg;
31326 MsgStruct.wParam := wParam;
31327 MsgStruct.lParam := lParam;
31328 Form := Combo.ParentForm;
31329 if fGlobalProcKeybd( Combo, MsgStruct, Result ) then Exit;
31330 if W <> Combo.FHandle then
31331 begin
31332 if Assigned( Applet ) and Assigned( Applet.OnMessage ) then
31333 if Applet.OnMessage( MsgStruct, Result ) then Exit;
31334 if (Applet <> Form) and (Form <> nil) then
31335 if Assigned( Form.OnMessage ) then
31336 if Form.OnMessage( MsgStruct, Result ) then Exit;
31337 end;
31338 if //(GetFocus = W) and
31339 (Msg = WM_KEYDOWN) or (Msg = WM_KEYUP) or (Msg = WM_CHAR) then
31340 begin
31341 Result := 0;
31342 if (wParam = VK_TAB) then
31343 begin
31344 case Msg of
31345 WM_KEYDOWN:
31346 if Assigned( Combo.fGotoControl ) and
31347 Combo.fGotoControl( Combo, wParam, FALSE ) then Exit;
31348 else Exit;
31349 end;
31351 else
31352 if (Msg = WM_CHAR) and ((wParam = VK_ESCAPE) or (wParam = VK_RETURN)) then
31353 begin
31354 if Combo.Perform( CB_GETDROPPEDSTATE, 0, 0 ) <> 0 then
31355 begin
31356 Combo.Perform( CB_SHOWDROPDOWN, 0, 0 );
31357 if wParam = VK_ESCAPE then
31358 Combo.Perform( CB_SETCURSEL, Combo.fCurIdxAtDrop, 0 );
31359 Combo.fWndProcKeybd( Combo, MsgStruct, Result );
31360 Exit;
31362 {$IFDEF ESC_CLOSE_DIALOGS}
31363 //---------------------------------Babenko Alexey--------------------------
31364 else
31365 if (wparam = VK_ESCAPE) then
31366 if (combo.ParentForm.ExStyle and WS_EX_DLGMODALFRAME) <> 0 then begin
31367 SendMessage(combo.ParentForm.Handle, WM_CLOSE, 0, 0);
31368 exit;
31369 end;
31370 //---------------------------------Babenko Alexey--------------------------
31371 {$ENDIF}
31372 end;
31373 Combo.fWndProcKeybd( Combo, MsgStruct, Result );
31375 else
31376 if Msg = WM_SETFOCUS then
31377 begin
31378 if Form <> nil then Form.fCurrentControl := Combo;
31379 end;
31380 MsgStruct.hwnd := W;
31381 //********************************************************** Added By M.Gerasimov
31383 PrevProc:=Pointer(GetProp( W, ID_PREVPROC ));
31384 if PrevProc <> Nil then
31385 Result := CallWindowProc( PrevProc , W, MsgStruct.message,
31386 MsgStruct.wParam, MsgStruct.lParam )
31387 else
31388 Result:=0;
31390 //********************************************************** Added By M.Gerasimov
31392 else
31393 Result := DefWindowProc( W, Msg, wParam, lParam );
31394 end;
31396 //[PROCEDURE CreateComboboxWnd]
31397 {$IFDEF ASM_VERSION}
31398 procedure CreateComboboxWnd( Combo: PControl );
31399 //********************************************************** Remarked By M.Gerasimov
31400 //const PrevProcStr: PChar = 'PREV_PROC';
31401 //********************************************************** Remarked By M.Gerasimov
31403 PUSH EDI
31404 PUSH EBX
31405 XCHG EBX, EAX
31406 PUSH GW_CHILD
31407 PUSH [EBX].TControl.fHandle
31408 //XOR EDI, EDI
31409 @@getwindow:
31410 CALL GetWindow
31411 TEST EAX, EAX
31412 JZ @@fin
31413 {TEST EDI, EDI
31414 XCHG EDI, EAX
31415 JZ @@2getnext}
31416 PUSH offset[WndFuncCombo]
31417 PUSH GWL_WNDPROC
31418 PUSH EAX
31419 XCHG EDI, EAX
31420 CALL SetWindowLong
31421 PUSH EAX
31422 //********************************************* By M.Gerasimov
31423 // PUSH [PrevProcStr]
31424 //************************************************************
31425 PUSH offset [ID_PREVPROC] //
31426 //************************************************************
31427 PUSH EDI
31428 CALL SetProp
31429 @@2getnext:
31430 PUSH GW_HWNDNEXT
31431 PUSH EDI
31432 JMP @@getwindow
31433 @@fin: POP EBX
31434 POP EDI
31435 end;
31436 {$ELSE ASM_VERSION} //Pascal
31437 procedure CreateComboboxWnd( Combo: PControl );
31438 var W : HWND;
31439 PrevProc: DWORD;
31440 begin
31441 W := GetWindow( Combo.fHandle, GW_CHILD );
31442 {if W <> 0 then
31443 W := GetWindow( W, GW_HWNDNEXT );}
31444 while W <> 0 do
31445 begin
31446 PrevProc :=
31447 SetWindowLong( W, GWL_WNDPROC, Longint( @WndFuncCombo ) );
31448 //********************************************* By M.Gerasimov
31449 // SetProp( W, 'PREV_PROC', PrevProc );
31450 //************************************************************
31451 SetProp( W, ID_PREVPROC, PrevProc ); //
31452 //************************************************************
31453 W := GetWindow( W, GW_HWNDNEXT );
31454 end;
31455 end;
31456 {$ENDIF ASM_VERSION}
31457 //[END CreateComboboxWnd]
31459 //[procedure RemoveChldPrevProc]
31460 procedure RemoveChldPrevProc( fHandle: HWnd );
31461 var Chld: HWnd;
31462 begin
31463 Chld := GetWindow( fHandle, GW_CHILD );
31464 while Chld <> 0 do
31465 begin
31466 if GetProp( Chld, ID_PREVPROC ) <> 0 then
31467 RemoveProp(Chld, ID_PREVPROC);
31468 Chld := GetWindow( Chld, GW_HWNDNEXT );
31469 end;
31470 end;
31472 //[function WndProcCombo]
31473 function WndProcCombo( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31474 begin
31475 Result := FALSE;
31476 if (Msg.message >= WM_CTLCOLORMSGBOX) and (Msg.message <= WM_CTLCOLORSTATIC) then
31477 begin
31478 Rslt := Sender.Perform( Msg.message + CN_BASE, Msg.wParam, Msg.lParam );
31479 Result := TRUE;
31481 else
31482 if //(Msg.message = CN_CTLCOLOREDIT)
31483 (Msg.message >= CN_CTLCOLORMSGBOX) and (Msg.message <= CN_CTLCOLORSTATIC)
31484 {and not AppletTerminated} then
31485 begin
31486 if Sender.fTransparent then
31487 case Msg.message of
31488 CN_CTLCOLORLISTBOX:
31489 begin
31490 SetBkMode( Msg.wParam, Windows.OPAQUE );
31491 SetBkColor(Msg.WParam, Color2RGB( Sender.fColor ) );
31492 Rslt := Global_GetCtlBrushHandle( Sender );
31493 Result := TRUE;
31494 end;
31495 //********************************************************** Added By M.Gerasimov
31497 WM_DESTROY:
31498 RemoveChldPrevProc( Sender.Handle );
31500 //********************************************************** Added By M.Gerasimov
31501 else
31502 if not Sender.DblBufTopParent.fDblBufPainting then
31503 Sender.Invalidate;
31504 end;
31505 //Result := FALSE;
31507 else
31508 if Msg.message = CM_COMMAND then
31509 begin
31510 case HiWord( Msg.wParam ) of
31511 CBN_DROPDOWN:
31512 begin
31513 Sender.fDropped := True;
31514 Sender.fCurIdxAtDrop := Sender.CurIndex;
31515 Sender.fDropDownProc( Sender );
31516 end;
31517 CBN_CLOSEUP:
31518 begin
31519 Sender.fDropped := False;
31520 if Assigned( Sender.fOnCloseUp ) then Sender.fOnCloseUp( Sender );
31521 end;
31522 CBN_SELCHANGE:
31523 begin
31524 PostMessage( Sender.fHandle, CM_COMMAND, CM_CBN_SELCHANGE shl 16, 0 );
31525 end;
31526 end;
31527 end;
31528 end;
31530 const ComboFlags: array[ TComboOption ] of Integer = (
31531 CBS_DROPDOWNLIST, not CBS_AUTOHScroll,
31532 CBS_DISABLENOSCROLL, CBS_LowerCase, CBS_NoIntegralHeight,
31533 CBS_OemConvert, CBS_Sort, CBS_UpperCase,
31534 CBS_OWNERDRAWFIXED, CBS_OWNERDRAWVARIABLE, CBS_SIMPLE );
31536 {$IFDEF USE_CONSTRUCTORS}
31537 //[function NewCombobox]
31538 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
31539 begin
31540 new( Result, CreateCombobox( AParent, Options ) );
31541 end;
31542 {$ELSE not_USE_CONSTRUCTORS}
31544 //[FUNCTION NewCombobox]
31545 {$IFDEF ASM_VERSION}
31546 const ComboboxClass: array[0..8] of Char = ('C','O','M','B','O','B','O','X',#0 );
31547 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
31549 PUSH EDX
31550 PUSH EAX
31551 PUSH EDX
31552 MOV EAX, ESP
31553 MOV EDX, offset[ComboFlags]
31554 XOR ECX, ECX
31555 MOV CL, 10
31556 CALL MakeFlags
31557 POP EDX
31558 XCHG ECX, EAX
31559 POP EAX
31560 PUSH 1
31561 PUSH offset[ComboActions]
31562 MOV EDX, offset[ComboboxClass]
31563 OR ECX, WS_VISIBLE or WS_CHILD or WS_VSCROLL or CBS_HASSTRINGS or WS_TABSTOP
31564 TEST ECX, CBS_SIMPLE
31565 JNZ @@O
31566 OR ECX, CBS_DROPDOWN
31567 @@O:
31568 CALL _NewControl
31569 MOV [EAX].TControl.fCreateWndExt, offset[CreateComboboxWnd]
31570 MOV [EAX].TControl.fDropDownProc, offset[ComboboxDropDown]
31571 OR byte ptr [EAX].TControl.fClsStyle, CS_DBLCLKS
31572 ADD [EAX].TControl.fBoundsRect.Right, 100-64
31573 ADD [EAX].TControl.fBoundsRect.Bottom, 22-64
31574 //MOV [EAX].TControl.fColor, clWindow
31575 MOV CL, 1
31576 POP EDX
31577 TEST DL, 1
31578 JZ @@exit
31579 MOV CL, 3
31580 @@exit:
31581 MOV [EAX].TControl.fLookTabKeys, CL
31582 PUSH EAX
31583 MOV EDX, offset[ WndProcCombo ]
31584 CALL TControl.AttachProc
31585 POP EAX
31586 end;
31587 {$ELSE ASM_VERSION} //Pascal
31588 function NewCombobox( AParent: PControl; Options: TComboOptions ): PControl;
31589 var Flags: Integer;
31590 begin
31591 Flags := MakeFlags( @Options, ComboFlags );
31592 if not LongBool( Flags and CBS_SIMPLE ) then
31593 Flags := Flags or CBS_DROPDOWN;
31594 Result := _NewControl( AParent, 'COMBOBOX',
31595 WS_VISIBLE
31596 or WS_CHILD
31597 or WS_VSCROLL
31598 or CBS_HASSTRINGS or WS_TABSTOP
31599 or Flags
31600 , True, @ComboActions );
31601 //Result.fCannotDoubleBuf := TRUE;
31602 Result.fCreateWndExt := CreateComboboxWnd;
31603 Result.fDropDownProc := ComboboxDropDown;
31604 Result.fClsStyle := Result.fClsStyle or CS_DBLCLKS;
31605 with Result.fBoundsRect do
31606 begin
31607 Right := Left + 100;
31608 Bottom := Top + 22;
31609 end;
31610 Result.fLookTabKeys := [ tkTab ];
31611 if coReadOnly in Options then
31612 Result.fLookTabKeys := [ tkTab, tkLeftRight ];
31613 Result.AttachProc( @ WndProcCombo );
31614 {$IFDEF USE_DROPDOWNCOUNT}
31615 Result.DropDownCount := 8;
31616 {$ENDIF}
31617 end;
31618 {$ENDIF ASM_VERSION}
31619 //[END NewCombobox]
31621 {$ENDIF USE_CONSTRUCTORS}
31623 //[FUNCTION WndProcResiz]
31624 {$IFDEF ASM_VERSION}
31625 function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31627 PUSH ESI
31628 CMP word ptr [EDX].TMsg.message, WM_SIZE
31629 JNZ @@exit
31631 MOV ESI, [EAX].TControl.fChildren
31632 MOV ECX, [ESI].TList.fCount
31633 JECXZ @@exit
31634 MOV ESI, [ESI].TList.fItems
31635 @@loo: PUSH ECX
31636 LODSD
31637 PUSH EAX
31638 PUSH EAX
31639 PUSH CM_SIZE
31640 PUSH EAX
31641 CALL TControl.Perform
31642 POP ECX
31643 LOOP @@loo
31645 @@exit: XOR EAX, EAX
31646 POP ESI
31647 end;
31648 {$ELSE ASM_VERSION} //Pascal
31649 function WndProcResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31650 var I: Integer;
31651 C: PControl;
31652 begin
31653 if Msg.message = WM_SIZE then
31654 begin
31655 for I:= 0 to Self_.fChildren.fCount - 1 do
31656 begin
31657 C := Self_.fChildren.fItems[ I ];
31658 C.Perform( CM_SIZE, 0, 0 );
31659 end;
31660 end;
31661 Result := False; // don't stop further processing
31662 end;
31663 {$ENDIF ASM_VERSION}
31664 //[END WndProcResiz]
31666 //[FUNCTION WndProcParentResize]
31667 {$IFDEF ASM_VERSION}
31668 function WndProcParentResize( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31670 CMP word ptr [EDX].TMsg.message, CM_SIZE
31671 JNZ @@exit
31672 PUSH 0
31673 PUSH 0
31674 PUSH WM_SIZE
31675 PUSH EAX
31676 CALL TControl.Perform
31677 @@exit: XOR EAX, EAX
31678 end;
31679 {$ELSE ASM_VERSION} //Pascal
31680 function WndProcParentResize(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31681 begin
31682 Result := False;
31683 case Msg.message of
31684 CM_SIZE:
31685 begin
31686 Self_.Perform( WM_SIZE, 0, 0 );
31687 end;
31688 end;
31689 end;
31690 {$ENDIF ASM_VERSION}
31691 //[END WndProcParentResize]
31693 //[procedure InitCommonControlCommonNotify]
31694 procedure InitCommonControlCommonNotify( Ctrl: PControl );
31695 var AParent: PControl;
31696 begin
31697 Ctrl.fIsCommonControl := True;
31698 AParent := Ctrl.Parent;
31699 if AParent <> nil then
31700 begin
31701 Ctrl.AttachProc( WndProcCommonNotify );
31702 AParent.AttachProc( WndProcNotify );
31703 end;
31704 end;
31706 //[procedure InitCommonControlSizeNotify]
31707 procedure InitCommonControlSizeNotify( Ctrl: PControl );
31708 var AParent: PControl;
31709 begin
31710 AParent := Ctrl.Parent;
31711 if AParent <> nil then
31712 begin
31713 Ctrl.AttachProc( WndProcParentResize );
31714 AParent.AttachProc( WndProcResize );
31715 end;
31716 end;
31718 //[function _NewCommonControl]
31719 function _NewCommonControl( AParent: PControl; ClassName: PChar; Style: DWORD;
31720 Ctl3D: Boolean; Actions: PCommandActions ): PControl;
31721 begin
31722 {*************} DoInitCommonControls( ICC_WIN95_CLASSES );
31723 Result := _NewControl( AParent, ClassName, Style, Ctl3D, Actions );
31724 //InitCommonControlSizeNotify( Result );
31725 InitCommonControlCommonNotify( Result );
31726 end;
31728 //==================== Progress bar ======================//
31730 {$IFDEF USE_CONSTRUCTORS}
31731 //[function NewProgressbar]
31732 function NewProgressbar( AParent: PControl ): PControl;
31733 begin
31734 new( Result, CreateProgressbar( AParent ) );
31735 end;
31736 //[END NewProgressbar]
31737 {$ELSE not_USE_CONSTRUCTORS}
31739 //[FUNCTION NewProgressbar]
31740 {$IFDEF ASM_VERSION}
31741 function NewProgressbar( AParent: PControl ): PControl;
31743 PUSH 1
31744 PUSH 0
31745 MOV EDX, offset[Progress_class]
31746 MOV ECX, WS_CHILD or WS_VISIBLE
31747 CALL _NewCommonControl
31748 LEA EDX, [EAX].TControl.fBoundsRect
31749 MOV ECX, [EDX].TRect.Left
31750 ADD ECX, 300
31751 MOV [EDX].TRect.Right, ECX
31752 MOV ECX, [EDX].TRect.Top
31753 ADD ECX, 20
31754 MOV [EDX].TRect.Bottom, ECX
31755 XOR EDX, EDX
31756 MOV [EAX].TControl.fMenu, EDX
31757 MOV [EAX].TControl.fTextColor, clHighlight
31758 MOV [EAX].TControl.fCommandActions.aSetBkColor, PBM_SETBKCOLOR
31759 end;
31760 {$ELSE ASM_VERSION} //Pascal
31761 function NewProgressbar( AParent: PControl ): PControl;
31762 begin
31763 Result := _NewCommonControl( AParent, PROGRESS_CLASS,
31764 WS_CHILD or WS_VISIBLE, True, nil );
31765 with Result.fBoundsRect do
31766 begin
31767 Right := Left + 300;
31768 Bottom := Top + 20;
31769 end;
31770 Result.fMenu := 0;
31771 Result.fTextColor := clHighlight;
31772 Result.fCommandActions.aSetBkColor := PBM_SETBKCOLOR;
31773 end;
31774 {$ENDIF ASM_VERSION}
31775 //[END NewProgressbar]
31777 {$ENDIF USE_CONSTRUCTORS}
31779 {$IFDEF USE_CONSTRUCTORS}
31780 //[function NewProgressbarEx]
31781 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
31782 begin
31783 new( Result, CreateProgressbarEx( AParent, Options ) );
31784 end;
31785 //[END NewProgressbarEx]
31786 {$ELSE not_USE_CONSTRUCTORS}
31788 //[FUNCTION NewProgressbarEx]
31789 {$IFDEF ASM_VERSION}
31790 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
31792 PUSH EDX
31793 CALL NewProgressbar
31794 POP ECX
31795 XOR EDX, EDX
31796 SHR ECX, 1
31797 JNC @@notVert
31798 MOV DL, 4
31799 @@notVert:
31800 SHR ECX, 1
31801 JNC @@notSmooth
31802 INC EDX
31803 @@notSmooth:
31804 OR [EAX].TControl.fStyle, EDX
31805 end;
31806 {$ELSE ASM_VERSION} //Pascal
31807 function NewProgressbarEx( AParent: PControl; Options: TProgressbarOptions ): PControl;
31808 const ProgressBarFlags: array[ TProgressbarOption ] of Integer =
31809 (PBS_VERTICAL, PBS_SMOOTH );
31810 begin
31811 Result := NewProgressbar( AParent );
31812 Result.fStyle := Result.fStyle or DWORD( MakeFlags( @Options, ProgressBarFlags ) );
31813 end;
31814 {$ENDIF ASM_VERSION}
31815 //[END NewProgressbarEx]
31817 {$ENDIF USE_CONSTRUCTORS}
31819 //===================== List view ========================//
31821 //[FUNCTION WndProcNotify]
31822 {$IFDEF ASM_VERSION}
31823 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31825 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
31826 JNE @@ret_false
31827 PUSH ECX
31828 PUSH EDX
31829 PUSH offset[ID_SELF]
31830 MOV ECX, [EDX].TMsg.lParam
31831 PUSH [ECX].TNMHdr.hwndFrom
31832 CALL GetProp
31833 POP EDX
31834 TEST EAX, EAX
31835 JZ @@ret_false_ECX
31836 MOV ECX, [EAX].TControl.fHandle
31837 MOV [EDX].TMsg.hwnd, ECX
31838 POP ECX
31839 JMP TControl.EnumDynHandlers
31840 @@ret_false_ECX:
31841 POP ECX
31842 @@ret_false:
31843 XOR EAX, EAX
31844 end;
31845 {$ELSE ASM_VERSION} //Pascal
31846 function WndProcNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31847 var NMhdr: PNMHdr;
31848 Child: PControl;
31849 begin
31850 Result := False;
31851 if Msg.message = WM_NOTIFY then
31852 begin
31853 NMhdr := Pointer( Msg.lParam );
31854 Child := Pointer( GetProp( NMhdr.hwndFrom, ID_SELF ) );
31855 if Child <> nil then
31856 begin
31857 {if Child = Self_ then
31858 begin
31859 Rslt := Self_.CallDefWndProc( Msg );
31860 Result := TRUE;
31862 else}
31863 begin
31864 Msg.hwnd := Child.fHandle;
31865 Result := EnumDynHandlers( Child, Msg, Rslt );
31866 end;
31867 end;
31868 end;
31869 end;
31870 {$ENDIF ASM_VERSION}
31871 //[END WndProcNotify]
31873 //[FUNCTION WndProcCommonNotify]
31874 {$IFDEF ASM_VERSION}
31875 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31877 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
31878 JNE @@ret_false
31879 PUSH EBX
31880 MOV EBX, [EDX].TMsg.lParam
31881 MOV EDX, [EBX].TNMHdr.code
31883 @@chk_nm_click:
31884 XOR ECX, ECX
31885 CMP EDX, NM_CLICK
31886 JZ @@click
31887 CMP EDX, NM_RCLICK
31888 JNE @@chk_killfocus
31889 INC ECX
31890 @@click:
31891 MOV [EAX].TControl.fRightClick, CL
31893 MOV ECX, [EAX].TControl.fOnClick.TMethod.Code
31894 JECXZ @@fin_false
31895 MOV EDX, [EAX].TControl.fOnClick.TMethod.Data
31896 JMP @@fin_event
31898 @@fin_false:
31899 POP EBX
31900 @@ret_false:
31901 XOR EAX, EAX
31904 @@chk_killfocus:
31905 CMP EDX, NM_KILLFOCUS
31906 JNE @@chk_setfocus
31907 MOV ECX, [EAX].TControl.fOnLeave.TMethod.Code
31908 JECXZ @@fin_false
31909 MOV EDX, [EAX].TControl.fOnLeave.TMethod.Data
31910 JMP @@fin_event
31911 @@chk_setfocus:
31912 CMP EDX, NM_RETURN
31913 JE @@set_focus
31914 CMP EDX, NM_SETFOCUS
31915 JNE @@fin_false
31917 @@set_focus:
31918 MOV ECX, [EAX].TControl.fOnEnter.TMethod.Code
31919 JECXZ @@fin_false
31920 MOV EDX, [EAX].TControl.fOnEnter.TMethod.Data
31922 @@fin_event:
31923 XCHG EAX, EDX
31924 CALL ECX
31925 POP EBX
31926 MOV AL, 1
31927 end;
31928 {$ELSE ASM_VERSION} //Pascal
31929 function WndProcCommonNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
31930 var NMhdr: PNMHdr;
31931 begin
31932 Result := False;
31933 if Msg.message = WM_NOTIFY then
31934 begin
31935 NMHdr := Pointer( Msg.lParam );
31936 case NMHdr.code of
31937 NM_RCLICK,
31938 NM_CLICK: if assigned( Self_.fOnClick ) then
31939 begin
31940 Self_.fRightClick := NMHdr.code=NM_RCLICK;
31941 Self_.fOnClick( Self_ );
31942 Result := TRUE;
31943 end;
31944 NM_KILLFOCUS: if assigned( Self_.fOnLeave ) then
31945 Self_.fOnLeave( Self_ );
31946 NM_RETURN,
31947 NM_SETFOCUS: if assigned( Self_.fOnEnter ) then
31948 Self_.fOnEnter( Self_ );
31949 end;
31950 end;
31951 end;
31952 {$ENDIF ASM_VERSION}
31953 //[END WndProcCommonNotify]
31955 const ListViewStyles: array[ TListViewStyle ] of DWORD = ( LVS_ICON, LVS_SMALLICON,
31956 LVS_LIST, LVS_REPORT, LVS_REPORT or LVS_NOCOLUMNHEADER );
31957 ListViewFlags: array[ TListViewOption ] of Integer = ( LVS_ALIGNLEFT, LVS_AUTOARRANGE,
31958 $400 {LVS_BUTTON}, LVS_EDITLABELS, LVS_NOLABELWRAP,
31959 LVS_NOSCROLL, LVS_NOSORTHEADER,
31960 not LVS_SHOWSELALWAYS, not LVS_SINGLESEL, LVS_SORTASCENDING,
31961 LVS_SORTDESCENDING, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
31962 LVS_OWNERDATA, LVS_OWNERDRAWFIXED );
31964 ListViewExFlags: array[ TListViewOption ] of Integer = ( 0, 0,
31965 0, 0, 0, 0, 0, 0, 0, 0, 0, LVS_EX_GRIDLINES,
31966 LVS_EX_SUBITEMIMAGES, LVS_EX_CHECKBOXES, LVS_EX_TRACKSELECT,
31967 LVS_EX_HEADERDRAGDROP, LVS_EX_FULLROWSELECT, LVS_EX_ONECLICKACTIVATE,
31968 LVS_EX_TWOCLICKACTIVATE, LVS_EX_FLATSB, LVS_EX_REGIONAL,
31969 LVS_EX_INFOTIP, LVS_EX_UNDERLINEHOT, LVS_EX_MULTIWORKAREAS, 0, 0 );
31972 //[FUNCTION ApplyImageLists2Control]
31973 {$IFDEF ASM_VERSION}
31974 procedure ApplyImageLists2Control( Sender: PControl );
31976 PUSHAD
31977 XCHG ESI, EAX
31978 MOVZX ECX, [ESI].TControl.fCommandActions.aSetImgList
31979 JECXZ @@fin
31980 MOV EBP, ECX
31981 XOR EBX, EBX
31982 MOV BL, 32
31983 XOR EDI, EDI
31984 @@loo:
31985 MOV EAX, ESI
31986 MOV EDX, EBX
31987 CALL TControl.GetImgListIdx
31988 TEST EAX, EAX
31989 JZ @@nx
31990 CALL TImageList.GetHandle
31991 PUSH EAX
31992 PUSH EDI
31993 PUSH EBP
31994 PUSH ESI
31995 CALL TControl.Perform
31996 @@nx:
31997 INC EDI
31998 SHR EBX, 1
31999 JZ @@fin
32000 CMP BL, 16
32001 JGE @@loo
32002 XOR EBX, EBX
32003 JMP @@loo
32004 @@fin:
32005 POPAD
32006 end;
32007 {$ELSE ASM_VERSION} //Pascal
32008 procedure ApplyImageLists2Control( Sender: PControl );
32009 var IL: PImageList;
32010 begin
32011 if Sender.fCommandActions.aSetImgList = 0 then Exit;
32012 IL := Sender.ImageListNormal;
32013 if IL <> nil then
32014 Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_NORMAL, IL.Handle );
32015 IL := Sender.ImageListSmall;
32016 if IL <> nil then
32017 Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_SMALL, IL.Handle );
32018 IL := Sender.ImageListState;
32019 if IL <> nil then
32020 Sender.Perform( Sender.fCommandActions.aSetImgList, LVSIL_STATE, IL.Handle );
32021 end;
32022 {$ENDIF ASM_VERSION}
32023 //[END ApplyImageLists2Control]
32025 //[FUNCTION ApplyImageLists2ListView]
32026 {$IFDEF ASM_VERSION}
32027 procedure ApplyImageLists2ListView( Sender: PControl );
32029 PUSHAD
32031 XCHG ESI, EAX
32032 PUSH dword ptr [ESI].TControl.fLVOptions
32033 MOV EAX, ESP
32034 MOV EDX, offset[ListViewFlags]
32035 XOR ECX, ECX
32036 MOV CL, 25
32037 CALL MakeFlags
32038 POP ECX
32039 PUSH ECX
32041 MOV EDX, [ESI].TControl.fStyle
32042 //AND DH, 3
32043 AND DX, not $403F
32044 OR EDX, EAX
32046 MOVZX EAX, [ESI].TControl.fLVStyle
32047 OR EDX, [EAX*4 + offset ListViewStyles]
32049 MOV EAX, ESI
32050 CALL TControl.SetStyle
32052 MOV EAX, ESP
32053 MOV EDX, offset[ListViewExFlags]
32054 XOR ECX, ECX
32055 MOV CL, 23
32056 CALL MakeFlags
32057 POP EDX
32058 PUSH EAX
32059 PUSH $3FFF
32060 PUSH LVM_SETEXTENDEDLISTVIEWSTYLE
32061 PUSH ESI
32062 CALL TControl.Perform
32064 POPAD
32065 CALL ApplyImageLists2Control
32066 end;
32067 {$ELSE ASM_VERSION} //Pascal
32068 procedure ApplyImageLists2ListView( Sender: PControl );
32069 var Flags: DWORD;
32070 begin
32071 Flags := MakeFlags( @Sender.fLVOptions, ListViewFlags );
32072 Sender.Style := Sender.Style and not $403F
32073 or Flags or ListViewStyles[ Sender.fLVStyle ];
32074 Flags := MakeFlags( @Sender.fLVOptions, ListViewExFlags );
32075 Sender.Perform( LVM_SETEXTENDEDLISTVIEWSTYLE, $3FFF, Flags );
32076 ApplyImageLists2Control( Sender );
32077 end;
32078 {$ENDIF ASM_VERSION}
32079 //[END ApplyImageLists2ListView]
32081 {$IFDEF USE_CONSTRUCTORS}
32082 //[function NewListView]
32083 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
32084 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
32085 begin
32086 new( Result, CreateListView( AParent, Style, Options, ImageListSmall,
32087 ImageListNormal, ImageListState ) );
32088 end;
32089 //[END NewListView]
32090 {$ELSE not_USE_CONSTRUCTORS}
32092 //[FUNCTION NewListView]
32093 {$IFDEF ASM_VERSION}
32094 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
32095 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
32097 PUSH EDX
32098 PUSH ECX
32099 MOVZX EDX, DL
32100 MOV ECX, [EDX*4 + offset ListViewStyles]
32101 OR ECX, LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP
32102 MOV EDX, offset[WC_LISTVIEW]
32103 PUSH 1
32104 PUSH offset[ListViewActions]
32105 CALL _NewCommonControl
32107 MOV EDX, ESP
32108 PUSH EAX
32109 XCHG EAX, EDX
32110 MOV EDX, offset ListViewFlags
32111 XOR ECX, ECX
32112 MOV CL, 25
32113 CALL MakeFlags
32114 XCHG EDX, EAX
32115 POP EAX
32116 MOV ECX, [EAX].TControl.fStyle
32117 AND ECX, not LVS_TYPESTYLEMASK
32118 OR EDX, ECX
32119 MOV [EAX].TControl.fStyle, EDX
32121 POP [EAX].TControl.fLVOptions
32122 POP EDX
32123 MOV [EAX].TControl.fLVStyle, DL
32124 MOV [EAX].TControl.fCreateWndExt, offset[ApplyImageLists2ListView]
32125 ADD [EAX].TControl.fBoundsRect.Right, 200-64
32126 ADD [EAX].TControl.fBoundsRect.Bottom, 150-64
32127 MOV ECX, [ImageListState]
32128 XOR EDX, EDX
32129 PUSHAD
32130 CALL TControl.SetImgListIdx
32131 POPAD
32132 MOV ECX, [ImageListSmall]
32133 MOV DL, 16
32134 PUSHAD
32135 CALL TControl.SetImgListIdx
32136 POPAD
32137 MOV ECX, [ImageListNormal]
32138 ADD EDX, EDX
32139 PUSH EAX
32140 CALL TControl.SetImgListIdx
32141 POP EAX
32142 MOV [EAX].TControl.fLVTextBkColor, clWindow
32143 XOR EDX, EDX
32144 //MOV [EAX].TControl.fMargin, EDX
32145 INC EDX
32146 MOV [EAX].TControl.fLookTabKeys, DL
32147 end;
32148 {$ELSE ASM_VERSION} //Pascal
32149 function NewListView( AParent: PControl; Style: TListViewStyle; Options: TListViewOptions;
32150 ImageListSmall, ImageListNormal, ImageListState: PImageList ): PControl;
32151 begin
32152 Result := _NewCommonControl( AParent, WC_LISTVIEW, ListViewStyles[ Style ] or
32153 LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP or WS_CLIPCHILDREN,
32154 True, @ListViewActions );
32156 Result.fLVOptions := Options;
32157 Result.fLVStyle := Style;
32158 Result.fStyle := Result.fStyle and not LVS_TYPESTYLEMASK
32159 or DWORD( MakeFlags( @Options, ListViewFlags ) );
32160 Result.fCreateWndExt := ApplyImageLists2ListView;
32161 with Result.fBoundsRect do
32162 begin
32163 Right := Left + 200;
32164 Bottom := Top + 150;
32165 end;
32166 Result.ImageListSmall := ImageListSmall;
32167 Result.ImageListNormal := ImageListNormal;
32168 Result.ImageListState := ImageListState;
32169 Result.fLVTextBkColor := clWindow;
32170 Result.fLookTabKeys := [ tkTab ];
32171 //Result.fMargin := 0;
32172 end;
32173 {$ENDIF ASM_VERSION}
32174 //[END NewListView]
32176 {$ENDIF USE_CONSTRUCTORS}
32178 //===================== Tree view ========================//
32180 //[FUNCTION WndProcTreeView]
32181 {$IFDEF ASM_VERSION}
32182 function WndProcTreeView( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32183 asm //cmd //opd
32184 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
32185 JNZ @@ret_false
32186 PUSH EBX
32187 XCHG EBX, EAX
32188 MOV EDX, [EDX].TMsg.lParam
32189 LEA EAX, [EBX].TControl.fOnTVBeginDrag
32190 CMP word ptr [EDX].TNMTreeView.hdr.code, NM_RCLICK
32191 JNE @@chk_TVN_BEGINDRAG
32192 PUSH ECX
32193 PUSH ECX
32194 PUSH ESP
32195 CALL GetCursorPos
32196 MOV EAX, EBX
32197 MOV EDX, ESP
32198 MOV ECX, EDX
32199 CALL TControl.Screen2Client
32200 POP EAX
32201 AND EAX, $FFFF
32202 POP EDX
32203 SHL EDX, 16
32204 OR EAX, EDX
32205 PUSH EAX
32206 CALL GetShiftState
32207 PUSH EAX
32208 PUSH WM_RBUTTONUP
32209 PUSH [EBX].TControl.fHandle
32210 CALL PostMessage
32211 JMP @@2fin_false1
32213 @@chk_TVN_BEGINDRAG:
32214 {$IFDEF UNICODE_CTRLS}
32215 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINDRAGW
32216 JZ @@event_drag
32217 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINRDRAGW
32218 JZ @@event_drag
32219 {$ENDIF UNICODE_CTRLS}
32220 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINDRAG
32221 JZ @@event_drag
32222 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINRDRAG
32223 JNZ @@chk_BEGINLABELEDIT
32224 @@event_drag:
32225 MOV EDX, [EDX].TNMTreeView.itemNew.hItem
32226 @@event_call:
32227 MOV ECX, [EAX].TMethod.Code
32228 JECXZ @@2fin_false1
32229 MOV EAX, [EAX].TMethod.Data
32230 XCHG EBX, ECX
32231 XCHG EDX, ECX
32232 CALL EBX
32233 @@2fin_false1: JMP @@fin_false
32234 @@chk_BEGINLABELEDIT:
32235 LEA EAX, [EBX].TControl.fOnTVBeginEdit
32236 {$IFDEF UNICODE_CTRLS}
32237 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINLABELEDITW
32238 JZ @@beginlabeledit
32239 {$ENDIF UNICODE_CTRLS}
32240 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_BEGINLABELEDIT
32241 JNZ @@chk_ITEMEXPANDED //@@chk_DELETEITEM
32242 @@beginlabeledit:
32244 CMP [EBX].TControl.fDragging, 0
32245 JZ @@allow_LABELEDIT
32246 XOR EAX, EAX
32247 INC EAX
32248 MOV [ECX], EAX
32249 JMP @@ret_true
32251 @@allow_LABELEDIT:
32252 PUSH ECX // @Rslt
32254 MOV ECX, [EAX].TMethod.Code
32255 JECXZ @@2fin_false1
32256 PUSH EBX
32257 XCHG EBX, ECX
32258 MOV EDX, [EDX].TTVDispInfo.item.hItem
32259 XCHG EDX, ECX
32260 MOV EAX, [EAX].TMethod.Data
32261 CALL EBX
32262 TEST AL, AL
32263 SETZ AL // Rslt := not event result;
32264 POP EBX
32265 JZ @@ret_EAX
32266 INC [EBX].TControl.fEditing
32267 JMP @@ret_EAX
32269 @@call_EBX:
32270 CALL EBX
32271 @@2fin_false:
32272 JMP @@fin_false
32273 @@chk_ITEMEXPANDED:
32274 LEA EAX, [EBX].TControl.fOnTVExpanded
32275 {$IFDEF UNICODE_CTRLS}
32276 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDEDW
32277 JZ @@itemexpanded
32278 {$ENDIF UNICODE_CTRLS}
32279 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDED
32280 JNZ @@chk_SELCHANGING
32281 @@itemexpanded:
32282 MOV ECX, [EAX].TMethod.Code
32283 JECXZ @@2fin_false
32284 CMP [EDX].TNMTreeView.action, TVE_EXPAND
32285 PUSH ECX
32286 SETZ CL
32287 XCHG ECX, [ESP]
32288 JMP @@event_drag
32289 @@chk_SELCHANGING:
32290 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGING
32291 JNE @@chk_ITEMEXPANDING
32292 XCHG EAX, ECX
32293 MOV ECX, [EBX].TControl.fOnTVSelChanging.TMethod.Code
32294 @@2fin_false2:
32295 JECXZ @@2fin_false
32296 PUSH EAX //@Rslt
32297 PUSH [EDX].TNMTreeView.itemNew.hItem
32298 XCHG ECX, EBX //EBX=OnTVSelChanging.Code ECX=Sender
32299 XCHG ECX, EDX //EDX=Sender ECX=Msg
32300 MOV ECX, [ECX].TNMTreeView.itemOld.hItem
32301 MOV EAX, [EDX].TControl.fOnTVSelChanging.TMethod.Data
32302 JMP @@111
32304 @@chk_ITEMEXPANDING:
32305 {$IFDEF UNICODE_CTRLS}
32306 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDINGW
32307 JZ @@itemexpanding
32308 {$ENDIF UNICODE_CTRLS}
32309 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ITEMEXPANDING
32310 JNE @@chk_ENDLABELEDIT
32311 @@itemexpanding:
32312 XCHG EAX, ECX
32313 MOV ECX, [EBX].TControl.fOnTVExpanding.TMethod.Code
32314 JECXZ @@2fin_false2
32315 PUSH EAX // @Rslt
32316 CMP [EDX].TNMTreeView.action, TVE_EXPAND
32317 PUSH ECX
32318 SETZ CL
32319 XCHG ECX, [ESP]
32320 XCHG ECX, EBX //EBX=OnTVExpanding.Code ECX=Seneder
32321 XCHG EDX, ECX //ECX=Msg EDX=Sender
32322 MOV ECX, [ECX].TNMTreeView.itemNew.hItem //ECX=Item
32323 MOV EAX, [EDX].TControl.fOnTVExpanding.TMethod.Data //EAX=object
32324 @@111:
32325 CALL EBX
32326 @@ret_EAX:
32327 POP EDX //EDX=@Rslt
32328 MOVZX EAX, AL
32329 NEG EAX
32330 MOV [EDX], EAX
32331 @@ret_true:
32332 MOV AL, 1
32333 POP EBX
32335 @@chk_ENDLABELEDIT:
32336 {$IFDEF UNICODE_CTRLS}
32337 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ENDLABELEDITW
32338 JZ @@endlabeledit
32339 {$ENDIF UNICODE_CTRLS}
32340 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_ENDLABELEDIT
32341 JNZ @@chk_SELCHANGED
32342 @@endlabeledit:
32343 MOV [EBX].TControl.fEditing, 0
32344 XCHG EAX, ECX
32345 MOV ECX, [EBX].TControl.fOnTVEndEdit.TMethod.Code
32346 JECXZ @@ret_1
32347 PUSH EAX
32348 PUSH EBX
32349 PUSH 0
32351 XCHG EDX, EBX
32352 MOV EAX, [EBX].TTVDispInfo.item.pszText
32353 PUSH EDX
32354 PUSH ECX
32355 XCHG EAX, EDX
32356 {$IFDEF UNICODE_CTRLS}
32357 CMP [EBX].TNMTreeView.hdr.code, TVN_ENDLABELEDITW
32358 JNZ @@endlabeleditA
32359 CALL TControl.TVGetItemTextW
32360 JMP @@NewTxt_ready
32361 @@endlabeleditA:
32362 {$ENDIF UNICODE_CTRLS}
32363 TEST EDX, EDX
32364 JNZ @@prepare_NewTxt
32365 // NewTxt := [EDX].TControl.TVItemText[ hItem ]
32366 LEA ECX, [ESP + 8]
32367 MOV EDX, [EBX].TTVDispInfo.item.hItem
32368 CALL TControl.TVGetItemText
32369 JMP @@NewTxt_ready
32370 @@prepare_NewTxt:
32371 LEA EAX, [ESP+8]
32372 CALL System.@LStrFromPChar
32373 @@NewTxt_ready:
32374 POP ECX
32375 POP EDX
32376 POP EAX
32377 PUSH EAX
32378 PUSH EAX
32379 MOV EAX, [EDX].TControl.fOnTVEndEdit.TMethod.Data
32380 MOV EBX, [EBX].TTVDispInfo.item.hItem
32381 XCHG ECX, EBX
32382 CALL EBX
32383 XCHG EBX, EAX
32384 CALL RemoveStr
32385 XCHG EAX, EBX
32386 POP EBX
32387 JMP @@ret_EAX
32388 @@ret_1:
32389 INC ECX
32390 MOV [EAX], ECX
32391 JMP @@ret_true
32393 @@chk_SELCHANGED:
32394 {$IFDEF UNICODE_CTRLS}
32395 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGEDW
32396 JZ @@selchanged
32397 {$ENDIF UNICODE_CTRLS}
32398 CMP word ptr [EDX].TNMTreeView.hdr.code, TVN_SELCHANGED
32399 JNZ @@fin_false
32400 @@selchanged:
32401 XCHG EAX, EBX
32402 CALL TControl.DoSelChange
32404 @@fin_false:
32405 POP EBX
32406 @@ret_false:
32407 XOR EAX, EAX
32408 end;
32409 {$ELSE ASM_VERSION} //Pascal
32410 function WndProcTreeView( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32411 var NM: PNMTreeView;
32412 DI: PTVDispInfo;
32413 P: TPoint;
32414 S: String;
32415 begin
32416 if Msg.message = WM_NOTIFY then
32417 begin
32418 NM := Pointer( Msg.lParam );
32419 case NM.hdr.code of
32420 NM_RCLICK:
32421 begin
32422 GetCursorPos( P );
32423 P := Self_.Screen2Client( P );
32424 PostMessage( Self_.fHandle, WM_RBUTTONUP, MK_RBUTTON or GetShiftState,
32425 (P.x and $FFFF) or (P.y shl 16) );
32426 end;
32428 {$IFDEF UNICODE_CTRLS}
32429 TVN_BEGINDRAGW, TVN_BEGINRDRAGW,
32430 {$ENDIF} TVN_BEGINDRAG, TVN_BEGINRDRAG:
32431 if Assigned( Self_.fOnTVBeginDrag ) then
32432 Self_.fOnTVBeginDrag( Self_, NM.itemNew.hItem );
32433 TVN_BEGINLABELEDIT {$IFDEF UNICODE_CTRLS}, TVN_BEGINLABELEDITW{$ENDIF}:
32434 begin
32435 if Self_.fDragging then
32436 begin
32437 Rslt := 1; // do not allow edit while dragging
32438 Result := TRUE;
32439 Exit;
32440 end;
32441 DI := Pointer( NM );
32442 if Assigned( Self_.fOnTVBeginEdit ) then
32443 begin
32444 Rslt := Integer( not Self_.fOnTVBeginEdit( Self_, DI.item.hItem ) );
32445 if Rslt = 0 then
32446 Self_.fEditing := TRUE;
32447 Result := TRUE;
32448 Exit;
32449 end;
32450 end;
32451 TVN_ENDLABELEDIT {$IFDEF UNICODE_CTRLS}, TVN_ENDLABELEDITW {$ENDIF}:
32452 begin
32453 DI := Pointer( NM );
32454 if Assigned( Self_.fOnTVEndEdit ) then
32455 begin
32456 S := DI.item.pszText;
32457 if DI.item.pszText = nil then
32458 begin
32459 {$IFDEF UNICODE_CTRLS}
32460 if NM.hdr.code = TVN_ENDLABELEDITW then
32461 S := Self_.TVItemTextW[ DI.item.hItem ]
32462 else
32463 {$ENDIF UNICODE_CTRLS}
32464 S := Self_.TVItemText[ DI.item.hItem ];
32465 end;
32466 if Self_.fOnTVEndEdit( Self_, DI.item.hItem, S )
32467 then Rslt := 1
32468 else Rslt := 0;
32470 else
32471 Rslt := 1;
32472 Self_.fEditing := FALSE;
32473 Result := True;
32474 Exit;
32475 end;
32476 TVN_ITEMEXPANDING {$IFDEF UNICODE_CTRLS}, TVN_ITEMEXPANDINGW {$ENDIF}:
32477 begin
32478 if Assigned( Self_.fOnTVExpanding ) then
32479 begin
32480 Rslt := Integer( not Self_.fOnTVExpanding( Self_, NM.itemNew.hItem,
32481 NM.action = TVE_EXPAND ) );
32482 Result := TRUE;
32483 Exit;
32484 end;
32485 end;
32486 TVN_ITEMEXPANDED {$IFDEF UNICODE_CTRLS}, TVN_ITEMEXPANDEDW {$ENDIF}:
32487 if Assigned( Self_.fOnTVExpanded ) then
32488 Self_.fOnTVExpanded( Self_, NM.itemNew.hItem, NM.action=TVE_EXPAND );
32489 {TVN_DELETEITEM:
32490 if Assigned( Self_.fOnTVDelete ) then
32491 Self_.fOnTVDelete( Self_, NM.itemOld.hItem );}
32492 //------------------ by Sergey Shisminzev:
32493 TVN_SELCHANGING {$IFDEF UNICODE_CTRLS}, TVN_SELCHANGINGW {$ENDIF}:
32494 begin
32495 if Assigned( Self_.fOnTVSelChanging ) then
32496 begin
32497 Rslt := Integer( not Self_.fOnTVSelChanging( Self_, NM.itemOld.hItem, NM.itemNew.hItem ) );
32498 Result := TRUE;
32499 Exit;
32500 end;
32501 end;
32502 //----------------------------------------
32503 TVN_SELCHANGED {$IFDEF UNICODE_CTRLS}, TVN_SELCHANGEDW {$ENDIF}:
32504 Self_.DoSelChange;
32505 end;
32506 end;
32507 Result := False;
32508 end;
32509 {$ENDIF ASM_VERSION}
32510 //[END WndProcTreeView]
32512 //[function ProcTVDeleteItem]
32513 function ProcTVDeleteItem( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32514 var NM: PNMTreeView;
32515 begin
32516 if Msg.message = WM_NOTIFY then
32517 begin
32518 NM := Pointer( Msg.lParam );
32519 case NM.hdr.code of
32520 TVN_DELETEITEM:
32521 if Assigned( Self_.fOnTVDelete ) then
32522 Self_.fOnTVDelete( Self_, NM.itemOld.hItem );
32523 end;
32524 end;
32525 Result := FALSE;
32526 end;
32528 //[procedure ClearTreeView]
32529 procedure ClearTreeView( TV: PControl );
32530 begin
32531 TV.TVDelete( TVI_ROOT );
32532 end;
32534 const
32535 TreeViewFlags: array[ TTreeViewOption ] of Integer = ( not TVS_HASLINES, TVS_LINESATROOT,
32536 not TVS_HASBUTTONS, TVS_EDITLABELS, not TVS_SHOWSELALWAYS,
32537 not TVS_DISABLEDRAGDROP, TVS_NOTOOLTIPS, TVS_CHECKBOXES,
32538 TVS_TRACKSELECT, TVS_SINGLEEXPAND, TVS_INFOTIP,
32539 TVS_FULLROWSELECT, TVS_NOSCROLL, TVS_NONEVENHEIGHT );
32541 {$IFDEF USE_CONSTRUCTORS}
32542 //[function NewTreeView]
32543 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
32544 ImgListNormal, ImgListState: PImageList ): PControl;
32545 begin
32546 new( Result, CreateTreeView( AParent, Options, ImgListNormal, ImgListState ) );
32547 end;
32548 {$ELSE not_USE_CONSTRUCTORS}
32550 //[FUNCTION NewTreeView]
32551 {$IFDEF ASM_VERSION}
32552 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
32553 ImgListNormal, ImgListState: PImageList ): PControl;
32554 asm //cmd //opd
32555 PUSH EBX
32556 PUSH ECX
32557 PUSH EAX
32558 PUSH EDX
32559 MOV EAX, ESP
32560 MOV EDX, offset[TreeViewFlags]
32561 XOR ECX, ECX
32562 MOV CL, 13
32563 CALL MakeFlags
32564 POP EDX
32565 OR EAX, WS_VISIBLE or WS_CHILD or WS_TABSTOP
32566 XCHG ECX, EAX
32567 POP EAX
32568 MOV EDX, offset[WC_TREEVIEW]
32569 PUSH 1
32570 PUSH offset[TreeViewActions]
32571 CALL _NewCommonControl
32572 MOV EBX, EAX
32573 MOV [EBX].TControl.fCreateWndExt, offset[ApplyImageLists2Control]
32574 MOV [EBX].TControl.fColor, clWindow
32575 MOV EDX, offset[WndProcTreeView]
32576 CALL TControl.AttachProc
32577 ADD [EBX].TControl.fBoundsRect.Right, 150-64
32578 ADD [EBX].TControl.fBoundsRect.Bottom, 200-64
32579 MOV EAX, EBX
32580 XOR EDX, EDX
32581 MOV DL, 32
32582 POP ECX // ImageListNormal
32583 CALL TControl.SetImgListIdx
32584 MOV EAX, EBX
32585 XOR EDX, EDX
32586 MOV ECX, [ImgListState]
32587 CALL TControl.SetImgListIdx
32588 MOV byte ptr [EBX].TControl.fLookTabKeys, 1
32589 XCHG EAX, EBX
32590 POP EBX
32591 end;
32592 {$ELSE ASM_VERSION} //Pascal
32593 function NewTreeView( AParent: PControl; Options: TTreeViewOptions;
32594 ImgListNormal, ImgListState: PImageList ): PControl;
32595 var Flags: Integer;
32596 begin
32597 Flags := MakeFlags( @Options, TreeViewFlags );
32598 Result := _NewCommonControl( AParent, WC_TREEVIEW, Flags or WS_VISIBLE or
32599 WS_CHILD or WS_TABSTOP, True, @TreeViewActions );
32600 Result.fCreateWndExt := ApplyImageLists2Control;
32601 Result.fColor := clWindow;
32602 Result.AttachProc( WndProcTreeView );
32603 with Result.fBoundsRect do
32604 begin
32605 Right := Left + 150;
32606 Bottom := Top + 200;
32607 end;
32608 Result.ImageListNormal := ImgListNormal;
32609 Result.ImageListState := ImgListState;
32610 //Result.fLVTextBkColor := clWindow;
32611 Result.fLookTabKeys := [ tkTab ];
32612 end;
32613 {$ENDIF ASM_VERSION}
32614 //[END NewTreeView]
32616 {$ENDIF USE_CONSTRUCTORS}
32618 //===================== Tab Control ========================//
32620 //[FUNCTION WndProcTabControl]
32621 {$IFDEF ASM_VERSION}
32622 function WndProcTabControl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32623 asm //cmd //opd
32624 PUSH EBP
32625 PUSH EBX
32626 PUSH ESI
32627 PUSH EDI
32628 MOV EBX, EAX
32629 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
32630 JNZ @@chk_WM_SIZE
32631 MOV EDX, [EDX].TMsg.lParam
32632 CMP word ptr [EDX].TNMHdr.code, TCN_SELCHANGE
32633 JNZ @@ret_false
32635 CALL TControl.GetCurIndex
32636 XCHG EDI, EAX
32637 CMP EDI, [EBX].TControl.fCurIndex
32638 PUSHFD // WasActive = ZF
32640 MOV [EBX].TControl.FCurIndex, EDI
32642 MOV EAX, EBX
32643 CALL TControl.GetItemsCount
32644 XCHG ESI, EAX // ESI := Self_.Count
32646 @@loo: DEC ESI
32647 JS @@e_loo
32648 MOV EDX, ESI
32649 MOV EAX, EBX
32650 CALL TControl.GetPages
32652 CMP ESI, EDI
32653 PUSH EAX
32654 SETZ DL
32655 CALL TControl.SetVisible
32656 POP EAX
32657 CMP ESI, EDI
32658 JNE @@nx_loo
32659 CALL TControl.BringToFront
32660 @@nx_loo:
32661 JMP @@loo
32662 @@e_loo:
32664 MOV EAX, EBX
32665 CALL TControl.ParentForm
32666 TEST EAX, EAX
32667 JZ @@1
32668 MOV ECX, [EAX].TControl.fCurrentControl
32669 JECXZ @@1
32670 MOV EAX, EBX
32671 MOV DL, 1
32672 CALL TControl.SetFocused
32673 MOV EAX, EBX
32674 CALL TControl.Invalidate
32675 TEST byte ptr [EBX].TControl.fStyle+1, $10
32676 JNZ @@1
32677 MOV EAX, EBX
32678 XOR EDX, EDX
32679 MOV DL, VK_TAB
32680 CALL TControl.GotoControl
32681 @@1: }
32682 POPFD
32683 JZ @@ret_false
32685 MOV ECX, [EBX].TControl.fOnSelChange.TMethod.Code
32686 JECXZ @@ret_false
32687 MOV EDX, EBX
32688 MOV EAX, [EBX].TControl.fOnSelChange.TMethod.Data
32689 CALL ECX
32690 JMP @@ret_false
32691 @@chk_WM_SIZE:
32692 CMP word ptr [EDX].TMsg.message, WM_SIZE
32693 JNE @@ret_false
32694 ADD ESP, -16
32695 PUSH ESP
32696 PUSH [EBX].TControl.fHandle
32697 CALL Windows.GetClientRect
32698 PUSH ESP
32699 PUSH 0
32700 PUSH TCM_ADJUSTRECT
32701 PUSH EBX
32702 CALL TControl.Perform
32703 MOV EAX, EBX
32704 CALL TControl.GetItemsCount
32705 XCHG ESI, EAX
32706 @@loo2:
32707 DEC ESI
32708 JS @@e_loo2
32709 MOV EDX, ESI
32710 MOV EAX, EBX
32711 CALL TControl.GetPages
32712 MOV EDX, ESP
32713 CALL TControl.SetBoundsRect
32714 JMP @@loo2
32715 @@e_loo2:
32716 ADD ESP, 16
32717 @@ret_false:
32718 XOR EAX, EAX
32719 POP EDI
32720 POP ESI
32721 POP EBX
32722 POP EBP
32723 end;
32724 {$ELSE ASM_VERSION} //Pascal
32725 function WndProcTabControl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
32726 var Hdr: PNMHdr;
32727 Page: PControl;
32728 I, A: Integer;
32729 R: TRect;
32730 //Form: PControl;
32731 WasActive: Boolean;
32732 begin
32733 case Msg.message of
32734 WM_NOTIFY:
32735 begin
32736 Hdr := Pointer( Msg.lParam );
32737 case Hdr.code of
32738 TCN_SELCHANGE:
32739 begin
32740 A := Self_.Perform( TCM_GETCURSEL, 0, 0 );
32741 WasActive := Self_.fCurIndex = A;
32742 Self_.fCurIndex := A;
32743 for I := 0 to Self_.Count - 1 do
32744 begin
32745 Page := Self_.Pages[ I ];
32746 Page.Visible := A = I;
32747 if A = I then
32748 Page.BringToFront;
32749 end;
32750 {Form := Self_.ParentForm;
32751 if Form <> nil then
32752 begin
32753 if Form.fCurrentControl <> nil then
32754 begin
32755 Self_.Focused := True;
32756 Self_.Invalidate;
32757 if not Longbool( Self_.fStyle and TCS_FOCUSONBUTTONDOWN ) then
32758 Self_.GotoControl( VK_TAB );
32759 end;
32760 end;}
32761 if not WasActive then
32762 if Assigned( Self_.fOnSelChange ) then
32763 Self_.fOnSelChange( Self_ );
32764 //Result := True;
32765 end;
32766 end;
32767 end;
32768 WM_SIZE:
32769 begin
32770 GetClientRect( Self_.fHandle, R );
32771 Self_.Perform( TCM_ADJUSTRECT, 0, Integer( @R ) );
32772 for I := 0 to Self_.Count - 1 do
32773 begin
32774 Page := Self_.Pages[ I ];
32775 Page.BoundsRect := R;
32776 end;
32777 end;
32778 end;
32779 Result := False;
32780 end;
32781 {$ENDIF ASM_VERSION}
32782 //[END WndProcTabControl]
32784 const TabControlFlags: array[ TTabControlOption ] of Integer = ( TCS_BUTTONS,
32785 TCS_FIXEDWIDTH, not TCS_FOCUSNEVER,
32786 TCS_FIXEDWIDTH or TCS_FORCEICONLEFT, TCS_FIXEDWIDTH or TCS_FORCELABELLEFT,
32787 TCS_MULTILINE, TCS_MULTISELECT, TCS_RIGHTJUSTIFY, TCS_SCROLLOPPOSITE,
32788 TCS_BOTTOM, TCS_VERTICAL, TCS_FLATBUTTONS, TCS_HOTTRACK, 0, TCS_OWNERDRAWFIXED );
32790 {$IFDEF USE_CONSTRUCTORS}
32791 //[function NewTabControl]
32792 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
32793 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
32794 begin
32795 new( Result, CreateTabControl( AParent, Tabs, Options, ImgList, ImgList1stIdx ) );
32796 end;
32797 //[END NewTabControl]
32798 {$ELSE not_USE_CONSTRUCTORS}
32800 //[FUNCTION NewTabControl]
32801 {$IFDEF ASM_VERSION}
32802 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
32803 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
32804 asm //cmd //opd
32805 PUSH EBX
32806 PUSH ESI
32807 PUSH EDI
32808 XCHG EBX, EAX
32809 PUSH EDX
32810 PUSH ECX
32811 LEA EAX, [Options]
32812 MOV EDX, offset[TabControlFlags]
32813 XOR ECX, ECX
32814 MOV CL, 13
32815 CALL MakeFlags
32816 TEST byte ptr [Options], 4
32817 JZ @@0
32818 OR EAX, WS_TABSTOP or TCS_FOCUSONBUTTONDOWN
32819 @@0: OR EAX, WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_VISIBLE
32820 XCHG ECX, EAX
32821 XCHG EAX, EBX
32822 MOV EDX, offset[WC_TABCONTROL]
32823 PUSH 1
32824 PUSH offset[TabControlActions]
32825 CALL _NewCommonControl
32826 MOV EBX, EAX
32827 TEST [Options], 2 shl (tcoBorder - 1)
32828 JNZ @@borderfixed
32829 AND [EBX].TControl.fExStyle, not WS_EX_CLIENTEDGE
32830 @@borderfixed:
32831 MOV EDX, offset[WndProcTabControl]
32832 CALL TControl.AttachProc
32833 ADD [EBX].TControl.fBoundsRect.Right, 100-64
32834 ADD [EBX].TControl.fBoundsRect.Bottom, 100-64
32835 MOV ECX, [ImgList]
32836 JECXZ @@2
32837 XCHG EAX, ECX
32838 CALL TImageList.GetHandle
32839 PUSH EAX
32840 PUSH 0
32841 PUSH TCM_SETIMAGELIST
32842 PUSH EBX
32843 CALL TControl.Perform
32844 @@2:
32845 POP EDI // EDI = High(Tabs)
32846 POP ESI // ESI = Tabs
32847 XOR EDX, EDX // EBP := 0 (=I)
32848 MOV EAX, [ImgList1stIdx] //(=II)
32849 @@loop:
32850 CMP EDX, EDI
32851 JG @@e_loop
32852 PUSH EAX
32853 PUSH EDX
32854 PUSH EAX
32855 LODSD
32856 XCHG ECX, EAX
32857 MOV EAX, EBX
32858 CALL TControl.TC_Insert
32859 POP EDX
32860 POP EAX
32861 INC EAX
32862 INC EDX
32863 JMP @@loop
32864 @@e_loop:
32865 MOV byte ptr [EBX].TControl.fLookTabKeys, 1
32866 XCHG EAX, EBX
32867 POP EDI
32868 POP ESI
32869 POP EBX
32870 end;
32871 {$ELSE ASM_VERSION} //Pascal
32872 function NewTabControl( AParent: PControl; Tabs: array of String; Options: TTabControlOptions;
32873 ImgList: PImageList; ImgList1stIdx: Integer ): PControl;
32874 var I, II : Integer;
32875 Flags: Integer;
32876 begin
32877 Flags := MakeFlags( @Options, TabControlFlags );
32878 if tcoFocusTabs in Options then
32879 Flags := Flags or (WS_TABSTOP or TCS_FOCUSONBUTTONDOWN);
32880 Result := _NewCommonControl( AParent, WC_TABCONTROL,
32881 Flags or (WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or WS_VISIBLE), True,
32882 @TabControlActions );
32883 //***
32884 if not( tcoBorder in Options ) then
32885 begin
32886 Result.fExStyle := Result.fExStyle and not WS_EX_CLIENTEDGE;
32887 end;
32888 Result.AttachProc( WndProcTabControl );
32889 with Result.fBoundsRect do
32890 begin
32891 Right := Left + 100;
32892 Bottom := Top + 100;
32893 end;
32894 if ImgList <> nil then
32895 Result.Perform( TCM_SETIMAGELIST, 0, ImgList.Handle );
32896 II := ImgList1stIdx;
32897 for I := 0 to High( Tabs ) do
32898 begin
32899 Result.TC_Insert( I, Tabs[ I ], II );
32900 Inc( II );
32901 end;
32902 Result.fLookTabKeys := [ tkTab ];
32903 end;
32904 {$ENDIF ASM_VERSION}
32905 //[END NewTabControl]
32907 {$ENDIF USE_CONSTRUCTORS}
32909 //===================== Tool bar ========================//
32911 //[FUNCTION WndProcToolbarCtr]
32912 {$IFDEF ASM_noVERSION} //TTN_NEEDTEXTW
32913 function WndProcToolbarCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
32915 CMP word ptr [EDX].TMsg.message, WM_WINDOWPOSCHANGED
32916 JNE @@chk_CM_COMMAND
32917 MOV dword ptr [ECX], 0 // Rslt := 0
32918 MOV ECX, [EAX].TControl.fOnResize.TMethod.Code
32919 JECXZ @@ret_true
32920 XCHG EDX, EAX // Sender := Self_
32921 MOV EAX, [EDX].TControl.fOnResize.TMethod.Data
32922 CALL ECX // Self_.fOnResize
32923 @@ret_true:
32924 MOV AL, 1 // Result := TRUE
32926 @@chk_CM_COMMAND:
32927 CMP word ptr [EDX].TMsg.message, CM_COMMAND
32928 JNE @@chk_WM_NOTIFY
32929 MOVZX ECX, word ptr [EDX].TMsg.wParam
32930 MOV [EAX].TControl.fCurItem, ECX
32931 PUSH EAX
32932 PUSH 0
32933 PUSH ECX
32934 PUSH TB_COMMANDTOINDEX
32935 PUSH EAX
32936 CALL TControl.Perform
32937 PUSH EAX
32939 PUSH VK_RETURN
32940 CALL GetKeyState
32941 TEST EAX, EAX
32942 SETL DL
32943 POP ECX
32944 POP EAX
32945 MOV [EAX].TControl.fCurIndex, ECX
32946 MOV [EAX].TControl.fRightClick, DL
32947 @@ret_false:
32948 XOR EAX, EAX
32951 @@chk_WM_NOTIFY:
32952 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
32953 JNE @@ret_false
32954 MOV EDX, [EDX].TMsg.lParam
32955 MOV ECX, [EDX].TTooltipText.hdr.code
32956 CMP ECX, TTN_NEEDTEXT
32957 JNE @@chk_NM_RCLICK
32958 PUSH EAX
32959 PUSH EDX
32960 MOV EDX, [EDX].TTooltipText.hdr.idFrom
32961 MOV ECX, [EAX].TControl.fTBttCmd
32962 OR EAX, -1
32963 JECXZ @@idxReady
32964 XCHG EAX, ECX
32965 CALL TList.IndexOf
32966 @@idxReady: // EAX = -1 or index of button tooltip
32967 TEST EAX, EAX
32968 POP EDX
32969 LEA EDX, [EDX].TTooltipText.szText
32970 MOV byte ptr [EDX], 0
32971 POP ECX
32972 JL @@ret_true
32973 MOV ECX, [ECX].TControl.fTBttTxt
32974 MOV ECX, [ECX].TStrList.fList
32975 MOV ECX, [ECX].TList.fItems
32976 MOV EAX, [ECX+EAX*4]
32977 XCHG EAX, EDX
32978 XOR ECX, ECX
32979 MOV CL, 79
32980 CALL StrLCopy
32981 JMP @@ret_true
32982 @@chk_NM_RCLICK:
32983 CMP ECX, NM_RCLICK
32984 JNE @@chk_NM_CLICK
32985 OR [EAX].TControl.fRightClick, 1
32986 MOV ECX, [EDX].TNMMouse.dwItemSpec
32987 MOV [EAX].TControl.fCurItem, -1
32988 PUSH EAX
32989 PUSH 0
32990 PUSH ECX
32991 PUSH TB_COMMANDTOINDEX
32992 PUSH EAX
32993 CALL TControl.Perform
32994 POP EDX
32995 MOV [EDX].TControl.fCurIndex, EAX
32996 XOR EAX, EAX
32998 @@chk_NM_CLICK:
32999 CMP ECX, NM_CLICK
33000 JNE @@chk_TBN_DROPDOWN
33001 MOV [EAX].TControl.fRightClick, 0
33002 OR [EAX].TControl.fCurItem, -1
33003 OR [EAX].TControl.fCurIndex, -1
33004 CMP [EDX].TTBNotify.iItem, -1
33005 SETNZ AL
33007 @@chk_TBN_DROPDOWN:
33008 CMP ECX, TBN_DROPDOWN
33009 JNE @@ret_false
33010 MOV EDX, [EDX].TTBNotify.iItem
33011 MOV [EAX].TControl.fCurItem, EDX
33012 PUSH EAX
33013 CALL TControl.TBItem2Index
33014 POP EDX
33015 MOV [EDX].TControl.fCurIndex, EAX
33016 MOV ECX, [EDX].TControl.fOnDropDown.TMethod.Code
33017 JECXZ @@ret_z
33018 MOV EAX, [EDX].TControl.fOnDropDown.TMethod.Data
33019 CALL ECX
33020 @@ret_z:
33021 XOR EAX, EAX
33022 end;
33023 {$ELSE ASM_VERSION} //Pascal
33024 function WndProcToolbarCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
33025 var lpttt: PTooltipText;
33026 idBtn, Idx: Integer;
33027 var Notify: PTBNotify;
33028 Mouse: PNMMouse;
33029 {$IFNDEF _FPC}
33030 {$IFNDEF _D2}
33031 var Wstr: WideString;
33032 {$ENDIF _D2}
33033 {$ENDIF _FPC}
33034 begin
33035 Result := False;
33036 if Msg.message = WM_WINDOWPOSCHANGED then
33037 begin
33038 if Assigned( Self_.fOnResize ) then
33039 Self_.fOnResize( Self_ );
33040 Result := TRUE;
33041 Rslt := 0;
33043 else if Msg.message = CM_COMMAND then
33044 begin
33045 Self_.fCurItem := Loword( Msg.wParam );
33046 Self_.fCurIndex := Self_.Perform( TB_COMMANDTOINDEX, Loword( Msg.wParam ), 0 );
33047 Self_.fRightClick := GetKeyState( VK_RBUTTON ) < 0;
33049 else if Msg.message = WM_NOTIFY then
33050 begin
33051 lpttt := Pointer( Msg.lParam );
33052 Notify := Pointer( Msg.lParam );
33053 case lpttt.hdr.code of
33054 TTN_NEEDTEXT:
33055 begin
33056 Result := True;
33057 idBtn := lpttt.hdr.idFrom;
33058 Idx := -1;
33059 if Self_.fTBttCmd <> nil then
33060 Idx := Self_.fTBttCmd.IndexOf( Pointer( idBtn ) );
33061 lpttt.szText[ 0 ] := #0;
33062 if Idx >= 0 then
33063 StrLCopy( lpttt.szText, Self_.fTBttTxt.fList.fItems[ Idx ], 79 );
33064 Exit;
33065 end;
33066 // for Windows XP
33067 {$IFNDEF _FPC}
33068 {$IFNDEF _D2}
33069 TTN_NEEDTEXTW:
33070 begin
33071 Result := True;
33072 idBtn := lpttt.hdr.idFrom;
33073 Idx := -1;
33074 if Self_.fTBttCmd <> nil then
33075 Idx := Self_.fTBttCmd.IndexOf( Pointer( idBtn ) );
33076 FillChar( lpttt.szText[ 0 ], 160, 0 );
33077 if Idx >= 0 then
33078 begin
33079 WStr := Self_.fTBttTxt.Items[ Idx ];
33080 if WStr <> '' then
33081 Move( Wstr[ 1 ], lpttt.szText, Min( 158, (Length( WStr ) + 1) * 2 ) );
33082 end;
33083 Exit;
33084 end;
33085 {$ENDIF _D2}
33086 {$ENDIF _FPC}
33087 NM_RCLICK:
33088 begin
33089 Mouse := Pointer( Msg.lParam );
33090 Self_.fCurItem := Mouse.dwItemSpec;
33091 Self_.fCurIndex := Self_.Perform( TB_COMMANDTOINDEX, Mouse.dwItemSpec, 0 );
33092 Self_.fRightClick := GetKeyState( VK_RBUTTON ) < 0;
33093 Self_.fRightClick := True;
33094 end;
33095 NM_CLICK:
33096 begin
33097 Self_.fCurItem := -1; // return CurItem = -1
33098 Self_.fCurIndex := -1;
33099 Self_.fRightClick := False;
33100 Result := Notify.iItem <> -1;
33101 // do not handle - if it will be handled in WM_COMMAND
33102 Exit;
33103 end;
33104 TBN_DROPDOWN:
33105 begin
33106 Self_.fCurItem := Notify.iItem;
33107 Self_.fCurIndex := Self_.TBItem2Index( Self_.fCurItem );
33108 if assigned( Self_.fOnDropDown ) then
33109 Self_.fOnDropDown( Self_ );
33110 end;
33111 end;
33112 end;
33113 end;
33114 {$ENDIF ASM_VERSION}
33115 //[END WndProcToolbarCtr]
33117 const ToolbarAligns: array[ TControlAlign ] of DWORD =
33118 ( 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,
33119 CCS_TOP );
33120 ToolbarOptions: array[ TToolbarOption ] of Integer = ( TBSTYLE_LIST, not TBSTYLE_LIST,
33121 TBSTYLE_FLAT, TBSTYLE_TRANSPARENT, TBSTYLE_WRAPABLE, CCS_NODIVIDER, 0 );
33123 {$IFDEF USE_CONSTRUCTORS}
33124 //[function NewToolbar]
33125 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
33126 Bitmap: HBitmap; Buttons: array of PChar;
33127 BtnImgIdxArray: array of Integer ) : PControl;
33128 begin
33129 new( Result, CreateToolbar( AParent, Align, Options, Bitmap, Buttons, BtnImgIdxArray ) );
33130 end;
33131 //[END NewToolbar]
33132 {$ELSE not_USE_CONSTRUCTORS}
33134 //[FUNCTION NewToolbar]
33135 {$IFDEF ASM_VERSION}
33136 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
33137 Bitmap: HBitmap; Buttons: array of PChar;
33138 BtnImgIdxArray: array of Integer ) : PControl;
33139 const szTBButton = Sizeof( TTBButton );
33140 Option3DBorder = 1 shl Ord( tbo3DBorder );
33142 MOVZX EDX, DL
33143 PUSH EDX // Align
33144 PUSH EAX // AParent
33146 XOR EAX, EAX
33147 TEST CL, Option3DBorder
33148 SETNZ AL
33149 PUSH EAX
33151 PUSH ECX // Options
33153 MOV AL, ICC_BAR_CLASSES
33154 CALL DoInitCommonControls
33156 MOV EAX, ESP
33157 MOV EDX, offset[ToolbarOptions]
33158 XOR ECX, ECX
33159 MOV CL, 5
33160 CALL MakeFlags
33161 POP EDX
33163 PUSH 0
33164 XCHG ECX, EAX // ECX = MakeFlags(...)
33165 MOV EAX, [ESP+8] // EAX = AParent
33166 MOV EDX, [ESP+12] // EDX = Align
33167 OR ECX, [EDX*4+offset ToolbarAligns]
33168 OR ECX, WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS
33169 MOV EDX, offset[ TOOLBARCLASSNAME ]
33170 CALL _NewCommonControl
33171 MOV [EAX].TControl.fCommandActions.aClear, offset[ClearToolbar]
33172 MOV [EAX].TControl.fCommandActions.aGetCount, TB_BUTTONCOUNT
33173 INC [EAX].TControl.fIsButton
33174 POP EDX // pop AParent
33175 POP EDX // EDX = Align
33176 PUSH EDX
33177 TEST EDX, EDX
33178 JE @@zero_bounds
33179 ADD [EAX].TControl.fBoundsRect.Bottom, 26-64
33180 ADD [EAX].TControl.fBoundsRect.Right, 1000-64
33181 JMP @@bounds_ready
33182 @@zero_bounds:
33183 MOV [EAX].TControl.fBoundsRect.Left, EDX
33184 MOV [EAX].TControl.fBoundsRect.Top, EDX
33185 MOV [EAX].TControl.fBoundsRect.Right, EDX
33186 MOV [EAX].TControl.fBoundsRect.Bottom, EDX
33187 @@bounds_ready:
33188 PUSH EBX
33189 PUSH ESI
33190 XCHG EBX, EAX
33191 MOV ESI, offset[TControl.Perform]
33192 PUSH 0
33193 PUSH 0
33194 PUSH TB_GETEXTENDEDSTYLE
33195 PUSH EBX
33196 CALL ESI
33197 OR EAX, TBSTYLE_EX_DRAWDDARROWS
33198 PUSH EAX
33199 PUSH 0
33200 PUSH TB_SETEXTENDEDSTYLE
33201 PUSH EBX
33202 CALL ESI
33203 MOV EDX, offset[WndProcToolbarCtrl]
33204 MOV EAX, EBX
33205 CALL TControl.AttachProc
33206 MOV EDX, offset[WndProcDoEraseBkgnd]
33207 MOV EAX, EBX
33208 CALL TControl.AttachProc
33209 PUSH 0
33210 PUSH szTBButton
33211 PUSH TB_BUTTONSTRUCTSIZE
33212 PUSH EBX
33213 CALL ESI
33214 PUSH 0
33215 PUSH [EBX].TControl.fMargin
33216 PUSH TB_SETINDENT
33217 PUSH EBX
33218 CALL ESI
33219 MOV EAX, [ESP+8] // Align
33220 {$IFDEF PARANOIA}
33221 DB $2C, 1
33222 {$ELSE}
33223 SUB AL, 1
33224 {$ENDIF}
33225 JL @@bounds_correct
33226 JE @@corr_right
33227 {$IFDEF PARANOIA}
33228 DB $2C, 2
33229 {$ELSE}
33230 SUB AL, 2
33231 {$ENDIF}
33232 JNE @@corr_bottom
33233 @@corr_right:
33234 MOV EDX, [EBX].TControl.fBoundsRect.Left
33235 ADD EDX, 24
33236 MOV [EBX].TControl.fBoundsRect.Right, EDX
33237 JMP @@bounds_correct
33238 @@corr_bottom:
33239 MOV EDX, [EBX].TControl.fBoundsRect.Top
33240 ADD EDX, 22
33241 MOV [EBX].TControl.fBoundsrect.Bottom, EDX
33242 @@bounds_correct:
33243 MOV EDX, [Bitmap]
33244 TEST EDX, EDX
33245 JZ @@bitmap_added
33246 MOV EAX, EBX
33247 CALL TControl.TBAddBitmap
33248 @@bitmap_added:
33250 PUSH dword ptr [BtnImgIdxArray]
33251 PUSH dword ptr [BtnImgIdxArray-4]
33252 MOV ECX, [Buttons-4]
33253 MOV EDX, [Buttons]
33254 MOV EAX, EBX
33255 CALL TControl.TBAddButtons
33257 PUSH 0
33258 PUSH 0
33259 PUSH WM_SIZE
33260 PUSH EBX
33261 CALL ESI
33263 XCHG EAX, EBX
33264 POP ESI
33265 POP EBX
33266 ///POP EDX ///!!! next command is MOV ESP,EBP
33267 end;
33268 {$ELSE ASM_VERSION} //Pascal
33269 function NewToolbar( AParent: PControl; Align: TControlAlign; Options: TToolbarOptions;
33270 Bitmap: HBitmap; Buttons: array of PChar;
33271 BtnImgIdxArray: array of Integer ) : PControl;
33272 var Flags: DWORD;
33273 begin
33274 if not( tboTextBottom in Options ) then
33275 Options := Options + [ tboTextRight ];
33276 if tboTextRight in Options then
33277 Options := Options - [ tboTextBottom ];
33278 Flags := MakeFlags( @Options, ToolbarOptions );
33279 DoInitCommonControls( ICC_BAR_CLASSES );
33280 Result := _NewCommonControl( AParent, TOOLBARCLASSNAME,
33281 (ToolbarAligns[ Align ] or WS_CHILD or WS_VISIBLE or TBSTYLE_TOOLTIPS or Flags),
33282 //(not (Align in [caNone])) and not (tboNoDivider in Options), nil );
33283 tbo3DBorder in Options, nil );
33284 Result.fCommandActions.aClear := ClearToolbar;
33285 Result.fCommandActions.aGetCount := TB_BUTTONCOUNT;
33286 Result.fIsButton := TRUE;
33287 with Result.fBoundsRect do
33288 begin
33289 if Align in [ caNone ] then
33290 begin
33291 Bottom := Top + 26;
33292 Right := Left + 1000;
33294 else
33295 begin
33296 Left := 0; Right := 0;
33297 Top := 0; Bottom := 0;
33298 end;
33299 end;
33300 Result.AttachProc( WndProcToolbarCtrl );
33301 Result.AttachProc( WndProcDoEraseBkgnd );
33302 Result.Perform(TB_SETEXTENDEDSTYLE, 0, Result.Perform(TB_GETEXTENDEDSTYLE, 0, 0) or
33303 TBSTYLE_EX_DRAWDDARROWS);
33305 Result.Perform( TB_BUTTONSTRUCTSIZE, Sizeof( TTBButton ), 0 );
33306 Result.Perform( TB_SETINDENT, Result.fMargin, 0 );
33307 with Result.fBoundsRect do
33308 begin
33309 if Align in [ caLeft, caRight ] then
33310 Right := Left + 24
33311 else if not (Align in [caNone]) then
33312 Bottom := Top + 22;
33313 end;
33314 if Bitmap <> 0 then
33315 Result.TBAddBitmap( Bitmap );
33316 Result.TBAddButtons( Buttons, BtnImgIdxArray );
33317 Result.Perform( WM_SIZE, 0, 0 );
33318 end;
33319 {$ENDIF ASM_VERSION}
33320 //[END NewToolbar]
33322 {$ENDIF USE_CONSTRUCTORS}
33324 //================== DateTimePicker =====================//
33326 function WndProcDateTimePickerNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33327 var NMhdr: PNMHdr;
33328 D: TDateTime;
33329 AllowChg: Boolean;
33330 NMDTString: PNMDateTimeString;
33331 begin
33332 Result := False;
33333 if Msg.message = WM_NOTIFY then
33334 begin
33335 NMHdr := Pointer( Msg.lParam );
33336 CASE NMHdr.code OF
33337 DTN_DROPDOWN: if Assigned( Self_.fOnDropDown ) then
33338 Self_.fOnDropDown( Self_ );
33339 DTN_CLOSEUP: if Assigned( Self_.fOnCloseUp ) then
33340 Self_.fOnCloseUp( Self_ );
33341 DTN_DATETIMECHANGE:
33342 if Assigned( Self_.fOnChange ) then
33343 Self_.fOnChange( Self_ );
33344 {DTN_FORMAT:
33345 Rslt := 0;}
33346 DTN_USERSTRING:
33347 if Assigned( Self_.fOnDTPUserString ) then
33348 begin
33349 NMDTString := Pointer( NMHdr );
33350 D := 0.0;
33351 AllowChg := TRUE;
33352 Self_.fOnDTPUserString( Self_, NMDTString.pszUserString, D, AllowChg );
33353 NMDTString.dwFlags := Integer( not AllowChg );
33354 end;
33355 END;
33356 end;
33357 end;
33359 const
33360 //( dtpoTime, dtpoDateLong, dtpoUpDown, dtpoRightAlign,
33361 // dtpoShowNone, dtpoParseInput )
33363 DateTimePickerOptions: array[ TDateTimePickerOption ] of Integer = (
33364 DTS_TIMEFORMAT, DTS_LONGDATEFORMAT, DTS_UPDOWN, DTS_RIGHTALIGN,
33365 DTS_SHOWNONE, DTS_APPCANPARSE );
33367 function NewDateTimePicker( AParent: PControl; Options: TDateTimePickerOptions )
33368 : PControl;
33369 var Flags: DWORD;
33370 const
33371 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS or
33372 CS_VREDRAW or CS_HREDRAW;
33373 begin
33374 DoInitCommonControls( ICC_DATE_CLASSES );
33375 Flags := MakeFlags( @Options, DateTimePickerOptions );
33376 Result := _NewCommonControl( AParent, DATETIMEPICK_CLASS,
33377 (WS_CHILD or WS_VISIBLE or WS_TABSTOP or Flags), TRUE, nil );
33378 //Result.ClsStyle := Result.ClsStyle and not CS_OFF;
33379 Result.SetSize( 110, 24 );
33380 Result.AttachProc( WndProcDateTimePickerNotify );
33381 end;
33383 procedure TControl.SetDateTime(Value: TDateTime);
33384 var ST: TSystemTime;
33385 begin
33386 DateTime2SystemTime( Value, ST );
33387 Perform( DTM_SETSYSTEMTIME, Integer( IsNAN( Value ) ) , Integer( @ ST ) );
33388 end;
33390 function TControl.GetDateTime: TDateTime;
33391 var ST: TSystemTime;
33392 begin
33393 if Perform( DTM_GETSYSTEMTIME, 0, Integer( @ ST ) ) = GDT_VALID then
33394 SystemTime2DateTime( ST, Result )
33395 else
33396 Result := NAN;
33397 end;
33399 function TControl.GetDate: TDateTime;
33400 begin
33401 Result := DateTime;
33402 if not IsNAN( Result ) then
33403 Result := Trunc( DateTime );
33404 end;
33406 function TControl.GetTime: TDateTime;
33407 begin
33408 Result := DateTime;
33409 if not IsNAN( Result ) then
33410 Result := Frac( Result );
33411 end;
33413 procedure TControl.SetDate(const Value: TDateTime);
33414 begin
33415 if IsNAN( Value ) then
33416 DateTime := Value
33417 else
33418 if not IsNAN( DateTime ) then
33419 DateTime := Trunc( Value ) + Frac( DateTime )
33420 else
33421 DateTime := Trunc( Value );
33422 end;
33424 procedure TControl.SetTime(const Value: TDateTime);
33425 begin
33426 if IsNAN( Value ) then
33427 DateTime := Value
33428 else
33429 if not IsNAN( DateTime ) then
33430 DateTime := Trunc( DateTime ) + Frac( Value )
33431 else
33432 DateTime := 1.0 + Frac( Value );
33433 end;
33435 function TControl.GetDateTimeRange: TDateTimeRange;
33436 var ST_R: array[ 0..1 ] of TSystemTime;
33437 begin
33438 Perform( DTM_GETRANGE, 0, Integer( @ ST_R[ 0 ] ) );
33439 SystemTime2DateTime( ST_R[ 0 ], Result[ 0 ] );
33440 SystemTime2DateTime( ST_R[ 1 ], Result[ 1 ] );
33441 end;
33443 procedure TControl.SetDateTimeRange(Value: TDateTimeRange);
33444 var ST_R: array[ 0..1 ] of TSystemTime;
33445 begin
33446 DateTime2SystemTime( Value[ 0 ], ST_R[ 0 ] );
33447 DateTime2SystemTime( Value[ 1 ], ST_R[ 1 ] );
33448 Perform( DTM_SETRANGE,
33449 Integer( IsNAN( Value[ 0 ] ) ) or
33450 (Integer( IsNAN( Value[ 1 ] ) ) shl 1),
33451 Integer( @ ST_R[ 0 ] ) );
33452 end;
33454 function TControl.GetDateTimePickerColor( Index: TDateTimePickerColor): TColor;
33455 begin
33456 Result := Perform( DTM_GETMCCOLOR, Integer( Index ), 0 );
33457 end;
33459 procedure TControl.SetDateTimePickerColor(
33460 Index: TDateTimePickerColor; Value: TColor);
33461 begin
33462 Perform( DTM_SETMCCOLOR, Integer( Index ), Color2RGB( Value ) );
33463 end;
33465 procedure TControl.SetDateTimeFormat(const Value: String);
33466 begin
33467 Perform( DTM_SETFORMAT, 0, Integer( PChar( Value ) ) );
33468 end;
33470 function MakeDateTimeRange( D1, D2: TDateTime ): TDateTimeRange;
33471 begin
33472 Result[ 0 ] := D1;
33473 Result[ 1 ] := D2;
33474 end;
33477 //===================== RichEdit ========================//
33479 type PENLink = ^TENLink;
33480 TENLink = packed record
33481 hdr: TNMHDR;
33482 msg: DWORD;
33483 wParam: Integer;
33484 lParam: Integer;
33485 chrg: TCHARRANGE;
33486 end;
33487 TEXTRANGEA = packed record
33488 chrg: TCharRange;
33489 lpstrText: PAnsiChar;
33490 end;
33492 //[FUNCTION WndProc_RE_LinkNotify]
33493 {$IFDEF ASM_VERSION}
33494 function WndProc_RE_LinkNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33496 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
33497 JNE @@ret_false
33498 MOV EDX, [EDX].TMsg.lParam
33499 CMP [EDX].TNMHdr.code, EN_LINK
33500 JNE @@ret_false
33501 PUSH EBX
33502 PUSH EDX
33503 XCHG EBX, EAX
33504 XOR EAX, EAX
33505 MOV [ECX], EAX
33506 ADD ESP, -1020
33507 PUSH EAX
33508 PUSH ESP
33509 PUSH [EDX].TENLink.chrg.cpMax
33510 PUSH [EDX].TENLink.chrg.cpMin
33511 PUSH ESP
33512 PUSH 0
33513 PUSH EM_GETTEXTRANGE
33514 PUSH EBX
33515 CALL TControl.Perform
33516 ADD ESP, 12
33517 MOV EDX, ESP
33518 LEA EAX, [EBX].TControl.fREUrl
33519 CALL System.@LStrFromPChar
33520 ADD ESP, 1024
33521 POP EDX
33522 MOV ECX, [EDX].TENLink.msg
33523 LEA EAX, [EBX].TControl.fOnREOverURL
33524 CMP ECX, WM_MOUSEMOVE
33525 JE @@Url_event
33526 LEA EAX, [EBX].TControl.fOnREUrlClick
33527 CMP ECX, WM_LBUTTONDOWN
33528 JE @@Url_Event
33529 CMP ECX, WM_RBUTTONDOWN
33530 JNE @@after_Url_event
33531 @@Url_event:
33532 MOV ECX, [EAX].TMethod.Code
33533 JECXZ @@after_Url_event
33534 MOV EDX, EBX
33535 MOV EAX, [EAX].TMethod.Data
33536 CALL ECX
33537 @@after_Url_event:
33538 POP EBX
33539 MOV AL, 1
33541 @@ret_false:
33542 XOR EAX, EAX
33543 end;
33544 {$ELSE ASM_VERSION} //Pascal
33545 function WndProc_RE_LinkNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33546 var Link: PENLink;
33547 Range: TextRangeA;
33548 Buffer: array[ 0..1023 ] of Char;
33549 begin
33550 Result := False;
33551 if (Msg.message = WM_NOTIFY) and (PNMHdr( Msg.lParam ).code = EN_LINK) then
33552 begin
33553 Link := Pointer( Msg.lParam );
33554 Range.chrg := Link.chrg;
33555 Range.lpstrText := @Buffer[ 0 ]; //Pchar( @Buffer[ 0 ] );
33556 Buffer[ 0 ] := #0;
33557 Self_.Perform( EM_GETTEXTRANGE, 0, Integer( @Range ) );
33558 Self_.fREUrl := Buffer;
33559 case Link.msg of
33560 WM_MOUSEMOVE:
33561 if assigned( Self_.fOnREOverURL ) then
33562 Self_.fOnREOverURL( Self_ );
33563 WM_LBUTTONDOWN, WM_RBUTTONDOWN:
33564 if assigned( Self_.fOnREUrlClick ) then
33565 Self_.fOnREUrlClick( Self_ );
33566 end;
33567 Rslt := 0;
33568 Result := TRUE;
33569 end;
33570 end;
33571 {$ENDIF ASM_VERSION}
33572 //[END WndProc_RE_LinkNotify]
33574 var Global_DisableParentCursor: Boolean;
33576 //[FUNCTION WndProcRichEditNotify]
33577 {$IFDEF ASM_noVERSION}
33578 function WndProcRichEditNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33579 const int_IDC_ARROW = integer( IDC_ARROW );
33581 CMP word ptr [EDX].TMsg.message, WM_NOTIFY
33582 JNE @@ret_false {YS}
33583 // JNE @@chk_WM_SETCURSOR {YS}
33584 MOV EDX, [EDX].TMsg.lParam
33585 CMP [EDX].TNMHdr.code, EN_SELCHANGE
33586 JNE @@ret_false
33587 //PUSH EAX
33588 CALL TControl.DoSelChange
33589 //POP EAX
33590 {CMP [EAX].TControl.fTransparent, 0
33591 JZ @@ret_false
33592 CALL TControl.Invalidate}
33593 @@ret_false:
33594 XOR EAX, EAX
33596 { //YS
33597 @@chk_WM_SETCURSOR:
33598 CMP word ptr [EDX].TMsg.message, WM_SETCURSOR
33599 JNE @@ret_false
33600 PUSH EBX
33601 MOV EBX, EAX
33602 PUSH ECX
33603 PUSH EDX
33604 INC [Global_DisableParentCursor]
33605 CALL TControl.CallDefWndProc
33606 DEC [Global_DisableParentCursor]
33607 POP EDX
33608 MOVZX EDX, word ptr [EDX].TMsg.lParam
33609 POP ECX
33610 MOV [ECX], EAX
33611 TEST EAX, EAX
33612 MOV EAX, [EBX].TControl.fCursor
33613 POP EBX
33614 JNZ @@ret_true
33615 INC dword ptr [ECX]
33616 CMP EDX, HTCLIENT
33617 JE @@set_cursor
33618 CMP EDX, HTVSCROLL
33619 JE @@set_arrow_cursor
33620 CMP EDX, HTHSCROLL
33621 JNE @@ret_false
33622 @@set_arrow_cursor:
33623 PUSH int_IDC_ARROW
33624 PUSH 0
33625 CALL LoadCursor
33626 @@set_cursor:
33627 PUSH EAX
33628 CALL Windows.SetCursor
33629 @@ret_true:
33630 MOV AL, 1
33632 end;
33633 {$ELSE ASM_VERSION} //Pascal
33634 function WndProcRichEditNotify( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
33635 var NMhdr: PNMHdr;
33636 // TestCode: Integer;
33637 {FR: TFormatRange;
33638 I: Integer;
33639 R: TRect;
33640 LogX, LogY: Integer;}
33641 begin
33642 Result := False;
33643 if Msg.message = WM_NOTIFY then
33644 begin
33645 NMHdr := Pointer( Msg.lParam );
33646 case NMHdr.code of
33647 EN_SELCHANGE:
33648 begin
33649 Self_.DoSelChange;
33650 if Self_.fTransparent then
33651 Self_.Invalidate;
33652 end;
33653 end;
33655 { // YS
33656 else
33657 if Msg.message = WM_SETCURSOR then
33658 begin
33659 Result := True;
33660 TestCode := LoWord( Msg.lParam );
33661 Global_DisableParentCursor := True;
33662 Rslt := Self_.CallDefWndProc( Msg );
33663 Global_DisableParentCursor := False;
33664 if Rslt = 0 then
33665 begin
33666 Rslt := 1;
33667 case TestCode of
33668 HTVSCROLL, HTHSCROLL: Windows.SetCursor( LoadCursor( 0, IDC_ARROW ) );
33669 HTCLIENT: Windows.SetCursor( Self_.fCursor );
33670 else Result := False;
33671 end;
33672 end;
33673 end;
33675 end;
33676 {$ENDIF ASM_VERSION}
33677 //[END WndProcRichEditNotify]
33679 var FRichEditModule: Integer;
33680 RichEditClass: PChar = 'RichEdit20A';
33681 RichEditLib: PChar = 'RICHED32.DLL';
33683 const RichEditLibnames: array[ 0..2 ] of PChar =
33684 ( 'RICHED20.DLL', 'RICHED32.DLL', 'RICHED.DLL' );
33685 const RichEditflags: array [ TEditOption ] of Integer = (
33686 not (es_AutoHScroll or WS_HSCROLL),
33687 not (es_AutoVScroll or WS_VSCROLL),
33688 0 {es_Lowercase - not supported},
33689 0 {es_Multiline - RichEdit always multiline},
33690 es_NoHideSel,
33691 0 {es_OemConvert - not suppoted},
33692 0 {es_Password - not supported},
33693 es_Readonly,
33694 0 {es_UpperCase - not supported},
33695 es_WantReturn, 0, es_Number );
33697 {$IFDEF USE_CONSTRUCTORS}
33698 //[function NewRichEdit1]
33699 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
33700 begin
33701 new( Result, CreateRichEdit1( AParent, Options ) );
33702 end;
33703 //[END NewRichEdit1]
33704 {$ELSE not_USE_CONSTRUCTORS}
33706 //[FUNCTION NewRichEdit1]
33707 {$IFDEF ASM_VERSION}
33708 const RichEditClass10: array[0..8] of Char = ('R','i','c','h','E','d','i','t',#0);
33709 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
33711 PUSH EDX
33713 MOV ECX, [FRichEditModule]
33714 INC ECX
33715 LOOP @@loaded
33716 PUSHAD
33717 MOV BL, 3
33718 LEA ESI, [RichEditLibNames]
33719 @@loo:
33720 LODSD
33721 PUSH EAX
33722 CALL LoadLibrary
33723 CMP EAX, HINSTANCE_ERROR
33724 JG @@break
33725 MOV [RichEditClass], offset[RichEditClass10]
33726 DEC BL
33727 JNZ @@loo
33728 JMP @@fault
33729 @@break:
33730 MOV [FRichEditModule], EAX
33731 @@fault:
33732 POPAD
33733 @@loaded:
33734 PUSH EAX
33735 PUSH EDX
33736 MOV EAX, ESP
33737 MOV EDX, offset[RichEditFlags]
33738 XOR ECX, ECX
33739 MOV CL, 10
33740 CALL MakeFlags
33741 XCHG ECX, EAX
33742 POP EDX
33743 POP EAX
33744 PUSH 1
33745 PUSH offset[RichEditActions]
33746 MOV EDX, [RichEditClass]
33747 OR ECX, WS_VISIBLE or WS_CHILD or WS_TABSTOP or WS_BORDER or ES_MULTILINE
33748 CALL _NewCommonControl
33749 INC [EAX].TControl.fIgnoreDefault
33750 POP EDX
33751 TEST DH, 4 // is eoWantTab in Options ?
33752 SETZ DL
33753 MOV [EAX].TControl.fLookTabKeys, DL
33754 PUSH EBX
33755 MOV EBX, EAX
33756 MOV EDX, offset[WndProcRichEditNotify]
33757 CALL TControl.AttachProc
33758 MOV [EBX].TControl.fDoubleBuffered, 0
33759 INC [EBX].TControl.fCannotDoubleBuf
33760 ADD [EBX].TControl.fBoundsRect.Right, 100-64
33761 ADD [EBX].TControl.fBoundsRect.Bottom, 200-64
33762 PUSH ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or ENM_PROTECTED or $04000000
33763 PUSH 0
33764 PUSH EM_SETEVENTMASK
33765 PUSH EBX
33766 CALL TControl.Perform
33767 MOV EAX, clWindow
33768 MOV [EBX].TControl.fColor, EAX
33769 CALL Color2RGB
33770 PUSH EAX
33771 PUSH 0
33772 PUSH EM_SETBKGNDCOLOR
33773 PUSH EBX
33774 CALL TControl.Perform
33775 XCHG EAX, EBX
33776 POP EBX
33777 end;
33778 {$ELSE ASM_VERSION} //Pascal
33779 function NewRichEdit1( AParent: PControl; Options: TEditOptions ): PControl;
33780 var Flags, I: Integer;
33781 begin
33782 if FRichEditModule = 0 then
33783 begin
33784 for I := 0 to 2 do
33785 begin
33786 FRichEditModule := LoadLibrary( RichEditLibnames[ I ] );
33787 if FRichEditModule > HINSTANCE_ERROR then break;
33788 RichEditClass := 'RichEdit';
33789 end;
33790 if FRichEditModule <= HINSTANCE_ERROR then
33791 FRichEditModule := 0;
33792 end;
33793 Flags := MakeFlags( @Options, RichEditFlags );
33794 Result := _NewCommonControl( AParent, RichEditClass, WS_VISIBLE or WS_CHILD
33795 or WS_TABSTOP or WS_BORDER or ES_MULTILINE or Flags,
33796 True, @RichEditActions );
33797 Result.fIgnoreDefault := TRUE;
33798 Result.fLookTabKeys := [ tkTab ];
33799 if eoWantTab in Options then
33800 Result.fLookTabKeys := [ ];
33802 Result.AttachProc( WndProcRichEditNotify );
33803 Result.fDoubleBuffered := False;
33804 Result.fCannotDoubleBuf := True;
33805 with Result.fBoundsRect do
33806 begin
33807 Right := Right + 100;
33808 Bottom := Top + 200;
33809 end;
33810 Result.Perform( EM_SETEVENTMASK, 0,
33811 ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or
33812 ENM_PROTECTED or $04000000 {ENM_LINK} or ENM_KEYEVENTS {or ENM_MOUSEEVENTS} );
33813 Result.fColor := clWindow;
33814 Result.Perform( EM_SETBKGNDCOLOR, 0, Color2RGB(Result.fColor));
33815 //Result.Perform( WM_SIZE, 0, 0 );
33816 end;
33817 {$ENDIF ASM_VERSION}
33818 //[END NewRichEdit1]
33820 {$ENDIF USE_CONSTRUCTORS}
33822 //[API OleInitialize]
33823 function OleInitialize(pwReserved: Pointer): HResult; stdcall;
33824 external 'ole32.dll' name 'OleInitialize';
33825 procedure OleUninitialize; stdcall;
33826 external 'ole32.dll' name 'OleUninitialize';
33828 //[FUNCTION OleInit]
33829 {$IFDEF ASM_VERSION}
33830 function OleInit: Boolean;
33832 MOV ECX, [OleInitCount]
33833 INC ECX
33834 LOOP @@init1
33835 PUSH ECX
33836 CALL OleInitialize
33837 TEST EAX, EAX
33838 MOV AL, 0
33839 JNZ @@exit
33840 @@init1:
33841 INC [OleInitCount]
33842 MOV AL, 1
33843 @@exit:
33844 end;
33845 {$ELSE ASM_VERSION} //Pascal
33846 function OleInit: Boolean;
33847 begin
33848 if OleInitCount = 0 then
33849 begin
33850 Result := False;
33851 if OleInitialize( nil ) <> 0 then Exit;
33852 end;
33853 Inc( OleInitCount );
33854 Result := True;
33855 end;
33856 {$ENDIF ASM_VERSION}
33857 //[END OleInit]
33859 //[PROCEDURE OleUnInit]
33860 {$IFDEF ASM_VERSION}
33861 procedure OleUnInit;
33863 MOV ECX, [OleInitCount]
33864 JECXZ @@exit
33865 DEC [OleInitCount]
33866 JNZ @@exit
33867 CALL OleUninitialize
33868 @@exit:
33869 end;
33870 {$ELSE ASM_VERSION} //Pascal
33871 procedure OleUnInit;
33872 begin
33873 if OleInitCount > 0 then
33874 begin
33875 Dec( OleInitCount );
33876 if OleInitCount = 0 then
33877 OleUninitialize;
33878 end;
33879 end;
33880 {$ENDIF ASM_VERSION}
33881 //[END OleUnInit]
33883 //[API SysAllocStringLen]
33884 function SysAllocStringLen;
33885 external 'oleaut32.dll' name 'SysAllocStringLen';
33886 procedure SysFreeString( psz: PWideChar ); stdcall;
33887 external 'oleaut32.dll' name 'SysFreeString';
33890 //[function StringToOleStr]
33891 function StringToOleStr(const Source: string): PWideChar;
33893 SourceLen, ResultLen: Integer;
33894 Buffer: array[0..1023] of WideChar;
33895 begin
33896 SourceLen := Length(Source);
33897 if Length(Source) < SizeOf(Buffer) div 2 then
33898 Result := SysAllocStringLen(Buffer, MultiByteToWideChar(0, 0,
33899 PChar(Source), SourceLen, Buffer, SizeOf(Buffer) div 2))
33900 else
33901 begin
33902 ResultLen := MultiByteToWideChar(0, 0,
33903 Pointer(Source), SourceLen, nil, 0);
33904 Result := SysAllocStringLen(nil, ResultLen);
33905 MultiByteToWideChar(0, 0, Pointer(Source), SourceLen,
33906 Result, ResultLen);
33907 end;
33908 end;
33911 {$IFDEF USE_CONSTRUCTORS}
33912 //[function NewRichEdit]
33913 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
33914 begin
33915 new( Result, CreateRichEdit( AParent, Options ) );
33916 end;
33917 //[END NewRichEdit]
33918 {$ELSE not_USE_CONSTRUCTORS}
33920 //[FUNCTION NewRichEdit]
33921 {$IFDEF ASM_VERSION}
33922 const RichEdit20A: array[0..11] of Char = ('R','i','c','h','E','d','i','t','2','0','A',#0 );
33923 RichEd20_DLL: array[ 0..12] of Char = ('R','I','C','H','E','D','2','0','.','D','L','L',#0 );
33924 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
33925 const deltaChr = 24; // sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat );
33926 deltaPar = sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat );
33928 PUSHAD
33929 CALL OleInit
33930 TEST EAX, EAX
33931 POPAD
33932 JZ @@new1
33933 PUSH [RichEditClass]
33934 MOV [RichEditClass], offset[RichEdit20A]
33935 PUSH [RichEditLib]
33936 MOV [RichEditLib], offset[RichEd20_DLL]
33937 CALL NewRichEdit1
33938 POP [RichEditLib]
33939 POP [RichEditClass]
33940 MOV byte ptr [EAX].TControl.fCharFmtDeltaSz, deltaChr
33941 MOV byte ptr [EAX].TControl.fParaFmtDeltaSz, deltaPar
33943 @@new1: CALL NewRichEdit1
33944 end;
33945 {$ELSE ASM_VERSION} //Pascal
33946 function NewRichEdit( AParent: PControl; Options: TEditOptions ): PControl;
33947 var OldRichEditClass, OldRichEditLib: PChar;
33948 begin
33949 if OleInit then
33950 begin
33951 OldRichEditClass := RichEditClass;
33952 RichEditClass := 'RichEdit20A';
33953 OldRichEditLib := RichEditLib;
33954 RichEditLib := 'RICHED20.DLL';
33955 Result := NewRichEdit1( AParent, Options );
33956 Result.fCharFmtDeltaSz := 24; //sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat );
33957 // sizeof( TCharFormat2 ) is calculated incorrectly
33958 Result.fParaFmtDeltaSz := sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat );
33959 RichEditClass := OldRichEditClass;
33960 RichEditLib := OldRichEditLib;
33962 else
33963 Result := NewRichEdit1( AParent, Options );
33964 end;
33965 {$ENDIF ASM_VERSION}
33966 //[END NewRichEdit]
33968 {$ENDIF USE_CONSTRUCTORS}
33970 //=====================================================================//
33991 { TControl }
33993 {$IFDEF ASM_VERSION}
33994 //[procedure TControl.Init]
33995 procedure TControl.Init;
33996 const
33997 IniStyle = WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
33998 WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
33999 WS_BORDER or WS_THICKFRAME;
34000 asm //cmd //opd
34001 PUSH EBX
34002 MOV EBX, EAX
34003 CALL TObj.Init
34004 MOV EDX, offset WndProcDummy
34005 MOV [EBX].fOnDynHandlers, EDX
34006 MOV [EBX].fWndProcKeybd, EDX
34007 MOV [EBX].fWndProcResizeFlicks, EDX
34008 MOV [EBX].fPass2DefProc, EDX
34009 //**** MOV [EBX].fDefWndProc, offset DefWindowProc
34010 MOV [EBX].fWndFunc, offset WndFunc
34011 MOV EDX, offset ClearText
34012 MOV [EBX].fCommandActions.aClear, EDX
34013 INC dword ptr [EBX].fWindowed
34014 MOV EDX, offset DummyObjProc
34015 MOV [EBX].fControlClick, EDX
34016 MOV EDX, clBtnFace
34017 MOV [EBX].fColor, EDX
34018 MOV DL, clWindowText and $FF
34019 MOV [EBX].fTextColor, EDX
34020 MOV byte ptr [EBX].fMargin, 2
34021 INC dword ptr [EBX].fCtl3D
34022 INC dword ptr [EBX].fCtl3Dchild
34023 DEC byte ptr [EBX].fAlphaBlend
34024 CALL NewList
34025 MOV [EBX].fChildren, EAX
34026 MOV byte ptr[EBX].fClsStyle, CS_OWNDC
34027 MOV [EBX].fStyle, IniStyle
34028 INC dword ptr[EBX].fExStyle+2
34029 INC dword ptr[EBX].fVisible
34030 INC dword ptr[EBX].fEnabled
34031 CALL NewList
34032 MOV [EBX].fDynHandlers, EAX
34033 POP EBX
34034 end;
34035 {$ELSE ASM_VERSION} //Pascal
34036 procedure TControl.Init;
34037 begin
34038 inherited;
34039 fOnDynHandlers := WndProcDummy;
34040 fWndProcKeybd := WndProcDummy;
34041 fWndProcResizeFlicks := WndProcDummy;
34042 fPass2DefProc := WndProcDummy;
34043 //**** fDefWndProc := @DefWindowProc;
34044 fWndFunc := @ WndFunc;
34045 fCommandActions.aClear := ClearText;
34046 fWindowed := True;
34047 fControlClick := DummyObjProc;
34048 fColor := clBtnFace;
34049 fTextColor := clWindowText;
34050 fMargin := 2;
34051 fCtl3D := True;
34052 fCtl3Dchild := True;
34053 fAlphaBlend := 255;
34054 fChildren := NewList;
34055 fClsStyle := CS_OWNDC;
34056 fStyle := WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
34057 WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
34058 WS_BORDER or WS_THICKFRAME;
34059 fExStyle := WS_EX_CONTROLPARENT;
34060 fVisible := True;
34061 fEnabled := True;
34062 fDynHandlers := NewList;
34063 end;
34064 {$ENDIF ASM_VERSION}
34066 {$IFDEF ASM_VERSION}
34067 //[PROCEDURE CallTControlInit]
34068 procedure CallTControlInit( Ctl: PControl );
34069 begin
34070 Ctl.Init;
34071 end;
34072 //[END CallTControlInit]
34074 //[procedure TControl.InitParented]
34075 procedure TControl.InitParented( AParent: PControl );
34076 const IStyle = WS_VISIBLE or WS_CLIPCHILDREN or WS_CLIPSIBLINGS or
34077 WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
34078 WS_BORDER or WS_THICKFRAME;
34079 IExStyle = WS_EX_CONTROLPARENT;
34080 IClsStyle = CS_OWNDC;
34081 int_IDC_ARROW = integer( IDC_ARROW );
34083 PUSH EAX
34084 PUSH EDX
34085 CALL CallTControlInit
34086 POP EDX
34087 POP EAX
34088 TEST EDX, EDX
34089 JZ @@0
34090 MOV ECX, [EDX].fColor
34091 MOV [EAX].fColor, ECX
34092 @@0:
34093 CALL SetParent
34094 end;
34095 {$ELSE ASM_VERSION} //Pascal
34096 procedure TControl.InitParented( AParent: PControl );
34097 begin
34098 Init;
34099 if AParent <> nil then
34100 fColor := AParent.fColor;
34101 Parent := AParent;
34102 end;
34103 {$ENDIF ASM_VERSION}
34105 {$IFDEF ASM_VERSION}
34106 //[destructor TControl.Destroy]
34107 destructor TControl.Destroy;
34109 PUSH EBX
34110 MOV EBX, EAX
34111 CALL TControl.ParentForm
34112 TEST EAX, EAX
34113 JZ @@cur_ctl_removed
34114 CMP [EAX].TControl.fCurrentControl, EBX
34115 JNE @@cur_ctl_removed
34116 XOR EDX, EDX
34117 MOV [EAX].TControl.fCurrentControl, EDX
34118 @@cur_ctl_removed:
34120 MOV ECX, [EBX].fHandle
34121 JECXZ @@wndhidden
34122 PUSH SW_HIDE
34123 PUSH ECX
34124 CALL ShowWindow
34125 @@wndhidden:
34127 MOV EAX, EBX
34128 CALL Final
34129 MOV EAX, EBX
34130 CALL DestroyChildren
34132 XOR ECX, ECX
34133 CMP [EBX].fDestroying, CL
34134 JNZ @@destroyed
34136 XCHG CL, [EBX].fCtlClsNameChg
34137 JECXZ @@skip_free_clsname
34138 MOV EAX, [EBX].fControlClassName
34139 CALL System.@FreeMem
34140 @@skip_free_clsname:
34142 INC [EBX].fDestroying
34143 MOV EAX, [EBX].fFont
34144 CALL TObj.Free
34145 MOV EAX, [EBX].fBrush
34146 CALL TObj.Free
34147 MOV EAX, [EBX].fCanvas
34148 CALL TObj.Free
34150 XOR ECX, ECX
34152 MOV [EBX].fFont, ECX // +YS
34153 MOV [EBX].fBrush, ECX // +YS
34154 MOV [EBX].fCanvas, ECX // +YS
34156 XCHG ECX, [EBX].fCustomData
34157 JECXZ @@custfree
34158 XCHG EAX, ECX
34159 CALL System.@FreeMem
34160 @@custfree:
34161 MOV EAX, [EBX].fCustomObj
34162 CALL TObj.Free
34164 MOV EAX, [EBX].fHandle
34165 TEST EAX, EAX
34166 JZ @@free_fields
34168 XOR ECX, ECX
34169 XCHG ECX, [EBX].fAccelTable
34170 JECXZ @@accelTable_destroyed
34171 PUSH ECX
34172 CALL DestroyAcceleratorTable
34173 @@accelTable_destroyed:
34174 MOV EAX, [EBX].fMenuObj
34175 CALL TObj.Free
34176 @@destroy_img_list:
34177 MOV EAX, [EBX].fImageList
34178 TEST EAX, EAX
34179 JZ @@img_list_destroyed
34180 CALL TObj.Free
34181 JMP @@destroy_img_list
34182 @@img_list_destroyed:
34184 PUSH [EBX].fHandle
34185 CALL IsWindow
34186 TEST EAX, EAX
34187 JZ @@destroy2
34189 PUSH EAX
34190 PUSH 1
34191 PUSH WM_SETICON
34192 PUSH [EBX].fHandle
34193 CALL SendMessage
34194 TEST EAX, EAX
34195 JZ @@icoremoved
34196 CMP [EBX].fIconShared, 0
34197 JNZ @@icoremoved
34198 PUSH EAX
34199 CALL DestroyIcon
34200 @@icoremoved:
34201 //********************************************************** Remarked By M.Gerasimov
34202 // PUSH offset[ID_SELF]
34203 // PUSH [EBX].fHandle
34204 // CALL RemoveProp
34205 //********************************************************** Remarked By M.Gerasimov
34206 CMP [EBX].fNCDestroyed, 0
34207 JNZ @@destroy2
34208 PUSH [EBX].fHandle
34209 CALL DestroyWindow
34210 @@destroy2:
34211 XOR EAX, EAX
34212 MOV [EBX].fHandle, EAX
34214 @@free_fields:
34215 MOV EAX, [EBX].fCaption
34216 TEST EAX, EAX
34217 JZ @@caption_freed
34218 CALL System.@FreeMem
34219 @@caption_freed:
34220 MOV EAX, [EBX].fStatusTxt
34221 TEST EAX, EAX
34222 JZ @@statusTxt_freed
34223 CALL System.@FreeMem
34224 @@statusTxt_freed:
34225 MOV ECX, [EBX].fParent
34226 JECXZ @@removed_from_parent
34227 CMP [ECX].fCurrentControl, EBX
34228 JNE @@removefromParent
34229 XOR EAX, EAX
34230 MOV [ECX].fCurrentControl, EAX
34231 @@removefromParent:
34232 MOV EAX, [ECX].fChildren
34233 //PUSH EAX
34234 MOV EDX, EBX
34235 {CALL TList.IndexOf
34236 TEST EAX, EAX
34237 POP EDX
34238 JL @@removed_from_parent
34239 XCHG EAX, EDX
34240 CALL TList.Delete}
34241 CALL TList.Remove
34242 @@removed_from_parent:
34243 MOV ECX, [EBX].fTmpBrush
34244 JECXZ @@tmpBrush_deleted
34245 PUSH ECX
34246 CALL DeleteObject
34247 @@tmpBrush_deleted:
34249 PUSH EBX
34250 PUSH [EBX].fChildren
34251 PUSH [EBX].fTBttCmd
34252 PUSH [EBX].fTBttTxt
34253 PUSH [EBX].fTmpFont
34254 PUSH [EBX].fDynHandlers
34255 MOV BL, 5
34256 @@freeloo:
34257 POP EAX
34258 CALL TObj.Free
34259 DEC BL
34260 JNZ @@freeloo
34261 POP EBX
34262 LEA EAX, [EBX].fREUrl
34263 CALL System.@LStrClr
34264 XCHG EAX, EBX
34265 CALL TObj.Destroy
34266 @@destroyed:
34267 POP EBX
34268 end;
34269 {$ELSE ASM_VERSION} //Pascal
34270 destructor TControl.Destroy;
34271 var I: Integer;
34272 F: PControl;
34273 Ico: HIcon;
34274 begin
34275 {$IFDEF USE_MHTOOLTIP}
34276 {$DEFINE destroy}
34277 {$I KOLMHToolTip}
34278 {$UNDEF destroy}
34279 {$ENDIF USE_MHTOOLTIP}
34280 F := ParentForm; // or Applet - for form ???
34281 if F <> nil then
34282 if F.FCurrentControl = @Self then
34283 F.FCurrentControl := nil;
34285 if FHandle <> 0 then
34286 ShowWindow( fHandle, SW_HIDE );
34288 Final;
34289 DestroyChildren;
34291 if not fDestroying then
34292 begin
34293 fDestroying := True;
34295 if fCtlClsNameChg then
34296 begin
34297 FreeMem( fControlClassName );
34298 fCtlClsNameChg := FALSE;
34299 end;
34301 fFont.Free;
34302 fFont := nil;
34303 fBrush.Free;
34304 fBrush := nil;
34305 fCanvas.Free;
34306 fCanvas := nil;
34308 if fCustomData <> nil then
34309 FreeMem( fCustomData );
34310 fCustomData := nil;
34311 fCustomObj.Free;
34312 fCustomObj := nil;
34314 if fHandle <> 0 then
34315 begin
34316 {$IFNDEF NEW_MENU_ACCELL}
34317 if fAccelTable <> 0 then
34318 begin
34319 DestroyAcceleratorTable( fAccelTable );
34320 fAccelTable := 0;
34321 end;
34322 {$ENDIF}
34323 fMenuObj.Free;
34324 while fImageList <> nil do
34325 fImageList.Free;
34326 I := fHandle;
34327 if IsWindow( I ) then
34328 begin
34329 Ico := SendMessage( I, WM_SETICON, 1, 0 );
34330 if Ico <> 0 then
34331 if not fIconShared then
34332 DestroyIcon( Ico );
34333 //********************************************************** Remarked By M.Gerasimov
34334 // RemoveProp( I, ID_SELF );
34335 //********************************************************** Remarked By M.Gerasimov
34336 if not fNCDestroyed then
34337 begin
34338 {$IFDEF DEBUG_ENDSESSION}
34339 if EndSession_Initiated then
34340 LogFileOutput( GetStartDir + 'es_debug.txt',
34341 'DESTROYING HWND:' + Int2Str( I ) );
34342 {$ENDIF}
34343 DestroyWindow( I );
34344 end;
34346 {$IFDEF TEST_CLOSE}
34347 else
34349 int 3
34350 end;
34351 {$ENDIF}
34353 fHandle := 0;
34354 end;
34356 if fTmpBrush <> 0 then
34357 DeleteObject( fTmpBrush );
34358 fTmpBrush := 0;
34360 if FCaption <> nil then
34361 FreeMem( FCaption );
34362 if fStatusTxt <> nil then
34363 FreeMem( fStatusTxt );
34365 if fParent <> nil then
34366 begin
34367 {I := fParent.fChildren.IndexOf( @Self );
34368 if I >= 0 then
34369 fParent.fChildren.Delete( I );}
34370 fParent.fChildren.Remove( @Self );
34371 if fParent.fCurrentControl = @Self then
34372 fParent.fCurrentControl := nil;
34373 end;
34375 fChildren.Free;
34376 fTBttCmd.Free;
34377 fTBttTxt.Free;
34378 fTmpFont.Free;
34379 fDynHandlers.Free;
34380 fREUrl := '';
34381 inherited;
34382 end;
34383 end;
34384 {$ENDIF ASM_VERSION}
34386 {$IFDEF USE_MHTOOLTIP}
34387 {$DEFINE code}
34388 {$I KOLMHToolTip}
34389 {$UNDEF code}
34390 {$ENDIF}
34392 {$IFDEF ASM_VERSION}
34393 //[procedure TControl.SetEnabled]
34394 procedure TControl.SetEnabled( Value: Boolean );
34396 PUSH EBX
34397 MOV EBX, EAX
34398 MOVZX EDX, DL
34399 PUSH EDX
34400 CALL GetEnabled
34401 POP EDX
34402 CMP AL, DL
34403 JZ @@exit
34404 MOV [EBX].fEnabled, DL
34405 TEST EDX, EDX
34406 JNZ @@andnot
34407 OR byte ptr [EBX].fStyle + 3, 8
34408 JMP @@1
34409 @@andnot:
34410 AND byte ptr [EBX].fStyle + 3, $F7
34411 @@1:
34412 MOV ECX, [EBX].fHandle
34413 JECXZ @@2
34415 PUSH EDX
34416 PUSH ECX
34417 CALL EnableWindow
34419 @@2:
34420 XCHG EAX, EBX
34421 CALL Invalidate
34423 @@exit:
34424 POP EBX
34425 end;
34426 {$ELSE ASM_VERSION} //Pascal
34427 procedure TControl.SetEnabled( Value: Boolean );
34428 begin
34429 if GetEnabled = Value then Exit;
34430 fEnabled := Value;
34431 if Value then
34432 fStyle := fStyle and not WS_DISABLED
34433 else
34434 fStyle := fStyle or WS_DISABLED;
34435 if fHandle <> 0 then
34436 EnableWindow( fHandle, fEnabled );
34437 Invalidate; // necessary for Graphic controls
34438 end;
34439 {$ENDIF ASM_VERSION}
34441 {$IFDEF ASM_VERSION}
34442 //[function TControl.GetParentWindow]
34443 function TControl.GetParentWindow: HWnd;
34445 MOV EAX, [EAX].fParent
34446 TEST EAX, EAX
34448 JZ @@exit
34450 CALL TControl.GetWindowHandle
34451 @@exit: --- replaced with following (6 bytes instead of 7):
34453 JNZ TControl.GetWindowHandle
34454 end;
34455 {$ELSE ASM_VERSION} //Pascal
34456 function TControl.GetParentWindow: HWnd;
34457 begin
34458 Result := 0;
34459 if fParent = nil then Exit;
34460 Result := fParent.GetWindowHandle;
34461 end;
34462 {$ENDIF ASM_VERSION}
34464 {$IFDEF ASM_VERSION}
34465 function TControl.GetWindowHandle: HWnd;
34467 MOV ECX, [EAX].fHandle
34468 JECXZ @@1
34469 XCHG EAX, ECX
34471 @@1:
34472 CMP [EAX].fCreateVisible, 0
34473 JNZ @@2
34475 PUSH EAX
34476 XOR EDX, EDX
34477 CALL TControl.Set_Visible
34478 POP EAX
34479 PUSH EAX
34480 //CALL TControl.CreateWindow
34481 CALL CallTControlCreateWindow
34482 { This is a call to Pascal piece of code, which
34483 calls virtual method TControl.CreateWindow }
34484 POP EAX
34486 INC [EAX].fCreateHidden
34487 JMP @@0
34489 @@2: PUSH EAX
34490 //CALL TControl.CreateWindow
34491 CALL CallTControlCreateWindow
34492 POP EAX
34493 @@0:
34494 MOV EAX, [EAX].fHandle
34495 end;
34496 {$ELSE ASM_VERSION} //Pascal
34497 function TControl.GetWindowHandle: HWnd;
34498 begin
34499 if fHandle = 0 then
34500 begin
34501 if not fCreateVisible then
34502 begin
34503 Set_Visible( False );
34504 CreateWindow; //virtual!!!
34505 fCreateHidden := True;
34507 else
34508 CreateWindow; //virtual!!!
34509 end;
34510 Result := fHandle;
34511 end;
34512 {$ENDIF ASM_VERSION}
34515 {$IFDEF _D7orHigher}
34516 // may be it was a good idea to replace CreateWindowEx,
34517 // but Inprise forget about stdcall... In result, asm-version became broken.
34518 //[API CreateWindowEx]
34519 function CreateWindowEx(dwExStyle: DWORD; lpClassName: PChar;
34520 lpWindowName: PChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer;
34521 hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;
34522 stdcall; external user32 name 'CreateWindowExA';
34523 {$ENDIF}
34526 {$IFDEF ASM_VERSION}
34527 //[function TControl.CreateWindow]
34528 function TControl.CreateWindow: Boolean;
34529 const
34530 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;
34531 CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;
34532 szWndClass = sizeof( TWndClass );
34533 int_IDC_ARROW = integer( IDC_ARROW );
34535 PUSH EBX
34536 XCHG EBX, EAX
34537 MOV ECX, [EBX].fParent
34538 JECXZ @@chk_handle
34539 XCHG EAX, ECX
34540 CALL GetWindowHandle
34541 TEST EAX, EAX
34542 JZ @@ret_false
34543 @@chk_handle:
34544 MOV ECX, [EBX].fHandle
34545 JECXZ @@prepare_Params
34546 MOV DL, 0
34547 MOV EAX, EBX
34548 CMP [EBX].fCreateHidden, DL
34549 JZ @@create_children
34550 CALL CreateChildWindows
34551 MOV EAX, EBX
34552 MOV DL, 1
34553 CALL Set_Visible
34554 MOV [EBX].fCreateHidden, 0
34555 JMP @@ret_true
34556 @@create_children:
34557 CALL CreateChildWindows
34558 @@ret_true:
34559 MOV AL, 1
34560 @@ret_0:
34561 POP EBX
34563 @@prepare_params:
34564 MOV AL, [EBX].fWindowed
34565 CMP AL, 0
34566 JZ @@ret_0
34567 PUSH EBP
34568 MOV EBP, ESP
34570 PUSH ECX // Params.WindowClass.lpszClassName := nil
34571 PUSH ECX // Params.WindowClass.lpszMenuName := nil
34572 PUSH ECX // Params.WindowClass.hbrBackground := 0
34573 PUSH int_IDC_ARROW
34574 PUSH ECX
34575 CALL LoadCursor
34576 PUSH EAX // Params.WindowClass.hCursor := LoadCursor( 0, IDC_ARROW )
34577 XOR ECX, ECX
34578 PUSH ECX // Params.WindowClass.hIcon := 0
34579 PUSH [hInstance]// Params.WindowClass.hInstance := hInstance
34580 PUSH ECX // Params.WindowClass.cbWndExtra := 0
34581 PUSH ECX // Params.WindowClass.cbClsExtra := 0
34582 //PUSH offset DefWindowProc // Params.WindowClass.lpfnWndProc := @DefWindowProc
34583 PUSH [EBX].fDefWndProc // Params.WindowClass.lpfnWndProc := fDefWndProc
34584 PUSH [EBX].fClsStyle // Params.WindowClass.style := fStyle
34585 ADD ESP, -64
34586 PUSH ECX
34587 MOV EAX, EBX
34588 MOV EDX, ESP
34589 CALL get_ClassName
34590 POP EDX
34591 MOV EAX, ESP
34592 PUSH EDX
34593 //CALL StrPCopy // StrPCopy( Params.WinClsNamBuf, ClassName )
34594 CALL StrCopy
34595 CALL RemoveStr
34596 PUSH 0 // Params.Param := nil
34597 PUSH [hInstance] // Params.Inst := fInstance
34598 PUSH [EBX].fMenu // Params.Menu := fMenu
34599 MOV DL, 1
34600 MOV EAX, EBX
34601 CALL GetParentWnd
34602 PUSH EAX // Params.WndParent := GetParentWnd( True )
34604 MOV ECX, CW_USEDEFAULT
34605 MOV EAX, [EBX].fBoundsRect.Bottom
34606 MOV EDX, [EBX].fBoundsRect.Top
34607 SUB EAX, EDX
34608 JNZ @@1
34609 MOV EAX, ECX
34610 @@1: PUSH EAX // Params.Height := Height | CW_UseDefault
34611 MOV EAX, [EBX].fBoundsRect.Right
34612 SUB EAX, [EBX].fBoundsRect.Left
34613 {$IFDEF USE_CMOV}
34614 CMOVZ EAX, ECX
34615 {$ELSE}
34616 JNZ @@2
34617 MOV EAX, ECX
34618 @@2: {$ENDIF}
34620 PUSH EAX // Params.Width := Width | CW_UseDefault
34621 MOV EAX, [EBX].fBoundsRect.Left
34622 CMP [EBX].fIsControl, CL
34623 JNZ @@3
34624 TEST byte ptr [EBX].fChangedPosSz, 3
34625 JNZ @@3
34626 MOV EDX, ECX
34627 XCHG EAX, ECX
34628 @@3: PUSH EDX // Params.Y := Top | CW_UseDefault
34629 PUSH EAX // Params.X := Left | CW_UseDefault
34630 PUSH [EBX].fStyle // Params.Style := fStyle
34631 PUSH [EBX].fCaption // Params.Caption := fCaption
34632 LEA EAX, [ESP+40]
34633 PUSH EAX // Params.WinClassName := @Params.WinClsNamBuf
34634 PUSH [EBX].fExStyle // Params.ExStyle := fExStyle
34636 MOV ECX, [EBX].fControlClassName
34637 JECXZ @@registerClass
34638 LEA EAX, [ESP].TCreateWndParams.WindowClass
34639 PUSH EAX // @Params.WindowClass
34640 PUSH ECX // fControlClassName
34641 PUSH [hInstance] // hInstance
34642 CALL GetClassInfo
34643 MOV EAX, [ESP].TCreateWndParams.Inst
34644 MOV [ESP].TCreateWndParams.WindowClass.hInstance, EAX
34645 AND [ESP].TCreateWndParams.WindowClass.style, not CS_OFF
34646 @@registerClass:
34647 CMP [EBX].fDefWndProc, 0
34648 JNE @@fDefWndProc_ready
34649 MOV EAX, [ESP].TCreateWndParams.WindowClass.lpfnWndProc
34650 MOV [EBX].fDefWndProc, EAX
34651 @@fDefWndProc_ready:
34652 MOV ECX, [ESP].TCreateWndParams.WndParent
34653 INC ECX
34654 LOOP @@registerClass1
34655 TEST byte ptr [ESP].TCreateWndParams.Style+3, $40
34656 XCHG EAX, ECX
34657 JNZ @@fin
34658 @@registerClass1:
34659 MOV EAX, [ESP].TCreateWndParams.WinClassName
34660 MOV EDX, [ESP].TCreateWndParams.WindowClass.hInstance
34661 ADD ESP, -szWndClass
34662 PUSH ESP
34663 PUSH EAX
34664 PUSH EDX
34665 CALL GetClassInfo
34666 ADD ESP, szWndClass
34667 TEST EAX, EAX
34668 JNZ @@registered
34669 MOV EAX, [ESP].TCreateWndParams.WinClassName
34670 MOV [ESP].TCreateWndParams.WindowClass.lpszClassName, EAX
34671 MOV [ESP].TCreateWndParams.WindowClass.lpfnWndProc, offset WndFunc
34672 LEA EAX, [ESP].TCreateWndParams.WindowClass
34673 PUSH EAX
34674 CALL RegisterClass
34675 TEST EAX, EAX
34676 JZ @@fin
34677 @@registered:
34678 MOV [CreatingWindow], EBX
34679 CALL CreateWindowEx
34680 MOV [EBX].fHandle, EAX
34681 TEST EAX, EAX
34682 JZ @@fin
34683 PUSH EAX
34684 PUSH offset ID_SELF
34685 PUSH EAX
34687 //SendMessage(fHandle,WM_UPDATEUISTATE,UIS_CLEAR or (UISF_HIDEFOCUS shl 16),0);
34688 PUSH 0
34689 PUSH $10002 //UIS_CLEAR or (UISF_HIDEFOCUS shl 16)
34690 PUSH $0128 //WM_UPDATEUISTATE
34691 PUSH EAX
34692 CALL SendMessage
34694 CALL GetProp
34695 XCHG ECX, EAX
34696 POP EAX
34697 INC ECX
34698 LOOP @@propSet
34699 MOV [CreatingWindow], ECX
34700 PUSH EBX
34701 PUSH offset ID_SELF
34702 PUSH EAX
34703 CALL SetProp
34704 @@propSet:
34705 CMP [EBX].fIsControl, 0
34706 JNZ @@iconSet
34707 MOV EAX, EBX
34708 CALL GetIcon
34709 PUSH EAX
34710 PUSH 1
34711 PUSH WM_SETICON
34712 PUSH EBX
34713 CALL Perform
34714 @@iconSet:
34715 MOV ECX, [EBX].fCreateWndExt
34716 JECXZ @@dblbufcreate
34717 MOV EAX, EBX
34718 CALL ECX
34719 @@dblbufcreate:
34720 MOV EAX, EBX
34721 CALL Dword Ptr [ Global_DblBufCreateWnd ]
34722 @@applyfont:
34723 MOV EAX, EBX
34724 CALL ApplyFont2Wnd
34725 MOV EAX, EBX
34726 CALL ApplyFont2Wnd
34727 XCHG EAX, EBX
34728 CALL CreateChildWindows
34729 MOV AL, 1
34730 @@fin:
34731 MOV ESP, EBP
34732 POP EBP
34733 @@ret_false:
34734 POP EBX
34735 end;
34736 {$ELSE ASM_VERSION} //Pascal
34737 function TControl.CreateWindow: Boolean;
34738 const
34739 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;
34740 CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;
34741 var TempClass: TWndClass;
34742 Params: TCreateWndParams;
34743 ClassRegistered: Boolean;
34744 {$IFDEF _FPC}
34745 SClassName: String;
34746 {$ENDIF ASM_VERSION}
34747 begin
34748 {$IFDEF DEBUG_CREATEWINDOW}
34749 LogFileOutput( GetStartDir + 'Session.log', 'TControl.CreateWindow, ' +
34750 ' Self = ' + Int2Str( Integer( @ Self ) ) +
34751 ' Caption = ' + fCaption +
34752 ' fChildren = ' + Int2Hex( Integer( fChildren ), 4 ) +
34753 ' ChildCount = ' + Int2Str( ChildCount ) );
34754 {$ENDIF DEBUG_CREATEWINDOW}
34755 Result := False;
34756 if fParent <> nil then
34757 if fParent.GetWindowHandle = 0 then
34758 Exit;
34759 if fHandle <> 0 then
34760 begin
34761 if fCreateHidden then
34762 begin
34763 CreateChildWindows;
34764 Set_Visible( True );
34765 fCreateHidden := False;
34767 else
34768 begin
34769 CreateChildWindows;
34770 end;
34771 Result := True;
34772 Exit;
34773 end;
34775 if not fWindowed then Exit;
34777 FillChar( Params, Sizeof( Params ), 0 );
34778 Params.Caption := PChar( FCaption );
34779 Params.Style := FStyle;
34780 if not fEnabled then
34781 Params.Style := Params.Style or WS_DISABLED;
34782 Params.ExStyle := FExStyle;
34783 Params.WindowClass.style := FClsStyle;
34784 {Params.WindowClass.lpfnWndProc := @ DefWindowProc;
34785 if fDefWndProc <> nil then} //+-+
34786 Params.WindowClass.lpfnWndProc := FDefWndProc;
34787 Params.WindowClass.hCursor := LoadCursor( 0, IDC_ARROW );
34788 Params.WindowClass.hInstance := hInstance;
34789 Params.Inst := hInstance;
34790 {$IFDEF _FPC}
34791 SClassName := SubClassName;
34792 StrCopy( Params.WinClsNamBuf, @ SClassName[ 1 ] );
34793 {$ELSE}
34794 StrCopy( Params.WinClsNamBuf, @ SubClassName[ 1 ] );
34795 {$ENDIF}
34796 Params.WinClassName := @Params.WinClsNamBuf[ 0 ];
34797 Params.WndParent := GetParentWnd( True );
34798 Params.Menu := fMenu;
34799 Params.X := fBoundsRect.Left;
34800 Params.Y := fBoundsRect.Top;
34801 Params.Width := fBoundsRect.Right - fBoundsRect.Left;
34802 if Params.Width = 0 then
34803 Params.Width := CW_UseDefault;
34804 Params.Height := fBoundsRect.Bottom - fBoundsRect.Top;
34805 if Params.Height = 0 then
34806 Params.Height := CW_UseDefault;
34807 if not fIsControl then
34808 begin
34809 if not LongBool( fChangedPosSz and 3 ) then
34810 begin
34811 Params.X := CW_UseDefault;
34812 Params.Y := CW_UseDefault;
34813 end;
34814 end;
34816 if fControlClassName <> nil then
34817 begin // SUBCLASSING WINDOW
34818 GetClassInfo( Params.WindowClass.hInstance, fControlClassName,
34819 Params.WindowClass);
34820 Params.WindowClass.hInstance := Params.Inst;
34821 Params.WindowClass.style := Params.WindowClass.style
34822 and not CS_OFF or CS_ON;
34823 end;
34825 if FDefWndProc = nil then //+
34826 {$IFDEF F_P}
34827 Move( Params.WindowClass.lpfnWndProc, FDefWndProc, Sizeof( Pointer ) );
34828 {$ELSE}
34829 FDefWndProc := Params.WindowClass.lpfnWndProc;
34830 {$ENDIF}
34831 if (Params.WndParent = 0) and (Params.Style and WS_CHILD <> 0) then Exit;
34832 ClassRegistered := GetClassInfo( Params.WindowClass.hInstance,
34833 Params.WinClassName, TempClass );
34834 if not ClassRegistered then
34835 begin
34836 Params.WindowClass.lpszClassName := Params.WinClassName;
34837 Params.WindowClass.lpfnWndProc := fWndFunc;
34838 if RegisterClass( Params.WindowClass ) = 0 then Exit;
34839 end;
34840 {$IFDEF DEBUG_CREATEWINDOW}
34841 LogFileOutput( GetStartDir + 'Session.log',
34842 ' ExStyle=' + Int2Hex( Params.ExStyle, 4 ) +
34843 ' WinClassName=' + Params.WinClassName +
34844 ' Caption=' + Params.Caption +
34845 ' Style=' + Int2Hex( Params.Style, 4 ) +
34846 ' X=' + Int2Str( Params.X ) +
34847 ' Y=' + Int2Str( Params.Y ) +
34848 ' Width=' + Int2Str( Params.Width ) +
34849 ' Height=' + Int2Str( Params.Height ) +
34850 ' WndParent=' + Int2Str( Params.WndParent ) +
34851 ' Menu=' + Int2Str( Params.Menu ) +
34852 ' hInstance=' + Int2Str( Params.WindowClass.hInstance ) +
34853 ' Param=' + Int2Str( Integer( Params.Param ) )
34855 {$ENDIF}
34856 CreatingWindow := @Self;
34857 fHandle := CreateWindowEx( Params.ExStyle, Params.WinClassName,
34858 Params.Caption, Params.Style, Params.X, Params.Y,
34859 Params.Width, Params.Height, Params.WndParent,
34860 Params.Menu, Params.WindowClass.hInstance,
34861 Params.Param );
34862 if fHandle = 0 then Exit;
34863 SendMessage( fHandle, $0128 {WM_UPDATEUISTATE},
34864 2 {UIS_CLEAR} or (1 {UISF_HIDEFOCUS} shl 16),0);
34865 if GetProp(FHandle,ID_SELF) = 0 then
34866 begin
34867 CreatingWindow := nil;
34868 SetProp(FHandle, ID_SELF, THandle(@Self));
34869 end;
34870 //***
34871 if not fIsControl then
34872 SendMessage( fHandle, WM_SETICON, 1 {ICON_BIG}, GetIcon );
34873 if Assigned( FCreateWndExt ) then
34874 FCreateWndExt( @Self );
34875 Global_DblBufCreateWnd( @ Self );
34876 ApplyFont2Wnd;
34877 ApplyFont2Wnd;
34879 CreateChildWindows;
34880 Result := True;
34881 end;
34882 {$ENDIF}
34885 //[procedure TControl.CreateSubclass]
34886 procedure TControl.CreateSubclass(var Params: TCreateParams;
34887 ControlClassName: PChar);
34888 const
34889 CS_OFF = CS_OWNDC or CS_CLASSDC or CS_PARENTDC or CS_GLOBALCLASS;
34890 CS_ON = 0; //CS_VREDRAW or CS_HREDRAW;
34892 SaveInstance: THandle;
34893 begin
34894 if fControlClassName <> nil then
34895 with Params do
34896 begin
34897 SaveInstance := WindowClass.hInstance;
34898 if not GetClassInfo(HInstance, fControlClassName, WindowClass) and
34899 not GetClassInfo(0, fControlClassName, WindowClass)
34900 //and not GetClassInfo(HInstance {MainInstance}, fControlClassName, WindowClass)
34901 then
34902 GetClassInfo(WindowClass.hInstance, fControlClassName, WindowClass);
34903 WindowClass.hInstance := SaveInstance;
34904 WindowClass.style := WindowClass.style and not CS_OFF or CS_ON;
34905 end;
34906 end;
34908 //[FUNCTION WndProcMous]
34909 {$IFDEF ASM_VERSION}
34910 function WndProcMouse(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
34912 PUSH EBX
34913 PUSH ESI
34914 XCHG EBX, EAX
34916 XOR ECX, ECX // Rslt not used. ECX <= Result = 0
34917 MOV EAX, [EDX].TMsg.message
34918 SUB AH, WM_MOUSEFIRST shr 8
34919 CMP EAX, $20A - WM_MOUSEFIRST //WM_MOUSELAST - WM_MOUSEFIRST
34920 JA @@exit
34922 PUSH dword ptr [EDX].TMsg.lParam // prepare X, Y
34924 PUSHAD
34925 PUSH VK_MENU
34926 CALL GetKeyState
34927 ADD EAX, EAX
34928 POPAD
34930 XCHG EAX, EDX
34931 MOV EAX, [EAX].TMsg.wParam
34933 JNC @@noset_MKALT
34934 {$IFDEF PARANOIA}
34935 DB $0C, MK_ALT
34936 {$ELSE}
34937 OR AL, MK_ALT
34938 {$ENDIF}
34939 @@noset_MKALT:
34941 PUSH EAX // prepare Shift
34943 LEA ESI, [EBX].TControl.fOnMouseDown
34944 CALL dword ptr [EDX*4 + @@jump_table]
34946 @@call_evnt:
34948 PUSH ECX // prepare Button, StopHandling
34949 MOV ECX, ESP // ECX = @MouseData
34951 CMP word ptr [ESI].TMethod.Code+2, 0
34952 JZ @@after_call
34954 MOV EDX, EBX // EDX = Self_
34955 MOV EAX, [ESI].TMethod.Data // EAX = Target_
34956 CALL dword ptr [ESI].TMethod.Code
34958 @@after_call:
34959 POP ECX
34960 POP EDX
34961 POP EDX
34962 MOV CL, CH // Result := StopHandling
34964 @@exit:
34965 XCHG EAX, ECX
34966 POP ESI
34967 POP EBX
34970 @@jump_table:
34971 DD Offset[@@MMove],Offset[@@LDown],Offset[@@LUp],Offset[@@LDblClk]
34972 DD Offset[@@RDown],Offset[@@RUp],Offset[@@RDblClk]
34973 DD Offset[@@MDown],Offset[@@MUp],Offset[@@MDblClk],Offset[@@MWheel]
34975 @@MDown: INC ECX
34976 @@RDown: INC ECX
34977 @@LDown: INC ECX
34978 //LEA ESI, [EBX].TControl.fOnMouseDown
34981 @@MUp: INC ECX
34982 @@RUp: INC ECX
34983 @@LUp: INC ECX
34984 //LEA ESI, [EBX].TControl.fOnMouseUp
34985 LODSD
34986 LODSD
34989 @@MMove: LEA ESI, [EBX].TControl.fOnMouseMove
34990 //ADD ESI, 16
34993 @@MDblClk: INC ECX
34994 @@RDblClk: INC ECX
34995 @@LDblClk: INC ECX
34996 LEA ESI, [EBX].TControl.fOnMouseDblClk
34997 //ADD ESI, 24
35000 @@MWheel:LEA ESI, [EBX].TControl.fOnMouseWheel
35001 //ADD ESI, 32
35002 //RET
35003 end;
35004 {$ELSE ASM_VERSION} //Pascal
35005 function WndProcMouse(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35006 var MouseData: TMouseEventData;
35007 begin
35008 Result := False;
35009 if (Msg.message >= WM_MOUSEFIRST) and (Msg.message <= $20A {WM_MOUSELAST})
35010 { and
35011 ((Msg.hwnd = Self_.fHandle) or (not Self.fWindowed))} then
35012 with MouseData do
35013 begin
35014 Shift := Msg.wParam;
35015 if GetKeyState( VK_MENU ) < 0 then
35016 Shift := Shift or MK_ALT;
35017 X := LoWord( Msg.lParam );
35018 Y := HiWord( Msg.lParam );
35019 //Button := TMouseButton(Msg.wParam);
35020 // not possible: wParam can contain a combination of flags
35021 // MK_CONTROL, MK_LBUTTON, MK_RBUTTON, MK_MBUTTON, MK_SHIFT, MK_XBUTTON1, MK_XBUTTON2
35022 // So, Shift must be tested.
35023 Button := mbNone;
35025 StopHandling := FALSE;
35026 Rslt := 0; // needed ?
35027 case Msg.message of
35028 WM_LBUTTONDOWN:
35029 if Assigned( Self_.OnMouseDown ) then
35030 begin
35031 Button := mbLeft;
35032 Self_.OnMouseDown( Self_, MouseData );
35033 end;
35034 WM_RBUTTONDOWN:
35035 if Assigned( Self_.OnMouseDown ) then
35036 begin
35037 Button := mbRight;
35038 Self_.OnMouseDown( Self_, MouseData );
35039 end;
35040 WM_MBUTTONDOWN:
35041 if Assigned( Self_.OnMouseDown ) then
35042 begin
35043 Button := mbMiddle;
35044 Self_.OnMouseDown( Self_, MouseData );
35045 end;
35046 WM_LBUTTONUP:
35047 if Assigned( Self_.OnMouseUp ) then
35048 begin
35049 Button := mbLeft;
35050 Self_.OnMouseUp( Self_, MouseData );
35051 end;
35052 WM_RBUTTONUP:
35053 if Assigned( Self_.OnMouseUp ) then
35054 begin
35055 Button := mbRight;
35056 Self_.OnMouseUp( Self_, MouseData );
35057 end;
35058 WM_MBUTTONUP:
35059 if Assigned( Self_.OnMouseUp ) then
35060 begin
35061 Button := mbMiddle;
35062 Self_.OnMouseUp( Self_, MouseData );
35063 end;
35064 WM_MOUSEMOVE:
35065 if Assigned( Self_.OnMouseMove ) then
35066 Self_.OnMouseMove( Self_, MouseData );
35067 WM_LBUTTONDBLCLK:
35068 if Assigned( Self_.OnMouseDblClk ) then
35069 begin
35070 Button := mbLeft;
35071 Self_.OnMouseDblClk( Self_, MouseData );
35072 end;
35073 WM_RBUTTONDBLCLK:
35074 if Assigned( Self_.OnMouseDblClk ) then
35075 begin
35076 Button := mbRight;
35077 Self_.OnMouseDblClk( Self_, MouseData );
35078 end;
35079 WM_MBUTTONDBLCLK:
35080 if Assigned( Self_.OnMouseDblClk ) then
35081 begin
35082 Button := mbMiddle;
35083 Self_.OnMouseDblClk( Self_, MouseData );
35084 end;
35085 $020A {WM_MOUSEWHEEL}:
35086 if Assigned( Self_.OnMouseWheel ) then
35087 Self_.OnMouseWheel( Self_, MouseData );
35088 else
35089 Exit; //Result := False;
35090 end;
35091 Result := StopHandling;
35092 end;
35093 end;
35094 {$ENDIF ASM_VERSION}
35095 //[END WndProcMous]
35097 //[FUNCTION WndProcKeybd]
35098 {$IFDEF ASM_VERSION}
35099 function WndProcKeybd( Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35101 PUSH EBX
35102 MOV ECX, [EDX].TMsg.message
35103 SUB CX, $100
35104 CMP ECX, 5
35105 JA @@fin_false
35106 XCHG EBX, EAX // EBX = @Self
35107 XCHG EAX, ECX // EAX = message - WM_KEYFIRST
35108 LEA ECX, [EBX].TControl.fOnKeyUp
35109 JZ @@event
35110 {$IFDEF PARANOIA}
35111 DB $34, 1
35112 {$ELSE}
35113 XOR AL, 1
35114 {$ENDIF}
35115 JZ @@event
35116 LEA ECX, [EBX].TControl.fOnKeyDown
35117 {$IFDEF PARANOIA}
35118 DB $34, 1
35119 {$ELSE}
35120 XOR AL, 1
35121 {$ENDIF}
35122 JZ @@event
35123 {$IFDEF PARANOIA}
35124 DB $34, 4
35125 {$ELSE}
35126 XOR AL, 4
35127 {$ENDIF}
35128 JZ @@event
35129 LEA ECX, [EBX].TControl.fOnChar
35130 {$IFDEF PARANOIA}
35131 DB $34, 6
35132 {$ELSE}
35133 XOR AL, 2 xor 4
35134 {$ENDIF}
35135 JZ @@event
35136 {$IFDEF PARANOIA}
35137 DB $34, 4
35138 {$ELSE}
35139 XOR AL, 6 xor 2
35140 {$ENDIF}
35141 JNZ @@fin_false
35142 @@event:
35143 CMP word ptr [ECX].TMethod.Code+2, 0
35144 JZ @@fin_false
35145 PUSH EDX
35146 PUSH ECX
35147 LEA ECX, [EDX].TMsg.wParam
35148 PUSH ECX
35149 CALL GetShiftState
35150 POP ECX // @wParam
35151 XCHG EAX, [ESP] // ShiftState; EAX=@event
35152 MOV EDX, EBX // @Self
35153 MOV EBX, [EAX].TMethod.Code
35154 MOV EAX, [EAX].TMethod.Data
35155 CALL EBX
35157 POP EDX
35158 MOV ECX, [EDX].TMsg.wParam
35159 JECXZ @@fin_true
35161 @@fin_false:
35162 XOR EAX, EAX
35163 POP EBX
35166 @@fin_true:
35167 MOV AL, 1
35168 POP EBX
35169 end;
35170 {$ELSE ASM_VERSION} //Pascal
35171 function WndProcKeybd(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35172 var C : Char;
35173 begin
35174 Result := True;
35175 case Msg.message of
35176 WM_KEYDOWN, WM_SYSKEYDOWN:
35177 if assigned( Self_.fOnKeyDown ) then
35178 Self_.fOnKeyDown( Self_, Msg.wParam, GetShiftState );
35179 WM_KEYUP, WM_SYSKEYUP:
35180 if assigned( Self_.fOnKeyUp ) then
35181 Self_.fOnKeyUp( Self_, Msg.wParam, GetShiftState );
35182 WM_CHAR, WM_SYSCHAR:
35183 if assigned( Self_.fOnChar ) then
35184 begin
35185 C := Char( Msg.wParam );
35186 Self_.fOnChar( Self_, C, GetShiftState );
35187 Msg.wParam := Integer( C );
35188 end;
35189 else begin
35190 Result := False;
35191 Exit;
35192 end;
35193 end;
35194 if Msg.wParam <> 0 then
35195 Result := False;
35196 end;
35197 {$ENDIF ASM_VERSION}
35198 //[END WndProcKeybd]
35200 //[function WndProcDummy]
35201 function WndProcDummy(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
35202 begin
35203 Result := False;
35204 end;
35206 //[procedure ExcludeCtlsWhichCannotDblBuf]
35207 procedure ExcludeCtlsWhichCannotDblBuf( Sender, ParentCtl: PControl; DC: HDC );
35208 var I: Integer;
35209 C: PControl;
35210 R, R1: TRect;
35211 begin
35212 for I := 0 to ParentCtl.fChildren.Count-1 do
35213 begin
35214 C := ParentCtl.fChildren.Items[ I ];
35215 if C.fCannotDoubleBuf then
35216 begin
35217 GetWindowRect( Sender.fHandle, R );
35218 GetWindowRect( C.fHandle, R1 );
35219 OffsetRect( R1, -R.Left, -R.Top );
35220 ExcludeClipRect(DC, R1.Left, R1.Top, R1.Right, R1.Bottom);
35222 else
35223 ExcludeCtlsWhichCannotDblBuf( Sender, C, DC );
35224 end;
35225 end;
35227 //[procedure DoReleaseDblBufBmp]
35228 procedure DoReleaseDblBufBmp( Sender: PControl );
35229 begin
35230 if Sender.fDblBufBmp <> 0 then
35231 DeleteObject( Sender.fDblBufBmp );
35232 end;
35234 //[procedure DoDrawChildrenDblBuffered]
35235 procedure DoDrawChildrenDblBuffered( DC: HDC; WndParent: HWnd; const RectParent: TRect;
35236 W: HWnd );
35237 var R, CR: TRect;
35238 Save: Integer;
35239 P, P0: TPoint;
35240 begin
35241 while W <> 0 do
35242 begin
35243 if IsWindowVisible( W ) then
35244 begin
35245 Save := SaveDC( DC );
35246 GetWindowRect( W, R );
35247 GetWindowOrgEx( DC, P );
35248 SetWindowOrgEx( DC, P.x - ( R.Left - RectParent.Left ), P.y - ( R.Top - RectParent.Top ), nil );
35249 IntersectClipRect( DC, 0, 0, R.Right - R.Left, R.Bottom - R.Top );
35250 SendMessage( W, WM_PRINT, DC, PRF_NONCLIENT );
35251 GetClientRect( W, CR );
35252 P0.x := 0; P0.y := 0;
35253 ClientToScreen( W, P0 );
35254 OffsetRect( CR, P0.x, P0.y );
35255 SetWindowOrgEx( DC, P.x - (CR.Left - RectParent.Left), P.y - (CR.Top - RectParent.Top), nil );
35256 IntersectClipRect( DC, 0, 0, CR.Right - CR.Left, CR.Bottom - CR.Top );
35257 SendMessage( W, WM_ERASEBKGND, DC, 0 );
35258 SendMessage( W, WM_PAINT, DC, 0 );
35259 DoDrawChildrenDblBuffered( DC, W, CR, GetWindow( W, GW_CHILD ) );
35260 RestoreDC( DC, Save );
35261 end;
35262 W := GetWindow( W, GW_HWNDNEXT );
35263 end;
35264 end;
35266 //[procedure DoDrawDblBuffered]
35267 procedure DoDrawDblBuffered( Sender: PControl );
35268 var R: TRect;
35269 DC0, DC1, DC2: HDC;
35270 OldBmp: HBitmap;
35271 R2: TRect;
35272 P1, P2: TPoint;
35273 ClientOnly: Boolean;
35274 OldPaintDC: HDC;
35275 {$IFDEF DEBUGDBLBUFF}
35276 Tmp: PBitmap;
35277 {$ENDIF}
35278 begin
35279 if not GetUpdateRect( Sender.fHandle, R, FALSE ) then
35280 Exit; // nothing to paint
35282 Sender.fDblBufPainting := TRUE;
35284 ClientOnly := Sender.fIsForm {and (WinVer < wvNT)};
35285 if ClientOnly then
35286 GetClientRect( Sender.fHandle, R )
35287 else
35288 begin
35289 GetWindowRect( Sender.fHandle, R );
35290 OffsetRect( R, -R.Left, -R.Top );
35291 end;
35293 DC0 := GetDC( Sender.fHandle );
35294 DC1 := CreateCompatibleDC( DC0 );
35295 if Sender.fDblBufBmp = 0 then
35296 Sender.Add2AutoFreeEx( TObjectMethod( MakeMethod( Sender, @ DoReleaseDblBufBmp ) ) );
35297 if (Sender.fDblBufW < R.Right) or (Sender.fDblBufH < R.Bottom) or
35298 (Sender.fDblBufW > R.Right + 32) or (Sender.fDblBufH > R.Bottom + 32) then
35299 if Sender.fDblBufBmp <> 0 then
35300 begin
35301 DeleteObject( Sender.fDblBufBmp );
35302 Sender.fDblBufBmp := 0;
35303 end;
35304 if Sender.fDblBufBmp = 0 then
35305 begin
35306 Sender.fDblBufBmp := CreateCompatibleBitmap( DC0, R.Right, R.Bottom );
35307 Sender.fDblBufW := R.Right;
35308 Sender.fDblBufH := R.Bottom;
35309 end;
35310 OldBmp := SelectObject( DC1, Sender.fDblBufBmp );
35312 OldPaintDC := Sender.fPaintDC;
35313 Sender.fPaintDC := DC1;
35314 if ClientOnly then
35315 begin
35316 GetClientRect( Sender.fHandle, R2 );
35317 P2.x := 0; P2.y := 0;
35318 ClientToScreen( Sender.fHandle, P2 );
35319 OffsetRect( R2, P2.x, P2.y );
35320 SendMessage( Sender.fHandle, WM_ERASEBKGND, DC1, 0 );
35321 SendMessage( Sender.fHandle, WM_PAINT, DC1, 0 );
35322 DoDrawChildrenDblBuffered( DC1, Sender.fHandle, R2,
35323 GetWindow( Sender.fHandle, GW_CHILD ) );
35325 else
35326 begin
35327 {Sender.Perform( WM_PRINT, DC1,
35328 PRF_CLIENT or PRF_NONCLIENT or PRF_ERASEBKGND or PRF_CHILDREN );}
35329 GetWindowRect( Sender.fHandle, R2 );
35330 DoDrawChildrenDblBuffered( DC1, Sender.fHandle, R2, Sender.fHandle );
35331 end;
35332 //Sender.fPaintDC := DC1;
35334 DC2 := GetWindowDC( Sender.fHandle );
35336 ExcludeCtlsWhichCannotDblBuf( Sender, Sender, DC2 );
35338 P1.x := 0; P1.y := 0;
35339 if ClientOnly then
35340 begin
35341 GetWindowRect( Sender.fHandle, R2 );
35342 ClientToScreen( Sender.fHandle, P1 );
35343 P1.x := P1.x - R2.Left;
35344 P1.y := P1.y - R2.Top;
35345 GetClientRect( Sender.fHandle, R );
35346 end;
35347 BitBlt( DC2, P1.x, P1.y, R.Right, R.Bottom, DC1, 0, 0, SRCCOPY );
35349 {$IFDEF DEBUGDBLBUFF}
35350 Tmp := NewDIBBitmap( R.Right, R.Bottom, pf16bit );
35351 BitBlt( Tmp.Canvas.Handle, 0, 0, R.Right, R.Bottom, DC1, 0, 0, SRCCopy );
35352 Tmp.SaveToFile( 'c:\tmp.bmp' );
35353 Tmp.Free;
35354 {$ENDIF}
35356 ReleaseDC( Sender.fHandle, DC2 );
35358 SelectObject( DC1, OldBmp );
35359 DeleteDC( DC1 );
35360 ReleaseDC( Sender.fHandle, DC0 );
35362 Sender.fPaintDC := OldPaintDC;
35363 ValidateRect( Sender.fHandle, nil );
35365 Sender.fDblBufPainting := FALSE;
35366 end;
35368 //[function WndProcBufferedDraw]
35369 function WndProcBufferedDraw( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
35370 var Self_DblBufTopParent: PControl;
35371 begin
35372 Result := False;
35373 //if AppletTerminated then Exit;
35374 case Msg.message of
35375 WM_ERASEBKGND:
35376 begin
35377 if Self_.fCannotDoubleBuf then Exit;
35378 if Self_.DblBufTopParent <> nil then
35379 // if the Control is not DoubleBuffered, and none of its Parent controls are
35380 // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work
35381 // as usual.
35382 begin // Call made in WndProcBufferedDraw of the top DoubleBuffered
35383 // Parent control, while processing WM_PAINT
35384 if Self_.fTransparent
35385 // Handle opaque control as usual.
35386 // For transparent (child) controls, do nothing at all
35387 // in responce to WM_ERASEBKGND (just tell to the system, that
35388 // the operation completed).
35390 // If DoubleBuffered control or control's DoubleBuffered parent
35391 // is not painting now through buffer, just ignore the message
35392 not Self_.DblBufTopParent.fDblBufPainting
35393 then
35394 begin
35395 if Self_.fParent <> nil then
35396 begin
35397 Rslt := 1;
35398 Result := TRUE;
35399 Exit;
35400 end;
35401 end;
35402 end;
35403 end;
35404 WM_PAINT:
35405 begin
35406 if Self_.fCannotDoubleBuf then Exit;
35407 Self_DblBufTopParent := Self_.DblBufTopParent;
35408 if Self_DblBufTopParent = nil then
35409 // if the Control is not DoubleBuffered, and none of its Parent controls are
35410 // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work
35411 // as usual.
35412 Exit;
35413 if Self_DblBufTopParent <> Self_ then
35414 // if one of the Parent controls is DoubleBuffered, than ignore this call
35415 // in Global_OnBufferedDraw, and work as usual (actually this allows to
35416 // paint children of the DoubleBuffered Parent control to be painted on
35417 // its buffer).
35418 begin
35419 if (not Self_DblBufTopParent.fDblBufPainting) or
35420 (Self_DblBufTopParent.fPaintDC = 0) then
35421 begin // Usual call. Ignore it.
35422 ValidateRect( Self_.fHandle, nil );
35423 //RedrawWindow( Self_.fHandle, nil, 0, RDW_VALIDATE ); experiment
35424 if not Self_DblBufTopParent.fDblBufPainting then
35425 begin
35426 Self_.DblBufTopParent.Invalidate;
35427 //RedrawWindow( Self_DblBufTopParent.fHandle, nil, 0, RDW_INVALIDATE ); exp.
35428 //RedrawWindow( Self_DblBufTopParent.fHandle, nil, 0, RDW_UPDATENOW ); exp.
35429 end;
35430 Rslt := 0;
35431 Result := True;
35432 end;
35433 Exit; // Call from DoDrawDblBuffered of the top doublebuffered Parent
35434 end;
35435 if Msg.wParam <> 0 then Exit;
35436 DoDrawDblBuffered( Self_ );
35437 Rslt := 0;
35438 Result := True;
35439 end;
35440 WM_NCPAINT:
35441 begin
35442 if Self_.fIsForm {and (WinVer < wvNT)} then Exit;
35443 if Self_.CannotDoubleBuf then Exit;
35444 Self_DblBufTopParent := Self_.DblBufTopParent;
35445 if Self_DblBufTopParent = nil then
35446 // if the Control is not DoubleBuffered, and none of its Parent controls are
35447 // DoubleBuffered, than ignore this call in Global_OnBufferedDraw, and work
35448 // as usual.
35449 Exit;
35450 //if Self_.DblBufTopParent <> Self_ then
35451 // if one of the Parent controls is DoubleBuffered, than ignore this call
35452 // in Global_OnBufferedDraw, and work as usual (actually this allows to
35453 // paint children of the DoubleBuffered Parent control to be painted on
35454 // its buffer).
35455 begin
35456 if not Self_DblBufTopParent.fDblBufPainting
35457 then
35458 begin // Usual call. Ignore it.
35459 //ValidateRect( Self_.fHandle, nil );
35460 Rslt := 0;
35461 Result := True;
35462 end;
35463 end;
35464 end;
35465 WM_SETTEXT:
35466 begin
35467 if Self_.DblBufTopParent = nil then Exit;
35468 if Self_.fIsStaticControl = 0 then Exit;
35469 ShowWindow( Self_.fHandle, SW_HIDE );
35470 Rslt := DefWindowProc( Self_.fHandle, WM_SETTEXT, Msg.wParam, Msg.lParam );
35471 ShowWindow( Self_.fHandle, SW_SHOWNA );
35472 UpdateWindow( Self_.fHandle ); // necessary!!!
35473 Result := True;
35474 end;
35475 WM_HSCROLL, WM_VSCROLL, WM_WINDOWPOSCHANGED:
35476 begin
35477 if Self_.DblBufTopParent = nil then Exit;
35478 Self_.Invalidate;
35479 end;
35480 WM_COMMAND:
35481 case HiWord( Msg.wParam ) of
35482 LBN_SELCHANGE {, CBN_SELCHANGE }:
35483 begin
35484 if Self_.DblBufTopParent = nil then Exit;
35485 Self_.Invalidate;
35486 end;
35487 end;
35488 end;
35489 end;
35491 const
35492 MM_MCINOTIFY = $3B9;
35494 {$IFDEF ASM_VERSION}
35496 {$DEFINE ASM_LOCAL}
35497 {$IFDEF NEW_MODAL}
35498 {$UNDEF ASM_LOCAL}
35499 {$ENDIF}
35501 {$ELSE}
35503 {$IFDEF ASM_LOCAL}
35504 {$UNDEF ASM_LOCAL}
35505 {$ENDIF}
35507 {$ENDIF}
35509 {$IFDEF ASM_LOCAL}
35510 //[function TControl.WndProc]
35511 function TControl.WndProc( var Msg: TMsg ): Integer;
35512 asm //cmd //opd
35513 PUSH EBX
35514 PUSH ESI
35515 PUSH EDI
35516 XCHG ESI, EAX
35517 MOV EDI, EDX
35518 XOR EAX, EAX
35519 CMP EAX, [EDX].TMsg.hWnd
35520 JNE @@1
35521 CMP EAX, [ESI].TControl.fHandle
35522 JNE @@1
35523 CMP [ESI].TControl.fWindowed, AL
35524 JNZ @@1
35525 MOV EAX, [EDX].TMsg.hWnd
35526 MOV [ESI].TControl.fHandle, EAX
35527 @@1:
35528 PUSH 0
35529 MOV ECX, ESP
35530 MOV EAX, ESI
35531 CALL dword ptr [Global_OnBufferedDraw]
35532 TEST AL, AL
35533 POP EAX
35534 JNZ @@pass2defproc
35536 CMP [AppletRunning], 0
35537 JZ @@dyn2
35538 MOV ECX, [Applet]
35539 JECXZ @@dyn2
35540 CMP ECX, ESI
35541 JE @@dyn2
35543 CALL @@onmess
35545 @@dyn2: MOV ECX, ESI
35546 CALL @@onmess
35548 MOV EBX, [ESI].TControl.fOnDynHandlers
35549 MOV EAX, ESI
35550 CALL @@callonmes
35552 @@flicksproc:
35553 MOV EAX, ESI
35554 MOV EDX, EDI
35555 PUSH 0
35556 MOV ECX, ESP
35557 CALL dword ptr [ESI].TControl.fWndProcResizeFlicks
35558 TEST AL, AL
35559 POP EAX
35560 JNZ @@pass2defproc
35562 MOVZX EAX, word ptr [EDI].TMsg.message
35564 //CMP word ptr [EDI].TMsg.message, WM_CLOSE
35565 CMP AX, WM_CLOSE
35566 //********************************************************** Changed By M.Gerasimov
35567 // JNE @@chk_WM_NCDESTROY
35568 JNE @@chk_WM_DESTROY
35569 //********************************************************** Changed By M.Gerasimov
35571 MOV ECX, [ESI].TControl.fOnClose.TMethod.Code
35572 JECXZ @@wm_close1
35573 MOV EBX, ECX
35574 PUSH 1
35575 MOV ECX, ESP
35576 MOV EDX, ESI
35577 MOV EAX, [ESI].TControl.fOnClose.TMethod.Data
35578 CALL EBX
35579 POP ECX
35580 INC ECX
35581 LOOP @@wm_close0
35582 CMP [AppletRunning], CL
35583 JZ @@wm_close0
35584 //XOR EAX, EAX
35585 //MOV [ESI].TControl.fModalResult, 0
35586 JMP @@0pass2defproc
35588 /////////////////
35589 @@onmess:
35590 MOV EAX, [ECX].TControl.fOnMessage.TMethod.Data
35591 MOV EBX, [ECX].TControl.fOnMessage.TMethod.Code
35592 @@callonmes:
35593 TEST EBX, EBX
35594 JNZ @@onmess1 // @@dynmes1
35595 @@2onmessret:
35597 @@onmess1:
35598 PUSH 0
35600 MOV EDX, EDI
35601 MOV ECX, ESP
35602 CALL EBX
35603 TEST AL, AL
35605 POP EAX
35606 JZ @@2onmessret
35607 POP EDX // pop retaddr
35608 JMP @@pass2defproc
35609 /////////////////
35611 @@wm_close0:
35612 XOR EAX, EAX
35613 MOV [ESI].TControl.fOnClose.TMethod.Code, EAX
35614 @@wm_close1:
35615 MOV EAX, ESI
35616 CALL TControl.IsMainWindow
35617 TEST AL, AL
35618 MOV ECX, [Applet]
35619 JNZ @@wm_close2
35620 CMP ESI, ECX
35621 JNE @@calldef
35623 @@wm_close2:
35624 JECXZ @@postquit
35625 CMP ECX, ESI
35626 JE @@postquit
35627 PUSH 0
35628 PUSH 0
35629 PUSH WM_CLOSE
35630 PUSH ECX
35631 CALL TControl.Perform
35632 @@postquit:
35633 PUSH 0
35634 CALL PostQuitMessage
35635 //XOR EAX, EAX
35636 JMP @@0pass2defproc
35638 //********************************************************** Added By M.Gerasimov
35640 @@chk_WM_DESTROY:
35641 //********************************************************** Added By M.Gerasimov
35642 @@chk_WM_NCDESTROY:
35643 //CMP word ptr [EDI].TMsg.message, WM_NCDESTROY
35644 CMP AX, WM_NCDESTROY
35645 JNE @@chk_CM_RELEASE
35646 //********************************************************** Added By M.Gerasimov
35648 PUSH offset[ID_SELF]
35649 PUSH [ESI].fHandle
35650 CALL RemoveProp
35652 //********************************************************** Added By M.Gerasimov
35654 MOV ECX, [Applet]
35655 JECXZ @@nc_destroy1
35656 MOV EAX, [ESI].TControl.fHandle
35657 CMP EAX, [ECX].TControl.fHandle
35658 JE @@calldef
35659 @@nc_destroy1:
35660 MOV EAX, ESI
35661 CALL TControl.IsMainWindow
35662 TEST AL, AL
35663 JZ @@nc_destroy2
35664 PUSH 0
35665 PUSH 0
35666 PUSH CM_RELEASE
35667 PUSH [ESI].TControl.fHandle
35668 CALL PostMessage
35669 JMP @@calldef
35671 @@nc_destroy2:
35672 MOV EAX, [ESI].TControl.fParent
35673 CMP EAX, [Applet]
35674 JNE @@calldef
35676 MOV [ESI].TControl.fNCDestroyed, 1
35677 @@do_free:
35678 XCHG EAX, ESI
35679 CALL TObj.Free
35681 XOR EAX, EAX
35682 JMP @@exit // WM_NCDESTROY and CM_RELEASE
35683 // is not a subject to pass it
35684 // to fPass2DefProc
35686 @@chk_CM_RELEASE:
35687 CMP AX, CM_RELEASE
35688 JNE @@chk_WM_SIZE
35690 MOV [ESI].TControl.fDestroying, 1
35691 JMP @@do_free
35693 @@chk_WM_SIZE:
35694 CMP AX, WM_SIZE
35695 JNE @@chk_WM_SHOWWINDOW
35697 MOV EDX, EDI
35698 MOV EAX, ESI
35699 CALL TControl.CallDefWndProc
35700 PUSH EAX
35702 MOV ECX, [EDI].TMsg.wParam
35703 MOV [ESI].TControl.fWindowState, CL
35705 CMP [ESI].TControl.fIsForm, 0
35706 JNZ @@doGlobalAlignSelf
35707 MOV EAX, [ESI].TControl.fParent
35708 TEST EAX, EAX
35709 JZ @@doGlobalAlignSelf
35710 CALL dword ptr [Global_Align]
35711 @@doGlobalAlignSelf:
35712 XCHG EAX, ESI
35713 CALL dword ptr [Global_Align]
35715 JMP @@popeax_exit
35716 // fPass2DefProc not needed,
35717 // CallDefWndProc already called
35719 @@chk_WM_SHOWWINDOW:
35720 CMP AX, WM_SHOWWINDOW
35721 JNE @@chk_WM_SYSCOMMAND
35723 MOV ECX, [EDI].TMsg.lParam
35724 LOOP @@chk_SW_PARENTOPENING
35726 PUSH [ESI].TControl.fHandle
35727 CALL IsIconic
35728 XOR EBX, EBX
35729 MOV BL, SW_SHOWMINNOACTIVE
35730 TEST EAX, EAX
35731 JNZ @@store_action
35733 PUSH [ESI].TControl.fHandle
35734 CALL IsZoomed
35735 MOV BL, SW_SHOWMAXIMIZED
35736 TEST EAX, EAX
35737 JNZ @@store_action
35739 MOV BL, SW_SHOWNOACTIVATE
35740 @@store_action:
35741 MOV [ESI].TControl.fShowAction, EBX
35742 @@2calldef:
35743 JMP @@calldef
35745 @@chk_SW_PARENTOPENING:
35746 DEC ECX
35747 LOOP @@2calldef
35749 MOV ECX, [ESI].TControl.fShowAction
35750 JECXZ @@ret_0
35752 PUSH ECX
35753 PUSH [ESI].TControl.fHandle
35754 CALL ShowWindow
35756 XOR EAX, EAX
35757 MOV [ESI].TControl.fShowAction, EAX
35758 @@ret_0:
35759 //XOR EAX, EAX
35760 JMP @@0pass2defproc
35762 @@chk_WM_SYSCOMMAND:
35763 CMP AX, WM_SYSCOMMAND
35764 JNE @@chk_WM_SETFOCUS
35766 MOV EAX, [EDI].TMsg.wParam
35767 {$IFDEF PARANOIA}
35768 DB $24, $F0
35769 {$ELSE}
35770 AND AL, $F0
35771 {$ENDIF}
35772 CMP AX, SC_MINIMIZE
35773 JNE @@calldef
35775 MOV EAX, ESI
35776 CALL TControl.IsMainWindow
35777 TEST AL, AL
35778 JZ @@calldef
35780 CMP ESI, [Applet]
35781 JE @@calldef
35783 PUSH 0
35784 PUSH SC_MINIMIZE
35785 PUSH WM_SYSCOMMAND
35786 MOV EAX, [Applet]
35787 PUSH [EAX].TControl.fHandle
35788 CALL PostMessage
35789 JMP @@ret_0
35791 @@chk_WM_SETFOCUS:
35792 CMP AX, WM_SETFOCUS
35793 JNE @@chk_WM_SETCURSOR
35795 MOV EAX, ESI
35796 CALL TControl.DoSetFocus
35797 TEST AL, AL
35798 JZ @@0pass2defproc
35800 INC [ESI].TControl.fClickDisabled
35802 MOV EAX, ESI
35803 MOV EDX, EDI
35804 CALL TControl.CallDefWndProc
35806 DEC [ESI].TControl.fClickDisabled
35807 JMP @@exit
35809 @@chk_WM_SETCURSOR:
35810 CMP AX, WM_SETCURSOR
35811 JNE @@chk_WM_CTLCOLOR
35813 CMP [Global_DisableParentCursor], 0
35814 JNE @@calldef
35816 CALL GetCapture
35817 TEST EAX, EAX
35818 JNZ @@calldef
35820 CMP word ptr [EDI].TMsg.lParam, HTCLIENT
35821 JNE @@calldef
35823 MOV ECX, [ScreenCursor]
35824 INC ECX
35825 LOOP @@setupCursor
35827 MOV ECX, [ESI].TControl.fCursor
35828 TEST ECX, ECX //YS
35829 JE @@calldef //YS
35830 @@setupCursor:
35831 PUSH ECX
35832 CALL Windows.SetCursor
35834 MOV AL, 1
35835 JMP @@exit
35837 @@chk_WM_CTLCOLOR:
35838 //MOV EAX, [EDI].TMsg.message
35839 MOV EDX, EAX
35840 SUB DX, WM_CTLCOLORMSGBOX
35841 CMP DX, WM_CTLCOLORSTATIC-WM_CTLCOLORMSGBOX
35842 JA @@chk_WM_COMMAND
35844 PUSH [EDI].TMsg.lParam
35845 PUSH [EDI].TMsg.wParam
35846 ADD AX, CN_BASE //+WM_CTLCOLORMSGBOX
35847 PUSH EAX
35848 PUSH [EDI].TMsg.lParam
35849 CALL SendMessage
35850 JMP @@pass2defproc
35852 @@chk_WM_COMMAND:
35853 //CMP word ptr [EDI].TMsg.message, WM_COMMAND
35854 CMP AX, WM_COMMAND
35855 JNE @@chk_WM_KEY
35857 PUSH offset[ID_SELF]
35858 PUSH [EDI].TMsg.lParam
35859 CALL GetProp
35860 TEST EAX, EAX
35861 JZ @@calldef
35863 PUSH [EDI].TMsg.lParam
35864 PUSH [EDI].TMsg.wParam
35865 PUSH CM_COMMAND
35866 PUSH [EDI].TMsg.lParam
35867 CALL SendMessage
35868 JMP @@pass2defproc
35870 @@chk_WM_KEY:
35871 MOV EDX, EAX
35872 SUB DX, WM_KEYFIRST
35873 CMP DX, WM_KEYLAST-WM_KEYFIRST
35874 JA @@chk_CM_EXECPROC
35876 CALL GetFocus
35877 CMP EAX, [ESI].TControl.fFocusHandle
35878 JE @@in_focus
35879 CMP EAX, [ESI].TControl.fHandle
35880 JE @@in_focus
35881 CMP [ESI].fWindowed, 0
35882 JNE @@0pass2defproc
35884 @@in_focus:
35885 PUSH EAX
35887 MOV ECX, ESP
35888 MOV EDX, EDI
35889 MOV EAX, ESI
35890 CALL dword ptr [fGlobalProcKeybd]
35891 TEST AL, AL
35892 JNZ @@to_exit
35894 MOV ECX, ESP
35895 MOV EDX, EDI
35896 MOV EAX, ESI
35897 CALL [ESI].fWndProcKeybd
35898 TEST AL, AL
35899 @@to_exit:
35900 POP EAX
35901 JNZ @@pass2defproc
35903 PUSH VK_CONTROL
35904 CALL GetKeyState
35905 XCHG EBX, EAX
35906 PUSH VK_MENU
35907 CALL GetKeyState
35908 OR EAX, EBX
35909 JS @@calldef
35911 CMP word ptr [EDI].TMsg.message, WM_CHAR
35912 JNE @@to_fGotoControl
35914 CMP byte ptr [EDI].TMsg.wParam, 9
35915 JE @@clear_wParam
35916 JMP @@calldef
35918 @@to_fGotoControl:
35919 MOV EAX, ESI
35920 CALL TControl.ParentForm
35921 TEST EAX, EAX
35922 JZ @@calldef
35924 MOV ECX, [EAX].fGotoControl
35925 JECXZ @@calldef
35927 MOV EBX, ECX
35928 CMP [EDI].TMsg.message, WM_KEYDOWN
35929 SETNE CL
35930 CMP [EDI].TMsg.message, WM_SYSKEYDOWN
35931 SETNE CH
35932 AND CL, CH
35933 MOV EDX, [EDI].TMsg.wParam
35934 MOV EAX, ESI
35935 CALL EBX
35936 TEST AL, AL
35937 JZ @@calldef
35939 @@clear_wParam:
35940 XOR EAX, EAX
35941 MOV [EDI].TMsg.wParam, EAX
35942 JMP @@pass2defproc
35944 @@chk_CM_EXECPROC:
35945 CMP AX, CM_EXECPROC
35946 JNE @@chk_MM_MCINOTIFY
35948 MOV EAX, [EDI].TMsg.lParam
35949 MOV EDX, [EDI].TMsg.wParam
35950 CALL [Global_Synchronized]
35951 JMP @@0pass2defproc
35953 @@chk_MM_MCINOTIFY:
35954 CMP AX, MM_MCINOTIFY
35955 JNE @@calldef
35957 MOV ECX, [FMMNotify]
35958 JECXZ @@ret_0_MM
35960 XCHG EAX, EDI
35961 CALL ECX
35962 @@ret_0_MM:
35963 XOR EAX, EAX
35964 JMP @@exit
35966 @@calldef:
35967 XCHG EAX, ESI
35968 MOV EDX, EDI
35969 CALL TControl.CallDefWndProc
35970 JMP @@exit
35972 @@0pass2defproc:
35973 XOR EAX, EAX
35974 @@pass2defproc:
35975 PUSH EAX
35976 @@1pass2defproc:
35977 CMP [AppletTerminated], 0 //
35978 JNZ @@popeax_exit // uncommented 25-Oct-2003
35979 CMP [ESI].fNCDestroyed, 0 //
35980 JNZ @@popeax_exit //
35982 MOV ECX, ESP
35983 XCHG EAX, ESI
35984 MOV EDX, EDI
35985 CALL dword ptr[EAX].fPass2DefProc
35986 @@popeax_exit:
35987 POP EAX
35989 @@exit:
35990 POP EDI
35991 POP ESI
35992 POP EBX
35993 end;
35994 {$ELSE ASM_LOCAL} //Pascal
35996 {$IFDEF DEBUG_CREATEWINDOW}
35997 var DbgCWCount: Integer = 0;
35998 {$ENDIF DEBUG_CREATEWINDOW}
35999 function TControl.WndProc( var Msg: TMsg ): Integer;
36000 var Accept: Boolean;
36001 C : PControl;
36002 F {, Chld}: HWnd;
36003 Cur: HCURSOR; // YS
36004 PassFun: function( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
36006 procedure Default;
36007 begin
36008 Result := CallDefWndProc( Msg );
36009 end;
36011 begin
36012 {$IFDEF DEBUG_CREATEWINDOW}
36013 Inc( DbgCWCount );
36014 if DbgCWCount < 10 then
36015 LogFileOutput( GetStartDir + 'Session.log', 'TControl.WndProc: ' +
36016 ' Msg.hwnd=' + Int2Str( Msg.hwnd ) +
36017 ' Msg.message=' + Int2Hex( Msg.message, 2 ) +
36018 ' Msg.wParam=' + Int2Str( Msg.wParam ) + '=$' + Int2Hex( Msg.wParam, 4 ) +
36019 ' Msg.lParam=' + Int2Str( Msg.lParam ) + '=$' + Int2Hex( Msg.lParam, 4 ) );
36020 {$ENDIF DEBUG_CREATEWINDOW}
36021 if (Msg.hwnd <> 0) and (fHandle = 0) and fWindowed then
36022 fHandle := Msg.hwnd;
36024 PassFun := fPass2DefProc;
36025 if not Global_OnBufferedDraw( @Self, Msg, Result ) then
36026 if not (AppletRunning and (Applet <> @Self) and Assigned( Applet ) and
36027 Assigned( Applet.OnMessage ) and Applet.OnMessage( Msg, Result )) then
36028 if not (Assigned( OnMessage ) and OnMessage( Msg, Result )) then
36029 if not fOnDynHandlers( @Self, Msg, Result ) then
36030 begin
36031 if not fWndProcResizeFlicks( @Self, Msg, Result ) then
36032 case Msg.message of
36033 {$IFDEF NEW_MODAL}
36034 // version of code by Alexander Pravdin
36035 WM_CLOSE:
36036 begin
36037 Accept := True;
36038 if Assigned( fOnClose ) then begin
36039 fOnClose( @Self, Accept );
36040 if AppletRunning then
36041 if Accept then
36042 if fModal > 0 then begin
36043 if ModalResult = 0 then
36044 fModalResult := Integer($80000000);
36045 Msg.message := 0;
36046 Exit;
36048 else
36049 fOnClose := nil
36050 else begin
36051 Result := 0;
36052 fModalResult := 0;
36054 else
36055 fOnClose := nil;
36057 else begin
36058 if fModal > 0 then begin
36059 if ModalResult = 0 then
36060 fModalResult := Integer($80000000);
36061 Exit;
36062 end;
36063 end;
36065 if Accept then begin
36066 if IsMainWindow or ( Applet = @Self ) then begin
36067 if Assigned( Applet ) and ( Applet <> @Self ) then
36068 Applet.Perform( WM_CLOSE, 0, 0 );
36069 PostQuitMessage( 0 );
36070 Result := 0;
36072 else
36073 Default;
36074 end;
36075 end;
36076 {$ELSE}
36077 WM_CLOSE: begin
36078 Accept := True;
36079 if Assigned( fOnClose ) then
36080 begin
36081 fOnClose( @Self, Accept );
36082 if (not Accept) and (AppletRunning) then
36083 begin
36084 Result := 0;
36085 //ModalResult := 0;
36086 //Exit; //?????????????????
36088 else //+-+
36089 fOnClose := nil;
36090 end;
36091 if Accept then
36092 begin
36093 if IsMainWindow or (Applet = @Self) then
36094 begin
36095 if Assigned( Applet ) and (Applet <> @Self) then
36096 Applet.Perform( WM_CLOSE, 0, 0 );
36097 PostQuitMessage( 0 );
36098 Result := 0;
36099 //Exit; //???????????????
36101 else
36102 Default;
36103 end;
36104 end;
36105 {$ENDIF}
36106 {//********************************************************** Added By M.Gerasimov
36108 WM_DESTROY:
36109 begin
36110 Chld := GetWindow( fHandle, GW_CHILD );
36111 while Chld <> 0 do
36112 begin
36113 if GetProp( Chld, ID_PREVPROC ) <> 0 then
36114 RemoveProp(Chld, ID_PREVPROC);
36115 Chld := GetWindow( Chld, GW_HWNDNEXT );
36116 end;
36117 end;
36119 //********************************************************** Added By M.Gerasimov}
36120 WM_NCDESTROY:
36121 begin
36122 //********************************************************** Added By M.Gerasimov
36124 RemoveProp( fHandle, ID_SELF );
36126 //********************************************************** Added By M.Gerasimov
36127 if (Applet = nil) or (Handle <> Applet.Handle) then
36128 begin
36129 if IsMainWindow then
36130 begin
36131 PostMessage( fHandle, CM_RELEASE, 0, 0 );
36132 Default;
36134 else
36135 if fParent = Applet then
36136 begin
36137 fNCDestroyed := True;
36138 Free;
36139 Result := 0;
36140 Exit; //!!!!!!!!!!!!!!!!!!!!!!!!!
36142 else
36143 Default;
36144 end;
36145 end;
36147 CM_RELEASE: begin
36148 fDestroying := True;
36149 Free;
36150 Result := 0;
36151 end;
36153 WM_SIZE: begin
36154 Default;
36155 case Msg.wParam of
36156 SIZENORMAL: fWindowState := wsNormal;
36157 SIZEICONIC: fWindowState := wsMinimized;
36158 SIZEFULLSCREEN: fWindowState := wsMaximized;
36159 end;
36160 if not fIsForm and (fParent <> nil) then
36161 Global_Align( fParent );
36162 Global_Align( @Self );
36163 Exit;
36164 end;
36165 WM_SHOWWINDOW:
36166 begin
36167 case Msg.lParam of
36168 SW_PARENTCLOSING:
36169 begin
36170 if IsIconic( fHandle ) then
36171 fShowAction := SW_SHOWMINNOACTIVE
36172 else
36173 if IsZoomed( fHandle ) then
36174 fShowAction := SW_SHOWMAXIMIZED
36175 else
36176 fShowAction := SW_SHOWNOACTIVATE;
36177 Default;
36178 end;
36179 SW_PARENTOPENING:
36180 begin
36181 if fShowAction <> 0 then
36182 begin
36183 ShowWindow( Handle, fShowAction );
36184 fShowAction := 0;
36185 end;
36186 Result := 0;
36187 //Exit; //?????????????????????????
36188 end;
36189 else Default;
36190 end;
36191 end;
36192 WM_SysCommand:
36193 begin
36194 if ((Msg.wParam and $FFF0) = SC_MINIMIZE) and
36195 IsMainWindow and (@Self <> Applet) then
36196 begin
36197 PostMessage( Applet.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0 );
36198 Result := 0;
36200 else Default;
36201 end;
36202 WM_SETFOCUS:
36203 begin
36204 if not DoSetFocus then
36205 begin
36206 Result := 0;
36208 else
36209 begin
36210 Inc( fClickDisabled );
36211 Default;
36212 Dec( fClickDisabled );
36213 Exit;
36214 end;
36215 end;
36216 WM_SETCURSOR:
36217 if not Global_DisableParentCursor then
36218 begin
36219 if (GetCapture = 0) and
36220 (LOWORD( Msg.lParam ) = HTCLIENT) then
36221 begin
36222 if ScreenCursor <> 0 then //YS
36223 Cur := ScreenCursor //YS
36224 else //YS
36225 Cur := fCursor; //YS
36226 if Cur <> 0 then //YS
36227 begin //YS
36228 Windows.SetCursor( Cur ); //YS
36229 Result := 1; //YS
36230 end //YS
36231 else //YS
36232 Default; //YS
36234 else Default;
36236 else Default;
36237 WM_CTLCOLORMSGBOX..WM_CTLCOLORSTATIC:
36238 begin
36239 Result := SendMessage(Msg.LParam, CN_BASE + Msg.message, Msg.WParam, Msg.LParam);
36240 end;
36241 WM_COMMAND:
36242 begin
36243 C := Pointer( GetProp( Msg.lParam, ID_SELF ) );
36244 if C <> nil then
36245 begin
36246 Result := SendMessage( Msg.lParam, CM_COMMAND, Msg.wParam, Msg.lParam );
36248 else Default;
36249 end;
36250 WM_KEYFIRST..WM_KEYLAST:
36251 begin
36252 F := GetFocus;
36253 if (F <> fFocusHandle) and (F <> fHandle) and fWindowed then
36254 begin
36255 Result := 0;
36256 // Jump to PassFun here. Prevents beep in case when WM_KEYDOWN
36257 // called another form and focus is changed, so WM_KEYUP failed
36258 // to handle.
36260 else
36261 begin
36262 if fGlobalProcKeybd( @Self, Msg, Result ) then Exit; //??????????????????
36263 if fWndProcKeybd( @Self, Msg, Result ) then Exit; //???????????????????
36264 if ((GetKeystate( VK_CONTROL ) or GetKeyState( VK_MENU )) >= 0) then
36265 begin
36266 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36267 if (Msg.message <> WM_CHAR) // v1.02 Tabulate AND " in EditBox fix
36268 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36269 then
36270 begin
36271 C := ParentForm;
36272 if (C <> nil) and Assigned(C.fGotoControl) and
36273 C.fGotoControl( @Self, Msg.wParam,
36274 (Msg.message <> WM_KEYDOWN) and
36275 (Msg.message <> WM_SYSKEYDOWN) ) then
36276 begin
36277 Msg.wParam := 0;
36278 Result := 0;
36279 //+-+exit;
36281 else Default;
36283 //+++++++++++++++++++++++++++++++++++++++++++++//
36284 else //
36285 if Msg.wParam = 9 then // prevent system beep //
36286 begin //
36287 Msg.wParam := 0; //
36288 Result := 0; //
36289 //+-+exit; //
36290 end //
36291 //+++++++++++++++++++++++++++++++++++++++++++++//
36292 else Default;
36294 else Default;
36295 end;
36296 end;
36297 CM_EXECPROC: begin
36298 Global_Synchronized( Pointer( Msg.lParam ), Pointer( Msg.wParam ) );
36299 Result := 0;
36300 end;
36301 MM_MCINOTIFY: begin
36302 if Assigned( FMMNotify ) then
36303 FMMNotify( Msg );
36304 Result := 0;
36305 exit;
36306 end;
36307 else begin
36308 Default; //+-+
36309 Exit; //+-+
36310 end;
36311 end;
36312 end;
36314 if not AppletTerminated and not fNCDestroyed then
36315 PassFun( @Self, Msg, Result ); //+-+
36316 end;
36317 {$ENDIF ASM_LOCAL}
36318 //[END TContro]
36320 {$UNDEF ASM_LOCAL}
36322 //[procedure SetMouseEvent]
36323 procedure SetMouseEvent( Self_: PControl );
36324 begin
36325 Self_.AttachProc( WndProcMouse );
36326 end;
36328 //[procedure TControl.SetMouseDown]
36329 procedure TControl.SetMouseDown(const Value: TOnMouse);
36330 begin
36331 fOnMouseDown := Value;
36332 SetMouseEvent( @Self );
36333 end;
36335 //[procedure TControl.SetMouseMove]
36336 procedure TControl.SetMouseMove(const Value: TOnMouse);
36337 begin
36338 fOnMouseMove := Value;
36339 SetMouseEvent( @Self );
36340 end;
36342 //[procedure TControl.SetMouseUp]
36343 procedure TControl.SetMouseUp(const Value: TOnMouse);
36344 begin
36345 fOnMouseUp := Value;
36346 SetMouseEvent( @Self );
36347 end;
36349 //[procedure TControl.SetMouseDblClk]
36350 procedure TControl.SetMouseDblClk(const Value: TOnMouse);
36351 begin
36352 fOnMouseDblClk := Value;
36353 SetMouseEvent( @Self );
36354 end;
36356 //[procedure TControl.SetMouseWheel]
36357 procedure TControl.SetMouseWheel(const Value: TOnMouse);
36358 begin
36359 fOnMouseWheel := Value;
36360 SetMouseEvent( @Self );
36361 end;
36363 {$IFDEF ASM_VERSION}
36364 //[procedure TControl.SetClsStyle]
36365 procedure TControl.SetClsStyle( Value: DWord );
36366 asm //cmd //opd
36367 CMP EDX, [EAX].TControl.fClsStyle
36368 JE @@exit
36369 MOV [EAX].TControl.fClsStyle, EDX
36370 MOV ECX, [EAX].TControl.fHandle
36371 JECXZ @@exit
36372 PUSH EDX
36373 PUSH GCL_STYLE
36374 PUSH ECX
36375 CALL SetClassLong
36376 @@exit:
36377 end;
36378 {$ELSE ASM_VERSION} //Pascal
36379 procedure TControl.SetClsStyle( Value: DWord );
36380 begin
36381 if fClsStyle = Value then Exit;
36382 fClsStyle := Value;
36383 if fHandle = 0 then Exit;
36384 SetClassLong( fHandle, GCL_STYLE, Value );
36385 end;
36386 {$ENDIF ASM_VERSION}
36388 {$IFDEF ASM_VERSION}
36389 //[procedure TControl.SetStyle]
36390 procedure TControl.SetStyle( Value: DWord );
36391 const SWP_FLAGS = SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
36392 SWP_NOZORDER or SWP_FRAMECHANGED;
36394 CMP EDX, [EAX].fStyle
36395 JZ @@exit
36396 MOV [EAX].fStyle, EDX
36397 MOV ECX, [EAX].fHandle
36398 JECXZ @@exit
36400 PUSH EAX
36402 PUSH SWP_FLAGS
36403 XOR EAX, EAX
36404 PUSH EAX
36405 PUSH EAX
36406 PUSH EAX
36407 PUSH EAX
36408 PUSH EAX
36409 PUSH ECX
36411 PUSH EDX
36412 PUSH GWL_STYLE
36413 PUSH ECX
36414 CALL SetWindowLong
36416 CALL SetWindowPos
36418 POP EAX
36419 CALL Invalidate
36420 @@exit:
36421 end;
36422 {$ELSE ASM_VERSION} //Pascal
36423 procedure TControl.SetStyle( Value: DWord );
36424 begin
36425 if fStyle = Value then Exit;
36426 fStyle := Value;
36427 if fHandle = 0 then Exit;
36428 SetWindowLong( fHandle, GWL_STYLE, Value );
36430 SetWindowPos( fHandle, 0, 0, 0, 0, 0,
36431 SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
36432 SWP_NOZORDER or SWP_FRAMECHANGED );
36433 Invalidate;
36434 end;
36435 {$ENDIF ASM_VERSION}
36437 {$IFDEF ASM_VERSION}
36438 //[procedure TControl.SetExStyle]
36439 procedure TControl.SetExStyle( Value: DWord );
36440 const SWP_FLAGS = SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
36441 SWP_NOZORDER or SWP_FRAMECHANGED;
36443 CMP EDX, [EAX].fExStyle
36444 JZ @@exit
36445 MOV [EAX].fExStyle, EDX
36446 MOV ECX, [EAX].fHandle
36447 JECXZ @@exit
36449 PUSH EAX
36451 PUSH SWP_FLAGS
36452 XOR EAX, EAX
36453 PUSH EAX
36454 PUSH EAX
36455 PUSH EAX
36456 PUSH EAX
36457 PUSH EAX
36458 PUSH ECX
36460 PUSH EDX
36461 PUSH GWL_EXSTYLE
36462 PUSH ECX
36463 CALL SetWindowLong
36465 CALL SetWindowPos
36467 POP EAX
36468 CALL Invalidate
36469 @@exit:
36470 end;
36471 {$ELSE ASM_VERSION} //Pascal
36472 procedure TControl.SetExStyle( Value: DWord );
36473 begin
36474 if fExStyle = Value then Exit;
36475 fExStyle := Value;
36476 if fHandle = 0 then Exit;
36477 SetWindowLong( fHandle, GWL_EXSTYLE, Value );
36479 SetWindowPos( fHandle, 0, 0, 0, 0, 0,
36480 SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE or
36481 SWP_NOZORDER or SWP_FRAMECHANGED );
36482 Invalidate;
36483 end;
36484 {$ENDIF ASM_VERSION}
36486 {$IFDEF ASM_VERSION}
36487 //[procedure TControl.SetCursor]
36488 procedure TControl.SetCursor( Value: HCursor );
36489 asm //cmd //opd
36490 CMP EDX, [EAX].TControl.fCursor
36491 JE @@exit
36492 MOV [EAX].TControl.fCursor, EDX
36493 MOV ECX, [EAX].TControl.fHandle
36494 JECXZ @@exit
36495 TEST EDX, EDX //YS
36496 JE @@exit //YS
36497 MOV ECX, [ScreenCursor]
36498 INC ECX
36499 LOOP @@exit
36501 PUSH EBX
36502 XCHG EBX, EAX
36503 PUSH EDX
36504 PUSH EAX
36505 PUSH EAX
36506 PUSH ESP
36507 CALL GetCursorPos
36508 MOV EDX, ESP
36509 MOV ECX, EDX
36510 MOV EAX, EBX
36511 CALL Screen2Client
36512 ADD ESP, -16
36513 MOV EDX, ESP
36514 MOV EAX, EBX
36515 CALL TControl.ClientRect
36516 MOV EDX, ESP
36517 LEA EAX, [ESP+16]
36518 CALL PointInRect
36519 ADD ESP, 24
36520 TEST AL, AL
36521 JZ @@fin
36522 CALL Windows.SetCursor
36523 PUSH EAX
36524 @@fin: POP EAX
36525 POP EBX
36526 @@exit:
36527 end;
36528 {$ELSE ASM_VERSION} //Pascal
36529 procedure TControl.SetCursor( Value: HCursor );
36530 var P: TPoint;
36531 begin
36532 if fCursor = Value then Exit;
36533 fCursor := Value;
36534 if (fHandle = 0) or (fCursor = 0) then Exit; //YS
36535 if ScreenCursor <> 0 then Exit;
36536 GetCursorPos( P );
36537 P := Screen2Client( P );
36538 if PointInRect( P, ClientRect ) then
36539 Windows.SetCursor( Value );
36540 end;
36541 {$ENDIF ASM_VERSION}
36543 //[procedure TControl.CursorLoad]
36544 procedure TControl.CursorLoad(Inst: Integer; ResName: PChar);
36545 begin
36546 Cursor := LoadCursor( Inst, ResName );
36547 fCursorShared := TRUE;
36548 end;
36550 {$IFDEF ASM_VERSION}
36551 //[procedure TControl.SetIcon]
36552 procedure TControl.SetIcon( Value: HIcon );
36553 asm //cmd //opd
36554 CMP EDX, [EAX].TControl.fIcon
36555 JE @@exit
36556 MOV [EAX].TControl.fIcon, EDX
36557 INC EDX
36558 JZ @@1
36559 DEC EDX
36560 @@1:
36561 PUSH EDX
36562 PUSH 1 //ICON_BIG
36563 PUSH WM_SETICON
36564 PUSH EAX
36565 CALL Perform
36566 TEST EAX, EAX
36567 JZ @@exit
36568 PUSH EAX
36569 CALL DestroyIcon
36570 @@exit:
36571 end;
36572 {$ELSE ASM_VERSION} //Pascal
36573 procedure TControl.SetIcon( Value: HIcon );
36574 var OldIco: HIcon;
36575 begin
36576 if fIcon = Value then Exit;
36577 fIcon := Value;
36578 if Value = THandle(-1) then
36579 Value := 0;
36580 OldIco := Perform( WM_SETICON, 1 {ICON_BIG}, Value );
36581 if OldIco <> 0 then
36582 DestroyIcon( OldIco );
36583 end;
36584 {$ENDIF ASM_VERSION}
36586 {$IFDEF ASM_VERSION}
36587 //[procedure TControl.SetMenu]
36588 procedure TControl.SetMenu( Value: HMenu );
36590 PUSH EBX
36591 XCHG EBX, EAX
36592 CMP [EBX].fMenu, EDX
36593 JZ @@exit
36594 PUSH EDX
36595 MOV ECX, [EBX].fMenuObj
36596 JECXZ @@no_free_menuctl
36597 XCHG EAX, EDX
36598 CALL TObj.Free
36599 @@no_free_menuctl:
36600 MOV ECX, [EBX].fMenu
36601 JECXZ @@no_destroy
36602 PUSH ECX
36603 CALL DestroyMenu
36604 @@no_destroy:
36605 POP EDX
36606 MOV [EBX].fMenu, EDX
36607 MOV ECX, [EBX].fHandle
36608 JECXZ @@exit
36609 PUSH EDX
36610 PUSH ECX
36611 CALL Windows.SetMenu
36612 @@exit:
36613 POP EBX
36614 end;
36615 {$ELSE ASM_VERSION} //Pascal
36616 procedure TControl.SetMenu( Value: HMenu );
36617 begin
36618 if fMenu = Value then Exit;
36619 if fMenuObj <> nil then
36620 fMenuObj.Free;
36621 if fMenu <> 0 then
36622 DestroyMenu( fMenu );
36623 fMenu := Value;
36624 if fHandle = 0 then Exit;
36625 Windows.SetMenu( fHandle, Value );
36626 end;
36627 {$ENDIF ASM_VERSION}
36629 //[procedure CallWinHelp]
36630 procedure CallWinHelp( Context: Integer; CtxCtl: PControl );
36631 var Cmd: Integer;
36632 Form: PControl;
36633 Popup: Boolean;
36634 begin
36635 Cmd := HELP_CONTEXT;
36636 if CtxCtl <> nil then
36637 begin
36638 Form := CtxCtl.ParentForm;
36639 if Form <> nil then
36640 if Assigned( Form.OnHelp ) then
36641 begin
36642 Popup := FALSE;
36643 Form.OnHelp( CtxCtl, Context, Popup );
36644 if Popup then
36645 Cmd := HELP_CONTEXTPOPUP;
36646 if CtxCtl = nil then Exit;
36647 end;
36649 else
36650 if Context = 0 then
36651 Cmd := HELP_CONTENTS;
36652 WinHelp( Applet.Handle, PChar( Applet.GetHelpPath ), Cmd, Context );
36653 end;
36655 var HHCtrl: THandle;
36656 HtmlHelp: procedure( Wnd: HWnd; Path: PChar; Cmd, Data: Integer ); stdcall;
36658 //[procedure HtmlHelpCommand]
36659 procedure HtmlHelpCommand( Wnd: HWnd; const HelpFilePath: String; Cmd, Data: Integer );
36660 begin
36661 if HHCtrl = 0 then
36662 HHCtrl := LoadLibrary( 'HHCTRL.OCX' );
36663 if HHCtrl = 0 then Exit;
36664 if not Assigned( HtmlHelp ) then
36665 HtmlHelp := GetProcAddress( HHCtrl, 'HtmlHelpA' );
36666 if not Assigned( HtmlHelp ) then Exit;
36667 HtmlHelp( Wnd, PChar( HelpFilePath ), Cmd, Data );
36668 end;
36670 //[procedure CallHtmlHelp]
36671 procedure CallHtmlHelp( Context: Integer; CtxCtl: PControl );
36672 var Cmd: Integer;
36673 Form: PControl;
36674 Popup: Boolean;
36675 Ids: array[ 0..2 ] of DWORD;
36676 begin
36678 Cmd := $F; // HH_HELP_CONTEXT;
36679 if CtxCtl <> nil then
36680 begin
36681 Form := CtxCtl.ParentForm;
36682 if Form <> nil then
36683 if Assigned( Form.OnHelp ) then
36684 begin
36685 Popup := FALSE;
36686 Form.OnHelp( CtxCtl, Context, Popup );
36687 if Popup then
36688 begin
36689 Cmd := $10; //HH_TP_HELPCONTEXTMENU;
36690 Ids[ 0 ] := CtxCtl.fMenu;
36691 Ids[ 1 ] := Context;
36692 Ids[ 2 ] := 0;
36693 Context := Integer( @ Ids );
36694 end;
36695 if CtxCtl = nil then Exit;
36696 end;
36698 else
36699 if Context = 0 then
36700 Cmd := 1; // HH_DISPLAY_TOC;
36701 HtmlHelpCommand( Applet.Handle, HelpFilePath, Cmd, Context );
36702 end;
36705 Global_HelpProc: procedure( Context: Integer; CtxCtl: PControl ) = CallWinHelp;
36707 //[function WndProcHelp]
36708 function WndProcHelp( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
36709 var HI: PHelpInfo;
36710 Ctx: Integer;
36711 Ctl: PControl;
36712 begin
36713 Result := FALSE;
36714 if Msg.message = WM_HELP then
36715 begin
36716 Ctx := 0;
36717 Ctl := nil;
36718 HI := Pointer( Msg.lParam );
36719 if HI.iContextType = HELPINFO_WINDOW then
36720 begin
36721 Ctl := Pointer( GetProp( HI.hItemHandle, ID_SELF ) );
36722 while Ctl <> nil do
36723 begin
36724 Ctx := Ctl.fHelpContext;
36725 if Ctx <> 0 then break;
36726 Ctl := Ctl.Parent;
36727 end;
36729 else
36730 //if HI.iContextType = HELPINFO_MENUITEM then
36731 Ctx := GetMenuContextHelpID( HI.hItemHandle );
36732 Applet.CallHelp( Ctx, Ctl );
36733 Rslt := 1;
36734 Result := TRUE;
36736 {$IFDEF AUTO_CONTEXT_HELP}
36737 else
36738 if (Msg.message = WM_CONTEXTMENU) then
36739 begin
36740 Ctl := Pointer( GetProp( Msg.wParam, ID_SELF ) );
36741 if (Ctl <> nil) and (Ctl.fHelpContext <> 0) then
36742 //if (Ctl.fAutoPopupMenu = nil) then // seems not working
36743 begin
36744 Applet.CallHelp( Ctl.fHelpContext, Ctl );
36745 Rslt := 1;
36746 Result := TRUE;
36747 end;
36749 {$ENDIF}
36751 end;
36753 //[procedure TControl.SetHelpContext]
36754 procedure TControl.SetHelpContext(Value: Integer);
36755 var F: PControl;
36756 begin
36757 fHelpContext := Value;
36758 F := ParentForm;
36759 if F = nil then Exit;
36760 F.AttachProc( WndProcHelp );
36761 SetWindowContextHelpId( GetWindowHandle, Value );
36762 end;
36764 //[function TControl.AssignHelpContext]
36765 function TControl.AssignHelpContext(Context: Integer): PControl;
36766 begin
36767 SetHelpContext( Context );
36768 Result := @ Self;
36769 end;
36771 //[procedure AssignHtmlHelp]
36772 procedure AssignHtmlHelp( const HtmlHelpPath: String );
36773 begin
36774 Assert( (HtmlHelpPath <> '') and (Applet <> nil), 'Error parameters' );
36775 if HelpFilePath <> '' then
36776 FreeMem( HelpFilePath );
36777 GetMem( HelpFilePath, Length( HtmlHelpPath ) + 1 );
36778 StrCopy( HelpFilePath, @ HtmlHelpPath[ 1 ] );
36779 Global_HelpProc := CallHtmlHelp;
36780 Applet.AttachProc( WndProcHelp );
36781 end;
36783 //[procedure TControl.CallHelp]
36784 procedure TControl.CallHelp(Context: Integer; CtxCtl: PControl {; CtlID: Integer} );
36785 begin
36786 Global_HelpProc( Context, CtxCtl {, CtlID} );
36787 end;
36789 //[function TControl.GetHelpPath]
36790 function TControl.GetHelpPath: String;
36791 begin
36792 Result := HelpFilePath;
36793 if Result = '' then
36794 begin
36795 Result := ParamStr( 0 );
36796 Result := ReplaceFileExt( Result, '.hlp' );
36797 end;
36798 end;
36800 //[procedure TControl.SetHelpPath]
36801 procedure TControl.SetHelpPath(const Value: String);
36802 begin
36803 Assert( Value <> '', 'Error parameter' );
36804 if HelpFilePath <> '' then
36805 FreeMem( HelpFilePath );
36806 GetMem( HelpFilePath, Length( Value ) + 1 );
36807 StrCopy( HelpFilePath, @ Value[ 1 ] );
36808 end;
36810 {$IFDEF ASM_VERSION}
36811 //[function TControl.GetCaption]
36812 function TControl.GetCaption: String;
36814 PUSH EBX
36815 PUSH EDI
36816 XCHG EBX, EAX
36817 MOV EDI, EDX
36818 CMP [EBX].fIgnoreWndCaption, 0
36819 JNZ @@getFCaption
36820 MOV ECX, [EBX].fHandle
36821 JECXZ @@getFCaption
36823 @@getWndCaption:
36824 PUSH ECX
36825 CALL GetWindowTextLength
36826 PUSH EAX
36828 XCHG EDX, EAX
36829 MOV EAX, EDI
36830 CALL System.@LStrSetLength
36832 POP ECX
36833 JECXZ @@exit
36835 INC ECX
36836 PUSH ECX
36837 PUSH dword ptr [EDI]
36838 PUSH [EBX].fHandle
36839 CALL GetWindowText
36840 JMP @@exit
36842 @@getFCaption:
36843 MOV EDX, [EBX].fCaption
36844 XCHG EAX, EDI
36845 CALL System.@LStrFromPChar
36847 @@exit:
36848 POP EDI
36849 POP EBX
36850 end;
36851 {asm
36852 XCHG EAX, EDX
36853 MOVZX ECX, [EDX].fIgnoreWndCaption
36854 JECXZ @@getwndcaption
36856 @@ret_fCaption:
36857 MOV EDX, [EDX].fCaption
36858 JMP System.@LStrFromPChar
36860 @@getwndcaption:
36861 MOV ECX, [EDX].fHandle
36862 JECXZ @@ret_fCaption
36864 PUSH EBX
36865 PUSH ESI
36866 XCHG EBX, EAX
36868 MOV ESI, ECX
36869 PUSH ESI
36870 CALL GetWindowTextLength
36871 MOV EDX, EAX
36872 INC EAX
36873 PUSH EAX // MaxLen
36875 MOV EAX, EBX
36876 CALL System.@LStrSetLength
36878 POP EDX
36879 MOV ECX, [EBX]
36880 JECXZ @@exit
36881 PUSH EDX // MaxLen = Length(Result) + 1
36883 PUSH ECX //@Result[1]
36884 PUSH ESI // fHandle
36885 CALL GetWindowText
36887 @@exit:
36888 POP ESI
36889 POP EBX
36890 end;}
36891 {$ELSE ASM_VERSION} //Pascal
36892 function TControl.GetCaption: String;
36893 var Buf: PChar;
36894 Sz: Integer;
36895 begin
36896 if not fIgnoreWndCaption and (FHandle <> 0) then
36897 begin
36898 Sz := GetWindowTextLength( FHandle );
36899 if Sz = 0 then
36900 Buf := nil
36901 else
36902 begin
36903 GetMem( Buf, Sz + 1 );
36904 GetWindowText( FHandle, Buf, Sz + 1 );
36905 end;
36906 Result := Buf;
36907 if Buf <> nil then
36908 FreeMem( Buf );
36909 Exit;
36910 end;
36911 Result := FCaption;
36912 end;
36913 {$ENDIF ASM_VERSION}
36915 {$IFDEF ASM_VERSION}
36916 //[procedure TControl.SetCaption]
36917 procedure TControl.SetCaption( const Value: String );
36919 PUSH EBX
36920 XCHG EBX, EAX
36921 PUSH EDX
36922 MOV EAX, [EBX].fCaption
36923 TEST EAX, EAX
36924 JZ @@store_Caption
36925 CALL System.@FreeMem
36926 @@store_Caption:
36927 POP EAX
36928 CALL EAX2PChar
36929 PUSH EAX
36930 CALL StrLen
36931 INC EAX
36932 CALL System.@GetMem
36933 MOV [EBX].fCaption, EAX
36934 POP EDX
36935 CALL StrCopy
36936 MOV ECX, [EBX].fHandle
36937 JECXZ @@exit
36938 PUSH [EBX].fCaption
36939 PUSH ECX
36940 CALL SetWindowText
36941 CMP [EBX].fIsStaticControl, 1
36942 JZ @@1
36943 MOV EAX, EBX
36944 CALL Invalidate
36945 @@1:
36946 XCHG EAX, EBX
36947 MOV ECX, [EAX].fAutoSize
36948 JECXZ @@exit
36949 CALL ECX
36950 @@exit: POP EBX
36951 end;
36952 {$ELSE ASM_VERSION} //Pascal
36953 procedure TControl.SetCaption( const Value: String );
36954 var L: DWORD;
36955 begin
36956 //if fHandle = 0 then
36957 begin
36958 if fCaption <> nil then
36959 FreeMem( fCaption );
36960 L := Length( Value ) + 1;
36961 GetMem( fCaption, L );
36962 StrCopy( fCaption, PChar( Value ) );
36963 //Exit;
36964 end;
36965 if fHandle = 0 then Exit;
36966 SetWindowText( fHandle, @Value[ 1 ] );
36967 if fIsStaticControl <> 1 then
36968 Invalidate;
36969 if Assigned( fAutoSize ) then
36970 fAutoSize( @Self );
36971 end;
36972 {$ENDIF ASM_VERSION}
36974 {$IFDEF ASM_VERSION}
36975 //[function TControl.GetVisible]
36976 function TControl.GetVisible: Boolean;
36978 MOV ECX, [EAX].fHandle
36979 JECXZ @@check_fStyle
36981 {CMP [EAX].fIsControl, 0
36982 JNE @@check_fStyle}
36984 PUSH EAX
36985 PUSH ECX
36986 CALL IsWindowVisible
36987 TEST EAX, EAX
36988 POP EAX
36989 JMP @@checked // Z if not visible
36991 @@check_fStyle:
36992 TEST byte ptr [EAX].fStyle+3, 10h // WS_VISIBLE shr 3
36993 @@checked:
36994 SETNZ DL
36995 MOV [EAX].fVisible, DL
36996 XCHG EAX, EDX
36997 end;
36998 {$ELSE ASM_VERSION}
36999 function TControl.GetVisible: Boolean;
37000 begin
37001 if (fHandle <> 0)
37002 //and (not fIsControl or (ParentForm <> nil) and ParentForm.Visible)
37003 //and not fIsControl
37004 then
37005 fVisible :=
37006 //LongBool( GetWindowLong( fHandle, GWL_STYLE ) and WS_VISIBLE )
37007 IsWindowVisible( fHandle )
37008 else
37009 fVisible := (FStyle and WS_VISIBLE) <> 0;
37010 Result := fVisible;
37011 end;
37012 {$ENDIF ASM_VERSION}
37014 {$IFDEF ASM_VERSION}
37015 //[function TControl.Get_Visible]
37016 function TControl.Get_Visible: Boolean;
37017 asm // //
37018 MOV ECX, [EAX].fHandle
37019 JECXZ @@ret_fVisible
37020 CMP [EAX].fIsControl, 0
37021 JNZ @@ret_fVisible
37022 PUSH EAX
37023 PUSH ECX
37024 CALL IsWindowVisible
37025 XCHG EDX, EAX
37026 POP EAX
37027 MOV [EAX].fVisible, DL
37028 @@ret_fVisible:
37029 MOVZX EAX, [EAX].fVisible
37030 end;
37031 {$ELSE ASM_VERSION} // Pascal
37032 function TControl.Get_Visible: Boolean;
37033 begin
37034 if (fHandle <> 0)
37035 //and (not fIsControl or (ParentForm <> nil) and ParentForm.Visible)
37036 and not fIsControl
37037 then
37038 fVisible :=
37039 //LongBool( GetWindowLong( fHandle, GWL_STYLE ) and WS_VISIBLE )
37040 IsWindowVisible( fHandle );
37041 Result := fVisible;
37042 end;
37043 {$ENDIF ASM_VERSION}
37045 {$IFDEF ASM_VERSION}
37046 //[procedure TControl.Set_Visible]
37047 procedure TControl.Set_Visible( Value: Boolean );
37048 const wsVisible = $10;
37050 PUSH EBX
37051 PUSH ESI
37052 //MOV ESI, EAX
37053 XCHG ESI, EAX
37054 MOVZX EBX, DL
37055 {CALL Get_Visible
37056 CMP AL, BL
37057 JE @@reset_fCreateHidden}
37059 MOV AL, byte ptr [ESI].fStyle + 3
37060 TEST EBX, EBX
37061 JZ @@reset_WS_VISIBLE
37062 OR AL, wsVisible
37063 PUSH SW_SHOW
37064 JMP @@store_Visible
37065 @@reset_WS_VISIBLE:
37066 AND AL, not wsVisible
37067 PUSH SW_HIDE
37069 @@store_Visible:
37070 MOV byte ptr [ESI].fStyle + 3, AL
37071 MOV [ESI].fVisible, BL
37072 MOV ECX, [ESI].fHandle
37073 JECXZ @@after_showwindow
37075 PUSH ECX
37076 CALL ShowWindow
37077 PUSH ECX
37078 @@after_showwindow:
37079 POP ECX
37081 MOV ECX, [ESI].fParent
37082 JECXZ @@chk_align_Self
37083 XCHG EAX, ECX
37084 CALL dword ptr [Global_Align]
37086 @@chk_align_Self:
37087 TEST EBX, EBX
37088 JZ @@reset_fCreateHidden
37089 MOV EAX, ESI
37090 CALL dword ptr [Global_Align]
37093 @@reset_fCreateHidden:
37094 MOV ECX, [ESI].fHandle
37095 JECXZ @@exit
37096 TEST BL, BL
37097 JNZ @@exit
37098 MOV [ESI].fCreateHidden, 0 { +++ }
37099 @@exit:
37100 POP ESI
37101 POP EBX
37102 end;
37103 {$ELSE ASM_VERSION} // Pascal
37104 procedure TControl.Set_Visible( Value: Boolean );
37105 var CmdShow: DWORD;
37106 begin
37107 //if Get_Visible <> Value then // commented to allow to set up controls visibility
37108 begin // on invisible form (Vladimir Piven)
37109 if Value then
37110 begin
37111 fStyle := fStyle or WS_VISIBLE;
37112 CmdShow := SW_SHOW;
37114 else
37115 begin
37116 fStyle := fStyle and not WS_VISIBLE;
37117 CmdShow := SW_HIDE;
37118 end;
37119 fVisible := Value;
37120 if fHandle = 0 then Exit;
37121 ShowWindow( fHandle, CmdShow );
37122 if fParent <> nil then
37123 Global_Align( fParent );
37124 //else
37125 if Value then
37126 Global_Align( @Self );
37127 end;
37128 if not Value and (fHandle <> 0) then
37129 fCreateHidden := FALSE; // { +++ }
37130 end;
37131 {$ENDIF ASM_VERSION}
37133 //[procedure TControl.SetVisible]
37134 procedure TControl.SetVisible( Value: Boolean );
37135 begin
37136 fCreateVisible := TRUE;
37137 Set_Visible( Value );
37138 end;
37140 {$IFDEF ASM_VERSION}
37141 //[function TControl.GetBoundsRect]
37142 function TControl.GetBoundsRect: TRect;
37144 PUSH ESI
37145 PUSH EDI
37146 LEA ESI, [EAX].fBoundsRect
37147 MOV EDI, EDX
37149 PUSH EDX
37151 MOVSD
37152 MOVSD
37153 MOVSD
37154 MOVSD
37156 POP EDI
37158 XCHG ESI, EAX
37159 MOV ECX, [ESI].fHandle
37160 JECXZ @@exit
37162 PUSH EDI
37163 PUSH ECX
37164 CALL GetWindowRect
37166 CMP [ESI].fIsMDIChild, 0
37167 JNZ @@chk_Parent
37168 CMP [ESI].fIsControl, 0
37169 JZ @@storeBounds
37171 @@chk_Parent:
37172 MOV EAX, [ESI].fParent
37174 TEST EAX, EAX
37175 JZ @@exit
37177 XOR EDX, EDX
37178 PUSH EDX
37179 PUSH EDX
37180 MOV ECX, ESP
37181 PUSH EDX
37182 PUSH EDX
37183 MOV EDX, ESP
37184 CALL TControl.Client2Screen
37185 POP EAX
37186 POP EAX
37188 POP EAX
37189 NEG EAX
37190 POP ECX
37191 NEG ECX
37192 PUSH ECX
37193 PUSH EAX
37194 PUSH EDI
37195 CALL OffsetRect
37197 @@storeBounds:
37198 XCHG ESI, EDI
37199 LEA EDI, [EDI].fBoundsRect
37200 MOVSD
37201 MOVSD
37202 MOVSD
37203 MOVSD
37205 @@exit:
37206 POP EDI
37207 POP ESI
37208 end;
37209 {$ELSE ASM_VERSION} //Pascal
37210 function TControl.GetBoundsRect: TRect;
37211 var W: PControl;
37212 P: TPoint;
37213 begin
37214 Result := fBoundsRect;
37215 if fHandle <> 0 then
37216 begin
37217 GetWindowRect( fHandle, Result );
37218 if fIsControl or fIsMDIChild then
37219 begin
37220 W := fParent; // WindowedParent;
37221 if W <> nil then
37222 begin
37223 P.x := 0; P.y := 0;
37224 P := W.Client2Screen( P );
37225 OffsetRect( Result, -P.x, -P.y );
37226 end;
37227 end;
37228 fBoundsRect := Result;
37229 end;
37230 end;
37231 {$ENDIF ASM_VERSION}
37233 //[PROCEDURE HelpGetBoundsRect]
37234 {$IFDEF ASM_VERSION}
37235 procedure HelpGetBoundsRect;
37237 POP ECX
37238 ADD ESP, - size_TRect
37239 MOV EDX, ESP
37240 PUSH ECX
37241 PUSH EAX
37242 CALL TControl.GetBoundsRect
37243 POP EAX
37244 end;
37245 {$ENDIF ASM_VERSION}
37246 //[END HelpGetBoundsRect]
37248 {$IFDEF ASM_VERSION}
37249 //[procedure TControl.SetBoundsRect]
37250 procedure TControl.SetBoundsRect( const Value: TRect );
37251 const swp_flags = SWP_NOZORDER or SWP_NOACTIVATE;
37253 PUSH EDI
37254 MOV EDI, EAX
37256 PUSH ESI
37257 MOV ESI, EDX
37259 CALL HelpGetBoundsRect
37261 MOV EAX, ESI
37262 MOV EDX, ESP
37263 CALL RectsEqual
37264 TEST AL, AL
37265 JNZ @@exit
37267 POP EDX // left
37268 POP ECX // top
37269 POP EAX // right
37270 PUSH EAX
37271 PUSH ECX
37272 PUSH EDX
37274 SUB EAX, EDX // EAX = width
37275 CMP EDX, [ESI].TRect.Left
37276 MOV DL, 0
37277 JE @@1
37278 INC EDX
37279 @@1: CMP ECX, [ESI].TRect.Top
37280 JE @@2
37281 OR DL, 2
37282 @@2: OR [EDI].fChangedPosSz, DL
37284 PUSH EAX // W saved
37286 MOV EAX, [EDI].fBoundsRect.Bottom
37287 SUB EAX, ECX
37288 PUSH EAX // H saved
37290 PUSH EDI // @Self saved
37291 CMP [EDI].fWindowed, 0
37292 JNZ @@invalid1
37293 MOV EAX, EDI
37294 CALL TControl.Invalidate
37295 @@invalid1:
37297 LEA EDI, [EDI].fBoundsRect
37298 MOVSD
37299 MOVSD
37300 MOVSD
37301 MOVSD
37303 MOV ESI, EDI
37304 POP EDI // @ Self restored
37306 MOV ECX, [EDI].fHandle
37307 JECXZ @@fin
37311 PUSH swp_flags
37313 LODSD
37314 LODSD
37315 XCHG EDX, EAX // EDX = bottom
37316 LODSD
37317 XCHG ECX, EAX // ECX = right
37318 LODSD
37319 SUB EDX, EAX // EAX = bottom - top
37320 PUSH EDX // push HEIGHT
37321 XCHG EDX, EAX // EDX = top
37322 LODSD // EAX = left
37325 SUB ECX, EAX
37326 PUSH ECX // push WIDTH
37328 PUSH EDX // push TOP
37329 PUSH EAX // push LEFT
37330 PUSH 0
37332 PUSH [EDI].fHandle
37333 CALL SetWindowPos
37335 @@fin:
37336 POP EDX // H restored
37337 POP EAX // W restored
37339 {CMP [EDI].fWindowed, 0
37340 JZ @@invalid2}
37341 CMP [EDI].fSizeRedraw, 0
37342 JE @@exit
37343 @@invalid2:
37344 XCHG EAX, EDI
37345 CALL Invalidate
37347 @@exit:
37348 ADD ESP, size_TRect
37349 POP ESI
37350 POP EDI
37351 end;
37352 {$ELSE ASM_VERSION} //Pascal
37353 procedure TControl.SetBoundsRect( const Value: TRect );
37354 var Rect: TRect;
37355 begin
37356 Rect := GetBoundsRect;
37357 if RectsEqual( Value, Rect ) then Exit;
37358 if Value.Left <> fBoundsRect.Left then fChangedPosSz := fChangedPosSz or 1;
37359 if Value.Top <> fBoundsRect.Top then fChangedPosSz := fChangedPosSz or 2;
37360 if not fWindowed then
37361 Invalidate;
37363 fBoundsRect := Value;
37364 Rect := Value;
37366 if fHandle <> 0 then
37367 begin
37368 SetWindowPos( fHandle, 0, Rect.Left, Rect.Top, Rect.Right - Rect.Left,
37369 Rect.Bottom - Rect.Top, SWP_NOZORDER or SWP_NOACTIVATE );
37370 end;
37371 if {not fWindowed or} fSizeRedraw then
37372 Invalidate;
37373 end;
37374 {$ENDIF ASM_VERSION}
37376 const
37377 WindowStateShowCommands: array[TWindowState] of Byte =
37378 (SW_SHOWNOACTIVATE, SW_SHOWMINNOACTIVE, SW_SHOWMAXIMIZED);
37379 {$IFDEF ASM_VERSION}
37380 //[procedure TControl.SetWindowState]
37381 procedure TControl.SetWindowState( Value: TWindowState );
37382 asm //cmd //opd
37383 CMP [EAX].TControl.fWindowState, DL
37384 JE @@exit
37385 MOV [EAX].TControl.fWindowState, DL
37386 XCHG EAX, EDX
37388 CWDE
37389 MOV AL, byte ptr [WindowStateShowCommands+EAX]
37390 PUSH EAX
37391 XCHG EAX, EDX
37392 CALL TControl.GetWindowHandle
37393 PUSH EAX
37394 CALL ShowWindow
37395 @@exit:
37396 end;
37397 {$ELSE ASM_VERSION} //Pascal
37398 procedure TControl.SetWindowState( Value: TWindowState );
37399 begin
37400 if fWindowState <> Value then
37401 begin
37402 fWindowState := Value;
37403 ShowWindow(GetWindowHandle, WindowStateShowCommands[Value]);
37404 end;
37405 end;
37406 {$ENDIF ASM_VERSION}
37408 {$IFDEF ASM_VERSION}
37409 //[procedure TControl.Show]
37410 procedure TControl.Show;
37412 PUSH EBX
37413 MOV EBX, EAX
37414 CALL CreateWindow
37415 MOV DL, 1
37416 MOV EAX, EBX
37417 CALL SetVisible
37418 PUSH [EBX].fHandle
37419 CALL SetForegroundWindow
37420 XCHG EAX, EBX
37421 CALL DoSetFocus
37422 POP EBX
37423 end;
37424 {$ELSE ASM_VERSION} //Pascal
37425 procedure TControl.Show;
37426 begin
37427 CreateWindow;
37428 SetVisible( True );
37429 SetForegroundWindow( Handle );
37430 DoSetFocus;
37431 end;
37432 {$ENDIF ASM_VERSION}
37434 //[procedure TControl.Hide]
37435 procedure TControl.Hide;
37436 begin
37437 SetVisible( False );
37438 end;
37440 {$IFDEF ASM_VERSION}
37441 //[function TControl.Client2Screen]
37442 function TControl.Client2Screen( const P: TPoint ): TPoint;
37444 PUSH ESI
37445 PUSH EDI
37447 MOV ESI, EDX
37448 MOV EDI, ECX
37450 MOVSD
37451 MOVSD
37453 PUSH ECX
37454 MOV ECX, [EAX].fHandle
37455 JECXZ @@exit
37457 PUSH ECX
37458 CALL ClientToScreen
37459 PUSH ECX
37461 @@exit: POP ECX
37462 POP EDI
37463 POP ESI
37464 end;
37465 {$ELSE ASM_VERSION} //Pascal
37466 function TControl.Client2Screen( const P: TPoint ): TPoint;
37467 begin
37468 Result := P;
37469 if fHandle <> 0 then
37470 Windows.ClientToScreen( fHandle, Result );
37471 end;
37472 {$ENDIF ASM_VERSION}
37474 {$IFDEF ASM_VERSION}
37475 //[function TControl.Screen2Client]
37476 function TControl.Screen2Client( const P: TPoint ): TPoint;
37478 PUSH ESI
37479 PUSH EDI
37481 MOV ESI, EDX
37482 MOV EDI, ECX
37484 MOVSD
37485 MOVSD
37487 PUSH ECX
37488 MOV ECX, [EAX].fHandle
37489 JECXZ @@exit
37491 PUSH ECX
37492 CALL ScreenToClient
37493 PUSH ECX
37495 @@exit: POP ECX
37496 POP EDI
37497 POP ESI
37498 end;
37499 {$ELSE ASM_VERSION} //Pascal
37500 function TControl.Screen2Client( const P: TPoint ): TPoint;
37501 begin
37502 Result := P;
37503 if Handle <> 0 then
37504 Windows.ScreenToClient( Handle, Result );
37505 end;
37506 {$ENDIF ASM_VERSION}
37508 {$IFDEF ASM_VERSION}
37509 //[function TControl.ClientRect]
37510 function TControl.ClientRect: TRect;
37512 PUSH [EAX].fClientLeft
37513 PUSH [EAX].fClientRight
37514 PUSH [EAX].fClientTop
37515 PUSH [EAX].fClientBottom
37516 PUSH EDX
37517 PUSH EDX // prepare 'dest' for GetClientRect
37519 PUSH EAX
37520 LEA EAX, [EAX].fBoundsRect
37522 XOR ECX, ECX
37523 MOV CL, size_TRect
37525 CALL System.Move
37526 POP EAX // EAX = @Self
37528 CALL TControl.GetWindowHandle
37530 // this version is more correct ?:
37531 //------------------------------
37532 {PUSH EAX
37533 CALL CallTControlCreateWindow
37534 POP EAX
37535 MOV EAX, [EAX].fHandle}
37536 //-------------------------------
37538 TEST EAX, EAX
37539 JZ @@exit
37541 PUSH EAX // prepare 'handle' for GetClientRect
37542 CALL GetClientRect
37543 PUSH EAX
37545 @@exit: POP EDX
37546 POP EDX // EDX = @Result
37547 POP EAX // EAX = fClientBottom
37548 SUB [EDX].TRect.Bottom, EAX
37549 POP EAX // EAX = fClientTop
37550 ADD [EDX].TRect.Top, EAX // Correct Result.Top
37551 POP EAX // EAX = fClientRight
37552 SUB [EDX].TRect.Right, EAX
37553 POP EAX // EAX = fClientLeft
37554 ADD [EDX].TRect.Left, EAX
37555 end;
37556 {$ELSE ASM_VERSION} //Pascal
37557 function TControl.ClientRect: TRect;
37558 const BorderParams: array[ 0..5 ] of DWORD =
37559 ( SM_CXBORDER, SM_CXFRAME, SM_CXSIZEFRAME, SM_CYBORDER, SM_CYFRAME, SM_CYSIZEFRAME );
37560 begin
37561 Result := fBoundsRect;
37562 GetWindowHandle;
37563 //CreateWindow; //virtual!!!
37564 if (fHandle <> 0) then
37565 GetClientRect( fHandle, Result );
37566 Inc( Result.Top, fClientTop );
37567 Dec( Result.Bottom, fClientBottom );
37568 Inc( Result.Left, fClientLeft );
37569 Dec( Result.Right, fClientRight );
37570 end;
37571 {$ENDIF ASM_VERSION}
37573 //[procedure TControl.Invalidate]
37574 {$IFDEF ASM_VERSION}
37575 procedure TControl.Invalidate;
37577 XOR EDX, EDX
37578 CMP [AppletTerminated], DL
37579 JNZ @@exit
37580 MOV ECX, [EAX].fHandle
37581 JECXZ @@nohandle
37582 PUSH EAX
37583 PUSH 1
37584 PUSH EDX //=0
37585 PUSH ECX
37586 CALL Windows.InvalidateRect
37587 POP EAX
37588 JMP @@call_global_invalidate
37589 @@nohandle:
37590 CMP [EAX].fWindowed, 0
37591 JNZ @@exit
37592 MOV ECX, [EAX].fParent
37593 JECXZ @@exit
37594 MOV ECX, [ECX].fHandle
37595 JECXZ @@exit
37596 PUSH EAX
37597 PUSH 1
37598 LEA EDX, [EAX].fBoundsRect
37599 PUSH EDX
37600 PUSH ECX
37601 CALL InvalidateRect
37602 POP EAX
37603 @@call_global_invalidate:
37604 CALL dword ptr[Global_Invalidate]
37605 @@exit:
37606 end;
37607 {$ELSE PAS_VERSION}
37608 procedure TControl.Invalidate;
37609 var R: TRect;
37610 begin
37611 if AppletTerminated then Exit;
37612 if fHandle = 0 then
37613 begin
37614 if fWindowed or (fParent = nil) or (fParent.fHandle = 0) then
37615 Exit;
37616 R := BoundsRect;
37617 InvalidateRect( fParent.fHandle, @ R, TRUE );
37619 else
37620 InvalidateRect( fHandle, nil, TRUE );
37622 Global_Invalidate( @Self );
37623 end;
37624 {$ENDIF ASM_VERSION}
37628 {$IFDEF ASM_VERSION}
37629 //[function TControl.GetIcon]
37630 function TControl.GetIcon: HIcon;
37632 PUSH EBX
37633 XCHG EBX, EAX
37634 MOV EAX, [EBX].fIcon
37635 INC EAX
37636 JZ @@exit
37637 DEC EAX
37638 JNZ @@exit
37640 MOV ECX, [Applet]
37641 JECXZ @@load
37642 CMP ECX, EBX
37643 JZ @@load
37645 XCHG EAX, ECX
37646 CALL TControl.GetIcon
37647 TEST EAX, EAX
37648 JZ @@exit
37650 XOR EDX, EDX
37651 PUSH EDX
37652 PUSH EDX
37653 PUSH EDX
37654 INC EDX // IMAGE_ICON = 1
37655 PUSH EDX
37656 PUSH EAX
37657 CALL CopyImage
37658 JMP @@store_fIcon
37660 @@main_icon:
37661 DB 'MAINICON',0
37663 @@load:
37664 PUSH offset @@main_icon
37665 PUSH [hInstance]
37666 CALL LoadIcon
37667 @@store_fIcon:
37668 MOV [EBX].fIcon, EAX
37669 @@exit:
37670 POP EBX
37671 end;
37672 {$ELSE ASM_VERSION} //Pascal
37673 function TControl.GetIcon: HIcon;
37674 begin
37675 Result := fIcon;
37676 if Result = THandle( -1 ) then
37677 begin
37678 Result := 0;
37679 Exit;
37680 end;
37681 if Result = 0 then
37682 if (Assigned( Applet )) and
37683 (@Self <> Applet) then
37684 begin
37685 Result := Applet.Icon;
37686 if Result <> 0 then
37687 Result := CopyImage( Result, IMAGE_ICON, 0, 0, 0 );
37689 else
37690 begin
37691 //if Result = 0 then
37692 Result := LoadIcon( hInstance, 'MAINICON' );
37693 //Result := LoadImage( hInstance, 'MAINICON', IMAGE_ICON, 16, 16, LR_SHARED );
37694 end;
37695 fIcon := Result;
37696 end;
37697 {$ENDIF ASM_VERSION}
37700 //[procedure TControl.IconLoad]
37701 procedure TControl.IconLoad(Inst: Integer; ResName: PChar);
37702 begin
37703 Icon := LoadIcon( Inst, ResName );
37704 fIconShared := TRUE;
37705 end;
37707 //[procedure TControl.IconLoadCursor]
37708 procedure TControl.IconLoadCursor(Inst: Integer; ResName: PChar);
37709 begin
37710 Icon := LoadCursor( Inst, ResName );
37711 fIconShared := TRUE;
37712 end;
37714 {$IFDEF ASM_VERSION}
37715 //[function TControl.CallDefWndProc]
37716 function TControl.CallDefWndProc(var Msg: TMsg): Integer;
37718 PUSH [EDX].TMsg.lParam
37719 PUSH [EDX].TMsg.wParam
37720 PUSH [EDX].TMsg.message
37722 MOV ECX, [EAX].fDefWndProc
37723 JECXZ @@defwindowproc
37725 PUSH [EAX].fHandle
37726 PUSH ECX
37727 CALL CallWindowProc
37730 @@defwindowproc:
37731 PUSH [EDX].TMsg.hwnd
37732 CALL DefWindowProc
37733 end;
37734 {$ELSE ASM_VERSION} //Pascal
37735 function TControl.CallDefWndProc(var Msg: TMsg): Integer;
37736 begin
37737 if FDefWndProc <> nil then
37738 Result := CallWindowProc( FDefWndProc, FHandle, Msg.message, Msg.wParam, Msg.lParam )
37739 else
37740 Result := DefWindowProc( Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam );
37741 end;
37742 {$ENDIF ASM_VERSION}
37744 {$IFDEF ASM_VERSION}
37745 //[function TControl.GetWindowState]
37746 function TControl.GetWindowState: TWindowState;
37747 asm //cmd //opd
37748 PUSH EBX
37749 PUSH ESI
37750 XCHG ESI, EAX
37751 MOVZX EBX, [ESI].TControl.fWindowState
37752 MOV ECX, [ESI].TControl.fHandle
37753 JECXZ @@ret_EBX
37754 MOV BL, 2
37755 MOV ESI, ECX
37756 PUSH ESI
37757 CALL IsZoomed
37758 TEST EAX, EAX
37759 JNZ @@ret_EBX
37760 DEC EBX
37761 PUSH ESI
37762 CALL IsIconic
37763 TEST EAX, EAX
37764 JNZ @@ret_EBX
37765 DEC EBX
37766 @@ret_EBX:
37767 XCHG EAX, EBX
37768 POP ESI
37769 POP EBX
37770 end;
37771 {$ELSE ASM_VERSION} //Pascal
37772 function TControl.GetWindowState: TWindowState;
37773 begin
37774 Result := fWindowState;
37775 if Handle <> 0 then
37776 begin
37777 if IsIconic( Handle ) then
37778 Result := wsMinimized
37779 else
37780 if IsZoomed( Handle ) then
37781 Result := wsMaximized
37782 else
37783 Result := wsNormal;
37784 fWindowState := Result;
37785 end;
37786 end;
37787 {$ENDIF ASM_VERSION}
37789 {$IFDEF ASM_VERSION}
37790 //[function TControl.DoSetFocus]
37791 function TControl.DoSetFocus: Boolean;
37793 PUSH ESI
37794 MOV ESI, EAX
37796 {MOV EDX, [ESI].fStyle
37797 TEST EDX, WS_TABSTOP
37798 JZ @@exit}
37800 CALL GetEnabled
37801 TEST AL, AL
37802 JZ @@exit
37804 XOR EAX, EAX
37805 CMP [ESI].fTabstop, AL
37806 JZ @@exit
37808 INC [ESI].TControl.fClickDisabled
37810 PUSH [ESI].fHandle
37811 CALL SetFocus
37813 DEC [ESI].TControl.fClickDisabled
37815 MOV AL, 1
37817 @@exit:
37818 POP ESI
37819 end;
37820 {$ELSE ASM_VERSION} //Pascal
37821 function TControl.DoSetFocus: Boolean;
37822 begin
37823 Result := False;
37824 if Enabled and fTabstop {and (fStyle and WS_TABSTOP <> 0)} then
37825 begin
37826 Inc( fClickDisabled );
37827 SetFocus( fHandle );
37828 Dec( fClickDisabled );
37829 Result := True;
37830 end;
37831 end;
37832 {$ENDIF ASM_VERSION}
37834 //[function TControl.HandleAllocated]
37835 function TControl.HandleAllocated: Boolean;
37836 begin
37837 Result := FHandle <> 0;
37838 end;
37840 {$IFDEF ASM_VERSION}
37841 //[function TControl.GetEnabled]
37842 function TControl.GetEnabled: Boolean;
37844 MOV ECX, [EAX].fHandle
37845 JECXZ @@get_field
37847 PUSH ECX
37848 CALL IsWindowEnabled
37849 { but 00000001 is returned anywhere...
37850 NEG EAX
37851 SBB EAX, EAX
37852 NEG EAX
37856 @@get_field:
37857 TEST byte ptr [EAX].fStyle + 3, 8 //WS_DISABLED shr 3
37858 SETZ AL
37859 end;
37860 {$ELSE ASM_VERSION} //Pascal
37861 function TControl.GetEnabled: Boolean;
37862 begin
37863 if FHandle = 0 then
37864 Result := (Style and WS_DISABLED) = 0
37865 else
37866 Result := IsWindowEnabled( FHandle );
37867 end;
37868 {$ENDIF ASM_VERSION}
37870 {$IFDEF ASM_VERSION}
37871 //[function TControl.IsMainWindow]
37872 function TControl.IsMainWindow: Boolean;
37874 CMP [EAX].fIsControl, 0
37875 JNZ @@no_notmain
37877 XCHG EDX, EAX
37878 MOV EAX, [EDX].fParent
37880 TEST EAX, EAX
37881 JZ @@1
37883 MOV ECX, [EAX].fParent
37884 INC ECX
37885 LOOP @@no_notmain
37887 MOV EAX, [EAX].fChildren
37889 MOV ECX, [EAX].TList.fCount
37890 JECXZ @@no_notmain
37892 MOV EAX, [EAX].TList.fItems
37893 CMP EDX, [EAX]
37894 MOV AL, 1
37895 JMP @@2
37896 @@1:
37897 INC EAX
37898 MOVZX ECX, [AppButtonUsed]
37899 JECXZ @@yes_main
37900 CMP EDX, [Applet]
37901 @@2:
37902 JZ @@yes_main
37904 @@no_notmain:
37905 XOR EAX, EAX
37906 @@yes_main:
37907 end;
37908 {$ELSE ASM_VERSION} //Pascal
37909 function TControl.IsMainWindow: Boolean;
37910 var A: PControl;
37911 begin
37912 Result := False;
37913 if fIsControl then Exit;
37914 A := fParent; // WindowedParent;
37915 if A = nil then
37916 begin
37917 Result := (@Self = Applet) or not AppButtonUsed;
37918 Exit;
37920 else
37921 if A.fParent <> nil then Exit;
37922 //--------------------------------------------------------------------------------
37923 if A.fChildren.fCount = 0 then Exit; // by ECM, fixes AV when user changed (logoff)
37924 //--------------------------------------------------------------------------------
37925 Result := A.fChildren.fItems[ 0 ] = @Self;
37926 end;
37927 {$ENDIF ASM_VERSION}
37929 {$IFDEF ASM_VERSION}
37930 //[function TControl.get_ClassName]
37931 function TControl.get_ClassName: String;
37933 PUSH EBX
37934 XCHG EBX, EAX
37935 XCHG EAX, EDX
37936 MOV EDX, [EBX].fControlClassName
37937 PUSH EAX
37938 CALL System.@LStrFromPChar
37939 POP EAX
37940 CMP [EBX].fCtlClsNameChg, 0
37941 JNZ @@exit
37942 MOV ECX, [EAX]
37943 MOV EDX, offset[ @@obj ]
37944 CALL System.@LStrCat3
37945 JMP @@exit
37947 DD -1, 4
37948 @@obj: DB 'obj_', 0
37950 @@exit:
37951 POP EBX
37952 end;
37953 {$ELSE ASM_VERSION} //Pascal
37954 function TControl.get_ClassName: String;
37955 begin
37956 if not fCtlClsNameChg then
37957 Result := 'obj_' + fControlClassName
37958 else
37959 Result := fControlClassName;
37960 end;
37961 {$ENDIF ASM_VERSION}
37963 //[procedure TControl.set_ClassName]
37964 procedure TControl.set_ClassName(const Value: String);
37965 begin
37966 if fCtlClsNameChg then
37967 FreeMem( fControlClassName );
37968 GetMem( fControlClassName, Length( Value ) + 1 );
37969 StrCopy( fControlClassName, @ Value[ 1 ] );
37970 fCtlClsNameChg := TRUE;
37971 end;
37973 //[function WndProcQueryEndSession]
37974 function WndProcQueryEndSession( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
37975 var Accept: Boolean;
37976 begin
37977 Result := FALSE;
37978 if Msg.message = WM_QUERYENDSESSION then
37979 begin
37980 if Assigned( Sender.fOnQueryEndSession ) then
37981 begin
37982 Accept := TRUE;
37983 Sender.fCloseQueryReason := qShutdown;
37984 if LongBool(Msg.lParam and {ENDSESSION_LOGOFF} DWORD($80000000)) then
37985 Sender.fCloseQueryReason := qLogoff;
37986 Sender.fOnQueryEndSession( Sender, Accept );
37987 Sender.fCloseQueryReason := qClose;
37988 Rslt := Integer( Accept );
37989 // Äîáàâèòü. Íóæíî äëÿ òîãî, ÷òîáû îòìåíèëîñü çàâåðøåíèå ñåàíñà,
37990 // åñëè Accept óñòàíîâëåí â False è ñåàíñ çàâåðøèëñÿ ïðè Accept = True
37991 // Add (YS). To cancel ending session if Accept=FALSE but allow ending
37992 // session if Accept=TRUE.
37993 Result := True; // {YS}: no further processing
37994 end;
37995 end;
37996 end;
37998 //[procedure TControl.SetOnQueryEndSession]
37999 procedure TControl.SetOnQueryEndSession(const Value: TOnEventAccept);
38000 begin
38001 AttachProc( WndProcQueryEndSession );
38002 fOnQueryEndSession := Value;
38003 end;
38005 //[function WndProcMinMaxRestore]
38006 function WndProcMinMaxRestore( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
38007 begin
38008 Result := FALSE;
38009 if Msg.message = WM_SYSCOMMAND then
38010 begin
38011 case Msg.wParam of
38012 SC_MINIMIZE: if Assigned( Sender.fOnMinimize ) then
38013 Sender.fOnMinimize( Sender );
38014 SC_MAXIMIZE: if Assigned( Sender.fOnMaximize ) then
38015 Sender.fOnMaximize( Sender );
38016 SC_RESTORE: if Assigned( Sender.fOnRestore ) then
38017 Sender.fOnRestore( Sender );
38018 end;
38019 end;
38020 end;
38022 //[procedure TControl.SetOnMinMaxRestore]
38023 procedure TControl.SetOnMinMaxRestore(const Index: Integer;
38024 const Value: TOnEvent);
38025 type POnEvent = ^TOnEvent;
38026 {$IFDEF F_P}
38027 var Ptr1: Pointer;
38028 {$ELSE DELPHI}
38029 var Ev: POnEvent;
38030 {$ENDIF F_P/DELPHI}
38031 begin
38032 AttachProc( WndProcMinMaxRestore );
38033 {$IFDEF F_P}
38034 Ptr1 := Self;
38036 MOV EAX, [Ptr1]
38037 LEA EAX, [EAX].TControl.fOnMinimize
38038 ADD EAX, [Index]
38039 MOV EDX, [Value]
38040 MOV [EAX], EDX
38041 MOV EDX, [Value+4]
38042 MOV [EAX+4], EDX
38043 end [ 'EAX', 'EDX' ];
38044 {$ELSE DELPHI}
38045 Ev := Pointer( Integer( @ TMethod( fOnMinimize ).Code ) + Index );
38046 //Ev := Pointer( Integer( @ fOnMinimize ) + Index );
38047 Ev^ := Value;
38048 {$ENDIF}
38049 end;
38051 {$IFDEF F_P}
38052 //[function TControl.GetOnMinMaxRestore]
38053 function TControl.GetOnMinMaxRestore(const Index: Integer): TOnEvent;
38054 begin
38055 CASE Index OF
38056 0: Result := fOnMinimize;
38057 8: Result := fOnMaximize;
38058 16: Result := fOnRestore;
38059 END;
38060 end;
38061 {$ENDIF F_P}
38063 {$IFDEF INPACKAGE}
38064 {$IFDEF ASM_LOCAL}
38065 {$UNDEF ASM_LOCAL}
38066 {$ENDIF}
38067 {$ELSE}
38068 {$IFDEF ASM_VERSION}
38069 {$DEFINE ASM_LOCAL}
38070 {$ENDIF}
38071 {$ENDIF}
38073 {$IFDEF ASM_LOCAL}
38074 //[procedure TControl.SetParent]
38075 procedure TControl.SetParent( Value: PControl );
38077 PUSH EBX
38078 PUSH EDI
38079 XCHG EBX, EAX
38080 MOV EDI, EDX
38081 CMP EDI, [EBX].fParent
38082 JE @@exit
38084 MOV ECX, [EBX].fParent
38085 JECXZ @@1
38086 PUSH ECX
38088 MOV EAX, EBX
38089 CALL TControl.Invalidate
38091 POP ECX
38092 PUSH ECX
38094 MOV EAX, [ECX].fChildren
38095 MOV EDX, EBX
38096 CALL TList.Remove
38098 POP EAX
38099 MOV ECX, [EAX].fNotifyChild
38100 JECXZ @@1
38102 XOR EDX, EDX
38103 CALL ECX
38104 @@1:
38105 MOV [EBX].fParent, EDI
38106 TEST EDI, EDI
38107 JZ @@exit
38109 MOV EAX, [EDI].fChildren
38110 MOV EDX, EBX
38111 CALL TList.Add
38113 {$IFNDEF INPACKAGE}
38114 MOV ECX, [EBX].fHandle
38115 JECXZ @@2
38116 MOV EAX, EDI
38117 CALL TControl.GetWindowHandle
38118 PUSH EAX
38119 PUSH [EBX].fHandle
38120 CALL Windows.SetParent
38121 @@2:
38122 {$ENDIF}
38124 MOV ECX, [EDI].fNotifyChild
38125 JECXZ @@3
38126 MOV EAX, EDI
38127 MOV EDX, EBX
38128 CALL ECX
38129 @@3:
38130 MOV ECX, [EBX].fNotifyChild
38131 JECXZ @@4
38132 MOV EAX, EDI
38133 MOV EDX, EBX
38134 CALL ECX
38135 @@4:
38136 XCHG EAX, EBX
38137 CALL TControl.Invalidate
38138 @@exit:
38139 POP EDI
38140 POP EBX
38141 end;
38142 {$ELSE ASM_VERSION} //Pascal
38143 procedure TControl.SetParent( Value: PControl );
38144 begin
38145 if Value = fParent then Exit;
38146 if fParent <> nil then
38147 begin
38148 Invalidate; // necessary for graphic controls
38149 fParent.fChildren.Remove( @Self );
38150 if Assigned( fParent.fNotifyChild ) then
38151 fParent.fNotifyChild( fParent, nil );
38152 end;
38153 fParent := Value;
38154 if fParent <> nil then
38155 begin
38156 fParent.fChildren.Add( @Self );
38157 {$IFNDEF INPACKAGE}
38158 if FHandle <> 0 then
38159 Windows.SetParent( FHandle, Value.GetWindowHandle );
38160 {$ENDIF}
38161 if Assigned( fParent.fNotifyChild ) then
38162 fParent.fNotifyChild( fParent, @ Self );
38163 if Assigned( fNotifyChild ) then
38164 fNotifyChild( fParent, @ Self );
38165 Invalidate; // necessary for graphic controls
38166 end;
38167 end;
38168 {$ENDIF ASM_VERSION}
38170 //[function TControl.ChildIndex]
38171 function TControl.ChildIndex(Child: PControl): Integer;
38172 begin
38173 Result := fChildren.IndexOf( Child );
38174 end;
38177 //[procedure TControl.MoveChild]
38178 procedure TControl.MoveChild(Child: PControl; NewIdx: Integer);
38179 var I: Integer;
38180 begin
38181 I := ChildIndex( Child );
38182 Assert( I>=0, 'TControl.MoveChild: index out of bounds' );
38183 fChildren.MoveItem( I, NewIdx );
38184 end;
38186 //[procedure TControl.EnableChildren]
38187 procedure TControl.EnableChildren(Enable, Recursive: Boolean);
38188 var I: Integer;
38189 C: PControl;
38190 begin
38191 for I := 0 to ChildCount-1 do
38192 begin
38193 C := Children[ I ];
38194 C.Enabled := Enable;
38195 if Recursive then
38196 C.EnableChildren( Enable, TRUE );
38197 end;
38198 end;
38200 {$IFDEF ASM_VERSION}
38201 //[constructor TControl.CreateParented]
38202 constructor TControl.CreateParented(AParent: PControl);
38203 asm //cmd //opd
38204 //CALL System.@ObjSetup // generated automatically
38205 //JZ @@exit // generated automatically
38206 PUSH EAX
38207 MOV EDX, ECX
38208 MOV ECX, [EAX]
38209 CALL dword ptr [ECX+8]
38210 POP EAX
38211 @@exit:
38212 end;
38213 {$ELSE ASM_VERSION} //Pascal
38214 constructor TControl.CreateParented(AParent: PControl);
38215 begin
38216 InitParented( AParent );
38217 end;
38218 {$ENDIF ASM_VERSION}
38220 {$IFDEF ASM_VERSION}
38221 //[function TControl.GetLeft]
38222 function TControl.GetLeft: Integer;
38224 CALL HelpGetBoundsRect
38225 POP EAX
38227 POP ECX
38228 POP ECX
38229 POP ECX
38230 end;
38231 {$ELSE ASM_VERSION} //Pascal
38232 function TControl.GetLeft: Integer;
38233 begin
38234 Result := BoundsRect.Left;
38235 end;
38236 {$ENDIF ASM_VERSION}
38238 {$IFDEF ASM_VERSION}
38239 //[procedure TControl.SetLeft]
38240 procedure TControl.SetLeft( Value: Integer );
38242 PUSH EDI
38244 PUSH EDX
38245 CALL HelpGetBoundsRect
38246 POP EDX // EDX = Left
38247 POP ECX // ECX = Top
38248 POP EDI // EDI = Right
38250 SUB EDI, EDX // EDI = width
38251 MOV EDX, [ESP+4] // EDX = Left'
38252 ADD EDI, EDX // EDI = Right'
38254 PUSH EDI
38255 PUSH ECX
38256 PUSH EDX
38257 MOV EDX, ESP
38259 CALL SetBoundsRect
38260 ADD ESP, size_TRect + 4
38262 POP EDI
38264 end;
38265 {$ELSE ASM_VERSION} //Pascal
38266 procedure TControl.SetLeft( Value: Integer );
38267 var R: TRect;
38268 begin
38269 R := BoundsRect;
38270 R.Left := Value;
38271 R.Right := Value + Width;
38272 SetBoundsRect( R );
38273 end;
38274 {$ENDIF ASM_VERSION}
38276 {$IFDEF ASM_VERSION}
38277 //[function TControl.GetTop]
38278 function TControl.GetTop: Integer;
38280 CALL HelpGetBoundsRect
38281 POP EDX
38282 POP EAX
38283 POP EDX
38284 POP EDX
38285 end;
38286 {$ELSE ASM_VERSION} //Pascal
38287 function TControl.GetTop: Integer;
38288 begin
38289 Result := BoundsRect.Top;
38290 end;
38291 {$ENDIF ASM_VERSION}
38293 {$IFDEF ASM_VERSION}
38294 //[procedure TControl.SetTop]
38295 procedure TControl.SetTop( Value: Integer );
38297 PUSH ESI
38298 PUSH EDI
38300 PUSH EDX
38301 CALL HelpGetBoundsRect
38302 POP EDX // EDX = Left
38303 POP ECX // ECX = Top
38304 POP EDI // EDI = Right
38305 POP ESI // ESI = Bottom
38307 SUB ESI, ECX // ESI = Height'
38308 POP ECX // ECX = Top'
38309 ADD ESI, ECX // ESI = Bottom'
38311 PUSH ESI
38312 PUSH EDI
38313 PUSH ECX
38314 PUSH EDX
38315 MOV EDX, ESP
38317 CALL SetBoundsRect
38318 ADD ESP, size_TRect
38320 POP EDI
38321 POP ESI
38322 end;
38323 {$ELSE ASM_VERSION} //Pascal
38324 procedure TControl.SetTop( Value: Integer );
38325 var R: TRect;
38326 begin
38327 R := BoundsRect;
38328 R.Top := Value;
38329 R.Bottom := Value + Height;
38330 SetBoundsRect( R );
38331 end;
38332 {$ENDIF ASM_VERSION}
38334 {$IFDEF ASM_VERSION}
38335 //[function TControl.GetWidth]
38336 function TControl.GetWidth: Integer;
38338 CALL HelpGetBoundsRect
38339 POP EDX
38340 POP ECX
38341 POP EAX
38342 SUB EAX, EDX
38343 POP ECX
38344 end;
38345 {$ELSE ASM_VERSION} //Pascal
38346 function TControl.GetWidth: Integer;
38347 begin
38348 with BoundsRect do
38349 Result := Right - Left;
38350 end;
38351 {$ENDIF ASM_VERSION}
38353 {$IFDEF ASM_VERSION}
38354 //[procedure TControl.SetWidth]
38355 procedure TControl.SetWidth( Value: Integer );
38357 PUSH EDX
38359 CALL HelpGetBoundsRect
38360 POP EDX
38361 PUSH EDX
38362 ADD EDX, [ESP].size_TRect
38363 MOV [ESP].TRect.Right, EDX
38365 MOV EDX, ESP
38366 CALL SetBoundsRect
38368 ADD ESP, size_TRect + 4
38369 end;
38370 {$ELSE ASM_VERSION} //Pascal
38371 procedure TControl.SetWidth( Value: Integer );
38372 var R: TRect;
38373 begin
38374 R := BoundsRect;
38375 with R do
38376 Right := Left + Value;
38377 SetBoundsRect( R );
38378 end;
38379 {$ENDIF ASM_VERSION}
38381 {$IFDEF ASM_VERSION}
38382 //[function TControl.GetHeight]
38383 function TControl.GetHeight: Integer;
38385 CALL HelpGetBoundsRect
38386 POP ECX
38387 POP EDX // EDX = top
38388 POP ECX
38389 POP EAX // EAX = bottom
38390 SUB EAX, EDX // result = height
38391 end;
38392 {$ELSE ASM_VERSION} //Pascal
38393 function TControl.GetHeight: Integer;
38394 begin
38395 with BoundsRect do
38396 Result := Bottom - Top;
38397 end;
38398 {$ENDIF ASM_VERSION}
38400 {$IFDEF ASM_VERSION}
38401 //[procedure TControl.SetHeight]
38402 procedure TControl.SetHeight( Value: Integer );
38404 PUSH EDX
38406 CALL HelpGetBoundsRect
38407 MOV EDX, [ESP].TRect.Top
38408 ADD EDX, [ESP].size_TRect
38409 MOV [ESP].TRect.Bottom, EDX
38411 MOV EDX, ESP
38412 CALL SetBoundsRect
38414 ADD ESP, size_TRect + 4
38415 end;
38416 {$ELSE ASM_VERSION} //Pascal
38417 procedure TControl.SetHeight( Value: Integer );
38418 var R: TRect;
38419 begin
38420 R := BoundsRect;
38421 with R do
38422 Bottom := Top + Value;
38423 SetBoundsRect( R );
38424 end;
38425 {$ENDIF ASM_VERSION}
38427 {$IFDEF ASM_VERSION}
38428 //[function TControl.GetPosition]
38429 function TControl.GetPosition: TPoint;
38431 PUSH EDX
38432 CALL HelpGetBoundsRect
38433 POP EAX // EAX = left
38434 POP ECX // ECX = top
38435 POP EDX
38436 POP EDX
38437 POP EDX // EDX = @Result
38438 MOV [EDX], EAX
38439 MOV [EDX+4], ECX
38440 end;
38441 {$ELSE ASM_VERSION} //Pascal
38442 function TControl.GetPosition: TPoint;
38443 begin
38444 Result.x := BoundsRect.Left;
38445 Result.y := BoundsRect.Top;
38446 end;
38447 {$ENDIF ASM_VERSION}
38449 {$IFDEF ASM_VERSION}
38450 //[procedure TControl.Set_Position]
38451 procedure TControl.Set_Position( Value: TPoint );
38453 PUSH ESI
38454 PUSH EDI
38456 PUSH EAX
38457 PUSH EDX
38458 CALL HelpGetBoundsRect
38459 POP EDX // left
38460 POP EAX // top
38461 POP ECX // right
38462 SUB ECX, EDX // ECX = width
38463 POP EDX // bottom
38464 SUB EDX, EAX // EDX = height
38465 POP EAX // EAX = @Value
38466 POP ESI // ESI = @Self
38468 MOV EDI, [EAX+4] // top'
38469 ADD EDX, EDI
38470 PUSH EDX // bottom'
38472 MOV EAX, [EAX] // left'
38473 ADD ECX, EAX
38474 PUSH ECX // right'
38476 PUSH EDI // top'
38477 PUSH EAX // left'
38479 MOV EAX, ESI
38480 MOV EDX, ESP
38481 CALL SetBoundsRect
38483 ADD ESP, size_TRect
38485 POP EDI
38486 POP ESI
38487 end;
38488 {$ELSE ASM_VERSION} //Pascal
38489 procedure TControl.Set_Position( Value: TPoint );
38490 var R: TRect;
38491 begin
38492 R.Top := Value.y;
38493 R.Left := Value.x;
38494 R.Right := R.Left + Width;
38495 R.Bottom := R.Top + Height;
38496 BoundsRect := R;
38497 end;
38498 {$ENDIF ASM_VERSION}
38500 //[function WndProcConstraints]
38501 function WndProcConstraints( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
38502 var MMI: PMinMaxInfo;
38503 begin
38504 Result := FALSE;
38505 if Msg.message = WM_GETMINMAXINFO then
38506 begin
38507 Rslt := Sender.CallDefWndProc( Msg );
38508 MMI := Pointer( Msg.lParam );
38509 if Sender.FMaxWidth > 0 then
38510 begin
38511 MMI.ptMaxSize.x := Sender.FMaxWidth;
38512 MMI.ptMaxTrackSize.x := Sender.FMaxWidth;
38513 end;
38514 if Sender.FMaxHeight > 0 then
38515 begin
38516 MMI.ptMaxSize.y := Sender.FMaxHeight;
38517 MMI.ptMaxTrackSize.y := Sender.FMaxHeight;
38518 end;
38519 MMI.ptMinTrackSize := MakePoint( Sender.FMinWidth, Sender.FMinHeight );
38520 Rslt := 0;
38521 Result := TRUE;
38522 end;
38523 end;
38525 {$IFDEF USE_MHTOOLTIP}
38526 {$DEFINE implementation}
38527 {$I KOLMHToolTip}
38528 {$UNDEF implementation}
38529 {$ENDIF}
38531 //[procedure TControl.SetConstraint]
38532 procedure TControl.SetConstraint(const Index, Value: Integer);
38533 begin
38534 AttachProc( WndProcConstraints );
38535 case Index of
38536 0: FMinWidth := Value;
38537 1: FMinHeight := Value;
38538 2: FMaxWidth := Value;
38539 3: FMaxHeight := Value;
38540 end;
38541 end;
38543 {$IFDEF F_P}
38544 //[function TControl.GetConstraint]
38545 function TControl.GetConstraint(const Index: Integer): Integer;
38546 begin
38547 CASE Index OF
38548 0: Result := FMinWidth;
38549 1: Result := FMinHeight;
38550 2: Result := FMaxWidth;
38551 3: Result := FMaxHeight;
38552 END;
38553 end;
38554 {$ENDIF F_P}
38557 //[function TControl.ControlRect]
38558 function TControl.ControlRect: TRect;
38559 var C: PControl;
38560 R: TRect;
38561 begin
38562 Result := BoundsRect;
38563 C := Parent;
38564 if C <> nil then
38565 begin
38566 //DoScrollOffset( @Result );
38568 if not C.fIsControl then Exit;
38570 R := C.ControlRect;
38571 OffsetRect( Result, R.Left, R.Top );
38573 if C.fChildren <> nil then
38574 if C.FChildren.IndexOf( @Self ) >= C.MembersCount then
38575 begin
38576 R := C.ClientRect;
38577 Dec( R.Top, C.fClientTop );
38578 Dec( R.Left, C.fClientLeft );
38579 OffsetRect( Result, R.Left, R.Top );
38580 end;
38581 end;
38582 end;
38585 //[function TControl.ControlAtPos]
38586 function TControl.ControlAtPos( X, Y: Integer;
38587 IgnoreDisabled: Boolean ): PControl;
38588 var I: Integer;
38589 C: PControl;
38590 CR, VR: TRect;
38591 begin
38592 Result := nil;
38593 CR := ControlRect;
38594 if Windowed then
38595 CR := MakeRect( 0, 0, 0, 0 );
38596 X := X + CR.Left; // - R.Left;
38597 Y := Y + CR.Top; // - R.Top;
38598 for I := ChildCount { + MembersCount } - 1 downto 0 do
38599 begin
38600 C := Children[ I ]; //Members[ I ];
38601 if C.Visible then
38602 if (not IgnoreDisabled) or IgnoreDisabled and C.Enabled then
38603 begin
38604 VR := C.ControlRect;
38605 if (X >= VR.Left) and (X < VR.Right) and
38606 (Y >= VR.Top) and (Y < VR.Bottom) then
38607 begin
38608 Result := C;
38609 Exit;
38610 end;
38611 end;
38612 end;
38613 end;
38615 //[PROCEDURE DefaultPaintBackground]
38616 {$IFDEF ASM_VERSION}
38617 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );
38619 PUSH EDI
38621 PUSH EDI
38622 MOV EDI, ESP
38624 PUSH ECX
38625 PUSH EDX
38627 MOV EAX, [EAX].TControl.fColor
38628 CALL Color2RGB
38629 PUSH EAX
38630 CALL CreateSolidBrush
38631 STOSD
38632 MOV EDI, EAX
38633 CALL windows.FillRect
38634 PUSH EDI
38635 CALL DeleteObject
38636 POP EDI
38637 end;
38638 {$ELSE ASM_VERSION} //Pascal
38639 procedure DefaultPaintBackground( Sender: PControl; DC: HDC; Rect: PRect );
38640 var B: HBrush;
38641 begin
38642 B := CreateSolidBrush( Color2Rgb( Sender.Color ) );
38643 Windows.FillRect( DC, Rect^, B );
38644 DeleteObject( B );
38645 end;
38646 {$ENDIF ASM_VERSION}
38647 //[END DefaultPaintBackground]
38649 //[procedure TControl.PaintBackground]
38650 procedure TControl.PaintBackground( DC: HDC; Rect: PRect );
38651 begin
38652 Global_OnPaintBkgnd( @Self, DC, Rect );
38653 end;
38655 //[procedure TControl.SetCtlColor]
38656 {$IFDEF ASM_VERSION}
38657 procedure TControl.SetCtlColor( Value: TColor );
38659 PUSH EBX
38660 MOV EBX, EAX
38662 {$IFNDEF INPACKAGE}
38663 PUSH EDX
38665 CALL GetWindowHandle
38666 XCHG ECX, EAX
38668 POP EDX
38669 {$ELSE}
38670 MOV ECX, [EBX].fHandle
38671 {$ENDIF}
38673 JECXZ @@1
38675 MOVZX ECX, [EBX].fCommandActions.aSetBkColor
38676 JECXZ @@1
38678 PUSH EDX
38680 XCHG EAX, EDX
38681 PUSH ECX
38682 CALL Color2RGB
38683 POP ECX
38685 PUSH EAX // Color2RGB( Value )
38686 PUSH 0 // 0
38687 PUSH ECX // fCommandActions.aSetBkColor
38688 PUSH EBX // @ Self
38689 CALL TControl.Perform
38691 POP EDX
38693 @@1:
38694 CMP EDX, [EBX].fColor
38695 JZ @@exit
38697 MOV [EBX].fColor, EDX
38699 XOR ECX, ECX
38700 XCHG ECX, [EBX].fTmpBrush
38701 JECXZ @@setbrushcolor
38703 PUSH EDX
38704 PUSH ECX
38705 CALL DeleteObject
38706 POP EDX
38708 @@setbrushcolor:
38709 MOV ECX, [EBX].fBrush
38710 JECXZ @@invldte
38712 XCHG EAX, ECX
38713 MOV ECX, EDX
38714 //MOV EDX, go_Color
38715 XOR EDX, EDX
38716 CALL TGraphicTool.SetInt
38718 @@invldte:
38719 XCHG EAX, EBX
38720 CALL TControl.Invalidate
38721 @@exit:
38722 POP EBX
38723 end;
38724 {$ELSE ASM_VERSION} //Pascal
38725 procedure TControl.SetCtlColor( Value: TColor );
38726 begin
38727 {$IFNDEF INPACKAGE}
38728 if GetWindowHandle <> 0 then
38729 {$ELSE}
38730 if fHandle <> 0 then
38731 {$ENDIF}
38732 if fCommandActions.aSetBkColor <> 0 then
38733 Perform( fCommandActions.aSetBkColor, 0, Color2RGB( Value ) );
38734 if fColor = Value then Exit;
38735 fColor := Value;
38736 if fTmpBrush <> 0 then
38737 begin
38738 DeleteObject( fTmpBrush );
38739 fTmpBrush := 0;
38740 end;
38741 if fBrush <> nil then
38742 fBrush.Color := Value;
38743 Invalidate;
38744 end;
38745 {$ENDIF ASM_VERSION}
38747 {$IFDEF ASM_VERSION}
38748 //[function TControl.GetParentWnd]
38749 function TControl.GetParentWnd( NeedHandle: Boolean ): HWnd;
38751 MOV ECX, [EAX].fParent
38752 JECXZ @@exit
38754 PUSH ECX
38755 TEST DL, DL
38756 JZ @@load_handle
38758 XCHG EAX, ECX
38759 CALL GetWindowHandle
38761 @@load_handle:
38762 POP ECX
38763 MOV ECX, [ECX].fHandle
38765 @@exit: XCHG EAX, ECX
38767 end;
38768 {$ELSE ASM_VERSION} //Pascal
38769 function TControl.GetParentWnd( NeedHandle: Boolean ): HWnd;
38770 var C: PControl;
38771 begin
38772 Result := 0;
38773 C := fParent; // WindowedParent;
38774 if C <> nil then
38775 begin
38776 if NeedHandle then
38777 C.GetWindowHandle;
38778 Result := C.fHandle;
38779 end;
38780 end;
38781 {$ENDIF ASM_VERSION}
38783 {$IFDEF ASM_VERSION}
38784 //[procedure TControl.CreateChildWindows]
38785 procedure TControl.CreateChildWindows;
38787 PUSH ESI
38788 MOV ESI, [EAX].TControl.fChildren
38789 MOV ECX, [ESI].TList.fCount
38790 MOV ESI, [ESI].TList.fItems
38791 JECXZ @@exit
38793 @@loop: PUSH ECX
38794 LODSD
38795 CALL CallTControlCreateWindow
38796 //CALL TControl.GetWindowHandle
38797 POP ECX
38798 LOOP @@loop
38800 @@exit: POP ESI
38801 end;
38802 {$ELSE ASM_VERSION} //Pascal
38803 procedure TControl.CreateChildWindows;
38804 var I: Integer;
38805 C: PControl;
38806 begin
38807 for I := 0 to fChildren.Count - 1 do
38808 begin
38809 C := fChildren.fItems[ I ];
38810 //C.GetWindowHandle;
38811 C.CreateWindow; //virtual!!!
38812 end;
38813 end;
38814 {$ENDIF ASM_VERSION}
38816 //[function TControl.GetMembers]
38817 function TControl.GetMembers(Idx: Integer): PControl;
38818 begin
38819 Result := fChildren.fItems[ Idx ];
38820 end;
38822 {$IFDEF ASM_VERSION}
38823 //[procedure TControl.DestroyChildren]
38824 procedure TControl.DestroyChildren;
38826 PUSH ESI
38828 MOV EAX, [EAX].fChildren
38829 PUSH EAX
38830 MOV ECX, [EAX].TList.fCount
38831 JECXZ @@clear
38832 MOV ESI, [EAX].TList.fItems
38833 LEA ESI, [ESI + ECX*4 - 4] // is order really important ?
38835 @@loop: STD //
38836 LODSD
38837 CLD //
38839 PUSH ECX
38840 CALL TObj.Free
38841 POP ECX
38843 LOOP @@loop
38845 @@clear:
38846 POP EAX
38847 CALL TList.Clear
38849 POP ESI
38850 end;
38851 {$ELSE ASM_VERSION} //Pascal
38852 procedure TControl.DestroyChildren;
38853 var I: Integer;
38854 W: PControl;
38855 begin
38856 for I := fChildren.fCount - 1 downto 0 do
38857 begin
38858 W := fChildren.fItems[ I ];
38859 W.Free;
38860 end;
38861 fChildren.Clear;
38862 end;
38863 {$ENDIF ASM_VERSION}
38865 {//-
38866 //[function TControl.WindowedParent]
38867 function TControl.WindowedParent: PControl;
38868 begin
38869 Result := fParent;
38870 end;}
38872 {$IFDEF ASM_VERSION}
38873 //[function TControl.ProcessMessage]
38874 function TControl.ProcessMessage: Boolean;
38875 const size_TMsg = sizeof( TMsg );
38877 PUSH EBX
38878 XCHG EBX, EAX
38880 ADD ESP, -size_TMsg-4
38882 MOV EDX, ESP
38883 PUSH 1
38884 XOR ECX, ECX
38885 PUSH ECX
38886 PUSH ECX
38887 PUSH ECX
38888 PUSH EDX
38889 CALL PeekMessage
38891 TEST EAX, EAX
38892 JZ @@exit
38894 MOV EDX, [ESP].TMsg.message
38895 CMP DX, WM_QUIT
38896 JNZ @@tran_disp
38897 MOV [AppletTerminated], 1
38898 {$IFDEF PROVIDE_EXITCODE}
38899 MOV EDX, [ESP].TMsg.wParam
38900 MOV [ExitCode], EDX
38901 {$ENDIF PROVIDE_EXITCODE}
38902 JMP @@fin
38904 @@tran_disp:
38905 MOV ECX, [EBX].fExMsgProc
38906 JECXZ @@do_tran_disp
38907 MOV EAX, EBX
38908 MOV EDX, ESP
38909 CALL ECX
38910 TEST AL, AL
38911 JNZ @@fin
38913 @@do_tran_disp:
38914 MOV EAX, ESP
38915 PUSH EAX
38916 PUSH EAX
38917 CALL TranslateMessage
38918 CALL DispatchMessage
38920 @@fin:
38921 MOV AX, word ptr [ESP].TMsg.message
38922 TEST AX, AX
38923 SETNZ AL
38925 @@exit: ADD ESP, size_TMsg+4
38926 POP EBX
38927 end;
38928 {$ELSE ASM_VERSION} //Pascal
38929 function TControl.ProcessMessage: Boolean;
38930 var Msg: TMsg;
38931 begin
38932 Result := False;
38933 if PeekMessage( Msg, 0, 0, 0, PM_REMOVE ) then
38934 begin
38935 Result := Msg.message <> 0;
38936 if (Msg.message = WM_QUIT) then
38937 begin
38938 AppletTerminated := True;
38939 {$IFDEF PROVIDE_EXITCODE}
38940 ExitCode := Msg.wParam;
38941 {$ENDIF PROVIDE_EXITCODE}
38943 else
38944 begin
38945 if not(Assigned( fExMsgProc ) and fExMsgProc( @Self, Msg )) then
38946 begin
38947 TranslateMessage( Msg );
38948 DispatchMessage( Msg );
38949 end;
38950 end;
38951 end;
38952 end;
38953 {$ENDIF ASM_VERSION}
38955 {$IFDEF ASM_VERSION}
38956 //[procedure TControl.ProcessMessages]
38957 procedure TControl.ProcessMessages;
38959 @@loo: PUSH EAX
38960 CALL ProcessMessage
38961 DEC AL
38962 POP EAX
38963 JZ @@loo
38964 end;
38965 {$ELSE ASM_VERSION} //Pascal
38966 procedure TControl.ProcessMessages;
38967 begin
38968 while ProcessMessage do ;
38969 end;
38970 {$ENDIF ASM_VERSION}
38972 //[procedure TControl.ProcessMessagesEx]
38973 procedure TControl.ProcessMessagesEx;
38974 begin
38975 PostMessage( GetWindowHandle, CM_PROCESS, 0, 0 );
38976 ProcessMessages;
38977 end;
38979 //[FUNCTION WndProcForm]
38980 {$IFDEF ASM_VERSION}
38981 function WndProcForm(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
38982 const szPaintStruct = sizeof(TPaintStruct);
38983 asm //cmd //opd
38984 CMP word ptr [EDX].TMsg.message, WM_ENDSESSION
38985 JNE @@chk_WM_SETFOCUS
38987 CMP [EDX].TMsg.wParam, 0
38988 JZ @@ret_false
38990 CALL TObj.RefDec
38991 XOR EAX, EAX
38992 MOV [AppletRunning], AL
38993 XCHG EAX, [Applet]
38994 INC [AppletTerminated]
38996 CALL TObj.Free
38997 CALL System.@Halt0
38998 //-------
39000 @@chk_WM_SETFOCUS:
39001 CMP word ptr [EDX].TMsg.message, WM_SETFOCUS
39002 JNE @@ret_false
39004 PUSH EBX
39005 PUSH ESI
39006 XOR EBX, EBX
39007 XCHG ESI, EAX
39008 {$IFDEF FIX_MODAL_SETFOCUS}
39009 MOV ECX, [ESI].TControl.fModalForm
39010 JECXZ @@no_fix_modal_setfocus
39011 PUSH [ECX].TControl.fHandle
39012 CALL SetFocus
39013 @@no_fix_modal_setfocus:
39014 {$ENDIF}
39016 MOV ECX, [ESI].TControl.FCurrentControl
39017 JECXZ @@1
39018 INC EBX
39019 XCHG EAX, ECX
39021 // or CreateForm?
39022 PUSH EAX
39023 CALL CallTControlCreateWindow
39024 TEST AL, AL
39025 POP EAX
39026 JZ @@1
39027 PUSH [EAX].TControl.fHandle
39029 CALL SetFocus
39030 @@1: MOV ECX, [Applet]
39031 JECXZ @@ret_EBX
39032 CMP ECX, ESI
39033 JE @@ret_EBX
39034 MOV [ECX].TControl.FCurrentControl, ESI
39035 @@ret_EBX:
39036 XCHG EAX, EBX
39037 POP ESI
39038 POP EBX
39041 @@ret_false:
39042 XOR EAX, EAX
39043 end;
39044 {$ELSE ASM_VERSION} //Pascal
39045 function WndProcForm(Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39046 var App: PControl;
39047 begin
39048 Result := True;
39049 with Self_{-}^{+} do
39050 case Msg.message of
39051 WM_ENDSESSION:
39052 begin
39053 if Msg.wParam <> 0 then
39054 begin
39055 Self_.RefDec;
39056 { Normally, WM_ENDSESSION is sent to a main form, not to Applet.
39057 Since we do not plan further working after handling this message,
39058 we decrease RefCount for the form (in was increased in EnumDynHandlers
39059 to prevent object destroying while its message processing is not
39060 finished). }
39061 App := Applet;
39062 //Rslt := 0; { We will not return any result at all. }
39063 {$IFDEF DEBUG_ENDSESSION}
39064 EndSession_Initiated := TRUE;
39065 LogFileOutput( GetStartDir + 'es_debug.txt',
39066 'Self_=' + Int2Hex( DWORD( Self_ ), 8 ) +
39067 ' Self_.Handle=' + Int2Str( Self_.FHandle ) );
39068 {$ENDIF}
39069 AppletTerminated := TRUE;
39070 AppletRunning := FALSE;
39071 Applet := nil;
39072 App.Free; { We provide OnDestroy handlers to be called for any objects here }
39073 Halt; { Stop further executing. }
39074 end else Result := FALSE;
39075 end;
39076 WM_SETFOCUS:
39077 begin
39078 {$IFDEF NEW_MODAL}
39079 if fModalForm <> nil then
39080 SetFocus( fModalForm.fHandle )
39081 else if ( FCurrentControl <> nil ) and not ( fCurrentControl.IsForm xor fIsApplet ) then
39082 {$ELSE not NEW_MODAL}
39083 if FCurrentControl <> nil then
39084 {$ENDIF}
39085 begin
39086 if FCurrentControl.CreateWindow then
39087 SetFocus( FCurrentControl.fHandle );
39089 else
39090 Result := False;
39091 if assigned( Applet ) and (Applet <> Self_) then
39092 Applet.FCurrentControl := Self_;
39093 end;
39094 else Result := False;
39095 end;
39096 end;
39097 {$ENDIF ASM_VERSION}
39098 //[END WndProcForm]
39100 //[FUNCTION GetPrevCtrlBoundsRect]
39101 {$IFDEF ASM_VERSION}
39102 function GetPrevCtrlBoundsRect( P: PControl; var R: TRect ): Boolean;
39104 MOV EDX, EBX
39105 MOV EAX, [EBX].TControl.fParent
39106 TEST EAX, EAX
39107 JZ @@exit
39108 PUSH EAX
39109 CALL TControl.ChildIndex
39110 TEST EAX, EAX
39111 XCHG EDX, EAX
39112 POP EAX
39113 JZ @@exit
39114 DEC EDX
39115 CALL TControl.GetMembers
39117 POP ECX // retaddr
39118 ADD ESP, -size_TRect
39119 MOV EDX, ESP
39120 PUSH ECX
39121 CALL TControl.GetBoundsRect
39122 STC // return CARRY
39123 @@exit:
39124 end;
39125 {$ELSE ASM_VERSION} //Pascal
39126 function GetPrevCtrlBoundsRect( P: PControl; var R: TRect ): Boolean;
39127 var Idx: Integer;
39128 begin
39129 Result := False;
39130 if P.FParent = nil then Exit;
39131 Idx := P.FParent.ChildIndex( P ) - 1;
39132 if Idx < 0 then Exit;
39133 Result := True;
39134 R := P.FParent.Children[ Idx ].BoundsRect;
39135 end;
39136 {$ENDIF ASM_VERSION}
39137 //[END GetPrevCtrlBoundsRect]
39139 {$IFDEF ASM_VERSION}
39140 //[function TControl.PlaceUnder]
39141 function TControl.PlaceUnder: PControl;
39143 PUSH EBX
39144 XCHG EBX, EAX
39145 CALL GetPrevCtrlBoundsRect
39146 JNC @@exit
39147 POP EDX // EDX = Left
39148 MOV EAX, EBX
39149 CALL TControl.SetLeft
39151 POP EDX
39152 POP EDX
39153 POP EDX // EDX = Bottom
39155 MOV EAX, [EBX].fParent
39156 ADD EDX, [EAX].fMargin
39158 MOV EAX, EBX
39159 CALL TControl.SetTop
39160 @@exit:
39161 XCHG EAX, EBX
39162 POP EBX
39163 end;
39164 {$ELSE ASM_VERSION} //Pascal
39165 function TControl.PlaceUnder: PControl;
39166 var R: TRect;
39167 begin
39168 Result := @Self;
39169 if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;
39170 Top := R.Bottom + fParent.fMargin;
39171 Left := R.Left;
39172 end;
39173 {$ENDIF ASM_VERSION}
39175 {$IFDEF ASM_VERSION}
39176 //[function TControl.PlaceDown]
39177 function TControl.PlaceDown: PControl;
39179 PUSH EBX
39180 XCHG EBX, EAX
39181 CALL GetPrevCtrlBoundsRect
39182 JNC @@exit
39183 POP EDX
39184 POP EDX
39185 POP EDX
39186 POP EDX // EDX = Bottom
39188 MOV EAX, [EBX].fParent
39189 ADD EDX, [EAX].fMargin
39191 MOV EAX, EBX
39192 CALL TControl.SetTop
39193 @@exit:
39194 XCHG EAX, EBX
39195 POP EBX
39196 end;
39197 {$ELSE ASM_VERSION} //Pascal
39198 function TControl.PlaceDown: PControl;
39199 var R: TRect;
39200 begin
39201 Result := @Self;
39202 if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;
39203 Top := R.Bottom + fParent.fMargin;
39204 end;
39205 {$ENDIF ASM_VERSION}
39207 {$IFDEF ASM_VERSION}
39208 //[function TControl.PlaceRight]
39209 function TControl.PlaceRight: PControl;
39211 PUSH EBX
39212 XCHG EBX, EAX
39213 CALL GetPrevCtrlBoundsRect
39214 JNC @@exit
39215 POP EDX
39216 POP EDX // EDX = Top
39217 MOV EAX, EBX
39218 CALL TControl.SetTop
39219 POP EDX // EDX = Right
39221 MOV EAX, [EBX].fParent
39222 ADD EDX, [EAX].fMargin
39224 POP ECX
39225 MOV EAX, EBX
39226 CALL TControl.SetLeft
39227 @@exit:
39228 XCHG EAX, EBX
39229 POP EBX
39230 end;
39231 {$ELSE ASM_VERSION} //Pascal
39232 function TControl.PlaceRight: PControl;
39233 var R: TRect;
39234 begin
39235 Result := @Self;
39236 if not GetPrevCtrlBoundsRect( @Self, R ) then Exit;
39237 Top := R.Top;
39238 Left := R.Right + fParent.fMargin;
39239 end;
39240 {$ENDIF ASM_VERSION}
39242 {$IFDEF ASM_VERSION}
39243 //[function TControl.SetSize]
39244 function TControl.SetSize(W, H: Integer): PControl;
39246 PUSH EBX
39247 XCHG EBX, EAX
39248 SUB ESP, 16
39249 XCHG EAX, EDX
39250 MOV EDX, ESP
39251 PUSH ECX // save H
39252 PUSH EAX // save W
39253 MOV EAX, EBX
39254 CALL GetBoundsRect
39255 POP ECX // pop W
39256 JECXZ @@nochg_W
39257 ADD ECX, [ESP+4].TRect.Left
39258 MOV [ESP+4].TRect.Right, ECX
39259 @@nochg_W:
39260 POP ECX // pop H
39261 JECXZ @@nochg_H
39262 ADD ECX, [ESP].TRect.Top
39263 MOV [ESP].TRect.Bottom, ECX
39264 @@nochg_H:
39265 MOV EAX, EBX
39266 MOV EDX, ESP
39267 CALL TControl.SetBoundsRect
39268 ADD ESP, 16
39269 XCHG EAX, EBX
39270 POP EBX
39271 end;
39272 {$ELSE ASM_VERSION} //Pascal
39273 function TControl.SetSize(W, H: Integer): PControl;
39274 var R: TRect;
39275 begin
39276 R := BoundsRect;
39277 if W > 0 then R.Right := R.Left + W;
39278 if H > 0 then R.Bottom := R.Top + H;
39279 SetBoundsRect( R );
39280 Result := @Self;
39281 end;
39282 {$ENDIF ASM_VERSION}
39284 //[function TControl.SetClientSize]
39285 function TControl.SetClientSize(W, H: Integer): PControl;
39286 begin
39287 if W > 0 then ClientWidth := W;
39288 if H > 0 then ClientHeight := H;
39289 Result := @Self;
39290 end;
39292 {$IFDEF ASM_VERSION}
39293 //[function TControl.AlignLeft]
39294 function TControl.AlignLeft(P: PControl): PControl;
39296 PUSH EAX
39297 MOV EAX, EDX
39298 CALL TControl.GetLeft
39299 MOV EDX, EAX
39300 POP EAX
39301 PUSH EAX
39302 CALL TControl.SetLeft
39303 POP EAX
39304 end;
39305 {$ELSE ASM_VERSION} //Pascal
39306 function TControl.AlignLeft(P: PControl): PControl;
39307 begin
39308 Result := @Self;
39309 Left := P.Left;
39310 end;
39311 {$ENDIF ASM_VERSION}
39313 {$IFDEF ASM_VERSION}
39314 //[function TControl.AlignTop]
39315 function TControl.AlignTop(P: PControl): PControl;
39317 PUSH EAX
39318 MOV EAX, EDX
39319 CALL TControl.GetTop
39320 MOV EDX, EAX
39321 POP EAX
39322 PUSH EAX
39323 CALL TControl.SetTop
39324 POP EAX
39325 end;
39326 {$ELSE ASM_VERSION} //Pascal
39327 function TControl.AlignTop(P: PControl): PControl;
39328 begin
39329 Result := @Self;
39330 Top := P.Top;
39331 end;
39332 {$ENDIF ASM_VERSION}
39334 {$IFDEF KEY_PREVIEW}
39335 {$DEFINE KEY_PREVIEW_OR_ESC_CLOSE_DIALOGS}
39336 {$ENDIF}
39337 {$IFDEF ESC_CLOSE_DIALOGS}
39338 {$IFNDEF KEY_PREVIEW_OR_ESC_CLOSE_DIALOGS}
39339 {$DEFINE KEY_PREVIEW_OR_ESC_CLOSE_DIALOGS}
39340 {$ENDIF}
39341 {$ENDIF}
39343 //[FUNCTION WndProcCtrl]
39344 {$IFDEF ASM_VERSION} // see addition for combobox in pas version
39345 function WndProcCtrl( Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
39346 asm //cmd //opd
39347 PUSH EBX
39348 XCHG EBX, EAX
39349 PUSH ESI
39350 PUSH EDI
39351 MOV EDI, EDX
39352 MOV EDX, [EDI].TMsg.message
39354 SUB DX, CN_CTLCOLORMSGBOX
39355 CMP DX, CN_CTLCOLORSTATIC-CN_CTLCOLORMSGBOX
39356 JA @@chk_CM_COMMAND
39357 @@2:
39358 PUSH ECX
39359 MOV EAX, [EBX].TControl.fTextColor
39360 CALL Color2RGB
39361 XCHG ESI, EAX
39362 PUSH ESI
39363 PUSH [EDI].TMsg.wParam
39364 CALL SetTextColor
39365 CMP [EBX].TControl.fTransparent, 0
39366 JZ @@opaque
39368 PUSH Windows.TRANSPARENT
39369 PUSH [EDI].TMsg.wParam
39370 CALL SetBkMode
39371 PUSH NULL_BRUSH
39372 CALL GetStockObject
39373 JMP @@ret_rslt
39375 @@opaque:
39376 MOV EAX, [EBX].TControl.fColor
39377 CALL Color2RGB
39378 XCHG ESI, EAX
39379 PUSH OPAQUE
39380 PUSH [EDI].TMsg.wParam
39381 CALL SetBkMode
39382 PUSH ESI
39383 PUSH [EDI].TMsg.wParam
39384 CALL SetBkColor
39386 MOV EAX, EBX
39387 CALL Global_GetCtlBrushHandle
39388 @@ret_rslt:
39389 XCHG ECX, EAX
39390 @@tmpbrushready:
39391 POP EAX
39392 MOV [EAX], ECX
39393 @@ret_true:
39394 MOV AL, 1
39396 JMP @@ret_EAX
39398 @@chk_CM_COMMAND:
39399 CMP word ptr [EDI].TMsg.message, CM_COMMAND
39400 JNE @@chk_WM_SETFOCUS
39402 PUSH ECX
39404 MOVZX ECX, word ptr [EDI].TMsg.wParam+2
39405 CMP CX, [EBX].TControl.fCommandActions.aClick
39406 JNE @@chk_aEnter
39408 CMP [EBX].TControl.fClickDisabled, 0
39409 JG @@calldef
39410 MOV EAX, EBX
39411 MOV DL, 1
39412 CALL TControl.SetFocused
39413 MOV EAX, EBX
39414 CALL TControl.DoClick
39415 JMP @@calldef
39417 @@chk_aEnter:
39418 LEA EAX, [EBX].TControl.fOnEnter
39419 CMP CX, [EBX].TControl.fCommandActions.aEnter
39420 JE @@goEvent
39421 LEA EAX, [EBX].TControl.fOnLeave
39422 CMP CX, [EBX].TControl.fCommandActions.aLeave
39423 JE @@goEvent
39424 LEA EAX, [EBX].TControl.fOnChange
39425 CMP CX, [EBX].TControl.fCommandActions.aChange
39426 JNE @@chk_aSelChange
39427 @@goEvent:
39428 MOV ECX, [EAX].TMethod.Code
39429 JECXZ @@2calldef
39430 MOV EAX, [EAX].TMethod.Data
39431 MOV EDX, EBX
39432 CALL ECX
39433 @@2calldef:
39434 JMP @@calldef
39436 @@chk_aSelChange:
39437 CMP CX, [EBX].TControl.fCommandActions.aSelChange
39438 JNE @@chk_WM_SETFOCUS_1
39439 MOV EAX, EBX
39440 CALL TControl.DoSelChange
39442 @@calldef:
39443 XCHG EAX, EBX
39444 MOV EDX, EDI
39445 CALL TControl.CallDefWndProc
39446 JMP @@ret_rslt
39448 @@chk_WM_SETFOCUS_1:
39449 POP ECX
39450 @@chk_WM_SETFOCUS:
39451 XOR EAX, EAX
39452 CMP word ptr [EDI].TMsg.message, WM_SETFOCUS
39453 JNE @@chk_WM_KEYDOWN
39455 MOV [ECX], EAX
39456 MOV EAX, EBX
39457 CALL TControl.ParentForm
39458 TEST EAX, EAX
39459 JZ @@ret_true
39461 PUSH EAX
39462 MOV ECX, [EAX].TControl.FCurrentControl
39463 JECXZ @@a1
39464 CMP ECX, EBX
39465 JZ @@a1
39466 XCHG EAX, ECX
39467 MOV ECX, [EAX].TControl.fLeave.TMethod.Code
39468 JECXZ @@a1
39469 XCHG EDX, EAX
39470 MOV EAX, [EDX].TControl.fLeave.TMethod.Data
39471 CALL ECX
39472 @@a1: POP EAX
39474 MOV [EAX].TControl.FCurrentControl, EBX
39475 XOR EAX, EAX
39477 PUSH EDX
39478 @@2ret_EAX:
39479 POP EDX
39481 @@chk_WM_KEYDOWN:
39482 {$IFDEF KEY_PREVIEW_OR_ESC_CLOSE_DIALOGS}
39483 CMP word ptr [EDI].TMsg.message, WM_KEYDOWN
39484 JNE @@ret0
39486 {$IFDEF KEY_PREVIEW}
39487 MOV EAX, EBX
39488 CALL TControl.ParentForm
39489 CMP EAX, EBX
39490 JE @@kp_end
39492 CMP [EAX].TControl.fKeyPreview, 0
39493 JZ @@kp_end
39495 PUSH [EDI].TMsg.lParam
39496 PUSH [EDI].TMsg.wParam
39497 PUSH WM_KEYDOWN
39498 PUSH EAX
39499 CALL TControl.Perform
39500 @@kp_end:
39501 {$ENDIF}
39503 {$IFDEF ESC_CLOSE_DIALOGS}
39504 MOV EAX, EBX
39505 CALL TControl.ParentForm
39506 TEST [EAX].TControl.fExStyle, WS_EX_DLGMODALFRAME
39507 JZ @@ecd_end
39508 CMP [EDI].TMsg.wParam, 27
39509 JNE @@ecd_end
39510 PUSH 0
39511 PUSH 0
39512 PUSH WM_CLOSE
39513 PUSH EAX
39514 CALL TControl.Perform
39515 @@ecd_end:
39516 {$ENDIF}
39518 @@ret0:
39519 XOR EAX, EAX
39520 {$ENDIF KEY_PREVIEW_OR_ESC_CLOSE_DIALOGS}
39522 @@ret_EAX:
39523 POP EDI
39524 POP ESI
39525 POP EBX
39526 end;
39527 {$ELSE ASM_VERSION} //Pascal
39528 function WndProcCtrl(Self_: PControl; var Msg: TMsg; var Rslt: Integer): Boolean;
39529 var F: PControl;
39530 Cmd : DWORD;
39531 begin
39532 //Result := FALSE;
39533 with Self_{-}^{+} do
39534 case Msg.message of
39535 CN_CTLCOLORMSGBOX..CN_CTLCOLORSTATIC:
39536 begin
39537 SetTextColor(Msg.WParam, Color2RGB(fTextColor));
39538 if fTransparent {AND (fPaintDC = Msg.wParam)} then
39539 begin
39540 SetBkMode( Msg.wParam, Windows.TRANSPARENT );
39541 Rslt := GetStockObject( NULL_BRUSH );
39543 else
39544 begin
39545 SetBkMode( Msg.wParam, Windows.OPAQUE );
39546 SetBkColor(Msg.WParam, Color2RGB( fColor ) );
39547 Rslt := Global_GetCtlBrushHandle( Self_ );
39548 end;
39549 Result := TRUE;
39550 end;
39551 CM_COMMAND:
39552 begin
39553 Result := True;
39554 Cmd := HiWord( Msg.wParam );
39555 if Cmd = fCommandActions.aClick then
39556 begin
39557 if Integer( fClickDisabled ) <= 0 then
39558 begin
39559 Focused := TRUE; //!!!!!!!!!!!!!!!!!!<><><>
39560 //Postmsg( WM_SETFOCUS, 0, 0 );
39561 DoClick;
39562 end;
39563 end else
39564 if Cmd = fCommandActions.aEnter then
39565 begin
39566 if Assigned( fOnEnter ) then fOnEnter( Self_ );
39567 end else
39568 if Cmd = fCommandActions.aLeave then
39569 begin
39570 if Assigned( fOnLeave ) then fOnLeave( Self_ );
39571 end else
39572 if Integer(Cmd) = fCommandActions.aChange then
39573 begin
39574 if Assigned( fOnChange ) then fOnChange( Self_ );
39575 //if fTransparent then Invalidate;
39576 end else
39577 if Integer(Cmd) = fCommandActions.aSelChange then
39578 begin
39579 DoSelChange;
39580 // if fTransparent then Invalidate;
39582 else Result := False;
39584 if Result then
39585 Rslt := CallDefWndProc( Msg );
39587 end;
39589 WM_SETFOCUS:
39590 begin
39591 Rslt := 0;
39592 Result := TRUE;
39593 F := ParentForm;
39594 if F <> nil then
39595 begin
39596 if (F.fCurrentControl <> nil) and (F.fCurrentControl <> Self_) and
39597 //(Self_.fChildren.IndexOf( F.fCurrentControl ) < 0) and
39598 Assigned( F.fCurrentControl.fLeave ) then
39599 F.fCurrentControl.fLeave( F.fCurrentControl );
39600 F.fCurrentControl := Self_;
39601 Result := False; // go further handling
39602 end;
39603 end;
39604 {$IFDEF KEY_PREVIEW_OR_ESC_CLOSE_DIALOGS}
39605 WM_KEYDOWN:
39606 begin
39607 Result := FALSE;
39608 {$IFDEF KEY_PREVIEW}
39609 //--------------------------------Truf-------------------------------------
39610 if ParentForm <> Self_ then
39611 begin
39612 if ParentForm.KeyPreview then
39613 ParentForm.Perform(WM_KEYDOWN,msg.wParam,msg.lParam);
39614 end;
39615 //--------------------------------Truf-------------------------------------
39616 {$ENDIF KEY_PREVIEW}
39617 {$IFDEF ESC_CLOSE_DIALOGS}
39618 //---------------------------------Babenko Alexey--------------------------
39619 begin
39620 if (Self_.ParentForm.fExStyle and WS_EX_DLGMODALFRAME) <> 0 then
39621 if Msg.wParam = 27 then Self_.ParentForm.Perform(WM_CLOSE, 0, 0);
39622 result:=false;
39623 end;
39624 //---------------------------------Babenko Alexey--------------------------
39625 {$ENDIF ESC_CLOSE_DIALOGS}
39626 end;
39627 {$ENDIF}
39628 else Result := False;
39629 end;
39630 end;
39631 {$ENDIF ASM_VERSION}
39632 //[END WndProcCtrl]
39634 //[FUNCTION WndProcPaint]
39635 {$IFDEF ASM_noVERSION}
39636 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39637 const szPaintStruct = sizeof(TPaintStruct);
39638 asm //cmd //opd
39639 CMP word ptr [EDX].TMsg.message, WM_PRINT
39640 JE @@print
39641 CMP word ptr [EDX].TMsg.message, WM_PAINT
39642 JNE @@ret_false
39643 @@print:
39644 //CMP word ptr [EAX].TControl.fPaintProc.TMethod.Code+2, 0
39645 //JNZ @@dopaint
39646 CMP word ptr [EAX].TControl.fOnPaint.TMethod.Code+2, 0
39647 JE @@ret_false
39648 //@@dopaint:
39649 PUSH EBX
39650 PUSH ESI
39652 XCHG EBX, EAX
39653 MOV ESI, EDX
39654 XOR EAX, EAX
39655 PUSH ECX
39656 PUSH EAX
39657 PUSH EAX
39658 PUSH EAX
39659 PUSH EAX
39660 CALL CreateRectRgn
39661 MOV [EBX].TControl.fUpdRgn, EAX
39663 MOVSX EDX, [EBX].TControl.fEraseUpdRgn
39664 PUSH EDX
39665 PUSH EAX
39666 PUSH [EBX].TControl.fHandle
39667 CALL GetUpdateRgn
39669 CMP EAX, 1
39670 JA @@collectUpdRgn
39672 XOR EAX, EAX
39673 XCHG EAX, [EBX].TControl.fUpdRgn
39674 PUSH EAX
39675 CALL DeleteObject
39677 @@collectUpdRgn:
39678 MOV ECX, [EBX].TControl.fCollectUpdRgn
39679 JECXZ @@asg_fPaintDC
39680 XCHG EAX, ECX
39681 MOV ECX, [EBX].TControl.fUpdRgn
39682 JECXZ @@asg_fPaintDC
39684 PUSH RGN_OR
39685 PUSH ECX
39686 PUSH EAX
39687 PUSH EAX
39688 CALL CombineRgn
39690 DEC EAX
39691 JNZ @@invalidateRgn
39693 ADD ESP, -16
39694 PUSH ESP
39695 PUSH [EBX].TControl.fHandle
39696 CALL Windows.GetClientRect
39698 PUSH [EBX].TControl.fCollectUpdRgn
39699 CALL DeleteObject
39700 CALL CreateRectRgn
39701 MOV [EBX].TControl.fCollectUpdRgn, EAX
39703 @@invalidateRgn:
39704 MOVSX EDX, [EBX].TControl.fEraseUpdRgn
39705 PUSH EDX
39706 PUSH [EBX].TControl.fCollectUpdRgn
39707 PUSH [EBX].TControl.fHandle
39708 CALL InvalidateRgn
39711 @@asg_fPaintDC:
39712 MOV ECX, [ESI].TMsg.wParam
39713 INC ECX
39714 LOOP @@storePaintDC
39716 ADD ESP, -szPaintStruct
39717 PUSH ESP
39718 PUSH [EBX].TControl.fHandle
39719 CALL BeginPaint
39720 XCHG ECX, EAX
39721 @@storePaintDC:
39722 MOV [EBX].TControl.fPaintDC, ECX
39723 XCHG EAX, ECX
39725 MOV ECX, [EBX].TControl.fCollectUpdRgn
39726 JECXZ @@doOnPaint
39728 PUSH ECX
39729 PUSH EAX
39730 CALL SelectClipRgn
39732 @@doOnPaint:
39733 MOV ECX, [EBX].TControl.fPaintDC
39734 MOV EDX, EBX
39735 //CMP [EBX].TControl.fPaintProc.TMethod.Code, 0
39736 //JZ @@callOnPaint
39737 //MOV EAX, [EBX].TControl.fPaintProc.TMethod.Data
39738 //CALL dword ptr [EBX].TControl.fPaintProc.TMethod.Code
39739 //JMP @@calledPaintProc
39741 //@@callOnPaint:
39742 MOV EAX, [EBX].TControl.fOnPaint.TMethod.Data
39743 CALL dword ptr [EBX].TControl.fOnPaint.TMethod.Code
39744 //@@calledPaintProc:
39746 MOV ECX, [EBX].TControl.fCanvas
39747 JECXZ @@e_paint
39749 XCHG EAX, ECX
39750 XOR EDX, EDX
39751 CALL TCanvas.SetHandle
39753 @@e_paint:
39754 MOV ECX, [ESI].TMsg.wParam
39755 INC ECX
39756 LOOP @@zero_fPaintDC
39758 PUSH ESP
39759 PUSH [EBX].TControl.fHandle
39760 CALL EndPaint
39761 ADD ESP, szPaintStruct
39763 @@zero_fPaintDC:
39764 XOR ECX, ECX
39765 MOV [EBX].TControl.fPaintDC, ECX
39767 POP EAX
39768 MOV [EAX], ECX
39770 XCHG ECX, [EBX].TControl.fUpdRgn
39771 JECXZ @@exit_True
39773 PUSH ECX
39774 CALL DeleteObject
39776 @@exit_True:
39777 POP ESI
39778 POP EBX
39779 MOV AL, 1
39782 @@ret_false:
39783 XOR EAX, EAX
39784 end;
39785 {$ELSE ASM_VERSION} //Pascal
39786 function WndProcPaint( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39787 var PaintStruct: TPaintStruct;
39788 CR: TRect;
39789 Cplxity: Integer;
39790 OldPaintDC: HDC;
39791 begin
39792 with Self_{-}^{+} do
39793 case Msg.message of
39794 WM_PRINT,
39795 WM_PAINT: if assigned( fOnPaint ) {or Assigned( fPaintProc )} then
39796 begin
39797 fUpdRgn := CreateRectRgn( 0, 0, 0, 0 );
39798 Cplxity := Integer( GetUpdateRgn( fHandle, fUpdRgn, fEraseUpdRgn ) );
39799 if (Cplxity = NULLREGION) or (Cplxity = ERROR) then
39800 begin
39801 DeleteObject( fUpdRgn );
39802 fUpdRgn := 0;
39803 end;
39805 if (fCollectUpdRgn <> 0) and (fUpdRgn <> 0) then
39806 begin
39807 if CombineRgn( fCollectUpdRgn, fCollectUpdRgn, fUpdRgn, RGN_OR )
39808 = COMPLEXREGION then
39809 begin
39810 windows.GetClientRect( Self_.fHandle, CR );
39811 DeleteObject( fCollectUpdRgn );
39812 fCollectUpdRgn := CreateRectRgnIndirect( CR );
39813 end;
39814 InvalidateRgn( fHandle, fCollectUpdRgn, fEraseUpdRgn );
39815 end;
39817 OldPaintDC := fPaintDC;
39818 fPaintDC := Msg.wParam;
39819 if fPaintDC = 0 then
39820 fPaintDC := BeginPaint( fHandle, PaintStruct );
39822 if fCollectUpdRgn <> 0 then
39823 SelectClipRgn( fPaintDC, fCollectUpdRgn );
39825 {if Assigned( fPaintProc ) then
39826 fPaintProc( fPaintDC )
39827 else}
39828 fOnPaint( Self_, fPaintDC );
39830 if assigned( Self_.fCanvas ) then
39831 Self_.fCanvas.SetHandle( 0 );
39833 if Msg.wParam = 0 then
39834 EndPaint( fHandle, PaintStruct );
39835 fPaintDC := OldPaintDC;
39837 Rslt := 0;
39839 Result := True;
39840 if fUpdRgn <> 0 then
39841 DeleteObject( fUpdRgn );
39842 fUpdRgn := 0;
39843 Exit;
39844 end;
39845 end;
39846 Result := FALSE;
39847 end;
39848 {$ENDIF ASM_VERSION}
39849 //[END WndProcPaint]
39851 //[procedure TControl.SetOnPaint]
39852 procedure TControl.SetOnPaint( const Value: TOnPaint );
39853 begin
39854 fOnPaint := Value;
39855 AttachProc( WndProcPaint );
39856 end;
39859 //[function WndProcEraseBkgnd]
39860 function WndProcEraseBkgnd( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39861 var PaintStruct: TPaintStruct;
39862 OldPaintDC: HDC;
39863 begin
39864 Result := FALSE;
39865 if Msg.message = WM_ERASEBKGND then
39866 begin
39867 if Assigned( Sender.OnEraseBkgnd ) then
39868 begin
39869 OldPaintDC := Sender.fPaintDC;
39870 Sender.fPaintDC := Msg.wParam;
39871 if Sender.fPaintDC = 0 then
39872 Sender.fPaintDC := BeginPaint( Sender.fHandle, PaintStruct );
39873 Sender.OnEraseBkgnd( Sender, Msg.wParam );
39874 if Msg.wParam = 0 then
39875 EndPaint( Sender.fHandle, PaintStruct );
39876 if Assigned( Sender.fCanvas ) then
39877 Sender.fCanvas.SetHandle( 0 );
39878 Sender.fPaintDC := OldPaintDC;
39879 Rslt := 0;
39880 Result := TRUE;
39882 else
39883 Rslt := 0;
39884 end;
39885 end;
39887 //[procedure TControl.SetOnEraseBkgnd]
39888 procedure TControl.SetOnEraseBkgnd(const Value: TOnPaint);
39889 begin
39890 fOnEraseBkgnd := Value;
39891 AttachProc( WndProcEraseBkgnd );
39892 end;
39894 //[FUNCTION WndProcGradient]
39895 {$IFDEF ASM_noVERSION}
39896 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
39897 const szPaintStruct = sizeof( TPaintStruct );
39898 asm //cmd //opd
39899 CMP word ptr [EDX].TMsg.message, WM_PRINTCLIENT
39900 JE @@print
39901 CMP word ptr [EDX].TMsg.message, WM_PAINT
39902 JNE @@ret_false
39903 @@print:
39904 PUSHAD
39905 XCHG EDI, EAX
39906 MOV ESI, EDX
39907 XOR EAX, EAX
39908 MOV [ECX], EAX
39909 OR EAX, [ESI].TMsg.wParam
39910 JNZ @@1
39911 ADD ESP, -szPaintStruct
39912 PUSH ESP
39913 PUSH [EDI].TControl.fHandle
39914 CALL BeginPaint
39915 @@1: MOV [EDI].TControl.fPaintDC, EAX
39916 ADD ESP, -16
39917 MOV EDX, ESP
39918 MOV EAX, EDI
39919 CALL TControl.ClientRect
39920 MOV EAX, [EDI].TControl.fColor1
39921 CALL Color2RGB
39922 XCHG EBX, EAX
39923 MOV EAX, [EDI].TControl.fColor2
39924 CALL Color2RGB
39925 MOV EBP, [ESP].TRect.Bottom
39926 @@loo:
39927 MOV EDX, [ESP].TRect.Top
39928 CMP EBP, EDX
39929 JLE @@e_loo
39930 INC EDX
39931 MOV [ESP].TRect.Bottom, EDX
39933 INC EBP
39934 PUSH EAX
39936 PUSH EAX
39937 {SUB AL, BL
39938 MOV AH, 0
39940 CWDE}
39941 AND EAX, $FF
39942 MOV EDX, EBX
39943 AND EDX, $FF
39944 SUB EAX, EDX
39947 MOV ECX, [ESP+8].TRect.Top
39948 IMUL ECX
39949 IDIV EBP
39950 XOR EDX, EDX
39951 ADD AL, BL
39952 MOV AH, 0
39953 CWDE
39954 XCHG [ESP], EAX
39956 PUSH EAX
39957 {SUB AH, BH
39958 MOV AL, AH
39959 MOV AH, 0
39961 CWDE}
39962 SHR EAX, 8
39963 AND EAX, $FF
39964 MOV EDX, EBX
39965 SHR EDX, 8
39966 AND EDX, $FF
39967 SUB EAX, EDX
39969 IMUL ECX
39970 IDIV EBP
39971 ADD AL, BH
39972 AND EAX, $FF
39973 SHL EAX, 8
39974 XCHG [ESP], EAX
39976 SHR EAX, 16
39977 MOV EDX, EBX
39978 SHR EDX, 16
39979 PUSH EDX
39980 SUB EAX, EDX
39981 IMUL ECX
39982 IDIV EBP
39983 POP EDX
39984 //AND EAX, $FF00
39985 ADD EAX, EDX
39986 SHL EAX, 16
39988 POP EDX
39989 MOV AH, DH
39990 POP EDX
39991 MOV AL, DL
39993 PUSH EAX
39994 CALL CreateSolidBrush
39996 PUSH EAX
39998 PUSH EAX
39999 LEA EDX, [ESP+12]
40000 PUSH EDX
40001 PUSH [EDI].TControl.fPaintDC
40002 CALL Windows.FillRect
40004 CALL DeleteObject
40006 POP EAX
40007 DEC EBP
40008 INC [ESP].TRect.Top
40009 JMP @@loo
40010 @@e_loo:
40011 ADD ESP, 16
40012 MOV ECX, [ESI].TMsg.wParam
40013 INC ECX
40014 LOOP @@2
40015 PUSH ESP
40016 PUSH [EDI].TControl.fHandle
40017 CALL EndPaint
40018 ADD ESP, szPaintStruct
40019 @@2: XOR EAX, EAX
40020 MOV [EDI].TControl.fPaintDC, EAX
40021 POPAD
40022 MOV Al, 1
40024 @@ret_false:
40025 XOR EAX, EAX
40026 end;
40027 {$ELSE ASM_VERSION} //Pascal
40028 function WndProcGradient( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40029 var PaintStruct: TPaintStruct;
40030 Bmp: PBitmap;
40031 CR: TRect;
40032 I: Integer;
40033 R, G, B: Integer;
40034 R1, G1, B1: Integer;
40035 C: TColor;
40036 W, H, WH: Integer;
40037 W9x: Boolean;
40038 Br: HBrush;
40039 //Save: Integer;
40040 OldPaintDC: HDC;
40041 begin
40042 case Msg.message of
40043 WM_PAINT, WM_PRINTCLIENT:
40044 begin
40045 OldPaintDC := Self_.fPaintDC;
40046 Self_.fPaintDC := Msg.wParam;
40047 if Self_.fPaintDC = 0 then
40048 Self_.fPaintDC := BeginPaint( Self_.fHandle, PaintStruct );
40049 CR := Self_.ClientRect;
40050 W9x := WinVer < wvNT;
40051 W := 1;
40052 H := CR.Bottom;
40053 WH := H;
40054 Bmp := nil;
40055 if Self_.fGradientStyle = gsHorizontal then
40056 begin
40057 W := CR.Right;
40058 H := 1;
40059 WH := W;
40060 end;
40061 if not W9x then
40062 Bmp := NewDIBBitmap( W, H, pf32bit );
40063 C := Color2RGB( Self_.fColor1 );
40064 R := C shr 16;
40065 G := (C shr 8) and $FF;
40066 B := C and $FF;
40067 C := Color2RGB( Self_.fColor2 );
40068 R1 := C shr 16;
40069 G1 := (C shr 8) and $FF;
40070 B1 := C and $FF;
40071 for I := 0 to WH-1 do
40072 begin
40073 C := ((( R + (R1 - R) * I div WH ) and $FF) shl 16) or
40074 ((( G + (G1 - G) * I div WH ) and $FF) shl 8) or
40075 ( B + (B1 - B) * I div WH ) and $FF;
40076 if W9x then
40077 begin
40078 if Self_.fGradientStyle = gsVertical then
40079 CR.Bottom := CR.Top + 1
40080 else
40081 CR.Right := CR.Left + 1;
40082 Br := CreateSolidBrush( C );
40083 Windows.FillRect( Self_.fPaintDC, CR, Br );
40084 DeleteObject( Br );
40085 if Self_.fGradientStyle = gsVertical then
40086 Inc( CR.Top )
40087 else
40088 Inc( CR.Left );
40090 else
40091 begin
40092 if Self_.fGradientStyle = gsVertical then
40093 Bmp.DIBPixels[ 0, I ] := C
40094 else
40095 Bmp.DIBPixels[ I, 0 ] := C;
40096 end;
40097 end;
40098 if not W9x then
40099 begin
40100 SetStretchBltMode( Self_.fPaintDC, HALFTONE );
40101 SetBrushOrgEx( Self_.fPaintDC, 0, 0, nil );
40102 StretchBlt( Self_.fPaintDC, 0, 0, CR.Right, CR.Bottom, Bmp.Canvas.Handle,
40103 0, 0, W, H, SRCCOPY );
40104 Bmp.Free;
40105 end;
40106 if Msg.wParam = 0 then
40107 EndPaint( Self_.fHandle, PaintStruct );
40108 Self_.fPaintDC := OldPaintDC;
40109 Rslt := 0;
40110 Result := True;
40111 Exit;
40112 end;
40113 end;
40114 Result := False;
40115 end;
40116 {$ENDIF ASM_VERSION}
40117 //[END WndProcGradient]
40119 //[function WndProcGradientEx]
40120 function WndProcGradientEx( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40121 function Ceil( X: Double ): Integer;
40122 begin
40123 Result := Round( X ) + 1;
40124 end;
40125 const
40126 SQRT2 = 1.4142135623730950488016887242097;
40128 RC, R0: TRect;
40129 C, C2: TColor;
40130 R1, G1, B1: Integer;
40131 R2, G2, B2: Integer;
40132 DX1, DX2, DY1, DY2, DR, DG, DB, K: Double;
40133 PaintStruct: TPaintStruct;
40134 I: Integer;
40135 Br: HBrush;
40136 Rgn: HRgn;
40137 Poly: array[ 0..3 ] of TPoint;
40138 OldPaintDC: HDC;
40139 fX1, fX2, fY1, fY2: Double;
40141 procedure OffsetF( DX, DY: Double );
40142 begin
40143 fX1 := fX1 + DX;
40144 fX2 := fX2 + DX;
40145 fY1 := fY1 + DY;
40146 fY2 := fY2 + DY;
40147 end;
40148 begin
40149 Result := FALSE;
40150 if (Msg.message <> WM_PAINT) and (Msg.message <> WM_PRINTCLIENT) then Exit;
40151 if Self_.fGradientStyle in [ gsHorizontal, gsVertical ] then
40152 begin
40153 Result := WndProcGradient( Self_, Msg, Rslt );
40154 Exit;
40155 end;
40156 C := Color2RGB( Self_.fColor2 );
40157 R2 := C and $FF;
40158 G2 := (C shr 8) and $FF;
40159 B2 := (C shr 16) and $FF;
40160 C := Color2RGB( Self_.fColor1 );
40161 R1 := C and $FF;
40162 G1 := (C shr 8) and $FF;
40163 B1 := (C shr 16) and $FF;
40164 DR := (R2 - R1) / 256;
40165 DG := (G2 - G1) / 256;
40166 DB := (B2 - B1) / 256;
40167 OldPaintDC := Self_.fPaintDC;
40168 Self_.fPaintDC := Msg.wParam;
40169 if Self_.fPaintDC = 0 then
40170 Self_.fPaintDC := BeginPaint( Self_.fHandle, PaintStruct );
40171 RC := Self_.ClientRect;
40172 fX1 := 0;
40173 fY1 := 0;
40174 case Self_.fGradientStyle of
40175 gsRombic:
40176 //RF := MakeRect( 0, 0, RC.Right div 128, RC.Bottom div 128 );
40177 begin
40178 fX2 := RC.Right / 128;
40179 fY2 := RC.Bottom / 128;
40180 end;
40181 gsElliptic:
40182 //RF := MakeRect( 0, 0, Ceil( RC.Right / 256 * SQRT2 ), Ceil( RC.Bottom / 256 * SQRT2 ) );
40183 begin
40184 fX2 := RC.Right / 256 * SQRT2;
40185 fY2 := RC.Bottom / 256 * SQRT2;
40186 end;
40187 else
40188 //RF := MakeRect( 0, 0, RC.Right div 256, RC.Bottom div 256 );
40189 begin
40190 fX2 := RC.Right / 256;
40191 fY2 := RC.Bottom / 256;
40192 end;
40193 end;
40194 case Self_.fGradientStyle of
40195 gsRectangle, gsRombic, gsElliptic:
40196 begin
40197 case Self_.FGradientLayout of
40198 glCenter, glTop, glBottom:
40199 //OffsetRect( RF, (RC.Right - RF.Right) div 2, 0 );
40200 OffsetF( (RC.Right - fX2) / 2, 0 );
40201 glTopRight, glBottomRight, glRight:
40202 //OffsetRect( RF, RC.Right - RF.Right div 2, 0 );
40203 OffsetF( RC.Right - fX2 / 2, 0 );
40204 glTopLeft, glBottomLeft, glLeft:
40205 //OffsetRect( RF, -RF.Right div 2, 0 );
40206 OffsetF( -fX2 / 2, 0 );
40207 end;
40208 case Self_.FGradientLayout of
40209 glCenter, glLeft, glRight:
40210 //OffsetRect( RF, 0, (RC.Bottom - RF.Bottom) div 2 );
40211 OffsetF( 0, (RC.Bottom - fY2) / 2 );
40212 glBottom, glBottomLeft, glBottomRight:
40213 //OffsetRect( RF, 0, RC.Bottom - RF.Bottom div 2 );
40214 OffsetF( 0, RC.Bottom - fY2 / 2 );
40215 glTop, glTopLeft, glTopRight:
40216 //OffsetRect( RF, 0, -RF.Bottom div 2 );
40217 OffsetF( 0, -fY2 / 2 )
40218 end;
40219 end;
40220 end;
40221 DX1 := -fX1 / 255; //(-RF.Left) / 255;
40222 DY1 := -fY1 / 255; // (-RF.Top) / 255;
40223 DX2 := (RC.Right - fX2) / 255; //(RC.Right - RF.Right) / 255;
40224 DY2 := (RC.Bottom - fY2) / 255;
40225 case Self_.fGradientStyle of
40226 gsRombic, gsElliptic:
40227 begin
40228 if DX2 < -DX1 then DX2 := -DX1;
40229 if DY2 < -DY1 then DY2 := -DY1;
40230 K := 2;
40231 if Self_.fGradientStyle = gsElliptic then K := SQRT2;
40232 DX2 := DX2 * K;
40233 DY2 := DY2 * K;
40234 DX1 := -DX2;
40235 DY1 := -DY2;
40236 end;
40237 end;
40238 C2 := C;
40239 for I := 0 to 255 do
40240 begin
40241 if (I < 255) then
40242 begin
40243 C2 := TColor( (( Ceil( B1 + DB * (I+1) ) and $FF) shl 16) or
40244 (( Ceil( G1 + DG * (I+1) ) and $FF) shl 8) or
40245 Ceil( R1 + DR * (I+1) ) and $FF );
40246 if (Self_.fGradientStyle in [gsRombic,gsElliptic,gsRectangle]) and
40247 (C2 = C) then continue;
40248 end;
40249 Br := CreateSolidBrush( C );
40250 R0 := MakeRect( Ceil( fX1 + DX1 * I ),
40251 Ceil( fY1 + DY1 * I ),
40252 Ceil( fX2 + DX2 * I ) + 1,
40253 Ceil( fY2 + DY2 * I ) + 1 );
40254 Rgn := 0;
40255 case Self_.fGradientStyle of
40256 gsRectangle:
40257 Rgn := CreateRectRgnIndirect( R0 );
40258 gsRombic:
40259 begin
40260 Poly[ 0 ].x := R0.Left;
40261 Poly[ 0 ].y := R0.Top + (R0.Bottom - R0.Top) div 2;
40262 Poly[ 1 ].x := R0.Left + (R0.Right - R0.Left) div 2;
40263 Poly[ 1 ].y := R0.Top;
40264 Poly[ 2 ].x := R0.Right;
40265 Poly[ 2 ].y := Poly[ 0 ].y;
40266 Poly[ 3 ].x := Poly[ 1 ].x;
40267 Poly[ 3 ].y := R0.Bottom;
40268 Rgn := CreatePolygonRgn( Poly[ 0 ].x, 4, ALTERNATE );
40269 end;
40270 gsElliptic:
40271 Rgn := CreateEllipticRgnIndirect( R0 );
40272 end;
40273 if Rgn <> 0 then
40274 begin
40275 if Rgn <> NULLREGION then
40276 begin
40277 Windows.FillRgn( Self_.fPaintDC, Rgn, Br );
40278 ExtSelectClipRgn( Self_.fPaintDC, Rgn, RGN_DIFF );
40279 end;
40280 DeleteObject( Rgn );
40281 end;
40282 DeleteObject( Br );
40283 C := C2;
40284 end;
40285 if Self_.fPaintDC <> HDC( Msg.wParam ) then
40286 EndPaint( Self_.fHandle, PaintStruct );
40287 Self_.fPaintDC := OldPaintDC;
40288 Rslt := 0;
40289 Result := True;
40290 end;
40293 //[function WndProcLabelEffect]
40294 function WndProcLabelEffect( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
40296 Sz: TSize;
40297 P0: TPoint;
40298 CR: TRect;
40299 B : Boolean;
40300 CShadow: TColor;
40301 Target: PCanvas;
40302 Txt: String;
40303 LCaption: PChar;
40304 OldPaintDC: HDC;
40306 procedure doTextOut( shfx, shfy: Integer; col: TColor );
40307 begin
40308 SetTextColor( Target.fHandle, col );
40309 Windows.ExtTextOut( Target.fHandle, P0.x + shfx, P0.y + shfy,
40310 ETO_CLIPPED, @CR,
40311 PChar(Txt), Length(Txt), nil );
40312 //GDIFlush; // for test only
40313 end;
40315 var I, J, Istp : Integer;
40316 PS: TPaintStruct;
40317 //DoEndPaint: Boolean;
40318 begin
40319 Result := False;
40321 case Msg.message of
40323 WM_SETTEXT:
40324 begin
40325 LCaption := PChar( Msg.lParam );
40326 if LCaption <> Self_.fCaption then
40327 begin
40328 if Self_.fCaption <> nil then
40329 FreeMem( Self_.fCaption );
40330 GetMem( Self_.fCaption, StrLen( LCaption ) + 1 );
40331 StrCopy( Self_.fCaption, LCaption );
40332 end;
40333 Result := True;
40334 Rslt := 1;
40335 Exit;
40336 end;
40338 WM_PRINTCLIENT, WM_PAINT:
40339 begin
40340 OldPaintDC := Self_.fPaintDC;
40341 Self_.fPaintDC := Msg.wParam;
40342 if Self_.fPaintDC = 0 then
40343 Self_.fPaintDC := BeginPaint( Self_.fHandle, PS );
40344 begin
40345 Target := Self_.Canvas;
40346 Txt := Self_.fCaption;
40347 Target.TextArea( Txt, Sz, P0 );
40348 if Self_.fShadowDeep <> 0 then
40349 begin
40350 for B := False to Self_.fCtl3D do
40351 begin
40352 Inc( Sz.cx, Abs( Self_.fShadowDeep ) );
40353 Inc( Sz.cy, Abs( Self_.fShadowDeep ) );
40354 end;
40355 end;
40356 CR := Self_.ClientRect;
40357 case Self_.fTextAlign of
40358 taCenter: P0.x := P0.x + (CR.Right - Sz.cx) div 2;
40359 taRight: P0.x := P0.x + (CR.Right - Sz.cx);
40360 end;
40361 case Self_.fVerticalAlign of
40362 vaCenter: P0.y := P0.y + (CR.Bottom - Sz.cy) div 2;
40363 vaBottom: P0.y := P0.y + (CR.Bottom - Sz.cy);
40364 end;
40365 if Self_.fShadowDeep <> 0 then
40366 begin
40367 if Self_.fColor2 = clNone then
40368 CShadow := ColorsMix(Color2RGB(Self_.fTextColor),Color2RGB(Self_.fColor2))
40369 else
40370 CShadow := Color2RGB( Self_.fColor2 );
40371 if not Self_.fTransparent then
40372 Target.FillRect( CR ); // GDIFlush; for test only
40373 //Target.DeselectHandles;
40374 Target.RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
40375 SetBkMode( Target.fHandle, Windows.TRANSPARENT );
40376 if Self_.fCtl3D then
40377 begin
40378 I := - Self_.fShadowDeep;
40379 Istp := 1;
40380 if Self_.ShadowDeep > 0 then Istp := -1;
40381 repeat
40382 J := - Self_.fShadowDeep;
40383 repeat
40384 if not ( (I=0) and (J=0) ) then
40385 begin
40386 if (I * Istp < 0) and (J * Istp < 0) then
40387 begin
40388 doTextOut( I, J, CShadow );
40389 end;
40390 end;
40391 J := J - Istp;
40392 until J = Self_.fShadowDeep - IStp;
40393 I := I - Istp;
40394 until I = Self_.fShadowDeep - IStp;
40396 else
40397 doTextout( Self_.fShadowDeep, Self_.fShadowdeep, CShadow );
40398 doTextout( 0, 0, Color2RGB(Self_.fTextColor) );
40400 else
40401 begin
40402 //Target.DeselectHandles;
40403 Target.RequiredState( HandleValid or FontValid or BrushValid or ChangingCanvas );
40404 SetBkMode( Target.fHandle, Windows.TRANSPARENT );
40405 //Target.TextRect( CR, P0.x, P0.y, Txt );
40406 doTextout( 0, 0, Color2RGB(Self_.fTextColor) );
40407 end;
40408 end;
40409 if assigned( Self_.fCanvas ) then
40410 Self_.fCanvas.SetHandle( 0 );
40411 if MSg.wParam = 0 then
40412 EndPaint( Self_.fHandle, PS );
40413 Self_.fPaintDC := OldPaintDC;
40414 Rslt := 0;
40415 Result := True;
40416 Exit;
40417 end;
40418 end;
40419 end;
40421 {$IFDEF ASM_VERSION}
40422 //[procedure TControl.DoClick]
40423 procedure TControl.DoClick;
40425 PUSH EAX
40426 CALL [EAX].fControlClick
40427 POP EDX
40429 MOV ECX, [EDX].fOnClick.TMethod.Code
40430 JECXZ @@exit
40431 MOV EAX, [EDX].fOnClick.TMethod.Data
40432 CALL ECX
40433 @@exit:
40434 end;
40435 {$ELSE ASM_VERSION} //Pascal
40436 procedure TControl.DoClick;
40437 begin
40438 fControlClick( @Self );
40439 if Assigned( fOnClick ) then
40440 fOnClick( @Self );
40441 end;
40442 {$ENDIF ASM_VERSION}
40444 {$IFDEF ASM_VERSION}
40445 //[function TControl.ParentForm]
40446 function TControl.ParentForm: PControl;
40448 @@1: CMP [EAX].fIsControl, 0
40449 JZ @@exit
40450 MOV EAX, [EAX].fParent
40451 TEST EAX, EAX
40452 JNZ @@1
40453 @@exit:
40454 end;
40455 {$ELSE ASM_VERSION} //Pascal
40456 function TControl.ParentForm: PControl;
40457 begin
40458 Result := @Self;
40459 if Result.fIsControl then
40460 repeat
40461 Result := Result.fParent;
40462 until (Result = nil) or not Result.fIsControl;
40463 end;
40464 {$ENDIF ASM_VERSION}
40466 {$IFDEF ASM_VERSION}
40467 //[procedure TControl.SetProgressColor]
40468 procedure TControl.SetProgressColor(const Value: TColor);
40470 PUSH EDX
40471 PUSH EAX
40472 MOV EAX, EDX
40473 CALL Color2RGB
40474 POP EDX
40475 PUSH EDX
40476 PUSH EAX
40477 PUSH 0
40478 PUSH PBM_SETBARCOLOR
40479 PUSH EDX
40480 CALL Perform
40481 TEST EAX, EAX
40482 POP EAX
40483 POP EDX
40484 JZ @@exit
40485 MOV [EAX].fTextColor, EDX
40486 @@exit:
40487 end;
40488 {$ELSE ASM_VERSION} //Pascal
40489 procedure TControl.SetProgressColor(const Value: TColor);
40490 begin
40491 if Perform( PBM_SETBARCOLOR, 0, Color2RGB(Value) ) <> 0 then
40492 fTextColor := Value;
40493 end;
40494 {$ENDIF ASM_VERSION}
40496 //[procedure TControl.SetShadowDeep]
40497 procedure TControl.SetShadowDeep(const Value: Integer);
40498 begin
40499 fShadowDeep := Value;
40500 Invalidate;
40501 end;
40503 {$IFDEF ASM_VERSION}
40504 //[function TControl.GetFont]
40505 function TControl.GetFont: PGraphicTool;
40507 MOV ECX, [EAX].FFont
40508 INC ECX
40509 LOOP @@exit
40510 PUSH EAX
40511 CALL NewFont
40512 POP EDX
40513 MOV [EDX].FFont, EAX
40514 MOV ECX, [EDX].fTextColor
40515 MOV [EAX].TGraphicTool.fData.Color, ECX
40516 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[FontChanged]
40517 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
40519 @@exit: XCHG EAX, ECX
40520 end;
40521 {$ELSE ASM_VERSION} //Pascal
40522 function TControl.GetFont: PGraphicTool;
40523 begin
40524 if FFont = nil then
40525 begin
40526 FFont := NewFont;
40527 FFont.fData.Color := fTextColor;
40528 FFont.OnChange := FontChanged;
40529 end;
40530 Result := FFont;
40531 end;
40532 {$ENDIF ASM_VERSION}
40534 {$IFDEF ASM_VERSION}
40535 //[function TControl.GetBrush]
40536 function TControl.GetBrush: PGraphicTool;
40538 MOV ECX, [EAX].FBrush
40539 INC ECX
40540 LOOP @@exit
40541 PUSH EAX
40542 CALL NewBrush
40543 POP EDX
40544 MOV [EDX].FBrush, EAX
40545 MOV ECX, [EDX].fColor
40546 MOV [EAX].TGraphicTool.fData.Color, ECX
40547 MOV [EAX].TGraphicTool.fOnChange.TMethod.Code, offset[BrushChanged]
40548 MOV [EAX].TGraphicTool.fOnChange.TMethod.Data, EDX
40550 @@exit: XCHG EAX, ECX
40551 end;
40552 {$ELSE ASM_VERSION} //Pascal
40553 function TControl.GetBrush: PGraphicTool;
40554 begin
40555 if FBrush = nil then
40556 begin
40557 FBrush := NewBrush;
40558 FBrush.fData.Color := fColor;
40559 FBrush.OnChange := BrushChanged;
40560 end;
40561 Result := FBrush;
40562 end;
40563 {$ENDIF ASM_VERSION}
40565 {$IFDEF ASM_VERSION}
40566 //[procedure TControl.FontChanged]
40567 procedure TControl.FontChanged(Sender: PGraphicTool);
40569 MOV ECX, [EDX].TGraphicTool.fData.Color
40570 MOV [EAX].fTextColor, ECX
40571 PUSH EAX
40572 CALL ApplyFont2Wnd
40573 POP EAX
40574 CALL Invalidate
40575 end;
40576 {$ELSE ASM_VERSION} //Pascal
40577 procedure TControl.FontChanged(Sender: PGraphicTool);
40578 begin
40579 fTextColor := Sender.fData.Color;
40580 ApplyFont2Wnd;
40581 Invalidate;
40582 end;
40583 {$ENDIF ASM_VERSION}
40585 {$IFDEF ASM_VERSION}
40586 //[procedure TControl.BrushChanged]
40587 procedure TControl.BrushChanged(Sender: PGraphicTool);
40589 MOV ECX, [EDX].TGraphicTool.fData.Color
40590 MOV [EAX].fColor, ECX
40591 XOR ECX, ECX
40592 XCHG ECX, [EAX].fTmpBrush
40593 JECXZ @@inv
40594 PUSH EAX
40595 PUSH ECX
40596 CALL DeleteObject
40597 POP EAX
40598 @@inv: CALL Invalidate
40599 end;
40600 {$ELSE ASM_VERSION} //Pascal
40601 procedure TControl.BrushChanged(Sender: PGraphicTool);
40602 begin
40603 fColor := Sender.fData.Color;
40604 if fTmpBrush <> 0 then
40605 begin
40606 DeleteObject( fTmpBrush );
40607 fTmpBrush := 0;
40608 end;
40609 if fPaintDC = 0 then
40610 // only if not in painting already :
40611 Invalidate;
40612 end;
40613 {$ENDIF ASM_VERSION}
40615 {$IFDEF ASM_VERSION}
40616 //[procedure TControl.ApplyFont2Wnd]
40617 procedure TControl.ApplyFont2Wnd;
40619 PUSH EBX
40620 XCHG EBX, EAX
40622 MOV ECX, [EBX].fFont
40623 JECXZ @@exit
40624 XCHG EAX, ECX
40626 MOV ECX, [EBX].fHandle
40627 JECXZ @@0
40629 MOV EDX, [EAX].TGraphicTool.fData.Color
40630 MOV [EBX].fTextColor, EDX
40632 PUSH $FFFF
40633 CALL TGraphicTool.GetHandle
40634 PUSH EAX
40635 PUSH WM_SETFONT
40636 PUSH EBX
40637 CALL Perform
40639 @@0:
40640 XOR ECX, ECX
40641 XCHG ECX, [EBX].fCanvas
40642 JECXZ @@1
40644 XCHG EAX, ECX
40645 CALL TObj.Free
40646 @@1:
40647 MOV ECX, [EBX].fAutoSize
40648 JECXZ @@exit
40649 XCHG EAX, EBX
40650 CALL ECX
40651 @@exit:
40652 POP EBX
40653 end;
40654 {$ELSE ASM_VERSION} //Pascal
40655 procedure TControl.ApplyFont2Wnd;
40656 begin
40657 if fFont <> nil then
40658 begin
40659 if fHandle <> 0 then
40660 begin
40661 fTextColor := fFont.fData.Color;
40662 Perform( WM_SETFONT, FFont.Handle, 1 );
40663 end;
40665 if fCanvas <> nil then
40666 begin
40667 fCanvas.Free;
40668 fCanvas := nil;
40669 end;
40671 if Assigned( fAutoSize ) then
40672 fAutoSize( @Self );
40673 //if assigned( fCanvas ) then
40674 // {fCanvas.fFont :=} fCanvas.fFont.Assign( fFont );
40675 end;
40676 end;
40677 {$ENDIF ASM_VERSION}
40679 {$IFDEF ASM_VERSION}
40680 //[function TControl.ResizeParent]
40681 function TControl.ResizeParent: PControl;
40683 LEA EDX, [TControl.ResizeParentRight]
40684 PUSH EDX
40685 CALL EDX
40686 CALL TControl.ResizeParentBottom
40687 end;
40688 {$ELSE ASM_VERSION} //Pascal
40689 function TControl.ResizeParent: PControl;
40690 begin
40691 ResizeParentBottom;
40692 ResizeParentRight;
40693 // Once again, to fix Windows (or my???) bug with
40694 // incorrect calculating of GetClientRect after
40695 // SetWindowLong( GWL_[EX}STYLE,... )
40696 Result := ResizeParentBottom;
40697 end;
40698 {$ENDIF ASM_VERSION}
40700 {$IFDEF ASM_VERSION}
40701 //[function TControl.ResizeParentBottom]
40702 function TControl.ResizeParentBottom: PControl;
40704 PUSH EAX
40705 PUSH EBX
40706 MOV EBX, [EAX].fParent
40707 TEST EBX, EBX
40708 JZ @@exit
40710 MOV EDX, [EAX].fBoundsRect.Bottom
40711 ADD EDX, [EBX].fMargin
40713 TEST [EBX].fChangedPosSz, 20h
40714 JZ @@1
40716 PUSH EDX
40717 MOV EAX, EBX
40718 CALL GetClientHeight
40719 POP EDX
40721 CMP EDX, EAX
40722 JLE @@exit
40723 @@1:
40724 MOV EAX, EBX
40725 CALL TControl.SetClientHeight
40726 OR [EBX].fChangedPosSz, 20h
40727 @@exit:
40728 POP EBX
40729 POP EAX
40730 end;
40731 {$ELSE ASM_VERSION} //Pascal
40732 function TControl.ResizeParentBottom: PControl;
40733 var NewCH: Integer;
40734 begin
40735 Result := @Self;
40736 if fParent <> nil then
40737 begin
40738 NewCH := BoundsRect.Bottom + fParent.fMargin;
40739 if (fParent.fChangedPosSz and $20) <> 0 then
40740 if NewCH < fParent.ClientHeight then Exit;
40741 fParent.ClientHeight := NewCH;
40742 fParent.fChangedPosSz := fParent.fChangedPosSz or $20;
40743 end;
40744 end;
40745 {$ENDIF ASM_VERSION}
40747 {$IFDEF ASM_VERSION}
40748 //[function TControl.ResizeParentRight]
40749 function TControl.ResizeParentRight: PControl;
40751 PUSH EAX
40752 PUSH EBX
40753 MOV EBX, [EAX].fParent
40754 TEST EBX, EBX
40755 JZ @@exit
40757 MOV EDX, [EAX].fBoundsRect.Right
40758 ADD EDX, [EBX].fMargin
40760 TEST [EBX].fChangedPosSz, 10h
40761 JZ @@1
40763 PUSH EDX
40764 MOV EAX, EBX
40765 CALL GetClientWidth
40766 POP EDX
40768 CMP EDX, EAX
40769 JLE @@exit
40770 @@1:
40771 MOV EAX, EBX
40772 CALL TControl.SetClientWidth
40773 OR [EBX].fChangedPosSz, 10h
40774 @@exit:
40775 POP EBX
40776 POP EAX
40777 end;
40778 {$ELSE ASM_VERSION} //Pascal
40779 function TControl.ResizeParentRight: PControl;
40780 var NewCW: Integer;
40781 begin
40782 Result := @Self;
40783 if fParent <> nil then
40784 begin
40785 NewCW := fBoundsRect.Right + fParent.fMargin;
40786 if (fParent.fChangedPosSz and $10) <> 0 then
40787 if NewCW < fParent.ClientWidth then Exit;
40788 fParent.ClientWidth := NewCW;
40789 fParent.fChangedPosSz := fParent.fChangedPosSz or $10;
40790 end;
40791 end;
40792 {$ENDIF ASM_VERSION}
40794 {$IFDEF ASM_VERSION}
40795 //[function TControl.GetClientHeight]
40796 function TControl.GetClientHeight: Integer;
40798 ADD ESP, -size_TRect
40799 MOV EDX, ESP
40800 CALL TControl.ClientRect
40801 POP EDX
40802 POP ECX // Top
40803 POP EDX
40804 POP EAX // Bottom
40805 SUB EAX, ECX // Result = Bottom - Top
40806 end;
40807 {$ELSE ASM_VERSION} //Pascal
40808 function TControl.GetClientHeight: Integer;
40809 begin
40810 with ClientRect do
40811 Result := Bottom - Top;
40812 end;
40813 {$ENDIF ASM_VERSION}
40815 {$IFDEF ASM_VERSION}
40816 //[function TControl.GetClientWidth]
40817 function TControl.GetClientWidth: Integer;
40819 ADD ESP, -size_TRect
40820 MOV EDX, ESP
40821 CALL TControl.ClientRect
40822 POP ECX // Left
40823 POP EDX
40824 POP EAX // Right
40825 SUB EAX, ECX // Result = Right - Left
40826 POP EDX
40827 end;
40828 {$ELSE ASM_VERSION} //Pascal
40829 function TControl.GetClientWidth: Integer;
40830 begin
40831 with ClientRect do
40832 Result := Right - Left;
40833 end;
40834 {$ENDIF ASM_VERSION}
40836 {$IFDEF ASM_VERSION}
40837 //[procedure TControl.SetClientHeight]
40838 procedure TControl.SetClientHeight(const Value: Integer);
40840 PUSH EBX
40841 PUSH EDX
40843 MOV EBX, EAX
40844 CALL TControl.GetClientHeight
40845 PUSH EAX
40846 MOV EAX, EBX
40847 CALL TControl.GetHeight // EAX = Height
40849 POP EDX // EDX = ClientHeight
40850 SUB EAX, EDX // EAX = Delta
40851 POP EDX // EDX = Value
40852 ADD EDX, EAX // EDX = Value + Delta
40853 XCHG EAX, EBX // EAX = @Self
40854 CALL TControl.SetHeight
40855 POP EBX
40856 end;
40857 {$ELSE ASM_VERSION} //Pascal
40858 procedure TControl.SetClientHeight(const Value: Integer);
40859 var Delta: Integer;
40860 begin
40861 Delta := ClientHeight;
40862 Delta := Height - Delta;
40863 Height := Value + Delta;
40864 end;
40865 {$ENDIF ASM_VERSION}
40867 {$IFDEF ASM_VERSION}
40868 //[procedure TControl.SetClientWidth]
40869 procedure TControl.SetClientWidth(const Value: Integer);
40871 PUSH EBX
40872 PUSH EDX
40874 MOV EBX, EAX
40875 CALL TControl.GetClientWidth
40876 PUSH EAX
40877 MOV EAX, EBX
40878 CALL TControl.GetWidth // EAX = Width
40880 POP EDX // EDX = ClientWidth
40881 SUB EAX, EDX // EAX = Width - ClientWidth
40882 POP EDX // EDX = Value
40883 ADD EDX, EAX // EDX = Value + Delta
40884 XCHG EAX, EBX // EAX = @Self
40885 CALL TControl.SetWidth
40886 POP EBX
40887 end;
40888 {$ELSE ASM_VERSION} //Pascal
40889 procedure TControl.SetClientWidth(const Value: Integer);
40890 var Delta: Integer;
40891 begin
40892 Delta := ClientWidth;
40893 Delta := Width - Delta;
40894 Width := Value + Delta;
40895 end;
40896 {$ENDIF ASM_VERSION}
40898 {$IFDEF ASM_VERSION}
40899 //[function TControl.CenterOnParent]
40900 function TControl.CenterOnParent: PControl;
40902 PUSHAD
40904 XCHG ESI, EAX
40905 MOV ECX, [ESI].fParent
40906 JECXZ @@1
40907 CMP [ESI].fIsControl, 0
40908 JNZ @@2
40910 @@1:
40911 PUSH SM_CYSCREEN
40912 CALL GetSystemMetrics
40913 PUSH EAX
40915 PUSH SM_CXSCREEN
40916 CALL GetSystemMetrics
40917 PUSH EAX
40919 PUSH 0
40920 PUSH 0 // ESP -> Rect( 0, 0, CX, CY )
40922 JMP @@3
40924 @@2: ADD ESP, -size_TRect
40925 MOV EDX, ESP
40926 XCHG EAX, ECX
40927 CALL TControl.ClientRect
40928 // ESP -> ClientRect
40929 @@3: MOV EAX, ESI
40930 CALL GetWindowHandle
40932 MOV EAX, ESI
40933 CALL GetWidth
40935 POP EDX // left
40936 ADD EAX, EDX // + width
40938 POP EDI // top
40939 POP EDX // right
40941 SUB EDX, EAX
40942 SAR EDX, 1
40944 MOV EAX, ESI
40945 CALL SetLeft
40947 MOV EAX, ESI
40948 CALL GetHeight
40950 ADD EAX, EDI // height + top
40952 POP EDX // bottom
40953 SUB EDX, EAX
40954 SAR EDX, 1
40956 XCHG EAX, ESI
40957 CALL SetTop
40959 POPAD
40960 end;
40961 {$ELSE ASM_VERSION} //Pascal
40962 function TControl.CenterOnParent: PControl;
40963 var PCR: TRect;
40964 begin
40965 Result := @Self;
40966 if (fParent = nil) or not fIsControl then
40967 PCR := MakeRect( 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) )
40968 else
40969 PCR := fParent.ClientRect;
40970 GetWindowHandle;
40971 Left := (PCR.Right - PCR.Left - Width) div 2;
40972 Top := (PCR.Bottom - PCR.Top - Height) div 2;
40973 end;
40974 {$ENDIF ASM_VERSION}
40976 {$IFDEF ASM_noVERSION}
40977 //[function TControl.GetHasBorder]
40978 function TControl.GetHasBorder: Boolean;
40979 const style_mask = WS_BORDER or WS_THICKFRAME or WS_DLGFRAME;
40981 CALL UpdateWndStyles
40982 MOV EAX, [EAX].fStyle
40983 AND EAX, style_mask
40984 SETNZ AL
40985 end;
40986 {$ELSE ASM_VERSION} //Pascal
40987 function TControl.GetHasBorder: Boolean;
40988 begin
40989 UpdateWndStyles;
40990 Result := LongBool( fStyle and (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME))
40991 or LongBool( fExStyle and WS_EX_CLIENTEDGE );
40992 end;
40993 {$ENDIF ASM_VERSION}
40995 {$IFDEF ASM_noVERSION} // YS
40996 //[procedure TControl.SetHasBorder]
40997 procedure TControl.SetHasBorder(const Value: Boolean);
40998 const style_mask = WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION
40999 or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU;
41000 exstyle_mask = not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME
41001 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);
41004 PUSH EAX
41005 PUSH EDX
41007 CALL GetHasBorder
41008 POP ECX
41009 CMP AL, CL
41011 POP EAX
41012 JZ @@exit
41014 MOV EDX, [EAX].fStyle
41015 DEC CL
41016 MOVZX ECX, [EAX].fIsControl
41017 JNZ @@1
41019 OR EDX, WS_THICKFRAME
41020 INC ECX
41021 LOOP @@set_style
41022 OR EDX, style_mask
41023 JMP @@set_style
41025 @@1: AND EDX, not style_mask
41026 INC ECX
41027 LOOP @@2
41028 OR EDX, WS_POPUP
41030 @@2: PUSH EDX
41032 MOV EDX, [EAX].fExStyle
41033 AND EDX, exstyle_mask
41035 PUSH EAX
41036 CALL SetExStyle
41037 POP EAX
41039 POP EDX
41040 @@set_style:
41041 CALL SetStyle
41042 @@exit:
41043 end;
41044 {$ELSE ASM_VERSION} //Pascal
41045 procedure TControl.SetHasBorder(const Value: Boolean);
41046 var NewStyle: DWORD;
41047 begin
41048 if Value = GetHasBorder then Exit;
41049 {if Value then
41050 begin
41051 NewStyle := fStyle or WS_THICKFRAME;
41052 if not fIsControl then
41053 NewStyle := NewStyle or WS_BORDER or
41054 WS_DLGFRAME or WS_CAPTION or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
41055 WS_SYSMENU;
41056 Style := NewStyle;
41057 end}
41058 if Value then
41059 begin
41060 if not fIsControl then
41061 Style := fStyle or WS_THICKFRAME or WS_BORDER or
41062 WS_DLGFRAME or WS_CAPTION or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or
41063 WS_SYSMENU
41064 else
41065 if fCtl3D then
41066 ExStyle := fExStyle or WS_EX_CLIENTEDGE
41067 else
41068 Style := fStyle or WS_BORDER;
41070 else
41071 begin
41072 NewStyle := fStyle and not (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION
41073 or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU);
41074 if not fIsControl then NewStyle := NewStyle or WS_POPUP;
41075 Style := NewStyle;
41076 ExStyle := fExStyle and not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME
41077 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);
41078 end;
41079 end;
41080 {$ENDIF ASM_VERSION}
41082 {$IFDEF ASM_VERSION}
41083 //[function TControl.GetHasCaption]
41084 function TControl.GetHasCaption: Boolean;
41085 const style_mask1 = (WS_POPUP or WS_DLGFRAME) shr 16;
41086 style_mask2 = WS_CAPTION shr 16;
41088 CALL UpdateWndStyles
41089 MOV ECX, [EAX].fStyle + 2
41090 MOV EDX, ECX
41091 MOV AL, 1
41092 AND DX, style_mask1
41093 JZ @@1
41094 AND CX, style_mask2
41095 JNZ @@1
41096 XOR EAX, EAX
41097 @@1:
41098 end;
41099 {$ELSE ASM_VERSION} //Pascal
41100 function TControl.GetHasCaption: Boolean;
41101 begin
41102 UpdateWndStyles;
41103 Result := not LongBool( fStyle and (WS_POPUP or WS_DLGFRAME))
41104 or LongBool( fStyle and WS_CAPTION);
41105 end;
41106 {$ENDIF ASM_VERSION}
41108 {$IFDEF ASM_VERSION}
41109 //[procedure TControl.SetHasCaption]
41110 procedure TControl.SetHasCaption(const Value: Boolean);
41111 const style_mask = not (WS_BORDER or WS_THICKFRAME or WS_DLGFRAME or WS_CAPTION
41112 or WS_MINIMIZEBOX or WS_MAXIMIZEBOX or WS_SYSMENU);
41113 exstyle_mask = not (WS_EX_CONTROLPARENT or WS_EX_DLGMODALFRAME
41114 or WS_EX_WINDOWEDGE or WS_EX_CLIENTEDGE);
41116 PUSH EAX
41117 PUSH EDX
41119 CALL GetHasCaption
41120 POP ECX
41121 CMP AL, CL
41123 POP EAX
41124 JZ @@exit // Value = HasCaption
41126 MOV EDX, [EAX].fStyle
41127 DEC CL
41128 JNZ @@1 // if not Value -> @@1
41130 AND EDX, not WS_POPUP
41131 OR EDX, WS_CAPTION
41132 JMP @@set_style
41134 @@1:
41135 CMP [EAX].fIsControl, 0
41136 JNZ @@2 // if fIsControl -> @@2
41138 AND EDX, not (WS_CAPTION or WS_SYSMENU)
41139 OR EDX, WS_POPUP
41140 JMP @@3
41142 @@2:
41143 AND EDX, not WS_CAPTION
41144 OR EDX, WS_DLGFRAME
41146 @@3:
41147 PUSH EDX
41149 MOV EDX, [EAX].fExStyle
41150 OR EDX, WS_EX_DLGMODALFRAME
41152 PUSH EAX
41153 CALL SetExStyle
41154 POP EAX
41156 POP EDX
41157 @@set_style:
41158 CALL SetStyle
41159 @@exit:
41160 end;
41161 {$ELSE ASM_VERSION} //Pascal
41162 procedure TControl.SetHasCaption(const Value: Boolean);
41163 begin
41164 if Value = GetHasCaption then Exit;
41165 if Value then
41166 begin
41167 Style := fStyle and not (WS_POPUP or WS_DLGFRAME) or WS_CAPTION;
41169 else
41170 begin
41171 if fIsControl then
41172 Style := fStyle and not WS_CAPTION or WS_DLGFRAME
41173 else
41174 Style := fStyle and not (WS_CAPTION or WS_SYSMENU) or WS_POPUP;
41175 ExStyle := fExStyle or WS_EX_DLGMODALFRAME;
41176 end;
41177 end;
41178 {$ENDIF ASM_VERSION}
41180 {$IFDEF ASM_VERSION}
41181 //[function TControl.GetCanResize]
41182 function TControl.GetCanResize: Boolean;
41184 MOV AL, [EAX].fPreventResize
41185 {$IFDEF PARANOIA}
41186 DB $34,$01
41187 {$ELSE}
41188 XOR AL, 1
41189 {$ENDIF}
41190 end;
41191 {$ELSE ASM_VERSION} //Pascal
41192 function TControl.GetCanResize: Boolean;
41193 begin
41194 //UpdateWndStyles;
41195 //Result := LongBool( fStyle and WS_THICKFRAME);
41196 Result := not fPreventResize;
41197 end;
41198 {$ENDIF ASM_VERSION}
41200 //[function WndProcCanResize]
41201 function WndProcCanResize( Sender: PControl; var M: TMsg; var Rslt: Integer ): Boolean;
41202 var W, H: Integer;
41203 P: PMinMaxInfo;
41204 begin
41205 if not Sender.CanResize then
41206 if M.message = WM_GETMINMAXINFO then
41207 begin
41208 Rslt := Sender.CallDefWndProc( M );
41209 W := Sender.FFixWidth;
41210 H := Sender.FFixHeight;
41211 P := Pointer( M.lParam );
41212 P.ptMinTrackSize.x := W;
41213 P.ptMinTrackSize.y := H;
41214 P.ptMaxTrackSize := P.ptMinTrackSize;
41215 Result := True; // stop further processing (prevent resizing)
41216 Exit;
41218 else
41219 if M.message = WM_NCHITTEST then
41220 begin
41221 Rslt := Sender.CallDefWndProc( M );
41222 if (Rslt >= 10) and (Rslt <= 17) then
41223 begin
41224 Rslt := {-}HTBORDER{+}{++}(*18{HTBORDER}*){--};
41225 Result := True;
41226 exit;
41227 end;
41228 end;
41229 Result := False; // continue message processing
41230 end;
41232 {$IFDEF ASM_VERSION}
41233 //[procedure TControl.SetCanResize]
41234 procedure TControl.SetCanResize( const Value: Boolean );
41236 PUSH EBX
41237 MOV EBX, EAX
41239 CALL GetCanResize
41240 CMP AL, DL
41242 JZ @@exit // Value = CanResize
41243 MOV [EBX].fPreventResize, AL
41244 TEST DL, DL
41246 MOV EDX, [EBX].fStyle
41247 JZ @@set_thick
41249 OR EDX, WS_THICKFRAME
41250 JMP @@set_style
41252 @@set_thick:
41253 AND EDX, not WS_THICKFRAME
41255 @@set_style:
41256 MOV EAX, EBX
41257 CALL SetStyle
41259 MOV EAX, EBX
41260 CALL GetWindowHandle
41262 MOV EAX, EBX
41263 CALL GetWidth
41264 MOV [EBX].FFixWidth, EAX
41266 MOV EAX, EBX
41267 CALL GetHeight
41268 MOV [EBX].FFixHeight, EAX
41270 XCHG EAX, EBX
41271 MOV EDX, offset[WndProcCanResize]
41272 CALL TControl.AttachProc
41273 @@exit:
41274 POP EBX
41275 end;
41276 {$ELSE ASM_VERSION} //Pascal
41277 procedure TControl.SetCanResize( const Value: Boolean );
41278 begin
41279 if Value = CanResize then Exit;
41280 fPreventResize := not Value;
41281 if Value then
41282 Style := Style or WS_THICKFRAME
41283 else
41284 Style := Style and not WS_THICKFRAME;
41285 GetWindowHandle;
41286 FFixWidth := Width;
41287 FFixHeight := Height;
41288 AttachProc( WndProcCanResize );
41289 end;
41290 {$ENDIF ASM_VERSION}
41292 {$IFDEF ASM_VERSION}
41293 //[function TControl.GetStayOnTop]
41294 function TControl.GetStayOnTop: Boolean;
41296 CALL UpdateWndStyles
41297 TEST byte ptr [EAX].fExStyle, WS_EX_TOPMOST
41298 SETNZ AL
41299 end;
41300 {$ELSE ASM_VERSION} //Pascal
41301 function TControl.GetStayOnTop: Boolean;
41302 begin
41303 UpdateWndStyles;
41304 Result := LongBool( fExStyle and WS_EX_TOPMOST);
41305 end;
41306 {$ENDIF ASM_VERSION}
41308 {$IFDEF ASM_VERSION}
41309 //[procedure TControl.SetStayOnTop]
41310 procedure TControl.SetStayOnTop(const Value: Boolean);
41312 PUSH EAX
41313 PUSH EDX
41315 CALL GetStayOnTop
41316 POP ECX
41317 MOVZX ECX, CL
41318 CMP AL, CL
41320 POP EAX
41321 JZ @@exit // Value = StayOnTop
41323 MOV EDX, [EAX].fHandle
41324 TEST EDX, EDX
41325 JZ @@1
41327 PUSH SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE
41328 XOR EAX, EAX
41329 PUSH EAX
41330 PUSH EAX
41331 PUSH EAX
41332 PUSH EAX
41333 DEC ECX
41334 DEC ECX
41335 PUSH ECX
41337 PUSH EDX
41338 CALL SetWindowPos
41341 @@1:
41342 JECXZ @@1and
41344 OR byte ptr [EAX].fExStyle, WS_EX_TOPMOST
41347 @@1and: AND byte ptr [EAX].fExStyle, not WS_EX_TOPMOST
41349 @@exit:
41350 end;
41351 {$ELSE ASM_VERSION} //Pascal
41352 procedure TControl.SetStayOnTop(const Value: Boolean);
41353 begin
41354 if Value = GetStayOnTop then Exit;
41355 if fHandle <> 0 then
41356 if Value then
41357 SetWindowPos( fHandle, HWND_TOPMOST, 0,0,0,0,
41358 SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE )
41359 else
41360 SetWindowPos( fHandle, HWND_NOTOPMOST, 0,0,0,0,
41361 SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE )
41362 else
41363 if Value then fExStyle := fExStyle or WS_EX_TOPMOST
41364 else fExStyle := fExStyle and not WS_EX_TOPMOST;
41365 end;
41366 {$ENDIF ASM_VERSION}
41368 {$IFDEF ASM_VERSION}
41369 //[function TControl.UpdateWndStyles]
41370 function TControl.UpdateWndStyles: PControl;
41372 MOV ECX, [EAX].fHandle
41373 JECXZ @@exit
41375 PUSH EBX
41377 XCHG EBX, EAX
41378 PUSH GCL_STYLE
41379 PUSH ECX
41381 PUSH GWL_EXSTYLE
41382 PUSH ECX
41384 PUSH GWL_STYLE
41385 PUSH ECX
41387 CALL GetWindowLong
41388 MOV [EBX].fStyle, EAX
41390 CALL GetWindowLong
41391 MOV [EBX].fExStyle, EAX
41393 CALL GetClassLong
41394 MOV [EBX].fClsStyle, EAX
41395 XCHG EAX, EBX
41396 POP EBX
41397 @@exit:
41398 end;
41399 {$ELSE ASM_VERSION} //Pascal
41400 function TControl.UpdateWndStyles: PControl;
41401 begin
41402 Result := @Self;
41403 if fHandle = 0 then Exit;
41404 fStyle := GetWindowLong( fHandle, GWL_STYLE );
41405 fExStyle := GetWindowLong( fHandle, GWL_EXSTYLE );
41406 fClsStyle := GetClassLong( fHandle, GCL_STYLE );
41407 end;
41408 {$ENDIF ASM_VERSION}
41410 {$IFDEF ASM_VERSION}
41411 //[function TControl.GetChecked]
41412 function TControl.GetChecked: Boolean;
41414 TEST [EAX].fBitBtnOptions, 8 //1 shl Ord(bboFixed)
41415 JZ @@1
41416 MOV AL, [EAX].fChecked
41418 @@1:
41419 PUSH 0
41420 PUSH 0
41421 PUSH BM_GETCHECK
41422 PUSH EAX
41423 CALL Perform
41424 @@exit:
41425 end;
41426 {$ELSE ASM_VERSION} //Pascal
41427 function TControl.GetChecked: Boolean;
41428 begin
41429 if bboFixed in fBitBtnOptions then
41430 Result := fChecked
41431 else
41432 Result := LongBool( Perform( BM_GETCHECK, 0, 0 ) ) ; //= BST_CHECKED;
41433 end;
41434 {$ENDIF ASM_VERSION}
41436 {$IFDEF ASM_VERSION}
41437 //[procedure TControl.Set_Checked]
41438 procedure TControl.Set_Checked(const Value: Boolean);
41440 TEST [EAX].fBitBtnOptions, 8 //1 shl Ord(bboFixed)
41441 JZ @@1
41442 MOV [EAX].fChecked, DL
41443 JMP Invalidate
41444 @@1:
41445 PUSH 0
41446 MOVZX EDX, DL
41447 PUSH EDX
41448 PUSH BM_SETCHECK
41449 PUSH EAX
41450 Call Perform
41451 end;
41452 {$ELSE ASM_VERSION} //Pascal
41453 procedure TControl.Set_Checked(const Value: Boolean);
41454 begin
41455 if bboFixed in fBitBtnOptions then
41456 begin
41457 fChecked := Value;
41458 Invalidate;
41460 else
41461 Perform( BM_SETCHECK, Integer( Value ), 0 );
41462 end;
41463 {$ENDIF ASM_VERSION}
41465 //[function TControl.SetChecked]
41466 function TControl.SetChecked(const Value: Boolean): PControl;
41467 begin
41468 Perform( BM_SETCHECK, Integer( Value ), 0 );
41469 Result := @Self;
41470 end;
41472 {$IFDEF ASM_VERSION}
41473 //[function TControl.SetRadioCheckedOld]
41474 function TControl.SetRadioCheckedOld: PControl;
41476 PUSH EAX
41477 MOV ECX, [EAX].fParent
41478 JECXZ @@exit
41480 PUSH [EAX].fMenu
41481 PUSH [ECX].fRadioLast
41482 PUSH [ECX].fRadio1st
41483 MOV EAX, ECX
41484 CALL GetWindowHandle
41485 PUSH EAX
41486 CALL CheckRadioButton
41487 @@exit:
41488 POP EAX
41489 end;
41490 {$ELSE ASM_VERSION} //Pascal
41491 function TControl.SetRadioCheckedOld: PControl;
41492 begin
41493 Result := @Self;
41494 if fParent = nil then Exit;
41495 CheckRadioButton( fParent.GetWindowHandle,
41496 fParent.fRadio1st,
41497 fParent.fRadioLast,
41498 fMenu );
41499 end;
41500 {$ENDIF ASM_VERSION}
41503 //[function TControl.SetRadioChecked]
41504 {$IFDEF ASM_VERSION}
41505 function TControl.SetRadioChecked: PControl;
41507 PUSH EAX
41508 PUSH DWORD PTR[EAX].fTabStop
41509 MOV [EAX].fTabStop, 0
41510 @@1:
41511 CALL DoClick
41512 POP EDX
41513 POP EAX
41514 MOV [EAX].fTabStop, DL
41515 end;
41516 {$ELSE PAS_VERSION}
41517 function TControl.SetRadioChecked: PControl;
41518 var WasTabStop: Boolean;
41519 begin
41520 WasTabStop := fTabStop;
41521 fTabStop := FALSE;
41522 DoClick;
41523 fTabStop := WasTabStop;
41524 Result := @Self;
41525 end;
41526 {$ENDIF ASM_VERSION}
41528 //[function TControl.GetCheck3]
41529 function TControl.GetCheck3: TTriStateCheck;
41530 begin
41531 Result := TTriStateCheck(Perform(BM_GETCHECK, 0, 0) and 3);
41532 end;
41534 //[procedure TControl.SetCheck3]
41535 procedure TControl.SetCheck3(value: TTriStateCheck);
41537 wp: WPARAM;
41538 begin
41539 wp := Perform(BM_GETCHECK, 0, 0) and not 3;
41540 wp := wp or ord(value);
41541 Perform(BM_SETCHECK, wp, 0);
41542 end;
41545 //[procedure TControl.Click]
41546 procedure TControl.Click;
41547 begin
41548 if (fCommandActions.aClick <> 0) or
41549 (fCommandActions.aEnter = BN_SETFOCUS) then
41550 Perform( WM_COMMAND, (fCommandActions.aClick shl 16) or fMenu,
41551 GetWindowHandle )
41552 else
41553 begin
41554 Perform( WM_LBUTTONDOWN, MK_LBUTTON, 0 );
41555 Perform( WM_LBUTTONUP, MK_LBUTTON, 0 );
41556 end;
41557 end;
41559 {$IFDEF ASM_VERSION}
41560 //[function TControl.GetSelStart]
41561 function TControl.GetSelStart: Integer;
41563 MOVZX ECX, [EAX].fCommandActions.aGetSelRange
41564 JECXZ @@1
41566 XOR EDX, EDX
41567 PUSH EDX
41568 PUSH EDX
41569 PUSH ECX
41570 PUSH EAX
41571 CALL Perform
41572 CWDE
41575 @@1:
41576 MOVZX ECX, [EAX].fCommandActions.aExGetSelRange
41577 JECXZ @@exit
41578 XCHG EAX, ECX
41580 PUSH EDX
41581 PUSH EDX
41582 PUSH ESP
41583 PUSH EDX
41584 PUSH EAX
41585 PUSH ECX
41586 CALL Perform
41587 POP ECX
41588 POP EDX
41590 @@exit:
41591 XCHG EAX, ECX
41592 end;
41593 {$ELSE ASM_VERSION} //Pascal
41594 function TControl.GetSelStart: Integer;
41595 var SR: TCharRange;
41596 begin
41597 Result := 0;
41598 if fCommandActions.aGetSelRange <> 0 then
41599 Result := LoWord( Perform( fCommandActions.aGetSelRange, 0, 0 ) )
41600 else
41601 if fCommandActions.aExGetSelRange <> 0 then
41602 begin
41603 Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );
41604 Result := SR.cpMin;
41605 end;
41606 end;
41607 {$ENDIF ASM_VERSION}
41609 //[procedure TControl.SetSelStart]
41610 procedure TControl.SetSelStart(const Value: Integer);
41611 begin
41612 ItemSelected[ Value ] := True;
41613 end;
41615 {$IFDEF ASM_VERSION}
41616 //[function TControl.GetSelLength]
41617 function TControl.GetSelLength: Integer;
41619 XOR EDX, EDX
41620 MOVZX ECX, word ptr[EAX].fCommandActions.aGetSelCount
41621 JECXZ @@check_ex
41623 PUSH ECX
41624 AND CH, $7F
41625 PUSH EDX
41626 PUSH EDX
41627 PUSH ECX
41628 PUSH EAX
41629 CALL Perform
41630 POP ECX
41631 SHL CH, 1
41632 JC @@fin_EAX
41634 CMP EAX, 32768
41635 JL @@2
41637 PUSH EAX
41638 POP DX
41639 POP AX
41640 SUB AX, DX
41641 MOVZX EAX, AX
41642 @@fin_EAX:
41645 @@check_ex:
41646 MOVZX ECX, [EAX].fCommandActions.aExGetSelRange
41647 JECXZ @@ret_0
41648 PUSH EDX
41649 PUSH EDX
41650 PUSH ESP
41651 PUSH EDX
41652 PUSH ECX
41653 PUSH EAX
41654 CALL Perform
41655 POP EDX
41656 POP EAX
41657 SUB EAX, EDX
41660 @@ret_0:
41661 XOR EAX, EAX
41662 //RET
41664 @@2: TEST EAX, EAX
41665 JL @@ret_0
41666 end;
41667 {$ELSE ASM_VERSION} //Pascal
41668 function TControl.GetSelLength: Integer;
41669 var SR: TCharRange;
41670 begin
41671 Result := 0;
41672 if fCommandActions.aGetSelCount <> 0 then
41673 begin
41674 Result := Perform( fCommandActions.aGetSelCount and $7FFF, 0, 0 );
41675 if (fCommandActions.aGetSelCount and $8000) = 0 then
41676 if Result >= 32768 then
41677 Result := HiWord( Result ) - LoWord( Result )
41678 else
41679 if Result < 0 then
41680 Result := 0;
41682 else
41683 if fCommandActions.aExGetSelRange <> 0 then
41684 begin
41685 Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );
41686 Result := SR.cpMax - SR.cpMin;
41687 end;
41688 end;
41689 {$ENDIF ASM_VERSION}
41691 {$IFDEF ASM_VERSION}
41692 //[procedure TControl.SetSelLength]
41693 procedure TControl.SetSelLength(const Value: Integer);
41695 PUSH EBP
41696 MOV EBP, ESP
41697 PUSH EAX
41698 PUSH EDX
41699 CALL GetSelStart
41700 POP ECX
41701 POP EDX
41702 ADD ECX, EAX
41703 PUSH ECX
41704 MOVZX ECX, [EDX].fCommandActions.aSetSelRange
41705 JECXZ @@check_ex
41706 PUSH EAX
41707 JMP @@perform
41709 @@check_ex:
41710 MOVZX ECX, [EDX].fCommandActions.aExSetSelRange
41711 JECXZ @@exit
41712 PUSH EAX
41713 PUSH ESP
41714 PUSH 0
41715 @@perform:
41716 PUSH ECX
41717 PUSH EDX
41718 CALL Perform
41719 @@exit: MOV ESP, EBP
41720 POP EBP
41721 end;
41722 {$ELSE ASM_VERSION} //Pascal
41723 procedure TControl.SetSelLength(const Value: Integer);
41725 SR: TCharRange;
41726 begin
41727 SR.cpMin := GetSelStart;
41728 SR.cpMax := SR.cpMin + Value;
41729 if Value < 0 then
41730 SR.cpMax := -1;
41731 if fCommandActions.aSetSelRange <> 0 then
41732 Perform( fCommandActions.aSetSelRange, SR.cpMin, SR.cpMax )
41733 else
41734 if fCommandActions.aExSetSelRange <> 0 then
41735 Perform( fCommandActions.aExSetSelRange, 0, Integer( @SR ) );
41736 // Preform( EM_SCROLLCARET, 0, 0 );
41737 end;
41738 {$ENDIF ASM_VERSION}
41740 {$IFDEF ASM_VERSION}
41741 //[function TControl.GetItems]
41742 function TControl.GetItems(Idx: Integer): String;
41744 PUSH ESI
41745 PUSH EDI
41746 PUSH EBX
41747 PUSH EBP
41748 MOV EBP, ESP
41750 MOV EBX, EAX // @Self
41751 MOV ESI, EDX // Idx
41752 MOV EDI, ECX // @Result
41754 CALL Item2Pos
41755 PUSH 0 // push 0
41756 PUSH EAX // store Pos
41758 XCHG EDX, EAX
41759 MOV EAX, EBX
41760 CALL Pos2Item // EAX = Idx'
41761 XCHG ESI, EAX // ESI = Idx'
41763 XOR EAX, EAX
41764 MOVZX ECX, [EBX].fCommandActions.aGetItemLength
41765 JECXZ @@ret_empty
41767 PUSH ECX // push aGetItemLength
41769 PUSH EBX
41770 CALL Perform
41772 TEST EAX, EAX
41773 JZ @@ret_empty
41775 PUSH EAX // save L
41776 ADD EAX, 4
41778 CALL System.@GetMem // GetMem( L+4 )
41779 POP EDX // restore L
41780 MOV byte ptr [EAX], 0
41781 MOVZX ECX, [EBX].fCommandActions.aGetItemText
41782 JECXZ @@ret_buf
41784 PUSH EDX // save L
41785 MOV word ptr [EAX], DX
41787 PUSH EAX
41788 PUSH EAX // push Buf
41789 PUSH ESI // push Idx
41791 PUSH ECX // push aGetItemText
41792 PUSH EBX
41793 CALL Perform
41794 POP EAX
41796 POP EDX
41797 @@ret_buf:
41798 MOV byte ptr [EAX + EDX], 0 // Buf[ L ] := #0
41800 @@ret_empty: // EAX = 0
41801 XCHG EDX, EAX
41802 MOV EAX, EDI
41803 PUSH EDX
41804 CALL System.@LStrFromPChar
41805 POP ECX
41806 JECXZ @@exit
41807 XCHG EAX, ECX
41808 CALL System.@FreeMem
41810 @@exit:
41811 MOV ESP, EBP
41812 POP EBP
41813 POP EBX
41814 POP EDI
41815 POP ESI
41816 end;
41817 {$ELSE ASM_VERSION} //Pascal
41818 function TControl.GetItems(Idx: Integer): String;
41819 var L, Pos: Integer;
41820 Buf: PChar;
41821 begin
41822 Result := '';
41823 Pos := Item2Pos( Idx );
41824 Idx := Pos2Item( Pos );
41825 if fCommandActions.aGetItemLength <> 0 then
41826 L := Perform( fCommandActions.aGetItemLength, Pos, 0 )
41827 else
41828 Exit;
41829 if L = 0 then Exit;
41830 GetMem( Buf, L + 4 );
41831 PWORD( Buf )^ := L + 1;
41832 if fCommandActions.aGetItemText <> 0 then
41833 Perform( fCommandActions.aGetItemText, Idx, Integer( Buf ) );
41834 Buf[ L ] := #0;
41835 Result := Buf;
41836 FreeMem( Buf );
41837 end;
41838 {$ENDIF ASM_VERSION}
41840 {$IFDEF ASM_VERSION}
41841 //[procedure TControl.SetItems]
41842 procedure TControl.SetItems(Idx: Integer; const Value: String);
41844 PUSH EDI
41845 PUSH EBX
41846 XCHG EBX, EAX
41847 XCHG EDI, EDX // EDI = Idx
41848 CALL ECX2PChar
41849 PUSH ECX // @Value[1]
41851 MOVZX ECX, [EBX].fCommandActions.aSetItemText
41852 JECXZ @@1
41854 PUSH 0
41855 PUSH ECX
41857 MOV EDX, EDI
41858 MOV EAX, EBX
41859 CALL Item2Pos
41860 PUSH EAX // store Strt
41862 MOV EDX, EDI
41863 INC EDX
41864 MOV EAX, EBX
41865 CALL Item2Pos
41866 POP EDX // EDX = Strt
41868 SUB EAX, EDX
41869 PUSH EAX // store L
41871 MOV EAX, EBX
41872 CALL SetSelStart
41874 POP EDX // EDX = L
41875 PUSH EBX // prepare @Self for Perform
41876 XCHG EAX, EBX
41877 CALL SetSelLength
41879 // @Value[1] already in stack,
41880 // 0 already in stack
41881 // aSetItemText already in stack
41882 // @Self already in stack
41884 CALL Perform
41885 JMP @@exit
41887 @@1: // @Value[1] in stack already
41888 POP EDX
41889 MOVZX ECX, [EBX].fCommandActions.aDeleteItem
41890 JECXZ @@exit
41892 {$IFNDEF NOT_FIX_CURINDEX}
41893 PUSH ESI
41894 PUSH EBP
41896 PUSH EDX
41898 MOV EAX, EBX // +AK
41899 CALL GetCurIndex // +AK
41900 XCHG ESI, EAX // ESI = TmpCurIdx
41902 MOV EAX, EBX
41903 MOV EDX, EDI
41904 CALL GetItemData
41905 XCHG EBP, EAX // EBP = TmpData
41907 MOV EDX, EDI
41908 MOV EAX, EBX
41909 CALL Delete
41911 MOV EAX, EBX // *AK
41912 MOV EDX, EDI
41913 POP ECX
41914 CALL Insert
41916 MOV ECX, EBP // ECX = TmpData
41917 MOV EDX, EDI
41918 MOV EAX, EBX
41919 CALL SetItemData
41921 XCHG EAX, EBX // +AK
41922 MOV EDX, ESI // +AK
41923 CALL SetCurIndex // +AK
41925 POP EBP
41926 POP ESI
41927 {$ELSE NOT_FIX_CURINDEX}
41928 PUSH EDX
41930 MOV EDX, EDI
41931 MOV EAX, EBX
41932 CALL Delete
41934 XCHG EAX, EBX
41935 XCHG EDX, EDI
41937 POP ECX
41938 CALL Insert
41939 {$ENDIF NOT_FIX_CURINDEX}
41941 @@exit:
41942 POP EBX
41943 POP EDI
41944 end;
41945 {$ELSE ASM_VERSION} //Pascal
41946 procedure TControl.SetItems(Idx: Integer; const Value: String);
41947 var Strt, L : Integer;
41948 {$IFNDEF NOT_FIX_CURINDEX}
41949 TmpCurIdx: Integer; // AK - Andrzey Kubasek
41950 TmpData: DWORD;
41951 {$ENDIF NOT_FIX_CURINDEX}
41952 begin
41953 if fCommandActions.aSetItemText <> 0 then
41954 begin
41955 Strt := Item2Pos( Idx );
41956 L := Item2Pos( Idx + 1 ) - Strt;
41957 SelStart := Strt;
41958 SelLength := L;
41959 Perform( fCommandActions.aSetItemText, 0, Integer( PChar( Value ) ) );
41961 else
41962 if fCommandActions.aDeleteItem <> 0 then
41963 begin
41964 {$IFNDEF NOT_FIX_CURINDEX}
41965 TmpCurIdx := CurIndex; // +AK
41966 TmpData := ItemData[ Idx ];
41967 {$ENDIF}
41968 Delete( Idx );
41969 Insert( Idx, Value );
41970 {$IFNDEF NOT_FIX_CURINDEX}
41971 CurIndex := TmpCurIdx; //+AK
41972 ItemData[ Idx ] := TmpData;
41973 {$ENDIF}
41974 end;
41975 end;
41976 {$ENDIF ASM_VERSION}
41978 {$IFDEF ASM_VERSION}
41979 //[function TControl.GetItemsCount]
41980 function TControl.GetItemsCount: Integer;
41982 PUSH 0
41983 MOVZX ECX, [EAX].fCommandActions.aGetCount
41984 JECXZ @@ret_0
41985 PUSH 0
41986 PUSH ECX
41987 PUSH EAX
41988 CALL Perform
41989 PUSH EAX
41991 @@ret_0:
41992 POP EAX
41993 end;
41994 {$ELSE ASM_VERSION} //Pascal
41995 function TControl.GetItemsCount: Integer;
41996 begin
41997 Result := 0;
41998 {$IFDEF DEBUG}
42000 {$ENDIF}
42001 if fCommandActions.aGetCount = 0 then Exit;
42002 Result := Perform( fCommandActions.aGetCount, 0, 0 );
42003 {$IFDEF DEBUG}
42004 except
42006 int 3
42007 end;
42008 end;
42009 {$ENDIF}
42010 end;
42011 {$ENDIF ASM_VERSION}
42014 //[procedure TControl.SetItemsCount]
42015 procedure TControl.SetItemsCount(const Value: Integer);
42016 begin
42017 if fCommandActions.aSetCount = 0 then Exit;
42018 Perform( fCommandActions.aSetCount, Value, 0 );
42019 end;
42021 //[PROCEDURE HelpConvertItem2Pos]
42022 {$IFDEF ASM_VERSION}
42023 procedure HelpConvertItem2Pos;
42025 JECXZ @@exit
42026 PUSH 0
42027 PUSH EDX
42028 PUSH ECX
42029 PUSH EAX
42030 CALL TControl.Perform
42031 XOR EDX, EDX
42032 TEST EAX, EAX
42033 JL @@exit
42035 @@exit:
42036 MOV EAX, EDX
42037 end;
42038 {$ENDIF ASM_VERSION}
42039 //[END HelpConvertItem2Pos]
42041 {$IFDEF ASM_VERSION}
42042 //[function TControl.Item2Pos]
42043 function TControl.Item2Pos(ItemIdx: Integer): Integer;
42045 MOVZX ECX, [EAX].fCommandActions.aItem2Pos
42046 JMP HelpConvertItem2Pos
42047 end;
42048 {$ELSE ASM_VERSION} //Pascal
42049 function TControl.Item2Pos(ItemIdx: Integer): Integer;
42050 begin
42051 Result := ItemIdx;
42052 if fCommandActions.aItem2Pos <> 0 then
42053 begin
42054 Result := Perform( fCommandActions.aItem2Pos, ItemIdx, 0 );
42055 if Result < 0 then Result := 0;
42056 end;
42057 end;
42058 {$ENDIF ASM_VERSION}
42060 {$IFDEF ASM_VERSION}
42061 //[function TControl.Pos2Item]
42062 function TControl.Pos2Item(Pos: Integer): Integer;
42064 MOVZX ECX, [EAX].fCommandActions.aPos2Item
42065 JMP HelpConvertItem2Pos
42066 end;
42067 {$ELSE ASM_VERSION} //Pascal
42068 function TControl.Pos2Item(Pos: Integer): Integer;
42069 begin
42070 Result := Pos;
42071 if fCommandActions.aPos2Item <> 0 then
42072 Result := Perform( fCommandActions.aPos2Item, Pos, 0 );
42073 end;
42074 {$ENDIF ASM_VERSION}
42076 //[function WndProcTabChar]
42077 function WndProcTabChar( Sender: PControl; var M: TMsg; var Rslt: Integer ): Boolean;
42078 begin
42079 if M.message = WM_CHAR then
42080 begin
42081 if M.wParam = 9 then
42082 begin
42083 //M.wParam := 0;
42084 Sender.ReplaceSelection( #9, TRUE );
42085 end;
42086 end;
42087 Result := FALSE;
42088 end;
42090 //[function TControl.EditTabChar]
42091 function TControl.EditTabChar: PControl;
42092 begin
42093 AttachProc( WndProcTabChar );
42094 Result := @Self;
42095 end;
42097 {$IFDEF ASM_VERSION}
42098 //[function TControl.Add]
42099 function TControl.Add(const S: String): Integer;
42101 PUSH EBX
42102 MOV EBX, EAX // EBX = @Self
42104 MOVZX ECX, [EBX].fCommandActions.aAddItem // ECX = aAddItem
42105 JECXZ @@chk_addtext
42107 CALL EDX2PChar
42108 PUSH EDX
42109 PUSH 0
42110 PUSH ECX
42111 PUSH EBX
42112 CALL Perform
42113 PUSH EAX
42115 MOV EAX, EBX
42116 CALL TControl.GetItemsCount
42117 XCHG EAX, ECX
42118 LOOP @@ret_EAX
42120 XCHG EAX, EBX
42121 INC ECX
42122 XOR EDX, EDX
42123 CALL TControl.SetItemSelected
42124 @@ret_EAX:
42125 POP EAX
42126 JMP @@exit
42128 @@chk_addtext:
42129 MOV ECX, [EBX].fCommandActions.aAddText
42130 JECXZ @@add_text_simple
42132 CALL ECX
42133 JMP @@exit_0
42135 @@add_text_simple:
42136 PUSH EDX
42137 PUSH 0
42138 MOV EDX, ESP
42139 CALL GetCaption
42140 POP EAX
42141 POP EDX
42142 PUSH EAX
42143 MOV EAX, ESP
42144 CALL System.@LStrCat
42145 MOV EAX, EBX
42146 POP EDX
42147 PUSH EDX
42148 CALL SetCaption
42149 CALL RemoveStr
42150 @@exit_0:
42151 XOR EAX, EAX
42152 @@exit:
42153 POP EBX
42154 end;
42155 {$ELSE ASM_VERSION} //Pascal
42156 function TControl.Add(const S: String): Integer;
42157 begin
42158 if fCommandActions.aAddItem <> 0 then
42159 begin
42160 Result := Perform( fCommandActions.aAddItem, 0, Integer( PChar( S ) ) );
42161 if Count = 1 then
42162 ItemSelected[ 0 ] := True;
42164 else
42165 begin
42166 if assigned( fCommandActions.aAddText ) then
42167 fCommandActions.aAddText( @Self, S )
42168 else
42169 Text := Text + S;
42170 Result := 0;
42171 end;
42172 end;
42173 {$ENDIF ASM_VERSION}
42175 {$IFDEF ASM_VERSION}
42176 //[procedure TControl.Delete]
42177 procedure TControl.Delete(Idx: Integer);
42179 MOVZX ECX, [EAX].fCommandActions.aDeleteItem
42180 JECXZ @@exit
42182 PUSH 0
42183 PUSH EDX
42184 PUSH ECX
42185 PUSH EAX
42186 CALL Perform
42187 @@exit:
42188 end;
42189 {$ELSE ASM_VERSION} //Pascal
42190 procedure TControl.Delete(Idx: Integer);
42191 begin
42192 if fCommandActions.aDeleteItem <> 0 then
42193 Perform( fCommandActions.aDeleteItem, Idx, 0 );
42194 end;
42195 {$ENDIF ASM_VERSION}
42197 {$IFDEF ASM_VERSION}
42198 //[function TControl.Insert]
42199 function TControl.Insert(Idx: Integer; const S: String): Integer;
42201 CALL ECX2PChar
42202 PUSH ECX
42203 MOVZX ECX, [EAX].fCommandActions.aInsertItem
42204 JECXZ @@exit_1
42206 PUSH EDX
42207 PUSH ECX
42208 PUSH EAX
42209 CALL Perform
42212 @@exit_1:OR EAX, -1
42213 POP ECX
42214 end;
42215 {$ELSE ASM_VERSION} //Pascal
42216 function TControl.Insert(Idx: Integer; const S: String): Integer;
42217 begin
42218 if fCommandActions.aInsertItem <> 0 then
42219 Result := Perform( fCommandActions.aInsertItem, Idx, Integer( PChar( S ) ) )
42220 else
42221 Result := -1;
42222 end;
42223 {$ENDIF ASM_VERSION}
42225 {$IFDEF ASM_VERSION}
42226 //[function TControl.GetItemSelected]
42227 function TControl.GetItemSelected(ItemIdx: Integer): Boolean;
42229 MOVZX ECX, [EAX].fCommandActions.aGetSelected
42230 JECXZ @@check_range
42232 PUSH 0
42233 PUSH EDX
42234 PUSH ECX
42235 PUSH EAX
42236 CALL Perform
42237 TEST EAX, EAX
42238 SETG AL
42241 @@check_range:
42242 MOVZX ECX, [EAX].fCommandActions.aGetSelRange
42243 JECXZ @@check_ex
42245 PUSH EDX
42246 PUSH 0
42247 PUSH 0
42248 PUSH ECX
42249 PUSH EAX
42250 CALL Perform
42251 POP EDX
42252 TEST EAX, EAX
42253 JL @@ret_false
42255 CMP DX, AX
42256 JL @@ret_false
42258 SHR EAX, 16
42259 SUB EDX, EAX
42260 SETL AL
42263 @@check_ex:
42264 MOVZX ECX, [EAX].fCommandActions.aExGetSelRange
42265 JECXZ @@ret_false
42266 PUSH EDX
42267 PUSH EDX
42268 PUSH EDX
42269 PUSH ESP
42270 PUSH 0
42271 PUSH ECX
42272 PUSH EAX
42273 CALL Perform
42274 POP ECX
42275 POP EDX
42276 POP EAX
42278 SUB EAX, EDX
42279 CMP EAX, ECX
42280 SETB AL
42283 @@ret_false:
42284 XOR EAX, EAX
42285 end;
42286 {$ELSE ASM_VERSION} //Pascal
42287 function TControl.GetItemSelected(ItemIdx: Integer): Boolean;
42288 var SR: TCharRange;
42289 begin
42290 Result := False;
42291 if fCommandActions.aGetSelected <> 0 then
42292 Result := 0 < Perform( fCommandActions.aGetSelected, ItemIdx, 0 )
42293 else if fCommandActions.aGetSelRange <> 0 then
42294 begin
42295 Perform( fCommandActions.aGetSelRange, Integer( @SR.cpMin ), Integer( @SR.cpMax ) );
42296 Result := (SR.cpMin <= ItemIdx) and (ItemIdx < SR.cpMax);
42298 else if fCommandActions.aExGetSelRange <> 0 then
42299 begin
42300 Perform( fCommandActions.aExGetSelRange, 0, Integer( @SR ) );
42301 Result := (SR.cpMin <= ItemIdx) and (ItemIdx < SR.cpMax);
42302 end;
42303 end;
42304 {$ENDIF ASM_VERSION}
42306 {$IFDEF ASM_VERSION}
42307 //[procedure TControl.SetItemSelected]
42308 procedure TControl.SetItemSelected(ItemIdx: Integer; const Value: Boolean);
42310 PUSH EDX
42311 PUSH ECX
42312 MOVZX ECX, [EAX].fCommandActions.aSetSelected
42313 JECXZ @@chk_aSetCurrent
42315 @@0:
42316 PUSH ECX
42317 PUSH EAX
42318 CALL Perform
42321 @@chk_aSetCurrent:
42322 POP ECX
42323 MOVZX ECX, [EAX].fCommandActions.aSetCurrent
42324 JECXZ @@chk_aSetSelRange
42326 POP EDX
42327 PUSH 0
42328 JMP @@3
42330 @@chk_aSetSelRange:
42331 MOVZX ECX, [EAX].fCommandActions.aSetSelRange
42332 JECXZ @@chk_aExSetSelRange
42333 @@3:
42334 PUSH EDX
42335 JMP @@0
42337 @@else: MOV [EAX].FCurIndex, EDX
42338 CALL Invalidate
42339 JMP @@exit
42341 @@chk_aExSetSelRange:
42342 MOVZX ECX, [EAX].fCommandActions.aExSetSelRange
42343 JECXZ @@else
42345 PUSH EDX
42346 PUSH ESP
42347 PUSH 0
42348 PUSH ECX
42349 PUSH EAX
42350 CALL Perform
42351 POP ECX
42353 @@exit:
42354 POP ECX
42355 end;
42356 {$ELSE ASM_VERSION} //Pascal
42357 procedure TControl.SetItemSelected(ItemIdx: Integer; const Value: Boolean);
42358 var SR: TCharRange;
42359 begin
42360 if fCommandActions.aSetSelected <> 0 then
42361 Perform( fCommandActions.aSetSelected, Integer( Value ), ItemIdx )
42362 else
42363 if fCommandActions.aSetCurrent <> 0 then
42364 Perform( fCommandActions.aSetCurrent, ItemIdx, 0 )
42365 else
42366 if fCommandActions.aSetSelRange <> 0 then
42367 Perform( fCommandActions.aSetSelRange, ItemIdx, ItemIdx )
42368 else
42369 if fCommandActions.aExSetSelRange <> 0 then
42370 begin
42371 SR.cpMin := ItemIdx;
42372 SR.cpMax := ItemIdx;
42373 Perform( fCommandActions.aExSetSelRange, 0, Integer( @SR ) );
42375 else
42376 begin // for ImageShow: set the index and invalidate the control
42377 FCurIndex := ItemIdx;
42378 Invalidate;
42379 end;
42380 end;
42381 {$ENDIF ASM_VERSION}
42383 {$IFDEF ASM_VERSION}
42384 //[procedure TControl.SetCtl3D]
42385 procedure TControl.SetCtl3D(const Value: Boolean);
42387 MOV [EAX].fCtl3Dchild, DL
42388 CMP [EAX].fCtl3D, DL
42389 JE @@exit
42390 MOV [EAX].fCtl3D, DL
42391 PUSHAD
42392 CALL UpdateWndStyles
42393 POPAD
42394 MOV ECX, [EAX].fExStyle
42395 DEC DL
42396 MOV EDX, [EAX].fStyle
42397 JNZ @@1
42398 AND EDX, not WS_BORDER
42399 OR CH, WS_EX_CLIENTEDGE shr 8
42400 JMP @@2
42401 @@1:
42402 OR EDX, WS_BORDER
42403 AND CH, not(WS_EX_CLIENTEDGE shr 8)
42404 @@2:
42405 PUSH ECX
42406 PUSH EAX
42407 CALL SetStyle
42408 POP EAX
42409 POP EDX
42410 JMP SetExStyle
42411 @@exit:
42412 end;
42413 {$ELSE ASM_VERSION} //Pascal
42414 procedure TControl.SetCtl3D(const Value: Boolean);
42415 begin
42416 fCtl3Dchild := Value;
42417 if fCtl3D = Value then Exit;
42418 fCtl3D := Value;
42419 UpdateWndStyles;
42420 if Value then
42421 begin
42422 ExStyle := fExStyle or WS_EX_CLIENTEDGE;
42423 Style := fStyle and not WS_BORDER;
42425 else
42426 begin
42427 ExStyle := fExStyle and not WS_EX_CLIENTEDGE;
42428 Style := fStyle or WS_BORDER;
42429 end;
42430 end;
42431 {$ENDIF ASM_VERSION}
42433 {$IFDEF ASM_VERSION}
42434 //[function TControl.Shift]
42435 function TControl.Shift(dX, dY: Integer): PControl;
42437 PUSHAD
42438 ADD EDX, [EAX].fBoundsRect.TRect.Left
42439 CALL SetLeft
42440 POPAD
42441 PUSH EAX
42442 MOV EDX, [EAX].fBoundsRect.TRect.Top
42443 ADD EDX, ECX
42444 CALL SetTop
42445 POP EAX
42446 end;
42447 {$ELSE ASM_VERSION} //Pascal
42448 function TControl.Shift(dX, dY: Integer): PControl;
42449 begin
42450 Left := fBoundsRect.Left + dX;
42451 Top := fBoundsRect.Top + dY;
42452 Result := @Self;
42453 end;
42454 {$ENDIF ASM_VERSION}
42456 //[procedure SetKeyEvent]
42457 procedure SetKeyEvent( Self_: PControl );
42458 begin
42459 Self_.fWndProcKeybd := WndProcKeybd;
42460 //Self_.AttachProc( WndProcKeyBd );
42461 end;
42463 //[procedure TControl.SetOnChar]
42464 procedure TControl.SetOnChar(const Value: TOnChar);
42465 begin
42466 fOnChar := Value;
42467 SetKeyEvent( @Self );
42468 end;
42470 //[procedure TControl.SetOnKeyDown]
42471 procedure TControl.SetOnKeyDown(const Value: TOnKey);
42472 begin
42473 fOnKeyDown := Value;
42474 SetKeyEvent( @Self );
42475 end;
42477 //[procedure TControl.SetOnKeyUp]
42478 procedure TControl.SetOnKeyUp(const Value: TOnKey);
42479 begin
42480 fOnKeyUp := Value;
42481 SetKeyEvent( @Self );
42482 end;
42484 //[FUNCTION CollectTabControls]
42485 {$IFDEF ASM_VERSION}
42486 function CollectTabControls( Form: PControl ): PList;
42488 PUSH EDI
42489 PUSH EAX
42490 CALL NewList
42491 XCHG EDI, EAX
42492 POP EAX
42493 CALL @@collecttab
42494 XCHG EAX, EDI
42495 POP EDI
42497 @@collecttab:
42498 { <- EDI = Result:PList
42499 EAX = Form (or Control)
42501 PUSH EBP
42502 XOR EBP, EBP // Result := FALSE;
42503 PUSH ESI
42504 PUSH EBX
42505 MOV EDX, [EAX].TControl.fChildren
42506 MOV ECX, [EDX].TList.fCount
42507 MOV ESI, [EDX].TList.fItems
42508 JECXZ @@e_loop
42509 @@loo: PUSH ECX
42510 LODSD
42512 PUSH EAX
42514 TEST byte ptr [EAX].TControl.fStyle+2, WS_TABSTOP shr 16
42515 JZ @@call_recur
42517 MOV DL, [EAX].TControl.fTabStop
42518 AND DL, [EAX].TControl.fEnabled
42519 JZ @@call_recur
42521 CALL TControl.GetToBeVisible
42522 TEST AL, AL
42523 POP EAX
42524 JZ @@next
42525 PUSH EAX
42527 XCHG EDX, EAX
42528 PUSH ESI
42529 MOV ECX, [EDI].TList.fCount
42530 MOV ESI, [EDI].TList.fItems
42531 XOR EBX, EBX
42532 JECXZ @@e_loo2
42533 @@loo2: LODSD
42534 MOV EAX, [EAX].TControl.fTabOrder
42535 CMP EAX, [EDX].TControl.fTabOrder
42536 JLE @@next2
42537 POP ESI
42538 MOV ECX, EDX
42539 MOV EDX, EBX
42540 MOV EAX, EDI
42541 CALL TList.Insert
42542 JMP @@call_recur
42544 @@next2: INC EBX
42545 LOOP @@loo2
42546 @@e_loo2:
42547 POP ESI
42548 MOV EAX, EDI
42549 CALL TList.Add
42551 @@call_recur:
42552 OR EBP, 1 // Result := TRUE;
42553 POP EAX
42554 MOVZX ECX, [EAX].TControl.fEnabled
42555 JECXZ @@next
42556 PUSH EAX
42557 CALL @@collecttab
42558 POP EDX
42559 JZ @@next
42561 MOV EAX, EDI
42562 CALL TList.Remove
42564 @@next: POP ECX
42565 LOOP @@loo
42567 @@e_loop:
42568 POP EBX
42569 POP ESI
42570 TEST EBP, EBP
42571 POP EBP
42572 end;
42573 {$ELSE ASM_VERSION} //Pascal
42574 function CollectTabControls( Form: PControl ): PList;
42575 var R: PList;
42576 function CollectTab( P: PControl ): Boolean;
42577 var I, J: Integer;
42578 C, D: PControl;
42579 begin
42580 Result := FALSE;
42581 for I := 0 to P.fChildren.fCount - 1 do
42582 begin
42583 C := P.fChildren.fItems[ I ];
42584 if C.fTabstop and C.fEnabled and C.ToBeVisible and
42585 (C.fStyle and WS_TABSTOP <> 0) then
42586 begin
42587 D := nil;
42588 for J := 0 to R.fCount - 1 do
42589 begin
42590 D := R.fItems[ J ];
42591 if D.fTabOrder > C.fTabOrder then
42592 begin
42593 Result := TRUE;
42594 R.Insert( J, C );
42595 break;
42597 else
42598 D := nil;
42599 end;
42600 if D = nil then
42601 begin
42602 R.Add( C );
42603 Result := TRUE;
42604 end;
42605 end;
42606 if C.fEnabled then
42607 begin
42608 if CollectTab( C ) then
42609 R.Remove( C );
42610 end;
42611 end;
42612 end;
42613 {$IFDEF DEBUG_COLLECTTABCONTROLS}
42614 var SL: PStrList;
42615 i: Integer;
42616 C: PControl;
42617 {$ENDIF}
42618 begin
42619 R := NewList;
42620 CollectTab( Form );
42621 {$IFDEF DEBUG_COLLECTTABCONTROLS}
42622 SL := NewStrList;
42623 for i := 0 to R.Count-1 do
42624 begin
42625 C := R.Items[ i ];
42626 SL.Add( Int2Str( C.fTabOrder ) + ' ' + Int2Str( C.fTag ) + ' ' + C.fCaption );
42627 end;
42628 SL.SaveToFile( GetStartDir + 'debug_collecttabcontrols.txt' );
42629 SL.Free;
42630 {$ENDIF}
42632 Result := R;
42633 end;
42634 {$ENDIF ASM_VERSION}
42635 //[END CollectTabControls]
42637 //[PROCEDURE Tabulate2Next]
42638 {$IFDEF ASM_VERSION}
42639 procedure Tabulate2Next( Form: PControl; Dir: Integer );
42641 PUSHAD
42642 PUSH EAX // save Form
42643 MOV EBX, EAX
42644 MOV EBP, EDX // EBP = Dir (direction <0 or >0)
42645 CALL CollectTabControls
42646 XCHG EDI, EAX // EDI = CL (list of controls)
42648 MOV ECX, [EBX].TControl.fCurrentControl // C := Form.fCurrentControl
42649 XOR EBX, EBX // I = 0
42650 JECXZ @@1
42651 MOV EBX, [ECX].TControl.fTabOrder // I = C.fTabOrder
42652 @@1:
42653 MOV ECX, [EDI].TList.fCount
42654 MOV ESI, [EDI].TList.fItems
42655 XOR EDX, EDX
42656 PUSH EDX // Ctrl1 = nil
42657 PUSH EDX // Ctrl2 = nil
42658 //JECXZ @@e_loop
42659 TEST ECX, ECX
42660 JZ @@e_loop
42662 @@loop: PUSH ECX
42663 LODSD
42664 CMP [EAX].TControl.fTabOrder, EBX
42665 JZ @@next
42667 MOV ECX, [ESP+8] // ECX = Ctrl1
42668 JECXZ @@c1nil
42669 MOV ECX, [ECX].TControl.fTabOrder // ECX = Ctrl1.fTabOrder
42670 TEST EBP, EBP
42671 JGE @@c1ge
42673 CMP [EAX].TControl.fTabOrder, EBX
42674 JGE @@2
42675 CMP [EAX].TControl.fTabOrder, ECX
42676 JLE @@2
42678 @@c1new:
42679 MOV [ESP+8], EAX // Ctrl1 := C
42680 JMP @@2
42682 @@c1ge: CMP [EAX].TControl.fTabOrder, EBX
42683 JLE @@2
42684 CMP [EAX].TControl.fTabOrder, ECX
42685 JL @@c1new
42686 JMP @@2
42688 @@c1nil:
42689 TEST EBP, EBP
42690 JL @@c1nil_dirL
42691 CMP [EAX].TControl.fTabOrder, EBX
42692 JG @@c1new
42693 JMP @@2
42695 @@c1nil_dirL:
42696 CMP [EAX].TControl.fTabOrder, EBX
42697 JL @@c1new
42699 @@2:
42700 MOV ECX, [ESP+4] // ECX = Ctrl2
42701 JECXZ @@c2new
42702 MOV ECX, [ECX].TControl.fTabOrder
42704 TEST EBP, EBP
42705 JL @@c2dirL
42706 CMP [EAX].TControl.fTabOrder, ECX
42707 JGE @@next
42708 JMP @@c2new
42710 @@c2dirL:
42711 CMP [EAX].TControl.fTabOrder, ECX
42712 JLE @@next
42713 @@c2new:
42714 MOV [ESP+4], EAX
42716 @@next: POP ECX
42717 DEC ECX
42718 JNZ @@loop
42719 //LOOP @@loop
42720 @@e_loop:
42722 POP EDX // Ctrl2
42723 POP ECX // Ctrl1
42724 INC ECX
42725 LOOP @@3
42726 MOV ECX, EDX
42727 @@3:
42728 POP EBX // EBX = Form
42729 JECXZ @@exit
42731 XCHG EAX, ECX
42732 CMP [EAX].TControl.fWindowed, 0
42733 JZ @@4
42734 MOV ECX, [EAX].TControl.fHandle
42735 JECXZ @@no_handle
42736 @@4:
42737 INC [EAX].TControl.fClickDisabled
42739 PUSH EAX
42740 MOV DL, 1
42741 CALL TControl.SetFocused
42742 POP EAX
42744 DEC [EAX].TControl.fClickDisabled
42746 @@no_handle:
42747 MOV [EBX].TControl.fCurrentControl, EAX
42749 @@exit:
42750 XCHG EAX, EDI
42751 CALL TObj.Free
42752 POPAD
42753 end;
42754 {$ELSE ASM_VERSION} //Pascal
42755 procedure Tabulate2Next( Form: PControl; Dir: Integer );
42756 var CL : PList;
42757 I, J : Integer;
42758 Ctrl1, Ctrl2, C : PControl;
42759 begin
42760 CL := CollectTabControls( Form );
42762 I := 0;
42763 C := Form.fCurrentControl;
42764 if C <> nil then
42765 I := C.fTabOrder;
42766 Ctrl2 := nil;
42767 Ctrl1 := nil;
42768 for J := 0 to CL.fCount - 1 do
42769 begin
42770 C := CL.fItems[ J ];
42771 if C.fTabOrder = I then continue;
42772 if (Ctrl1 = nil)
42773 and ( (Dir >= 0) and (C.fTabOrder > I)
42774 or (Dir < 0) and (C.fTabOrder < I) )
42775 or (Dir >= 0)
42776 and (C.fTabOrder > I) and (C.fTabOrder < Ctrl1.fTabOrder)
42777 or (Dir < 0)
42778 and (C.fTabOrder < I) and (C.fTabOrder > Ctrl1.fTabOrder)
42779 then Ctrl1 := C;
42780 if (Ctrl2 = nil)
42781 or (Dir >= 0) and (C.fTabOrder < Ctrl2.fTabOrder)
42782 or (Dir < 0) and (C.fTabOrder > Ctrl2.fTabOrder)
42783 then Ctrl2 := C;
42784 end;
42785 if Ctrl1 = nil then
42786 Ctrl1 := Ctrl2;
42787 if Ctrl1 <> nil then
42788 begin
42789 if (Ctrl1.fHandle <> 0) or not Ctrl1.fWindowed then
42790 begin
42791 Inc( Ctrl1.fClickDisabled );
42792 Ctrl1.Focused := TRUE;
42793 Dec( Ctrl1.fClickDisabled );
42794 end;
42795 Form.fCurrentControl := Ctrl1;
42796 end;
42797 CL.Free;
42798 end;
42799 {$ENDIF ASM_VERSION}
42800 //[END Tabulate2Next]
42802 //[FUNCTION Tabulate2Control]
42803 {$IFDEF ASM_VERSION}
42804 function Tabulate2Control( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
42805 const tk_Tab = 1;
42806 tk_LR = 2;
42807 tk_UD = 4;
42808 tk_PuPd= 8;
42810 PUSH ESI
42811 MOV ESI, offset[@@data]
42812 PUSH EAX
42813 MOV AH, 9
42814 @@loop:
42815 LODSB
42816 CMP DL, AL
42817 JE @@1
42818 LODSB
42819 CMP DL, AL
42820 JE @@2
42821 ADD AH, AH
42822 JNB @@loop
42823 POP EAX
42824 @@exit0:
42825 XOR EAX, EAX
42826 JMP @@exit
42828 @@data:
42829 DB -1, VK_TAB, VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, VK_PRIOR, VK_NEXT
42831 @@1:
42832 OR EDX, -1
42833 JMP @@3
42834 @@2:
42835 XOR EDX, EDX
42836 TEST AH, 1
42837 JZ @@3
42839 PUSH ECX
42840 PUSH EAX
42841 PUSH VK_SHIFT
42842 CALL GetAsyncKeyState
42844 POP EAX
42845 POP ECX
42846 @@3:
42847 POP ESI
42848 //////////////////////////////////////////////////
42849 MOV AL, AH
42850 {$IFDEF PARANOIA}
42851 DB $24, 1
42852 {$ELSE}
42853 AND AL, 1
42854 {$ENDIF}
42855 TEST byte ptr [ESI].TControl.fLookTabKeys, AL
42856 //////////////////////////////////////////////////
42857 JZ @@exit0
42859 TEST CL, CL
42860 JNZ @@exit
42862 PUSH EDX
42863 MOV EAX, ESI
42864 CALL TControl.ParentForm
42865 POP EDX
42866 CALL Tabulate2Next
42867 @@exit:
42868 POP ESI
42869 end;
42870 {$ELSE ASM_VERSION} //Pascal
42871 function Tabulate2Control( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
42872 var Form: PControl;
42873 begin
42874 Result := False;
42875 case Key of
42876 VK_TAB: if not (tkTab in Self_.fLookTabKeys) then exit;
42877 VK_LEFT, VK_RIGHT: if not (tkLeftRight in Self_.fLookTabKeys) then exit;
42878 VK_UP, VK_DOWN: if not (tkUpDown in Self_.fLookTabKeys) then exit;
42879 VK_NEXT, VK_PRIOR: if not (tkPageUpPageDn in Self_.fLookTabKeys) then exit;
42880 else Exit;
42881 end;
42883 Result := True;
42884 if checkOnly then Exit;
42886 Form := Self_.ParentForm;
42887 case Key of
42888 VK_TAB:
42889 if GetKeyState( VK_SHIFT ) < 0 then
42890 Tabulate2Next( Form, -1 )
42891 else
42892 Tabulate2Next( Form, 1 );
42893 VK_RIGHT, VK_DOWN, VK_NEXT: Tabulate2Next( Form, 1 );
42894 VK_LEFT, VK_UP, VK_PRIOR: Tabulate2Next( Form, -1 );
42895 end;
42896 end;
42897 {$ENDIF ASM_VERSION}
42898 //[END Tabulate2Control]
42900 //[FUNCTION Tabulate2ControlEx]
42901 {$IFDEF ASM_VERSION}
42902 function Tabulate2ControlEx( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
42904 PUSH EDI
42905 MOVZX EDI, CL
42906 TEST byte ptr [EAX].TControl.fLookTabKeys, 1
42907 JZ @@1
42908 @@0:
42909 MOV ECX, EDX
42910 AND CL, 7Fh
42911 CMP CL, VK_TAB
42912 JNE @@1
42914 PUSH EDX
42915 CALL TControl.ParentForm
42916 POP EDX
42917 MOVSX EDX, DL
42918 TEST EDX, EDX
42919 JS @@tab
42921 PUSH EAX
42923 PUSH VK_SHIFT
42924 CALL GetAsyncKeyState
42925 SAR EAX, 31
42926 {$IFDEF PARANOIA}
42927 DB $0C, $01
42928 {$ELSE}
42929 OR AL, 1
42930 {$ENDIF}
42931 MOV EDX, EAX
42933 POP EAX
42934 @@tab:
42935 TEST EDI, EDI
42936 POP EDI
42937 JNZ @@no_tab
42938 CALL Tabulate2Next
42939 @@no_tab:
42940 MOV AL, 1
42943 @@data: DB VK_LEFT, VK_LEFT
42944 DD offset[@@left]
42945 DB VK_UP, 2
42946 DB VK_RIGHT, VK_RIGHT
42947 DD offset[@@right]
42948 DB VK_DOWN, 2
42949 DB VK_UP, VK_PRIOR
42950 DD offset[@@up]
42951 DB VK_TAB or 80h, $C
42952 DB VK_DOWN, VK_NEXT
42953 DD offset[@@down]
42954 DB VK_TAB, $C
42956 @@1:
42958 EAX <- Self_:PControl
42959 DL <- Key
42961 PUSH ESI
42962 MOV ESI, offset[@@data]-6
42963 MOV DH, 9
42964 PUSH EAX
42965 @@loop:
42966 ADD DH, DH
42967 JNB @@l1
42968 JMP @@abort
42969 @@fault1:
42970 POP EDI
42971 POPAD
42972 PUSH EAX
42973 @@abort:
42974 POP EAX
42975 @@abort1:
42976 POP ESI
42977 POP EDI
42978 XOR EAX, EAX
42981 @@right:
42982 MOV EAX, [ESP].TRect.Left
42983 SUB EAX, [ESP+16].TRect.Left
42984 @@left_right:
42985 JL @@next1
42986 MOV EDX, [ESP].TRect.Bottom
42987 SUB EDX, [ESP+16].TRect.Top
42988 JL @@next1
42989 MOV EDX, [ESP].TRect.Top
42990 SUB EDX, [ESP+16].TRect.Bottom
42991 JGE @@next1
42992 @@chk_dist:
42993 CMP EAX, EDI
42994 JA @@next1
42995 MOV EDI, EAX
42996 MOV EAX, [EBX+ECX*4-4]
42997 MOV [ESP+36], EAX // Found = Ctrl
42998 JMP @@next1
43000 @@l1:
43001 LODSD
43002 LODSW
43003 LODSW
43004 CMP AL, DL
43005 JE @@2
43006 CMP AH, DL
43007 JNE @@loop
43009 @@2:
43010 PUSH ESI
43011 LODSD
43012 LODSW
43013 POP ESI
43014 XCHG EDX, EAX
43015 POP EAX
43016 TEST [EAX].TControl.fLookTabKeys, DH
43017 JZ @@abort1
43019 PUSHAD
43020 PUSH EDI
43021 CALL TControl.ParentForm
43022 MOV ECX, [EAX].TControl.fCurrentControl
43023 JECXZ @@fault1
43024 MOV EBP, ECX // EBP = CurCtrl
43026 PUSH EAX // save Form
43027 MOV EBX, EAX
43028 CALL CollectTabControls
43029 PUSH 0 // save Found = nil
43030 PUSH EAX // save CollectedList
43031 MOV EDI, EAX
43033 MOV EBX, [EDI].TList.fItems
43034 ADD ESP, -16
43035 PUSH ESP
43036 PUSH [EBP].TControl.fHandle
43037 CALL GetWindowRect
43039 MOV ECX, [EDI].TList.fCount
43040 OR EDI, -1 // EDI = minDist
43041 @@loop1:
43042 MOV EAX, [EBX+ECX*4-4]
43043 CMP EAX, EBP
43044 JE @@next
43046 MOV DL, [EAX].TControl.fEnabled
43047 AND DL, [EAX].TControl.fTabstop
43048 JZ @@next
43050 ADD ESP, -16
43051 MOV EDX, ESP
43052 PUSH ECX
43054 //CALL TControl.ControlRect
43055 PUSH EDX
43056 PUSH [EAX].TControl.fHandle
43057 CALL GetWindowRect
43059 POP ECX
43060 JMP dword ptr [ESI]
43062 @@left:
43063 MOV EAX, [ESP+16].TRect.Left
43064 SUB EAX, [ESP].TRect.Left
43065 JMP @@left_right
43067 @@not_found:
43068 POP EDI
43069 POPAD
43070 MOV DL, [ESI+4]
43071 POP ESI
43072 JMP @@0
43074 @@up:
43075 MOV EAX, [ESP+16].TRect.Top
43076 SUB EAX, [ESP].TRect.Top
43077 JMP @@up_down
43078 @@down:
43079 MOV EAX, [ESP].TRect.Top
43080 SUB EAX, [ESP+16].TRect.Top
43081 @@up_down:
43082 JL @@next1
43083 MOV EDX, [ESP].TRect.Right
43084 SUB EDX, [ESP+16].TRect.Left
43085 JL @@next1
43086 MOV EDX, [ESP].TRect.Left
43087 SUB EDX, [ESP+16].TRect.Right
43088 JL @@chk_dist
43090 @@next1:
43091 ADD ESP, 16
43092 @@next:
43093 LOOP @@loop1
43094 ADD ESP, 16
43095 POP EAX // pop CollectedList
43096 CALL TObj.Free
43097 POP ECX // pop Found
43098 POP EAX // pop Form
43099 JECXZ @@not_found
43101 POP EDI
43102 TEST EDI, EDI
43103 JNZ @@no_go
43105 MOV [EAX].TControl.fCurrentControl, ECX
43106 INC [ECX].TControl.fClickDisabled
43107 PUSH ECX
43108 MOV ECX, [ECX].TControl.fHandle
43109 JECXZ @@4
43110 PUSH ECX
43111 CALL Windows.SetFocus
43112 @@4: POP ECX
43113 DEC [ECX].TControl.fClickDisabled
43114 @@no_go:
43115 POPAD
43116 POP ESI
43117 POP EDI
43118 MOV AL, 1 // Result = True
43119 end;
43120 {$ELSE ASM_VERSION} //Pascal
43121 function Tabulate2ControlEx( Self_: PControl; Key: DWORD; checkOnly: Boolean ): Boolean;
43122 label search_tabcontrol;
43123 var Form: PControl;
43124 CL : PList;
43125 I : Integer;
43126 CurCtrl, Ctrl, Found : PControl;
43127 MinDist, Dist: Integer;
43128 R, R1 : TRect;
43129 begin
43130 Result := False;
43131 case Key of
43132 VK_TAB: if not (tkTab in Self_.fLookTabKeys) then exit;
43133 VK_LEFT, VK_RIGHT: if not (tkLeftRight in Self_.fLookTabKeys) then exit;
43134 VK_UP, VK_DOWN: if not (tkUpDown in Self_.fLookTabKeys) then exit;
43135 VK_NEXT, VK_PRIOR: if not (tkPageUpPageDn in Self_.fLookTabKeys) then exit;
43136 else exit;
43137 end;
43139 Result := True;
43140 if checkOnly then Exit;
43142 Form := Self_.ParentForm;
43143 if Key = VK_TAB then
43144 if GetKeyState( VK_SHIFT ) < 0 then
43145 Tabulate2Next( Form, -1 )
43146 else
43147 Tabulate2Next( Form, 1 )
43148 else
43149 begin
43150 CL := CollectTabControls( Form );
43151 I := CL.IndexOf( Form.fCurrentControl );
43152 Found := nil;
43153 if I >= 0 then
43154 begin
43155 CurCtrl := CL.fItems[ I ];
43156 //R := CurCtrl.ControlRect;
43157 GetWindowRect( CurCtrl.Handle, R );
43158 search_tabcontrol:
43159 MinDist := MaxInt;
43160 for I := CL.fCount - 1 downto 0 do
43161 begin
43162 Ctrl := CL.fItems[ I ];
43163 if Ctrl = CurCtrl then continue;
43164 if not (Ctrl.fEnabled and Ctrl.fTabstop) then continue;
43165 //R1 := Ctrl.ControlRect;
43166 GetWindowRect( Ctrl.Handle, R1 );
43167 Dist := MaxInt;
43168 case Key of
43169 VK_LEFT:
43170 begin
43171 if (R1.Bottom < R.Top)
43172 or (R1.Top >= R.Bottom)
43173 or (R1.Left > R.Left) then continue;
43174 Dist := R.Left - R1.Left;
43175 end;
43176 VK_RIGHT:
43177 begin
43178 if (R1.Bottom < R.Top)
43179 or (R1.Top >= R.Bottom)
43180 or (R1.Left < R.Left) then continue;
43181 Dist := R1.Left - R.Left;
43182 end;
43183 VK_UP, VK_PRIOR:
43184 begin
43185 if (R1.Right < R.Left)
43186 or (R1.Left >= R.Right)
43187 or (R1.Top > R.Top) then continue;
43188 Dist := R.Top - R1.Top;
43189 end;
43190 VK_DOWN, VK_NEXT:
43191 begin
43192 if (R1.Right < R.Left)
43193 or (R1.Left >= R.Right)
43194 or (R1.Top < R.Bottom) then continue;
43195 Dist := R1.Top - R.Top;
43196 end;
43197 end;
43198 if Dist < MinDist then
43199 begin
43200 Found := Ctrl;
43201 MinDist := Dist;
43202 end;
43203 end;
43204 if Found = nil then
43205 begin
43206 case Key of
43207 VK_LEFT:
43208 begin
43209 Key := VK_UP; goto search_tabcontrol;
43210 end;
43211 VK_RIGHT:
43212 begin
43213 Key := VK_DOWN; goto search_tabcontrol;
43214 end;
43215 VK_UP, VK_PRIOR:
43216 Tabulate2Next( Form, -1 );
43217 VK_DOWN, VK_NEXT:
43218 Tabulate2Next( Form, 1 );
43219 end;
43221 else
43222 begin
43223 if Found.fHandle <> 0 then
43224 begin
43225 Inc( Found.fClickDisabled );
43226 SetFocus( Found.fHandle );
43227 Dec( Found.fClickDisabled );
43228 end;
43229 Form.fCurrentControl := Found;
43230 end;
43231 end;
43232 CL.Free;
43233 end;
43234 end;
43235 {$ENDIF ASM_VERSION}
43236 //[END Tabulate2ControlEx]
43238 {$IFDEF ASM_VERSION}
43239 //[function TControl.Tabulate]
43240 function TControl.Tabulate: PControl;
43242 PUSH EAX
43243 CALL ParentForm
43244 TEST EAX, EAX
43245 JZ @@exit
43246 MOV [EAX].fGotoControl, offset[Tabulate2Control]
43247 @@exit: POP EAX
43248 end;
43249 {$ELSE ASM_VERSION} //Pascal
43250 function TControl.Tabulate: PControl;
43251 var F : PControl;
43252 begin
43253 Result := @Self;
43254 F := ParentForm;
43255 if F = nil then Exit;
43256 F.fGotoControl := Tabulate2Control;
43257 end;
43258 {$ENDIF ASM_VERSION}
43260 {$IFDEF ASM_VERSION}
43261 //[function TControl.TabulateEx]
43262 function TControl.TabulateEx: PControl;
43264 PUSH EAX
43265 CALL ParentForm
43266 TEST EAX, EAX
43267 JZ @@exit
43268 MOV [EAX].fGotoControl, offset[Tabulate2ControlEx]
43269 @@exit: POP EAX
43270 end;
43271 {$ELSE ASM_VERSION} //Pascal
43272 function TControl.TabulateEx: PControl;
43273 var F : PControl;
43274 begin
43275 Result := @Self;
43276 F := ParentForm;
43277 if F = nil then Exit;
43278 F.fGotoControl := Tabulate2ControlEx;
43279 end;
43280 {$ENDIF ASM_VERSION}
43283 //[procedure TControl.GotoControl]
43284 procedure TControl.GotoControl(Key: DWORD);
43285 var Form: PControl;
43286 begin
43287 Form := ParentForm;
43288 if Form <> nil then
43289 if assigned( Form.fGotoControl ) then
43290 Form.fGotoControl( Form.fCurrentControl, Key, false );
43291 end;
43293 {$IFDEF ASM_VERSION}
43294 //[function TControl.GetCurIndex]
43295 function TControl.GetCurIndex: Integer;
43297 PUSH EBX
43298 XCHG EBX, EAX
43299 MOV EAX, [EBX].fCurIndex
43300 MOVZX ECX, [EBX].fCommandActions.aGetCurrent
43301 JECXZ @@exit
43302 XOR EAX, EAX
43304 CMP CX, LVM_GETNEXTITEM
43305 JNE @@0
43306 INC EAX
43307 INC EAX
43308 JMP @@1
43309 @@0:
43310 CMP CL, EM_LINEINDEX and $FF
43311 JNZ @@2
43312 @@1:
43313 DEC EDX
43314 @@2:
43315 PUSH EAX
43316 PUSH EDX
43317 PUSH ECX
43318 PUSH EBX
43319 CALL Perform
43321 @@exit: POP EBX
43322 end;
43323 {$ELSE ASM_VERSION} //Pascal
43324 function TControl.GetCurIndex: Integer;
43325 var I, J: Integer;
43326 begin
43327 Result := fCurIndex;
43328 if fCommandActions.aGetCurrent = 0 then
43329 Exit;
43330 I := 0;
43331 if fCommandActions.aGetCurrent = EM_LINEINDEX then
43332 Dec( I );
43333 J := 0;
43334 if fCommandActions.aGetCurrent = LVM_GETNEXTITEM then
43335 begin
43336 J := 2 {LVNI_SELECTED};
43337 Dec( I );
43338 end;
43339 Result := Perform( fCommandActions.aGetCurrent, I, J );
43340 end;
43341 {$ENDIF ASM_VERSION}
43343 {$IFDEF ASM_VERSION}
43344 //[procedure TControl.SetCurIndex]
43345 procedure TControl.SetCurIndex(const Value: Integer);
43347 MOVZX ECX, [EAX].fCommandActions.aSetCurrent
43348 JECXZ @@set_item_sel
43349 PUSHAD
43350 PUSH 0
43351 PUSH EDX
43352 PUSH ECX
43353 PUSH EAX
43354 CALL Perform
43355 POPAD
43356 CMP CX, TCM_SETCURSEL
43357 JNE @@exit
43358 PUSH TCN_SELCHANGE
43359 PUSH EAX // idfrom doesn't matter
43360 PUSH [EAX].fHandle
43361 PUSH ESP
43362 PUSH 0
43363 PUSH WM_NOTIFY
43364 PUSH EAX
43365 CALL Perform
43366 POP ECX
43367 POP ECX
43368 POP ECX
43369 @@exit:
43371 @@set_item_sel:
43372 INC ECX
43373 CALL SetItemSelected
43374 end;
43375 {$ELSE ASM_VERSION} //Pascal
43376 procedure TControl.SetCurIndex(const Value: Integer);
43377 var NMHdr: TNMHdr;
43378 begin
43379 if fCommandActions.aSetCurrent <> 0 then
43380 begin
43381 Perform( fCommandActions.aSetCurrent, Value, 0 );
43382 if fCommandActions.aSetCurrent = TCM_SETCURSEL then
43383 begin
43384 NMHdr.code := TCN_SELCHANGE;
43385 NMHdr.hwndFrom := fHandle;
43386 Perform( WM_NOTIFY, 0, Integer( @NMHdr ) );
43387 end;
43389 else
43390 ItemSelected[ Value ] := True;
43391 end;
43392 {$ENDIF ASM_VERSION}
43394 {$IFDEF ASM_VERSION}
43395 //[function TControl.GetTextAlign]
43396 function TControl.GetTextAlign: TTextAlign;
43398 PUSH EAX
43399 CALL UpdateWndStyles
43400 MOV ECX, [EAX].fStyle
43401 MOV EDX, dword ptr [EAX].fCommandActions.aTextAlignRight
43402 XOR EAX, EAX
43403 AND DX, CX
43404 JNZ @@ret_1
43405 SHR EDX, 16
43406 AND ECX, EDX
43407 JNZ @@ret_2
43408 POP EAX
43409 MOVZX EAX, [EAX].fTextAlign
43412 @@ret_2:INC EAX
43413 @@ret_1:INC EAX
43414 @@ret_0:POP ECX
43415 end;
43416 {$ELSE ASM_VERSION} //Pascal
43417 function TControl.GetTextAlign: TTextAlign;
43418 begin
43419 UpdateWndStyles;
43420 if (fStyle and fCommandActions.aTextAlignRight) = fCommandActions.aTextAlignRight then
43421 Result := taRight
43422 else
43423 if (fStyle and fCommandActions.aTextAlignCenter) = fCommandActions.aTextAlignCenter then
43424 Result := taCenter
43425 else
43426 Result := fTextAlign;
43427 end;
43428 {$ENDIF ASM_VERSION}
43430 {$IFDEF ASM_VERSION}
43431 //[function TControl.GetVerticalAlign]
43432 function TControl.GetVerticalAlign: TVerticalAlign;
43434 PUSH EAX
43435 CALL UpdateWndStyles
43436 MOV EDX, dword ptr [EAX].fCommandActions.aVertAlignCenter
43437 MOV ECX, [EAX].fStyle
43438 XOR EAX, EAX
43439 MOV DH, DL
43440 AND DL, CH
43441 JZ @@1
43442 CMP DL, DH
43443 JE @@ret_0
43444 @@1: SHR EDX, 16
43445 MOV DH, DL
43446 AND DL, CH
43447 JZ @@2
43448 CMP DL, DH
43449 JE @@ret_2
43450 @@2: POP EAX
43451 MOVZX EAX, [EAX].fVerticalAlign
43453 @@ret_2:INC EAX
43454 @@ret_1:INC EAX
43455 @@ret_0:POP ECX
43456 end;
43457 {$ELSE ASM_VERSION} //Pascal
43458 function TControl.GetVerticalAlign: TVerticalAlign;
43459 begin
43460 UpdateWndStyles;
43461 if (fStyle and (fCommandActions.aVertAlignCenter shl 8)) = (fCommandActions.aVertAlignCenter shl 8) then
43462 Result := vaCenter
43463 else
43464 if (fStyle and (fCommandActions.aVertAlignBottom shl 8)) = (fCommandActions.aVertAlignBottom shl 8) then
43465 Result := vaBottom
43466 else
43467 Result := fVerticalAlign;
43468 end;
43469 {$ENDIF ASM_VERSION}
43471 {$IFDEF ASM_VERSION}
43472 //[procedure TControl.SetTextAlign]
43473 procedure TControl.SetTextAlign(const Value: TTextAlign);
43475 MOV [EAX].fTextAlign, DL
43476 XOR ECX, ECX
43477 MOV CX, [EAX].fCommandActions.aTextAlignLeft
43478 OR CX, [EAX].fCommandActions.aTextAlignCenter
43479 OR CX, [EAX].fCommandActions.aTextAlignRight
43480 NOT ECX
43481 AND ECX, [EAX].fStyle
43483 AND EDX, 3
43484 OR CX, [EAX + EDX * 2].fCommandActions.aTextAlignLeft
43486 MOV DL, [EAX].fCommandActions.aTextAlignMask
43487 NOT EDX
43488 AND EDX, ECX
43489 CALL SetStyle
43490 end;
43491 {$ELSE ASM_VERSION} //Pascal
43492 procedure TControl.SetTextAlign(const Value: TTextAlign);
43493 var NewStyle: DWORD;
43494 begin
43495 fTextAlign := Value;
43496 NewStyle := 0;
43497 with fCommandActions do
43498 case Value of
43499 taLeft: NewStyle := fStyle and not DWORD(aTextAlignCenter or aTextAlignRight)
43500 or aTextAlignLeft;
43501 taRight: NewStyle := fStyle and not DWORD(aTextAlignLeft or aTextAlignCenter)
43502 or aTextAlignRight;
43503 taCenter: NewStyle := fStyle and not DWORD(aTextAlignLeft or aTextAlignRight)
43504 or aTextAlignCenter;
43505 end;
43506 NewStyle := NewStyle and not DWORD(fCommandActions.aTextAlignMask);
43507 Style := NewStyle;
43508 end;
43509 {$ENDIF ASM_VERSION}
43511 {$IFDEF ASM_noVERSION}
43512 //[procedure TControl.SetVerticalAlign]
43513 procedure TControl.SetVerticalAlign(const Value: TVerticalAlign);
43515 MOV [EAX].fVerticalAlign, DL
43516 XOR ECX, ECX
43517 MOV CX, word ptr [EAX].fCommandActions.aVertAlignTop
43518 OR CH, CL
43519 MOV CL, 0
43520 NOT ECX
43521 AND ECX, [EAX].fStyle
43522 AND EDX, 3
43523 MOV DH, [EAX + EDX].fCommandActions.aVertAlignCenter
43524 MOV DL, 0
43525 OR EDX, ECX
43526 CALL SetStyle
43527 end;
43528 {$ELSE ASM_VERSION} //Pascal
43529 procedure TControl.SetVerticalAlign(const Value: TVerticalAlign);
43530 var NewStyle: DWORD;
43531 begin
43532 fVerticalAlign := Value;
43533 with fCommandActions do
43534 begin
43535 NewStyle := fStyle and not DWORD((aVertAlignTop or aVertAlignCenter or aVertAlignBottom) shl 8);
43536 case Value of
43537 vaCenter: NewStyle := NewStyle or (aVertAlignCenter shl 8);
43538 vaTop: NewStyle := NewStyle or (aVertAlignTop shl 8);
43539 vaBottom: NewStyle := NewStyle or (aVertAlignBottom shl 8);
43540 end;
43541 end;
43542 Style := NewStyle;
43543 end;
43544 {$ENDIF ASM_VERSION}
43546 {$IFDEF ASM_noVERSION}
43547 //[function TControl.Dc2Canvas]
43548 function TControl.Dc2Canvas( Sender: PCanvas ): HDC;
43550 MOV ECX, [EAX].fPaintDC
43551 JECXZ @@chk_fHandle
43552 PUSH ECX
43553 XCHG EAX, EDX // EAX <= Sender
43554 MOV EDX, ECX // EDX <= fPaintDC
43555 PUSH EAX
43556 CALL TCanvas.SetHandle
43557 POP EAX
43558 MOV [EAX].TCanvas.fIsPaintDC, 1
43559 POP ECX
43560 @@ret_ECX:
43561 XCHG EAX, ECX
43563 @@chk_fHandle:
43564 MOV ECX, [EDX].TCanvas.fHandle
43565 INC ECX
43566 LOOP @@ret_ECX
43567 CALL GetWindowHandle
43568 PUSH EAX
43569 CALL GetDC
43570 end;
43571 {$ELSE ASM_VERSION} //Pascal
43572 function TControl.Dc2Canvas( Sender: PCanvas ): HDC;
43573 begin
43574 if fPaintDC <> 0 then
43575 begin
43576 Result := fPaintDC;
43577 Sender.SetHandle( Result );
43578 Sender.fIsPaintDC := True;
43580 else
43581 begin
43582 if Sender.fHandle <> 0 then
43583 Result := Sender.fHandle
43584 else
43585 Result := GetDC( GetWindowHandle );
43586 end;
43587 end;
43588 {$ENDIF ASM_VERSION}
43590 {$IFDEF ASM_VERSION}
43591 //[function TControl.GetCanvas]
43592 function TControl.GetCanvas: PCanvas;
43594 PUSH EBX
43595 PUSH ESI
43596 XCHG EBX, EAX
43598 MOV ESI, [EBX].fCanvas
43599 TEST ESI, ESI
43600 JNZ @@exit
43602 XOR EAX, EAX
43603 CALL NewCanvas
43604 MOV [EBX].fCanvas, EAX
43605 MOV [EAX].TCanvas.fOwnerControl, EBX
43606 MOV [EAX].TCanvas.fOnGetHandle.TMethod.Code, offset[ DC2Canvas ]
43607 MOV [EAX].TCanvas.fOnGetHandle.TMethod.Data, EBX
43608 XCHG ESI, EAX
43610 MOV ECX, [EBX].fFont
43611 JECXZ @@exit
43613 MOV EAX, [ESI].TCanvas.fFont
43614 MOV EDX, ECX
43615 CALL TGraphicTool.Assign
43616 MOV [ESI].TCanvas.fFont, EAX
43618 MOV ECX, [EBX].fBrush
43619 JECXZ @@exit
43621 MOV EAX, [ESI].TCanvas.fBrush
43622 MOV EDX, ECX
43623 CALL TGraphicTool.Assign
43624 MOV [ESI].TCanvas.fBrush, EAX
43626 @@exit: XCHG EAX, ESI
43627 POP ESI
43628 POP EBX
43629 end;
43630 {$ELSE ASM_VERSION} //Pascal
43631 function TControl.GetCanvas: PCanvas;
43632 begin
43633 if not assigned( fCanvas ) then
43634 begin
43635 fCanvas := NewCanvas( 0 );
43636 fCanvas.OnGetHandle := Dc2Canvas;
43637 fCanvas.fOwnerControl := @Self;
43638 if assigned( fFont ) then
43639 fCanvas.fFont := fCanvas.fFont.Assign( fFont );
43640 if assigned( fBrush ) then
43641 fCanvas.fBrush := fCanvas.fBrush.Assign( fBrush );
43642 end;
43643 Result := fCanvas;
43644 end;
43645 {$ENDIF ASM_VERSION}
43647 //[function TControl.DblBufTopParent]
43648 function TControl.DblBufTopParent: PControl;
43649 var Ctl: PControl;
43650 begin
43651 Result := nil;
43652 Ctl := @ Self;
43653 while Ctl <> nil do
43654 begin
43655 if Ctl.fDoubleBuffered then
43656 Result := Ctl;
43657 Ctl := Ctl.fParent;
43658 end;
43659 end;
43661 //[procedure InvalidateDblBufParent]
43662 procedure InvalidateDblBufParent( Sender: PControl );
43663 var C: PControl;
43664 begin
43665 C := Sender.DblBufTopParent;
43666 if C <> nil then
43667 InvalidateRect( C.fHandle, nil, TRUE );
43668 end;
43670 //[function WndFuncPreventDraw]
43671 function WndFuncPreventDraw( W: HWnd; Msg: Cardinal; wParam, lParam: Integer ): Integer; stdcall;
43672 var C: PControl;
43673 PrntW: HWnd;
43674 //********************************************************** Added By M.Gerasimov
43676 PrevProc:Pointer;
43678 //********************************************************** Added By M.Gerasimov
43679 begin
43680 //if not AppletTerminated then
43681 case Msg of
43682 WM_NCPAINT,
43683 //WM_PAINT,
43684 WM_ERASEBKGND:
43685 begin
43686 C := Pointer( GetProp( W, ID_SELF ) );
43687 if C = nil then
43688 begin
43689 PrntW := GetParent( W );
43690 if PrntW <> 0 then
43691 begin
43692 C := Pointer( GetProp( PrntW, ID_SELF ) );
43693 if (C <> nil) and not C.fCannotDoubleBuf and
43694 (C.DblBufTopParent <> nil) and
43695 (not C.DblBufTopParent.fDblBufPainting) then
43696 begin
43697 case Msg of
43698 WM_NCPAINT: Result := 0;
43699 WM_PAINT: Result := 0;
43700 else Result := 1;
43701 end;
43702 Exit;
43703 end;
43704 end;
43705 end;
43706 end;
43707 end;
43708 //********************************************************** By M.Gerasimov
43710 PrevProc:=Pointer(GetProp( W, ID_PREVPROC ));
43711 if PrevProc <> Nil then
43712 Result := CallWindowProc( PrevProc , W, Msg, wParam, lParam )
43713 else
43714 Result:=0;
43716 //********************************************************** Remarked By M.Gerasimov
43717 //Result := CallWindowProc( Pointer( GetProp( W, 'PREV_PROC' ) ),
43718 // W, Msg, wParam, lParam );
43719 //******************************************************************************
43720 end;
43722 //[procedure DblBufCreateWndProc]
43723 procedure DblBufCreateWndProc( Sender: PControl );
43724 var Chld: HWnd;
43725 PrevProc: DWORD;
43726 begin
43727 Chld := GetWindow( Sender.fHandle, GW_CHILD );
43728 while Chld <> 0 do
43729 begin
43730 //********************************************************** Changed By M.Gerasimov
43731 // if GetProp( Chld, 'PREV_PROC' ) = 0 then
43732 //**********************************************************
43733 if GetProp( Chld, ID_PREVPROC ) = 0 then //
43734 //**********************************************************
43735 begin
43736 PrevProc :=
43737 SetWindowLong( Chld, GWL_WNDPROC, Longint( @WndFuncPreventDraw ) );
43738 //********************************************************** Changed By M.Gerasimov
43739 // SetProp( Chld, 'PREV_PROC', PrevProc );
43740 //**********************************************************
43741 SetProp( Chld, ID_PREVPROC, PrevProc ); //
43742 //**********************************************************
43743 end;
43744 Chld := GetWindow( Chld, GW_HWNDNEXT );
43745 end;
43746 end;
43748 //[procedure TControl.SetDoubleBuffered]
43749 procedure TControl.SetDoubleBuffered(const Value: Boolean);
43750 begin
43751 if CannotDoubleBuf then Exit;
43752 fDoubleBuffered := Value;
43753 Global_OnBufferedDraw := WndProcBufferedDraw;
43754 Global_Invalidate := @ InvalidateDblBufParent;
43755 Global_DblBufCreateWnd := @ DblBufCreateWndProc;
43756 end;
43758 {$IFDEF ASM_VERSION}
43759 //[procedure TControl.SetTransparent]
43760 procedure TControl.SetTransparent(const Value: Boolean);
43762 CMP [EAX].fTransparent, DL
43763 JZ @@exit
43764 MOV [EAX].fTransparent, DL
43765 TEST DL, DL
43766 JZ @@exit
43767 MOV ECX, [EAX].fParent
43768 JECXZ @@exit
43769 XCHG EAX, ECX
43770 CALL SetDoubleBuffered
43771 @@exit:
43772 end;
43773 {$ELSE ASM_VERSION} //Pascal
43774 procedure TControl.SetTransparent(const Value: Boolean);
43775 begin
43776 if fTransparent = Value then Exit;
43777 fTransparent := Value;
43778 //ExStyle := ExStyle or WS_EX_TRANSPARENT;
43779 if fParent = nil then Exit;
43780 if Value then
43781 fParent.DoubleBuffered := True;
43782 end;
43783 {$ENDIF ASM_VERSION}
43785 //[function TControl.SetBorder]
43786 function TControl.SetBorder( Value: Integer ): PControl;
43787 begin
43788 fMargin := Value;
43789 Result := @ Self;
43790 end;
43792 { TTrayIcon }
43794 var FTrayItems: PList;
43796 //[FUNCTION WndProcTray]
43797 {$IFDEF ASM_noVERSION}
43798 function WndProcTray( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
43800 PUSH ECX
43801 MOV ECX, [EDX].TMsg.message
43802 CMP CX, CM_TRAYICON
43803 JNE @@1
43805 MOV ECX, [EDX].TMsg.lParam
43806 MOV EDX, [EDX].TMsg.wParam
43807 MOV EAX, [EDX].TTrayIcon.fOnMouse.TMethod.Data
43808 CMP word ptr [EDX].TTrayIcon.fOnMouse.TMethod.Code+2, 0
43809 JE @@no_on
43811 CALL [EDX].TTrayIcon.fOnMouse.TMethod.Code
43812 @@no_on:
43813 POP ECX
43814 XOR EAX, EAX
43815 MOV [ECX], EAX
43816 INC EAX
43819 @@1:
43820 SUB ECX, WM_CLOSE
43821 JNE @@exit_0
43822 @@2:
43824 POP ECX
43825 PUSH EBX
43826 XCHG EBX, EAX
43828 MOV EAX, [EBX].TControl.fHandle
43829 CMP EAX, [EDX].TMsg.hwnd
43830 JNE @@otherwin
43832 MOV EDX, [FTrayItems]
43833 MOV ECX, [EDX].TList.fCount
43834 MOV EDX, [EDX].TList.fItems
43835 @@loop:
43836 MOV EAX, [EDX + ECX*4 - 4]
43837 CMP [EAX].TTray.FNoAutoDeactivate, 0
43838 JNZ @@3
43839 CMP [EAX].TTrayIcon.fControl, EBX
43840 JNE @@3
43841 PUSHAD
43842 XOR EDX, EDX
43843 CALL TTrayIcon.SetActive
43844 POPAD
43845 @@3: LOOP @@loop
43847 @@otherwin:
43848 POP EBX
43849 PUSH ECX
43851 @@exit_0:
43852 XOR EAX, EAX
43853 POP ECX
43854 end;
43855 {$ELSE ASM_VERSION} //Pascal
43856 function WndProcTray( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
43857 var Self_: PTrayIcon;
43858 I : Integer;
43859 begin
43860 Result := False;
43861 case Msg.message of
43862 CM_TRAYICON:
43863 begin
43864 Self_ := Pointer( Msg.wParam );
43865 if Assigned( Self_.FOnMouse ) then
43866 Self_.FOnMouse( @Self_, Msg.lParam );
43867 Rslt := 0;
43868 Result := True;
43869 end;
43870 WM_CLOSE:
43871 if Msg.hwnd = Control.fHandle then
43872 begin
43873 if FTrayItems <> nil then // ?????????????????
43874 for I := FTrayItems.Count - 1 downto 0 do
43875 begin
43876 Self_ := FTrayItems.Items[ I ];
43877 if not Self_.FNoAutoDeactivate then
43878 if Self_.FControl = Control then
43879 Self_.Active := False;
43880 end;
43881 end;
43882 end;
43883 end;
43884 {$ENDIF ASM_VERSION}
43885 //[END WndProcTray]
43887 //[FUNCTION _NewTrayIcon]
43888 {$IFDEF ASM_VERSION}
43889 function _NewTrayIcon: PTrayIcon;
43890 begin
43891 New(Result,Create);
43892 end;
43893 {$ENDIF ASM_VERSION}
43894 //[END _NewTrayIcon]
43896 function WndProcTrayIconWnd( Wnd: HWnd; Msg: DWORD; wParam, lParam: Integer ): Integer;
43897 stdcall;
43898 var PrevProc: function ( Wnd: HWnd; Msg: DWORD;
43899 wParam, lParam: Integer ): Integer; stdcall;
43900 var Tr: PTrayIcon;
43901 begin
43902 PrevProc := Pointer( GetProp( Wnd, 'TRAYSAVEPROC' ) );
43903 if Msg = CM_TRAYICON then
43904 begin
43905 Tr := Pointer( wParam );
43906 if Assigned( Tr.FOnMouse ) then
43907 Tr.FOnMouse( Tr, lParam );
43908 Result := 0;
43909 Exit;
43911 else
43912 if Msg = WM_CLOSE then
43913 begin
43914 if Assigned( PrevProc ) then
43915 begin
43916 SetWindowLong( Wnd, GWL_WNDPROC, Integer( @ PrevProc ) );
43917 RemoveProp( Wnd, 'TRAYSAVEPROC' );
43918 PostMessage( Wnd, WM_CLOSE, wParam, lParam );
43919 Result := 0;
43920 Exit;
43921 //Wnd := 0;
43922 end;
43923 end;
43924 if (Wnd <> 0) and IsWindow( Wnd ) and Assigned( PrevProc ) then
43925 Result := PrevProc( Wnd, Msg, wParam, lParam )
43926 else
43927 Result := DefWindowProc( Wnd, Msg, wParam, lParam );
43928 end;
43930 //[PROCEDURE TTrayIcon.AttachProc2Wnd]
43931 procedure TTrayIcon.AttachProc2Wnd;
43932 begin
43933 if FWnd = 0 then Exit;
43934 if GetProp( FWnd, 'TRAYSAVEPROC' ) <> 0 then Exit; // already attached
43935 SetProp( FWnd, 'TRAYSAVEPROC', GetWindowLong( FWnd, GWL_WNDPROC ) );
43936 SetWindowLong( FWnd, GWL_WNDPROC, Integer( @ WndProcTrayIconWnd ) );
43937 end;
43938 // [END TTrayIcon.AttachProc2Wnd]
43940 // [PROCEDURE TTrayIcon.DetachProc2Wnd]
43941 procedure TTrayIcon.DetachProc2Wnd;
43942 var OldProc: function ( Wnd: HWnd; Msg: DWORD;
43943 wParam, lParam: Integer ): Integer; stdcall;
43944 begin
43945 if FWnd = 0 then Exit;
43946 OldProc := Pointer( GetProp( FWnd, 'TRAYSAVEPROC' ) );
43947 if not Assigned( OldProc ) then Exit; // not attached
43948 SetWindowLong( FWnd, GWL_WNDPROC, Integer( @ OldProc ) );
43949 RemoveProp( FWnd, 'TRAYSAVEPROC' );
43950 end;
43951 // [END TTrayIcon.DetachProc2Wnd]
43953 //[FUNCTION NewTrayIcon]
43954 {$IFDEF ASM_VERSION}
43955 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;
43957 PUSH EBX
43958 PUSH EDX // push Icon
43959 PUSH EAX // push Wnd
43960 CALL _NewTrayIcon
43961 XCHG EBX, EAX
43963 MOV EAX, [FTrayItems]
43964 TEST EAX, EAX
43965 JNZ @@1
43966 CALL NewList
43967 MOV [FTrayItems], EAX
43968 @@1:
43969 MOV EDX, EBX
43970 CALL TList.Add
43972 POP EAX //Wnd
43973 MOV [EBX].TTrayIcon.fControl, EAX
43974 POP [EBX].TTrayIcon.fIcon //Icon
43976 MOV EDX, offset[WndProcTray]
43977 TEST EAX, EAX
43978 JZ @@2
43979 CALL TControl.AttachProc
43980 @@2:
43981 MOV DL, 1
43982 MOV EAX, EBX
43983 CALL TTrayIcon.SetActive
43984 XCHG EAX, EBX
43985 POP EBX
43986 end;
43987 {$ELSE ASM_VERSION} //Pascal
43988 function NewTrayIcon( Wnd: PControl; Icon: HIcon ): PTrayIcon;
43989 begin
43990 if FTrayItems = nil then
43991 FTrayItems := NewList;
43993 New( Result, Create );
43994 {+}{++}(*Result := PTrayIcon.Create;*){--}
43995 FTrayItems.Add( Result );
43996 if Wnd <> nil then
43997 Wnd.AttachProc( WndProcTray );
43998 Result.FControl := Wnd;
43999 Result.FIcon := Icon;
44000 Result.Active := True;
44001 end;
44002 {$ENDIF ASM_VERSION}
44003 //[END NewTrayIcon]
44005 var fRecreateMsg: DWORD;
44007 //[FUNCTION WndProcRecreateTrayIcons]
44008 {$IFDEF ASM_VERSION}
44009 function WndProcRecreateTrayIcons( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
44010 asm //cmd //opd
44011 MOV ECX, [fRecreateMsg]
44012 CMP word ptr [EDX].TMsg.message, CX
44013 JNE @@ret_false
44014 PUSH ESI
44015 MOV ESI, [FTrayItems]
44016 MOV ECX, [ESI].TList.fCount
44017 MOV ESI, [ESI].TList.fItems
44018 //JECXZ @@e_loo
44019 @@loo: PUSH ECX
44020 LODSD
44021 MOV DL, [EAX].TTrayIcon.fAutoRecreate
44022 AND DL, [EAX].TTrayIcon.fActive
44023 JZ @@nx
44024 DEC [EAX].TTrayIcon.fActive
44025 CALL TTrayIcon.SetActive
44026 @@nx: POP ECX
44027 LOOP @@loo
44028 @@e_loo:POP ESI
44029 @@ret_false:
44030 XOR EAX, EAX
44031 end;
44032 {$ELSE ASM_VERSION} //Pascal
44033 function WndProcRecreateTrayIcons( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
44034 var I: Integer;
44035 TI: PTrayIcon;
44036 begin
44037 if Msg.message = fRecreateMsg then
44038 begin
44039 for I := 0 to FTrayItems.fCount - 1 do
44040 begin
44041 TI := FTrayItems.Items[ I ];
44042 if TI.fAutoRecreate then
44043 if TI.fActive then
44044 begin
44045 TI.fActive := False;
44046 TI.Active := True;
44047 end;
44048 end;
44049 end;
44050 Result := False;
44051 end;
44052 {$ENDIF ASM_VERSION}
44053 //[END WndProcRecreateTrayIcons]
44055 const
44056 TaskbarCreatedMsg: array[ 0..14 ] of Char = ('T','a','s','k','b','a','r',
44057 'C','r','e','a','t','e','d',#0);
44058 {$IFDEF ASM_VERSION}
44059 //[procedure TTrayIcon.SetAutoRecreate]
44060 procedure TTrayIcon.SetAutoRecreate(const Value: Boolean);
44061 asm //cmd //opd
44062 MOV [EAX].fAutoRecreate, DL
44063 MOV EAX, [EAX].FControl
44064 CALL TControl.ParentForm
44065 MOV EDX, offset[WndProcRecreateTrayIcons]
44066 CALL TControl.AttachProc
44067 PUSH offset[TaskbarCreatedMsg]
44068 CALL RegisterWindowMessage
44069 MOV [fRecreateMsg], EAX
44070 end;
44071 {$ELSE ASM_VERSION} //Pascal
44072 procedure TTrayIcon.SetAutoRecreate(const Value: Boolean);
44073 begin
44074 fAutoRecreate := Value;
44075 FControl.ParentForm.AttachProc( WndProcRecreateTrayIcons );
44076 fRecreateMsg := RegisterWindowMessage( TaskbarCreatedMsg );
44077 end;
44078 {$ENDIF ASM_VERSION}
44080 {$IFDEF ASM_VERSION}
44081 //[destructor TTrayIcon.Destroy]
44082 destructor TTrayIcon.Destroy;
44084 PUSH EBX
44085 PUSH ESI
44086 MOV EBX, EAX
44087 XOR EDX, EDX
44088 CALL SetActive
44090 MOV ECX, [EBX].fIcon
44091 JECXZ @@icon_destroyed
44092 PUSH ECX
44093 CALL DestroyIcon
44094 @@icon_destroyed:
44096 MOV EDX, EBX
44097 MOV ESI, [FTrayItems]
44098 MOV EAX, ESI
44099 CALL TList.IndexOf
44100 TEST EAX, EAX
44101 JL @@fin
44102 XCHG EDX, EAX
44103 MOV EAX, ESI
44104 CALL TList.Delete
44105 MOV EAX, [ESI].TList.fCount
44106 TEST EAX, EAX
44107 JNZ @@fin
44108 XCHG EAX, [FTrayItems]
44109 CALL TObj.Free
44110 @@fin: LEA EAX, [EBX].FTooltip
44111 CALL System.@LStrClr
44112 XCHG EAX, EBX
44113 CALL TObj.Destroy
44114 POP ESI
44115 POP EBX
44116 end;
44117 {$ELSE ASM_VERSION} //Pascal
44118 destructor TTrayIcon.Destroy;
44119 begin
44120 Active := False;
44122 if fIcon <> 0 then
44123 DestroyIcon( fIcon );
44125 FTrayItems.Remove( @ Self );
44126 if FTrayItems.Count = 0 then
44127 Free_And_Nil( FTrayItems );
44128 FTooltip := '';
44129 inherited;
44130 end;
44131 {$ENDIF ASM_VERSION}
44133 {$IFDEF ASM_VERSION}
44134 //[procedure TTrayIcon.SetActive]
44135 procedure TTrayIcon.SetActive(const Value: Boolean);
44137 CMP [EAX].fActive, DL
44138 JE @@exit
44139 MOV ECX, [EAX].fIcon
44140 JECXZ @@exit
44141 PUSH EDX
44142 PUSH EAX
44143 MOV ECX, [EAX].FWnd
44144 INC ECX
44145 LOOP @@1
44146 MOV ECX, [EAX].fControl
44147 XOR EAX, EAX
44148 JECXZ @@1
44149 XCHG EAX, ECX
44150 CALL TControl.GetWindowHandle
44151 @@1:
44152 POP ECX
44153 POP EDX
44154 XCHG EAX, ECX
44155 JECXZ @@exit
44156 MOV [EAX].fActive, DL
44157 MOVZX EDX, DL
44158 XOR DL, 1
44159 ADD EDX, EDX
44160 CALL SetTrayIcon
44161 @@exit:
44162 end;
44163 {$ELSE ASM_VERSION} //Pascal
44164 procedure TTrayIcon.SetActive(const Value: Boolean);
44165 begin
44166 if FActive = Value then Exit;
44167 if FIcon = 0 then Exit;
44168 if (Wnd = 0) and ((FControl = nil) or (FControl.GetWindowHandle = 0)) then Exit;
44169 FActive := Value;
44170 if Value then
44171 SetTrayIcon( NIM_ADD )
44172 else
44173 SetTrayIcon( NIM_DELETE );
44174 end;
44175 {$ENDIF ASM_VERSION}
44177 {$IFDEF ASM_VERSION}
44178 //[procedure TTrayIcon.SetIcon]
44179 procedure TTrayIcon.SetIcon(const Value: HIcon);
44181 MOV ECX, [EAX].fIcon
44182 CMP ECX, EDX
44183 JE @@exit
44184 MOV [EAX].fIcon, EDX
44185 XOR EDX, EDX
44186 JECXZ @@nim_add
44187 INC EDX // NIM_MODIFY = 1
44188 @@nim_add:
44189 MOVZX ECX, [EAX].fActive
44190 JECXZ @@exit
44191 CALL SetTrayIcon
44192 @@exit:
44193 end;
44194 {$ELSE ASM_VERSION} //Pascal
44195 procedure TTrayIcon.SetIcon(const Value: HIcon);
44196 var Cmd : DWORD;
44197 begin
44198 if FIcon = Value then Exit;
44199 // Previous icon is not destroying. This is normal for
44200 // icons, loaded from resources using LoadIcon. For icons,
44201 // created using CreateIconIndirect, You have to call
44202 // DestroyIcon manually.
44203 Cmd := NIM_MODIFY;
44204 if FIcon = 0 then
44205 Cmd := NIM_ADD;
44206 FIcon := Value;
44207 if FActive then
44208 SetTrayIcon( Cmd );
44209 end;
44210 {$ENDIF ASM_VERSION}
44212 {$IFDEF ASM_VERSION}
44213 //[procedure TTrayIcon.SetTooltip]
44214 procedure TTrayIcon.SetTooltip(const Value: String);
44216 PUSH EBX
44217 XCHG EBX, EAX
44218 MOV EAX, [EBX].fTooltip
44219 PUSH EDX
44220 CALL System.@LStrCmp
44221 POP EDX
44222 JE @@exit
44223 LEA EAX, [EBX].fTooltip
44224 CALL System.@LStrAsg
44225 CMP [EBX].fActive, 0
44226 JE @@exit
44227 XOR EDX, EDX
44228 INC EDX // EDX = NIM_MODIFY
44229 XCHG EAX, EBX
44230 CALL SetTrayIcon
44231 @@exit:
44232 POP EBX
44233 end;
44234 {$ELSE ASM_VERSION} //Pascal
44235 procedure TTrayIcon.SetTooltip(const Value: String);
44236 begin
44237 if FTooltip = Value then Exit;
44238 FTooltip := Value;
44239 if Active then
44240 SetTrayIcon( NIM_MODIFY );
44241 end;
44242 {$ENDIF ASM_VERSION}
44244 {$IFDEF ASM_VERSION}
44245 //[procedure TTrayIcon.SetTrayIcon]
44246 procedure TTrayIcon.SetTrayIcon(const Value: DWORD);
44247 const sz_tid = sizeof( TNotifyIconData );
44249 //MOV ECX, [EAX].fIcon
44250 //JECXZ @@exit
44252 CMP [AppletTerminated], 0
44253 JE @@1
44254 MOV DL, NIM_DELETE
44255 @@1:
44256 PUSH EBX
44257 PUSH ESI
44258 MOV ESI, EAX
44259 MOV EBX, EDX
44261 XOR ECX, ECX
44262 PUSH ECX
44263 ADD ESP, -60
44264 MOV EDX, [ESI].fToolTip
44265 CALL EDX2PChar
44266 MOV EAX, ESP
44267 MOV CL, 63
44268 CALL StrLCopy
44270 PUSH [ESI].fIcon
44271 PUSH CM_TRAYICON
44272 XOR EDX, EDX
44273 CMP BL, NIM_DELETE
44274 JE @@2
44275 MOV DL, NIF_ICON or NIF_MESSAGE or NIF_TIP
44276 @@2: PUSH EDX
44277 PUSH ESI
44278 MOV EAX, [ESI].FWnd
44279 TEST EAX, EAX
44280 JNZ @@3
44281 MOV EAX, [ESI].fControl
44282 MOV EAX, [EAX].TControl.fHandle
44283 @@3:
44284 PUSH EAX
44285 PUSH sz_tid
44287 PUSH ESP
44288 PUSH EBX
44289 CALL Shell_NotifyIcon
44291 ADD ESP, sz_tid
44292 POP ESI
44293 POP EBX
44294 @@exit:
44295 end;
44296 {$ELSE ASM_VERSION} //Pascal
44297 procedure TTrayIcon.SetTrayIcon(const Value: DWORD);
44298 var NID : TNotifyIconData;
44299 L : Integer;
44300 V : DWORD;
44301 begin
44302 //if FIcon = 0 then Exit; - already tested
44303 V := Value;
44304 if AppletTerminated then
44305 V := NIM_DELETE;
44306 if Wnd <> 0 then
44307 NID.Wnd := Wnd
44308 else
44309 NID.Wnd := FControl.fHandle;
44311 NID.cbSize := Sizeof( NID );
44312 NID.uID := DWORD( @Self );
44313 NID.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
44314 if V = NIM_DELETE then
44315 NID.uFlags := 0;
44316 NID.uCallbackMessage := CM_TRAYICON;
44317 NID.hIcon := FIcon;
44318 L := Length( FToolTip );
44319 if L > 63 then L := 63;
44320 Move( FTooltip[1], NID.szTip[0], Min( 63, L ) );
44321 NID.szTip[ L ] := #0;
44323 Shell_NotifyIcon( V, @NID );
44324 end;
44325 {$ENDIF ASM_VERSION}
44327 { -- JustOne -- }
44329 var JustOneMutex: THandle;
44331 //[FUNCTION WndProcJustOne]
44332 {$IFDEF ASM_VERSION}
44333 function WndProcJustOne( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44335 MOV ECX, [EDX].TMsg.message
44336 SUB ECX, WM_CLOSE
44337 JE @@1
44338 SUB ECX, WM_NCDESTROY - WM_CLOSE
44339 JNE @@exit
44340 @@1:
44341 XCHG ECX, [JustOneMutex]
44342 JECXZ @@exit
44343 PUSH ECX
44344 PUSH ECX
44345 CALL ReleaseMutex
44346 CALL CloseHandle
44348 @@exit:
44349 XOR EAX, EAX
44350 end;
44351 {$ELSE ASM_VERSION} //Pascal
44352 function WndProcJustOne( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44353 begin
44354 Result := False;
44355 case Msg.message of
44356 WM_CLOSE, WM_NCDESTROY:
44357 if LongBool( JustOneMutex ) then
44358 begin
44359 ReleaseMutex( JustOneMutex );
44360 CloseHandle( JustOneMutex );
44361 JustOneMutex := 0;
44362 end;
44363 end;
44364 end;
44365 {$ENDIF ASM_VERSION}
44366 //[END WndProcJustOne]
44368 //[FUNCTION JustOne]
44369 {$IFDEF ASM_VERSION}
44370 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;
44371 const JOcs: PChar = 'KOL.Just1.CrtSec';
44373 PUSH EBX
44374 PUSH ESI
44375 XOR ESI, ESI
44376 PUSH EDI
44377 XCHG EBX, EAX
44379 CALL EDX2PChar
44380 PUSH EDX
44382 PUSH [JOcs]
44383 PUSH 1
44384 PUSH ESI
44385 MOV EDI, offset[CreateMutex]
44386 CALL EDI
44388 POP EDX
44389 TEST EAX, EAX
44390 JZ @@exit //
44391 PUSH EAX
44392 PUSH EAX
44394 PUSH EDX
44395 PUSH ESI
44396 PUSH ESI
44397 CALL EDI
44398 MOV [JustOneMutex], EAX
44399 TEST EAX, EAX
44400 JE @@1 //
44402 PUSH ESI
44403 PUSH EAX
44404 CALL WaitForSingleObject
44405 SUB EAX, WAIT_TIMEOUT
44406 JE @@1
44408 INC ESI
44409 @@1:
44410 //MOV [EBX].TControl.fWndProcJustOne, offset[WndProcJustOne]
44411 XCHG EAX, EBX
44412 MOV EDX, offset[WndProcJustOne]
44413 CALL TControl.AttachProc
44415 CALL ReleaseMutex
44416 CALL CloseHandle
44418 @@exit:
44419 XCHG EAX, ESI
44420 POP EDI
44421 POP ESI
44422 POP EBX
44423 end;
44424 {$ELSE ASM_VERSION} //Pascal
44425 function JustOne( Wnd: PControl; const Identifier : String ) : Boolean;
44426 var CritSecMutex : THandle;
44427 DW : Longint;
44428 begin
44429 Result := False;
44430 CritSecMutex := CreateMutex( nil, True, PChar( 'KOL.Just1.CrtSec' ) );
44431 if CritSecMutex = 0 then Exit;
44433 JustOneMutex := CreateMutex( nil, False, PChar( Identifier ) );
44434 if JustOneMutex <> 0 then
44435 begin
44436 DW := WaitForSingleObject( JustOneMutex, 0 );
44437 Result := (DW <> WAIT_TIMEOUT);
44438 end;
44440 //Wnd.fWndProcJustOne := WndProcJustOne;
44441 Wnd.AttachProc( WndProcJustOne );
44443 ReleaseMutex( CritSecMutex );
44444 CloseHandle( CritSecMutex );
44445 end;
44446 {$ENDIF ASM_VERSION}
44447 //[END JustOne]
44449 { JustOneNotify }
44452 OnAnotherInstance: TOnAnotherInstance;
44453 JustOneMsg: DWORD;
44455 //[FUNCTION WndProcJustOneNotify]
44456 {$IFDEF ASM_VERSION}
44457 function WndProcJustOneNotify( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44459 PUSH EBP
44460 MOV EBP, ESP
44461 PUSHAD
44462 CALL WndProcJustOne
44463 POPAD
44464 XOR EAX, EAX
44465 PUSH ECX
44466 MOV ECX, [EDX].TMsg.message
44467 SUB ECX, [JustOneMsg]
44468 POP ECX
44469 JNE @@exit
44470 MOV [ECX], EAX
44471 CMP [OnAnotherInstance].TMethod.Code, EAX
44472 JE @@exit_1
44474 //MOV EAX, (MAX_PATH + 3) and 0FFFFCh
44475 MOV AH, 2
44476 SUB ESP, EAX
44478 MOV ECX, ESP
44479 PUSH EAX
44480 PUSH ECX
44481 PUSH [EDX].TMsg.lParam
44482 CALL GetWindowText
44484 MOV EDX, ESP
44485 PUSH 0
44486 MOV EAX, ESP
44487 CALL System.@LStrFromPChar
44489 MOV EDX, [ESP]
44490 MOV EAX, [OnAnotherInstance].TMethod.Data
44491 CALL [OnAnotherInstance].TMethod.Code
44493 MOV EAX, ESP
44494 CALL System.@LStrClr
44495 @@exit_1:
44496 MOV AL, 1
44497 @@exit:
44498 MOV ESP, EBP
44499 POP EBP
44500 end;
44501 {$ELSE ASM_VERSION} //Pascal
44502 function WndProcJustOneNotify( Control: PControl; var Msg: TMsg; var Rslt: Integer ) : Boolean;
44503 var Buf : array[0..MAX_PATH] of Char;
44504 begin
44505 WndProcJustOne( Control, Msg, Rslt );
44506 Result := False;
44507 if Msg.message = JustOneMsg then
44508 begin
44509 Result := True;
44510 if assigned( OnAnotherInstance ) then
44511 begin
44512 GetWindowText( Msg.lParam, Buf, MAX_PATH );
44513 OnAnotherInstance( Buf );
44514 end;
44515 Rslt := 0;
44516 end;
44517 end;
44518 {$ENDIF ASM_VERSION}
44519 //[END WndProcJustOneNotify]
44521 // Redefine here incorrectly declared BroadcastSystemMessage API function.
44522 // It should not refer to BroadcastSystemMessageA, which is not present in
44523 // earlier versions of Windows95, but to BroadcastSystemMessage, which is
44524 // present in all Windows95/98/Me and NT/2K/XP.
44525 //[API BroadcastSystemMessage]
44526 function BroadcastSystemMessage(Flags: DWORD; Recipients: PDWORD;
44527 uiMessage: UINT; wParam: WPARAM; lParam: LPARAM): Longint; stdcall;
44528 external user32 name 'BroadcastSystemMessage';
44530 //[FUNCTION JustOneNotify]
44531 {$IFDEF ASM_VERSION}
44532 function JustOneNotify( Wnd: PControl; const Identifier : String;
44533 const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;
44535 PUSHAD
44536 MOV EBP, ESP
44538 XCHG EAX, EDX
44539 PUSH EAX
44540 CALL System.@LStrLen
44541 POP EDX
44542 ADD EAX, EAX
44543 SUB ESP, EAX
44544 MOV EAX, ESP
44545 CALL StrPCopy
44546 PUSH '.ega'
44547 PUSH 'sseM'
44548 PUSH ESP
44549 CALL RegisterWindowMessage
44550 MOV [JustOneMsg], EAX
44551 TEST EAX, EAX
44553 MOV ESP, EBP
44554 POPAD
44555 JE @@exit_f
44557 PUSHAD
44558 CALL JustOne
44559 DEC AL
44560 POPAD
44561 JZ @@exit_t
44563 PUSH EBX
44564 XCHG EBX, EAX
44565 XOR EDX, EDX
44566 XCHG [EBX].TControl.fCaption, EDX
44567 PUSH EDX
44569 CALL GetCommandLine
44570 XCHG EDX, EAX
44571 MOV EAX, EBX
44572 CALL TControl.SetCaption
44573 MOV EAX, EBX
44574 CALL TControl.GetWindowHandle
44575 TEST EAX, EAX
44576 JZ @@rest_cap
44578 PUSH BSM_APPLICATIONS
44579 MOV EDX, ESP
44581 PUSH EAX
44582 PUSH 0
44583 PUSH [JustOneMsg]
44584 PUSH EDX
44585 PUSH BSF_QUERY or BSF_IGNORECURRENTTASK
44586 CALL BroadcastSystemMessage
44588 POP EDX
44589 @@rest_cap:
44590 XOR EDX, EDX
44591 MOV EAX, EBX
44592 CALL TControl.SetCaption
44593 POP EDX
44594 MOV [EBX].TControl.fCaption, EDX
44595 PUSH EDX
44596 PUSH [EBX].TControl.fHandle
44597 CALL SetWindowText
44598 POP EBX
44599 @@exit_f:
44600 XOR EAX, EAX
44601 POP EBP // because compiler inserts PUSH EBP;MOV EBP,ESP at the BEGIN
44604 @@exit_t:
44605 PUSHAD
44606 LEA ESI, [aOnAnotherInstance]
44607 LEA EDI, [OnAnotherInstance]
44608 MOVSD
44609 MOVSD
44610 //MOV [EAX].TControl.fWndProcJustOne, offset[WndProcJustOneNotify]
44611 MOV EDX, offset[WndProcJustOneNotify]
44612 CALL TControl.AttachProc
44614 POPAD
44615 MOV AL, 1
44616 end;
44617 {$ELSE ASM_VERSION} //Pascal
44618 function JustOneNotify( Wnd: PControl; const Identifier : String;
44619 const aOnAnotherInstance: TOnAnotherInstance ) : Boolean;
44620 var Recipients : DWord;
44621 OldCap: String;
44622 begin
44623 Result := False;
44624 JustOneMsg := RegisterWindowMessage( PChar( 'Message.' + Identifier ) );
44625 if JustOneMsg = 0 then Exit;
44627 Result := JustOne( Wnd, Identifier );
44628 if not Result then
44629 begin
44630 // Send a message to the first instance of applet
44632 //Wnd.CreateVisible := False;
44633 OldCap := Wnd.Caption;
44634 Wnd.Caption := GetCommandLine;
44635 if Wnd.GetWindowHandle <> 0 then
44636 begin
44637 Recipients := BSM_APPLICATIONS;
44638 BroadcastSystemMessage( BSF_QUERY or BSF_IGNORECURRENTTASK, @Recipients,
44639 JustOneMsg, 0, Wnd.fHandle );
44640 end;
44641 Wnd.Caption := OldCap;
44643 else
44644 begin
44645 // Store event handler to notify this instance about another
44646 // instance staring:
44647 OnAnotherInstance := aOnAnotherInstance;
44648 //Wnd.fWndProcJustOne := WndProcJustOneNotify;
44649 Wnd.AttachProc( WndProcJustOneNotify );
44652 if JustOneNotifier = nil then
44653 JustOneNotifier := ZJustOneNotifier.Create;
44655 end;
44656 end;
44657 {$ENDIF ASM_VERSION}
44658 //[END JustOneNotify]
44661 ///////////////////////////////////////// STRING LIST OBJECT /////////////////
44663 { TStrList }
44665 //[function NewStrList]
44666 function NewStrList: PStrList;
44667 begin
44669 New( Result, Create );
44671 {++}(*
44672 Result := PStrList.Create;
44673 *){--}
44674 end;
44675 //[END NewStrList]
44677 {$IFDEF ASM_VERSION}
44678 //[destructor TStrList.Destroy]
44679 destructor TStrList.Destroy;
44681 PUSH EAX
44682 CALL Clear
44683 POP EAX
44684 CALL TObj.Destroy
44685 end;
44686 {$ELSE ASM_VERSION} //Pascal
44687 destructor TStrList.Destroy;
44688 begin
44689 Clear;
44690 inherited;
44691 end;
44692 {$ENDIF ASM_VERSION}
44694 //[procedure TStrList.Init]
44695 procedure TStrList.Init;
44696 begin
44697 //inherited;
44698 fNameDelim := DefaultNameDelimiter;
44699 end;
44701 {$IFDEF ASM_VERSION}
44702 //[function TStrList.Add]
44703 function TStrList.Add(const S: string): integer;
44705 MOV ECX, EDX
44706 MOV EDX, [EAX].fCount
44707 PUSH EDX
44708 CALL Insert
44709 POP EAX
44710 end;
44711 {$ELSE ASM_VERSION} //Pascal
44712 function TStrList.Add(const S: string): integer;
44713 begin
44714 Result := fCount;
44715 Insert( Result, S );
44716 end;
44717 {$ENDIF ASM_VERSION}
44719 {$IFDEF ASM_VERSION}
44720 //[procedure TStrList.AddStrings]
44721 procedure TStrList.AddStrings(Strings: PStrList);
44723 PUSH EAX
44724 XCHG EAX, EDX
44725 PUSH 0
44726 MOV EDX, ESP
44727 CALL GetTextStr
44728 POP EDX
44729 POP EAX
44730 MOV CL, 1
44731 PUSH EDX
44732 CALL SetText
44733 CALL RemoveStr
44734 end;
44735 {$ELSE ASM_VERSION} //Pascal
44736 procedure TStrList.AddStrings(Strings: PStrList);
44737 begin
44738 SetText( Strings.Text, True );
44739 end;
44740 {$ENDIF ASM_VERSION}
44742 {$IFDEF ASM_VERSION}
44743 //[function TStrList.AppendToFile]
44744 function TStrList.AppendToFile(const FileName: string): Boolean;
44746 PUSH EBX
44747 MOV EBX, EDX
44748 PUSH 0
44749 MOV EDX, ESP
44750 CALL GetTextStr
44751 XCHG EAX, EBX
44752 MOV EDX, ofOpenWrite or ofOpenAlways
44753 CALL FileCreate
44754 MOV EBX, EAX
44755 INC EAX
44756 JZ @@exit
44757 DEC EAX
44758 XOR EDX, EDX
44759 XOR ECX, ECX
44760 MOV CL, spEnd
44761 CALL FileSeek
44762 POP EAX
44763 PUSH EAX
44764 CALL System.@LStrLen
44765 XCHG ECX, EAX
44766 MOV EAX, EBX
44767 POP EDX
44768 PUSH EDX
44769 CALL FileWrite
44770 XCHG EAX, EBX
44771 CALL FileClose
44772 @@exit:
44773 CALL RemoveStr
44774 POP EBX
44775 end;
44776 {$ELSE ASM_VERSION} //Pascal
44777 function TStrList.AppendToFile(const FileName: string): Boolean;
44778 var F: HFile;
44779 Buf: String;
44780 L: Integer;
44781 begin
44782 F := FileCreate( FileName, ofOpenWrite or ofOpenAlways );
44783 Result := F <> INVALID_HANDLE_VALUE;
44784 if Result then
44785 begin
44786 FileSeek( F, 0, spEnd );
44787 Buf := Text;
44788 L := Length( Buf );
44789 FileWrite( F, Buf[ 1 ], L );
44790 FileClose( F );
44791 end;
44792 end;
44793 {$ENDIF ASM_VERSION}
44795 {$IFDEF ASM_VERSION}
44796 //[procedure TStrList.Assign]
44797 procedure TStrList.Assign(Strings: PStrList);
44799 PUSHAD
44800 CALL Clear
44801 POPAD
44802 JMP AddStrings
44803 end;
44804 {$ELSE ASM_VERSION} //Pascal
44805 procedure TStrList.Assign(Strings: PStrList);
44806 begin
44807 Clear;
44808 AddStrings( Strings );
44809 end;
44810 {$ENDIF ASM_VERSION}
44812 {$IFDEF ASM_VERSION}
44813 //[procedure TStrList.Clear]
44814 procedure TStrList.Clear;
44816 PUSH EBX
44817 XCHG EBX, EAX
44818 MOV EDX, [EBX].fCount
44819 @@loo: DEC EDX
44820 JL @@eloo
44821 PUSH EDX
44822 MOV EAX, EBX
44823 CALL Delete
44824 POP EDX
44825 JMP @@loo
44826 @@eloo:
44827 XOR EAX, EAX
44828 MOV [EBX].fTextSiz, EAX
44829 XCHG EAX, [EBX].fTextBuf
44830 TEST EAX, EAX
44831 JZ @@1
44832 CALL System.@FreeMem
44833 //XOR EAX, EAX // not needed: if OK, EAX = 0
44834 @@1: XCHG EAX, [EBX].fList
44835 CALL TObj.Free
44836 POP EBX
44837 end;
44838 {$ELSE ASM_VERSION} //Pascal
44839 procedure TStrList.Clear;
44840 var I: Integer;
44841 begin
44842 if fCount > 0 then
44843 for I := fList.Count - 1 downto 0 do
44844 Delete( I );
44845 fList.Free;
44846 fList := nil;
44847 fCount := 0;
44848 if fTextBuf <> nil then
44849 begin
44850 FreeMem( fTextBuf );
44851 fTextBuf := nil;
44852 fTextSiz := 0;
44853 end;
44854 end;
44855 {$ENDIF ASM_VERSION}
44857 {$IFDEF ASM_VERSION}
44858 //[procedure TStrList.Delete]
44859 procedure TStrList.Delete(Idx: integer);
44861 DEC [EAX].fCount
44862 PUSH EAX
44863 MOV EAX, [EAX].fList
44864 MOV ECX, [EAX].TList.fItems
44865 PUSH dword ptr [ECX+EDX*4]
44866 CALL TList.Delete
44867 POP EAX
44868 POP EDX
44869 MOV ECX, [EDX].fTextSiz
44870 JECXZ @@fremem
44871 CMP EAX, [EDX].fTextBuf
44872 JB @@fremem
44873 ADD ECX, [EDX].fTextBuf
44874 CMP EAX, ECX
44875 JB @@exit
44876 @@fremem:
44877 CALL System.@FreeMem
44878 @@exit:
44879 end;
44880 {$ELSE ASM_VERSION} //Pascal
44881 procedure TStrList.Delete(Idx: integer);
44882 var P: DWORD;
44883 El:Pointer;
44884 begin
44885 P := DWORD( fList.fItems[ Idx ] );
44886 if (fTextBuf <> nil) and ( P >= DWORD( fTextBuf )) and
44887 ( P < DWORD( fTextBuf ) + fTextSiz ) then
44888 else
44889 begin
44890 El := FList.Items[ Idx ];
44891 FreeMem( El );
44892 end;
44893 fList.Delete( Idx );
44894 Dec( fCount );
44895 end;
44896 {$ENDIF ASM_VERSION}
44898 {$IFDEF ASM_VERSION}
44899 //[function TStrList.Get]
44900 function TStrList.Get(Idx: integer): string;
44902 PUSH ECX
44903 MOV EAX, [EAX].fList
44904 TEST EAX, EAX
44905 JZ @@1
44906 CALL TList.Get
44907 @@1: XCHG EDX, EAX
44908 POP EAX
44909 JMP System.@LStrFromPChar
44910 end;
44911 {$ELSE ASM_VERSION} //Pascal
44912 function TStrList.Get(Idx: integer): string;
44913 begin
44914 if fList <> nil then
44915 Result := PChar( fList.Items[ Idx ] )
44916 else Result := '';
44917 end;
44918 {$ENDIF ASM_VERSION}
44920 {$IFDEF ASM_VERSION}
44921 //[function TStrList.GetPChars]
44922 function TStrList.GetPChars(Idx: Integer): PChar;
44924 MOV EAX, [EAX].fList
44925 MOV EAX, [EAX].TList.fItems
44926 MOV EAX, [EAX+EDX*4]
44927 end;
44928 {$ELSE ASM_VERSION} //Pascal
44929 function TStrList.GetPChars(Idx: Integer): PChar;
44930 begin
44931 Result := PChar( fList.fItems[ Idx ] );
44932 end;
44933 {$ENDIF ASM_VERSION}
44935 {$IFDEF ASM_VERSION}
44936 //[function TStrList.GetTextStr]
44937 function TStrList.GetTextStr: string;
44939 PUSH ESI
44940 PUSH EDI
44941 MOV ECX, [EAX].fCount
44942 MOV EAX, [EAX].fList
44943 PUSH ECX
44944 JECXZ @@1
44945 MOV ESI, [EAX].TList.fItems
44946 @@1: PUSH ESI
44947 XCHG EAX, EDX
44948 XOR EDX, EDX
44949 JECXZ @@10
44950 PUSH EAX
44951 @@loo1:
44952 PUSH ECX
44953 PUSH EDX
44954 LODSD
44955 CALL StrLen
44956 POP EDX
44957 LEA EDX, [EDX+EAX+2]
44958 POP ECX
44959 LOOP @@loo1
44961 POP EAX
44962 POP ESI
44963 XCHG ECX, EDX
44964 PUSH EAX
44965 @@10:
44966 {$IFDEF _D2}
44967 CALL _LStrFromPCharLen
44968 {$ELSE}
44969 CALL System.@LStrFromPCharLen
44970 {$ENDIF}
44972 POP EDI
44973 POP ECX
44974 JECXZ @@exit
44975 MOV EDI, [EDI]
44977 @@loo2: PUSH ECX
44978 LODSD
44979 PUSH EAX
44980 CALL StrLen
44981 XCHG ECX, EAX
44982 POP EAX
44983 XCHG EAX, ESI
44984 REP MOVSB
44985 XCHG ESI, EAX
44986 MOV AX, $0A0D
44987 STOSW
44988 POP ECX
44989 LOOP @@loo2
44991 XCHG EAX, ECX
44992 STOSB
44993 @@exit:
44994 POP EDI
44995 POP ESI
44996 end;
44997 {$ELSE ASM_VERSION} //Pascal
44998 function TStrList.GetTextStr: string;
45000 I, Len, Size: integer;
45001 P: PChar;
45002 begin
45003 Size := 0;
45005 for I := 0 to fCount - 1 do
45006 Inc(Size, StrLen( PChar(fList.fItems[I]) ) + 2);
45008 SetString(Result, nil, Size);
45010 P := Pointer(Result);
45011 for I := 0 to Count - 1 do
45012 begin
45013 Len := StrLen(PChar(fList.fItems[I]));
45014 if (Len > 0) then
45015 begin
45016 System.Move(PChar(fList.fItems[I])^, P^, Len);
45017 Inc(P, Len);
45018 end;
45019 P^ := #13;
45020 Inc(P);
45021 P^ := #10;
45022 Inc(P);
45023 end;
45024 end;
45025 {$ENDIF ASM_VERSION}
45027 {$IFDEF ASM_VERSION}
45028 //[function TStrList.IndexOf]
45029 function TStrList.IndexOf(const S: string): integer;
45031 PUSH EBX
45032 PUSH ESI
45033 OR EBX, -1
45034 MOV ECX, [EAX].fCount
45035 JECXZ @@exit
45036 MOV ESI, [EAX].fList
45037 MOV ESI, [ESI].TList.fItems
45038 @@loo: LODSD
45039 INC EBX
45040 CMP EAX, EDX
45041 JE @@exit
45042 OR EDX, EDX
45043 JZ @@1
45044 PUSH EDX
45045 PUSH ECX
45046 CALL StrComp
45047 POP ECX
45048 POP EDX
45049 JE @@exit
45050 @@1: LOOP @@loo
45051 OR EBX, -1
45052 @@exit: XCHG EAX, EBX
45053 POP ESI
45054 POP EBX
45055 end;
45056 {$ELSE ASM_VERSION} //Pascal
45057 function TStrList.IndexOf(const S: string): integer;
45058 begin
45059 for Result := 0 to fCount - 1 do
45060 if (S = PChar( fList.Items[Result] )) then Exit;
45061 Result := -1;
45062 end;
45063 {$ENDIF ASM_VERSION}
45065 //[function TStrList.IndexOf]
45066 function TStrList.IndexOf_NoCase(const S: string): integer;
45067 begin
45068 for Result := 0 to fCount - 1 do
45069 if StrComp_NoCase( PChar( S ), PChar( fList.Items[Result] ) ) = 0 then Exit;
45070 Result := -1;
45071 end;
45073 function TStrList.IndexOfStrL_NoCase( Str: PChar; L: Integer ): integer;
45074 begin
45075 for Result := 0 to fCount - 1 do
45076 if (StrLen( PChar( fList.fItems[ Result ] ) ) = DWORD( L )) and
45077 (StrLComp_NoCase( Str, PChar( fList.fItems[ Result ] ), L ) = 0) then Exit;
45078 Result := -1;
45079 end;
45081 //[function TStrList.Find]
45082 function TStrList.Find(const S: String; var Index: Integer): Boolean;
45084 L, H, I, C: Integer;
45085 begin
45086 Result := FALSE;
45087 L := 0;
45088 H := FCount - 1;
45089 while L <= H do
45090 begin
45091 I := (L + H) shr 1;
45092 C := AnsiCompareStr( PChar( fList.Items[ I ] ), S );
45093 if C < 0 then L := I + 1 else
45094 begin
45095 H := I - 1;
45096 if C = 0 then
45097 begin
45098 Result := TRUE;
45099 L := I;
45100 //break;
45101 //if Duplicates <> dupAccept then L := I;
45102 end;
45103 end;
45104 end;
45105 Index := L;
45106 end;
45108 {$IFDEF ASM_VERSION}
45109 //[procedure TStrList.Insert]
45110 procedure TStrList.Insert(Idx: integer; const S: string);
45112 PUSH EBX
45113 PUSH EDX
45114 PUSH ECX
45115 XCHG EBX, EAX
45116 MOV EAX, [EBX].fList
45117 TEST EAX, EAX
45118 JNZ @@1
45119 CALL NewList
45120 MOV [EBX].fList, EAX
45121 @@1:
45122 POP EAX
45123 PUSH EAX // push S
45124 CALL System.@LStrLen
45125 INC EAX
45126 PUSH EAX // push L
45127 CALL System.@GetMem
45128 MOV byte ptr[EAX], 0
45129 XCHG EDX, EAX
45130 POP ECX
45131 POP EAX
45132 PUSH EDX // push Mem
45133 TEST EAX, EAX
45134 JE @@2
45135 CALL System.Move
45136 @@2: POP ECX
45137 POP EDX
45138 MOV EAX, [EBX].fList
45139 CALL TList.Insert
45140 INC [EBX].fCount
45141 POP EBX
45142 end;
45143 {$ELSE ASM_VERSION} //Pascal
45144 procedure TStrList.Insert(Idx: integer; const S: string);
45145 var Mem: PChar;
45146 L: Integer;
45147 begin
45148 if fList = nil then
45149 fList := NewList;
45150 L := Length( S ) + 1;
45151 GetMem( Mem, L );
45152 Mem[0] := #0;
45153 if L > 1 then
45154 System.Move( S[1], Mem[0], L );
45155 fList.Insert( Idx, Mem );
45156 Inc( fCount );
45157 end;
45158 {$ENDIF ASM_VERSION}
45160 {$IFDEF ASM_VERSION}
45161 //[function TStrList.LoadFromFile]
45162 function TStrList.LoadFromFile(const FileName: string): Boolean;
45164 PUSH EAX
45165 XCHG EAX, EDX
45166 MOV EDX, ofOpenRead or ofShareDenyWrite or ofOpenExisting
45167 CALL FileCreate
45168 INC EAX
45169 JZ @@exit
45170 DEC EAX
45171 PUSH EBX
45172 XCHG EBX, EAX
45173 PUSH 0
45174 PUSH EBX
45175 CALL GetFileSize
45176 XOR EDX, EDX
45177 PUSH EDX
45178 XCHG ECX, EAX
45179 MOV EAX, ESP
45180 PUSH ECX
45181 {$IFDEF _D2}
45182 CALL _LStrFromPCharLen
45183 {$ELSE}
45184 CALL System.@LStrFromPCharLen
45185 {$ENDIF}
45186 POP ECX
45187 MOV EAX, EBX
45188 POP EDX
45189 PUSH EDX
45190 CALL FileRead
45191 XCHG EAX, EBX
45192 CALL FileClose
45193 POP EDX
45194 POP EBX
45195 POP EAX
45196 PUSH EDX
45197 XOR ECX, ECX
45198 CALL SetText
45199 CALL RemoveStr
45200 PUSH EDX
45201 MOV AL, 1
45202 @@exit: POP EDX
45203 end;
45204 {$ELSE ASM_VERSION} //Pascal
45205 function TStrList.LoadFromFile(const FileName: string): Boolean;
45206 var Buf: String;
45207 F: HFile;
45208 Sz: Integer;
45209 begin
45210 F := FileCreate( FileName, ofOpenRead or ofShareDenyWrite or ofOpenExisting );
45211 Result := F <> INVALID_HANDLE_VALUE;
45212 if Result then
45213 begin
45214 Sz := GetFileSize( F, nil );
45215 SetString( Buf, nil, Sz );
45216 FileRead( F, Buf[1], Sz );
45217 FileClose( F );
45219 SetText( Buf, False );
45220 end;
45221 end;
45222 {$ENDIF ASM_VERSION}
45224 {$IFDEF ASM_VERSION}
45225 //[procedure TStrList.LoadFromStream]
45226 procedure TStrList.LoadFromStream(Stream: PStream; Append2List: boolean);
45228 PUSH EAX
45229 PUSH ECX
45230 PUSH EBX
45231 XCHG EAX, EDX
45232 MOV EBX, EAX
45233 CALL TStream.GetSize
45234 PUSH EAX
45235 MOV EAX, EBX
45236 CALL TStream.GetPosition
45237 POP ECX
45238 SUB ECX, EAX
45239 XOR EDX, EDX
45240 PUSH EDX
45241 MOV EAX, ESP
45242 PUSH ECX
45243 {$IFDEF _D2}
45244 CALL _LStrFromPCharLen
45245 {$ELSE}
45246 CALL System.@LStrFromPCharLen
45247 {$ENDIF}
45248 POP ECX
45249 POP EDX
45250 XCHG EAX, EBX
45251 PUSH EDX
45252 CALL TStream.Read
45253 POP EDX
45254 POP EBX
45255 POP ECX
45256 POP EAX
45257 PUSH EDX
45258 CALL SetText
45259 CALL RemoveStr
45260 end;
45261 {$ELSE ASM_VERSION} //Pascal
45262 procedure TStrList.LoadFromStream(Stream: PStream; Append2List: boolean);
45263 var Buf: String;
45264 Sz: Integer;
45265 begin
45266 Sz := Stream.Size - Stream.Position;
45267 SetString( Buf, nil, Sz );
45268 Stream.Read( Buf[1], Sz );
45269 SetText( Buf, Append2List );
45270 end;
45271 {$ENDIF ASM_VERSION}
45273 {$IFDEF ASM_VERSION}
45274 //[procedure TStrList.MergeFromFile]
45275 procedure TStrList.MergeFromFile(const FileName: string);
45277 PUSH EAX
45278 XCHG EAX, EDX
45279 CALL NewReadFileStream
45280 XCHG EDX, EAX
45281 POP EAX
45282 MOV CL, 1
45283 PUSH EDX
45284 CALL LoadFromStream
45285 POP EAX
45286 JMP TObj.Free
45287 end;
45288 {$ELSE ASM_VERSION} //Pascal
45289 procedure TStrList.MergeFromFile(const FileName: string);
45290 var TmpStream: PStream;
45291 begin
45292 TmpStream := NewReadFileStream( FileName );
45293 LoadFromStream( TmpStream, True );
45294 TmpStream.Free;
45295 end;
45296 {$ENDIF ASM_VERSION}
45298 //[procedure TStrList.Move]
45299 procedure TStrList.Move(CurIndex, NewIndex: integer);
45300 begin
45301 fList.MoveItem( CurIndex, NewIndex );
45302 end;
45304 {$IFDEF ASM_VERSION}
45305 //[procedure TStrList.Put]
45306 procedure TStrList.Put(Idx: integer; const Value: string);
45308 PUSH EAX
45309 PUSH EDX
45310 CALL Insert
45311 POP EDX
45312 POP EAX
45313 INC EDX
45314 JMP Delete
45315 end;
45316 {$ELSE ASM_VERSION} //Pascal
45317 procedure TStrList.Put(Idx: integer; const Value: string);
45318 begin
45319 Delete( Idx );
45320 Insert( Idx, Value );
45321 end;
45322 {$ENDIF ASM_VERSION}
45324 {$IFDEF ASM_VERSION}
45325 //[function TStrList.SaveToFile]
45326 function TStrList.SaveToFile(const FileName: string): Boolean;
45328 PUSH EBX
45329 PUSH EAX
45330 XCHG EAX, EDX
45331 MOV EDX, ofOpenWrite or ofCreateAlways
45332 CALL FileCreate
45333 INC EAX
45334 JZ @@exit
45335 DEC EAX
45336 XCHG EBX, EAX
45337 POP EAX
45338 PUSH 0
45339 MOV EDX, ESP
45340 CALL GetTextStr
45341 POP EAX
45342 PUSH EAX
45343 CALL System.@LStrLen
45344 XCHG ECX, EAX
45345 POP EDX
45346 PUSH EDX
45347 MOV EAX, EBX
45348 CALL FileWrite
45349 PUSH EBX
45350 CALL SetEndOfFile
45351 XCHG EAX, EBX
45352 CALL FileClose
45353 CALL RemoveStr
45354 PUSH EDX
45355 INC EAX
45356 @@exit:
45357 POP EDX
45358 POP EBX
45359 end;
45360 {$ELSE ASM_VERSION} //Pascal
45361 function TStrList.SaveToFile(const FileName: string): Boolean;
45362 var F: HFile;
45363 Buf: String;
45364 begin
45365 F := FileCreate( FileName, ofOpenWrite or ofCreateAlways );
45366 Result := F <> INVALID_HANDLE_VALUE;
45367 if Result then
45368 begin
45369 Buf := Text;
45370 FileWrite( F, Buf[ 1 ], Length( Buf ) );
45371 SetEndOfFile( F ); // necessary! - V.K.
45372 FileClose( F );
45373 end;
45374 end;
45375 {$ENDIF ASM_VERSION}
45377 {$IFDEF ASM_VERSION}
45378 //[procedure TStrList.SaveToStream]
45379 procedure TStrList.SaveToStream(Stream: PStream);
45381 PUSH EDX
45382 PUSH 0
45383 MOV EDX, ESP
45384 CALL GetTextStr
45385 POP EAX
45386 PUSH EAX
45387 CALL System.@LStrLen
45388 XCHG ECX, EAX
45389 POP EDX
45390 POP EAX
45391 PUSH EDX
45392 JECXZ @@1
45393 CALL TStream.Write
45394 @@1:
45395 CALL RemoveStr
45396 end;
45397 {$ELSE ASM_VERSION} //Pascal
45398 procedure TStrList.SaveToStream(Stream: PStream);
45399 var S: string;
45400 L: Integer;
45401 begin
45402 S := GetTextStr;
45403 L := Length( S );
45404 if L <> 0 then
45405 Stream.Write( S[1], L );
45406 end;
45407 {$ENDIF ASM_VERSION}
45409 {$IFDEF ASM_VERSION}
45410 //[procedure TStrList.SetText]
45411 procedure TStrList.SetText(const S: string; Append2List: boolean);
45413 DEC CL
45414 JZ @@1
45415 PUSHAD
45416 CALL Clear
45417 POPAD
45418 @@1: CALL EDX2PChar
45419 JZ @@exit
45421 PUSH EBX
45422 PUSH EDI
45423 MOV EBX, EAX
45424 MOV EDI, [EBX].fTextSiz
45426 MOV EAX, [EDX-4] // EAX = Length(S)
45427 INC EAX
45428 PUSH EAX
45430 // add S to text buffer
45431 //CMP byte ptr [EDX], 0
45432 //JZ @@eatb
45434 PUSH EDX
45435 PUSH [EBX].fTextBuf
45436 ADD EAX, [EBX].fTextSiz
45437 CALL System.@GetMem
45438 MOV [EBX].fTextBuf, EAX
45440 MOV ECX, EDI
45441 XCHG EDX, EAX
45442 POP EAX
45443 JECXZ @@atb_fin
45444 PUSH EAX
45445 CALL System.Move
45447 POP EDX
45448 PUSH EDX
45450 PUSH ESI
45451 MOV ESI, [EBX].fList
45452 MOV ESI, [ESI].TList.fItems
45453 MOV ECX, [EBX].fCount
45455 @@atb_loo:
45456 LODSD
45457 SUB EAX, EDX
45458 CMP EAX, [EBX].fTextSiz
45459 JAE @@atb_nxt
45461 ADD EAX, [EBX].fTextBuf
45462 MOV [ESI-4], EAX
45464 @@atb_nxt: LOOP @@atb_loo
45466 POP ESI
45467 POP EAX
45468 CALL System.@FreeMem
45469 @@atb_fin:
45470 POP EAX
45472 MOV EDX, EDI
45473 ADD EDX, [EBX].fTextBuf
45474 POP ECX
45475 PUSH ECX
45476 ADD [EBX].fTextSiz, ECX
45478 CALL System.Move
45480 @@eatb:
45481 ADD EDI, [EBX].fTextBuf // EDI ~ P
45483 MOV ECX, [EBX].fList
45484 INC ECX
45485 LOOP @@2
45486 CALL NewList
45487 MOV [EBX].fList, EAX
45488 @@2:
45489 POP ECX
45490 MOV EDX, [EBX].fCount
45492 PUSH EDI
45493 PUSH ECX
45494 MOV AL, $0D
45496 @@loo1: CMP byte ptr [EDI], 0
45497 JZ @@eloo1
45499 INC EDX
45500 REPNZ SCASB
45501 JNZ @@eloo1
45503 CMP byte ptr [EDI], $0A
45504 JNZ @@loo1
45505 INC EDI
45506 LOOP @@loo1
45508 @@eloo1:
45509 MOV [EBX].fCount, EDX
45510 MOV EAX, [EBX].fList
45511 PUSH EDX
45512 PUSH EAX
45513 CMP EDX, [EAX].TList.fCapacity
45514 JLE @@3
45515 CALL TList.SetCapacity
45516 @@3: POP EAX
45517 POP ECX
45519 XCHG ECX, [EAX].TList.fCount
45520 MOV EDX, [EAX].TList.fItems
45521 LEA EDX, [EDX+ECX*4]
45523 POP ECX
45524 POP EDI
45526 MOV EAX, $0D
45527 @@loo2: CMP byte ptr [EDI], AH
45528 JZ @@eloo2
45530 MOV [EDX], EDI
45531 ADD EDX, 4
45533 REPNZ SCASB
45534 JNZ @@eloo2
45536 MOV [EDI-1], AH
45538 CMP byte ptr [EDI], $0A
45539 JNZ @@loo2
45540 INC EDI
45541 LOOP @@loo2
45542 @@eloo2:
45544 POP EDI
45545 POP EBX
45546 @@exit:
45547 end;
45548 {$ELSE ASM_VERSION} //Pascal
45549 //[procedure TStrList.SetText]
45550 procedure TStrList.SetText(const S: string; Append2List: boolean);
45552 P, TheLast : PChar;
45553 L, I : Integer;
45555 procedure AddTextBuf(Src: PChar; Len: DWORD);
45556 var OldTextBuf, P: PChar;
45557 I : Integer;
45558 begin
45559 if Src <> nil then
45560 begin
45561 OldTextBuf := fTextBuf;
45562 GetMem( fTextBuf, fTextSiz + Len );
45563 if fTextSiz <> 0 then
45564 begin
45565 System.Move( OldTextBuf^, fTextBuf^, fTextSiz );
45566 for I := 0 to fCount - 1 do
45567 begin
45568 P := fList.fItems[ I ];
45569 if (DWORD( P ) >= DWORD( OldTextBuf )) and
45570 (DWORD( P ) < DWORD( OldTextBuf ) + fTextSiz) then
45571 fList.fItems[ I ] := Pointer( DWORD( P ) - DWORD( OldTextBuf ) + DWORD( fTextBuf ) );
45572 end;
45573 FreeMem( OldTextBuf );
45574 end;
45575 System.Move( Src^, fTextBuf[ fTextSiz ], Len );
45576 Inc( fTextSiz, Len );
45577 end;
45578 end;
45580 begin
45581 if not Append2List then Clear;
45582 if S = '' then Exit;
45584 L := fTextSiz;
45585 AddTextBuf( PChar( S ), Length( S ) + 1 );
45587 P := PChar( DWORD( fTextBuf ) + DWORD( L ) );
45588 if fList = nil then
45589 fList := NewList;
45591 I := 0;
45592 TheLast := P + Length( S );
45593 while P^ <> #0 do
45594 begin
45595 Inc( I );
45596 P := StrScanLen( P, #13, TheLast - P );
45597 if P^ = #10 then
45598 Inc( P );
45599 end;
45601 Inc( fCount, I );
45602 if fList.fCapacity < fCount then
45603 fList.Capacity := fCount;
45605 P := PChar( DWORD( fTextBuf ) + DWORD( L ) );
45606 while P^ <> #0 do
45607 begin
45608 fList.Add( P );
45609 P := StrScanLen( P, #13, TheLast - P );
45610 if PChar( P - 1 )^ = #13 then
45611 PChar( P - 1 )^ := #0;
45612 if P^ = #10 then Inc(P);
45613 end;
45614 end;
45615 {$ENDIF ASM_VERSION}
45617 //[procedure TStrList.SetUnixText]
45618 procedure TStrList.SetUnixText(const S: String; Append2List: Boolean);
45619 var S1: String;
45620 begin
45621 S1 := S;
45622 NormalizeUnixText( S1 );
45623 SetText( S1, Append2List );
45624 end;
45626 //[procedure TStrList.SetTextStr]
45627 procedure TStrList.SetTextStr(const Value: string);
45628 begin
45629 SetText( Value, False );
45630 end;
45632 //[PROCEDURE LowerCaseStrFromPCharEDX]
45633 {$IFDEF ASM_VERSION}
45634 procedure LowerCaseStrFromPCharEDX;
45636 { <- EDX = PChar string
45637 -> [ESP] = LowerCase( PChar( EDX ) ),
45638 EAX, EDX, ECX - ?
45640 POP EAX
45641 PUSH 0
45642 PUSH EAX
45643 LEA EAX, [ESP+4]
45644 PUSH EAX
45645 CALL System.@LStrFromPChar
45646 POP EDX
45647 MOV EAX, [EDX]
45648 JMP LowerCase
45649 end;
45650 {$ENDIF ASM_VERSION}
45651 //[END LowerCaseStrFromPCharEDX]
45653 //[FUNCTION CompareStrListItems]
45654 {$IFDEF ASM_VERSION}
45655 function CompareStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
45657 CMP [EAX].TStrList.fCaseSensitiveSort, 0
45658 MOV EAX, [EAX].TStrList.fList
45659 MOV EAX, [EAX].TList.fItems
45660 MOV EDX, [EAX+EDX*4]
45661 MOV EAX, [EAX+ECX*4]
45662 XCHG EAX, EDX
45663 JNZ StrComp
45664 PUSH EBX
45666 XCHG EBX, EAX
45667 CALL LowerCaseStrFromPCharEDX
45669 MOV EDX, EBX
45670 CALL LowerCaseStrFromPCharEDX
45672 POP EAX
45673 POP EDX
45674 PUSH EDX
45675 PUSH EAX
45676 CALL EAX2PChar
45677 CALL EDX2PChar
45678 CALL StrComp
45679 XCHG EBX, EAX
45681 CALL RemoveStr
45682 CALL RemoveStr
45684 XCHG EAX, EBX
45685 POP EBX
45686 end;
45687 {$ELSE ASM_VERSION} //Pascal
45688 function CompareStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
45689 var S1, S2 : PChar;
45690 begin
45691 S1 := PStrList( Sender ).fList.Items[ e1 ];
45692 S2 := PStrList( Sender ).fList.Items[ e2 ];
45693 if PStrList( Sender ).fCaseSensitiveSort then
45694 Result := StrComp( S1, S2 )
45695 else
45696 Result := StrComp( PChar( LowerCase( S1 ) ), PChar( LowerCase( S2 ) ) );
45697 end;
45698 {$ENDIF ASM_VERSION}
45699 //[END CompareStrListItems]
45701 //[FUNCTION CompareAnsiStrListItems]
45702 {$IFDEF ASM_VERSION}
45703 function CompareAnsiStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
45705 CMP byte ptr [EAX].TStrList.fCaseSensitiveSort, 0
45706 MOV EAX, [EAX].TStrList.fList
45707 MOV EAX, [EAX].TList.fItems
45708 MOV EDX, [EAX+EDX*4]
45709 MOV EAX, [EAX+ECX*4]
45710 XCHG EAX, EDX
45711 JZ _AnsiCompareStrNoCase
45712 JMP _AnsiCompareStr
45713 end;
45714 {$ELSE ASM_VERSION} //Pascal
45715 function CompareAnsiStrListItems( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
45716 var S1, S2 : PChar;
45717 begin
45718 S1 := PStrList( Sender ).fList.Items[ e1 ];
45719 S2 := PStrList( Sender ).fList.Items[ e2 ];
45720 if PStrList( Sender ).fCaseSensitiveSort then
45721 Result := _AnsiCompareStr( S1, S2 )
45722 else
45723 Result := _AnsiCompareStrNoCase( S1, S2 );
45724 end;
45725 {$ENDIF ASM_VERSION}
45726 //[END CompareAnsiStrListItems]
45728 {$IFNDEF ASM_VERSION}
45729 //[procedure SwapStrListItems]
45730 procedure SwapStrListItems( const Sender: Pointer; const e1, e2: DWORD );
45731 begin
45732 PStrList( Sender ).Swap( e1, e2 );
45733 end;
45734 {$ENDIF}
45736 {$IFDEF ASM_VERSION}
45737 //[procedure TStrList.Sort]
45738 procedure TStrList.Sort(CaseSensitive: Boolean);
45740 MOV [EAX].fCaseSensitiveSort, DL
45741 PUSH Offset[TStrList.Swap]
45742 MOV ECX, Offset[CompareStrListItems]
45743 MOV EDX, [EAX].fCount
45744 CALL SortData
45745 end;
45746 {$ELSE ASM_VERSION} //Pascal
45747 procedure TStrList.Sort(CaseSensitive: Boolean);
45748 begin
45749 fCaseSensitiveSort := CaseSensitive;
45750 SortData( @Self, fCount, @CompareStrListItems, @SwapStrListItems );
45751 end;
45752 {$ENDIF ASM_VERSION}
45754 {$IFDEF ASM_VERSION}
45755 //[procedure TStrList.AnsiSort]
45756 procedure TStrList.AnsiSort(CaseSensitive: Boolean);
45758 MOV [EAX].fCaseSensitiveSort, DL
45759 PUSH Offset[TStrList.Swap]
45760 MOV ECX, Offset[CompareAnsiStrListItems]
45761 MOV EDX, [EAX].fCount
45762 CALL SortData
45763 end;
45764 {$ELSE ASM_VERSION} //Pascal
45765 procedure TStrList.AnsiSort(CaseSensitive: Boolean);
45766 begin
45767 fCaseSensitiveSort := CaseSensitive;
45768 SortData( @Self, fCount, @CompareAnsiStrListItems, @SwapStrListItems );
45769 end;
45770 {$ENDIF ASM_VERSION}
45772 //[procedure TStrList.Swap]
45773 procedure TStrList.Swap(Idx1, Idx2: Integer);
45774 begin
45775 fList.Swap( Idx1, Idx2 );
45776 end;
45778 //[function TStrList.Last]
45779 function TStrList.Last: String;
45780 begin
45781 if Count = 0 then
45782 Result := ''
45783 else
45784 Result := Items[ Count - 1 ];
45785 end;
45787 //-- code by Dod:
45788 //[function TStrList.IndexOfName]
45789 function TStrList.IndexOfName(AName: string): Integer;
45791 i: Integer;
45792 L: Integer;
45793 begin
45794 Result:=-1;
45795 // Do not start search if empty string
45796 L := Length( AName );
45797 if L > 0 then
45798 begin
45799 AName := LowerCase( AName ) + fNameDelim;
45800 Inc( L );
45801 for i := 0 to fCount - 1 do
45802 begin
45803 // For optimization, check only list entry that begin with same letter as searched name
45804 if StrLComp( PChar( LowerCase( ItemPtrs[ i ] ) ), PChar( AName ), L ) = 0 then
45805 begin
45806 Result:=i;
45807 exit;
45808 end;
45809 end;
45810 end;
45811 end;
45813 //-- code by Dod:
45814 //[function TStrList.GetValue]
45815 function TStrList.GetValue(const AName: string): string;
45817 i: Integer;
45818 begin
45819 I := IndexOfName(AName);
45820 if I >= 0
45821 then Result := Copy(Items[i], Length(AName) + 2, Length(Items[i])-Length(AName)-1)
45822 else Result := '';
45823 end;
45825 //-- code by Dod:
45826 //[procedure TStrList.SetValue]
45827 procedure TStrList.SetValue(const AName, Value: string);
45829 I: Integer;
45830 begin
45831 I := IndexOfName(AName);
45832 if i=-1
45833 then Add( AName + fNameDelim + Value )
45834 else Items[i] := AName + fNameDelim + Value;
45835 end;
45837 //[function TStrList.GetLineName]
45838 function TStrList.GetLineName(Idx: Integer): string;
45839 begin
45840 Result := Items[ Idx ];
45841 Result := Parse( Result, fNameDelim );
45842 end;
45844 //[procedure TStrList.SetLineName]
45845 procedure TStrList.SetLineName(Idx: Integer; const NV: string);
45846 begin
45847 Items[ Idx ] := NV + fNameDelim + LineValue[ Idx ];
45848 end;
45850 //[function TStrList.GetLineValue]
45851 function TStrList.GetLineValue(Idx: Integer): string;
45852 begin
45853 Result := Items[ Idx ];
45854 Parse( Result, fNameDelim );
45855 end;
45857 //[procedure TStrList.SetLineValue]
45858 procedure TStrList.SetLineValue(Idx: Integer; const Value: string);
45859 begin
45860 Items[ Idx ] := LineName[ Idx ] + fNameDelim + Value;
45861 end;
45863 function TStrList.Join( const sep: String ): String;
45865 I, Len, Size: integer;
45866 P: PChar;
45867 begin
45868 Size := 0;
45870 for I := 0 to Count - 1 do
45871 Inc(Size, Integer( StrLen( ItemPtrs[I] ) ) + Length(Sep));
45873 SetString(Result, nil, Size);
45875 P := @ Result[ 1 ];
45876 for I := 0 to Count - 1 do
45877 begin
45878 Len := StrLen( ItemPtrs[I] );
45879 if (Len > 0) then
45880 begin
45881 System.Move( ItemPtrs[I]^, P^, Len);
45882 Inc(P, Len);
45883 end;
45884 P := StrPCopy(P, Sep);
45885 end;
45886 end;
45888 ////////////////////////////////// EXTENDED STRING LIST OBJECT ////////////////
45890 { TStrListEx }
45892 //[function NewStrListEx]
45893 function NewStrListEx: PStrListEx;
45894 begin
45896 new( Result, Create );
45898 {++}(*
45899 Result := PStrListEx.Create;
45900 *){--}
45901 end;
45902 //[END NewStrListEx]
45904 //[destructor TStrListEx.Destroy]
45905 destructor TStrListEx.Destroy;
45906 var Obj: PList;
45907 begin
45908 Obj := FObjects;
45909 inherited;
45910 Obj.Free;
45911 end;
45913 //[function TStrListEx.GetObjects]
45914 function TStrListEx.GetObjects(Idx: Integer): DWORD;
45915 begin
45916 Result := DWORD( FObjects.Items[ Idx ] );
45917 end;
45919 //[procedure TStrListEx.SetObjects]
45920 procedure TStrListEx.SetObjects(Idx: Integer; const Value: DWORD);
45921 begin
45922 ProvideObjCapacity( Idx + 1 );
45923 FObjects.Items[ Idx ] := Pointer( Value );
45924 end;
45926 //[procedure TStrListEx.Init]
45927 procedure TStrListEx.Init;
45928 begin
45929 FObjects := NewList;
45930 end;
45932 //[procedure SwapStrListExItems]
45933 procedure SwapStrListExItems( const Sender: Pointer; const e1, e2: DWORD );
45934 begin
45935 PStrListEx( Sender ).Swap( e1, e2 );
45936 end;
45938 //[procedure TStrListEx.AnsiSort]
45939 procedure TStrListEx.AnsiSort(CaseSensitive: Boolean);
45940 begin
45941 fCaseSensitiveSort := CaseSensitive;
45942 SortData( @Self, fCount, @CompareAnsiStrListItems, @SwapStrListExItems );
45943 end;
45945 //[procedure TStrListEx.Sort]
45946 procedure TStrListEx.Sort(CaseSensitive: Boolean);
45947 begin
45948 fCaseSensitiveSort := CaseSensitive;
45949 SortData( @Self, fCount, @CompareStrListItems, @SwapStrListExItems );
45950 end;
45952 //[procedure TStrListEx.Move]
45953 procedure TStrListEx.Move(CurIndex, NewIndex: integer);
45954 begin
45955 // move string
45956 fList.MoveItem( CurIndex, NewIndex );
45957 // move object
45958 if FObjects.fCount >= Min( CurIndex, NewIndex ) then
45959 begin
45960 ProvideObjCapacity( max( CurIndex, NewIndex ) + 1 );
45961 FObjects.MoveItem( CurIndex, NewIndex );
45962 end;
45963 end;
45965 //[procedure TStrListEx.Swap]
45966 procedure TStrListEx.Swap(Idx1, Idx2: Integer);
45967 begin
45968 // swap strings
45969 fList.Swap( Idx1, Idx2 );
45970 // swap objects
45971 if FObjects.fCount >= Min( Idx1, Idx2 ) then
45972 begin
45973 ProvideObjCapacity( max( Idx1, Idx2 ) + 1 );
45974 FObjects.Swap( Idx1, Idx2 );
45975 end;
45976 end;
45978 //[procedure TStrListEx.ProvideObjCapacity]
45979 procedure TStrListEx.ProvideObjCapacity(NewCap: Integer);
45980 begin
45981 if FObjects.FCount < NewCap then
45982 begin
45983 FObjects.Capacity := NewCap;
45984 FillChar( FObjects.FItems[ FObjects.FCount ],
45985 (FObjects.Capacity - FObjects.Count) * sizeof( Pointer ), 0 );
45986 FObjects.FCount := NewCap;
45987 end;
45988 end;
45990 //[procedure TStrListEx.AddStrings]
45991 procedure TStrListEx.AddStrings(Strings: PStrListEx);
45992 var I: Integer;
45993 begin
45994 I := Count;
45995 if Strings.FObjects.fCount > 0 then
45996 ProvideObjCapacity( Count );
45997 inherited AddStrings( Strings );
45998 if Strings.FObjects.fCount > 0 then
45999 begin
46000 ProvideObjCapacity( I + Strings.FObjects.fCount );
46001 System.Move( Strings.FObjects.FItems[ 0 ],
46002 FObjects.FItems[ I ],
46003 Sizeof( Pointer ) * Strings.FObjects.fCount );
46004 end;
46005 end;
46007 //[procedure TStrListEx.Assign]
46008 procedure TStrListEx.Assign(Strings: PStrListEx);
46009 begin
46010 inherited Assign( Strings );
46011 FObjects.Assign( Strings.FObjects );
46012 end;
46014 //[procedure TStrListEx.Clear]
46015 procedure TStrListEx.Clear;
46016 begin
46017 inherited;
46018 FObjects.Clear;
46019 end;
46021 //[procedure TStrListEx.Delete]
46022 procedure TStrListEx.Delete(Idx: integer);
46023 begin
46024 inherited;
46025 if FObjects.fCount > Idx then // mdw: '>=' -> '>'
46026 FObjects.Delete( Idx );
46027 end;
46029 //[function TStrListEx.LastObj]
46030 function TStrListEx.LastObj: DWORD;
46031 begin
46032 if Count = 0 then
46033 Result := 0
46034 else
46035 Result := Objects[ Count - 1 ];
46036 end;
46038 //[function TStrListEx.AddObject]
46039 function TStrListEx.AddObject(const S: String; Obj: DWORD): Integer;
46040 begin
46041 Result := Count;
46042 InsertObject( Count, S, Obj );
46043 end;
46045 //[procedure TStrListEx.InsertObject]
46046 procedure TStrListEx.InsertObject(Before: Integer; const S: String; Obj: DWORD);
46047 begin
46048 Insert( Before, S );
46049 FObjects.Insert( Before, Pointer( Obj ) );
46050 end;
46052 //[function TStrListEx.IndexOfObj]
46053 function TStrListEx.IndexOfObj( Obj: Pointer ): Integer;
46054 begin
46055 Result := FObjects.IndexOf( Obj );
46056 end;
46058 //[function WStrLen]
46059 function WStrLen( W: PWideChar ): Integer;
46061 XCHG EDI, EAX
46062 XCHG EDX, EAX
46063 OR ECX, -1
46064 XOR EAX, EAX
46065 CMP EAX, EDI
46066 JE @@exit0
46067 REPNE SCASW
46068 DEC EAX
46069 DEC EAX
46070 SUB EAX, ECX
46071 @@exit0:
46072 MOV EDI, EDX
46073 end;
46077 //////////////////////////////////////////////////////////////////////////
46080 // S O R T I N G
46083 //////////////////////////////////////////////////////////////////////////
46085 { -- qsort -- }
46087 //[PROCEDURE SortData]
46088 {$IFDEF ASM_VERSION} // translated to BASM by Kladov Vladimir
46089 procedure SortData( const Data: Pointer; const uNElem: Dword;
46090 const CompareFun: TCompareEvent;
46091 const SwapProc: TSwapEvent );
46093 CMP EDX, 2
46094 JL @@exit
46096 PUSH EAX // [EBP-4] = Data
46097 PUSH ECX // [EBP-8] = CompareFun
46098 PUSH EBX // EBX = pivotP
46099 XOR EBX, EBX
46100 INC EBX // EBX = 1 to pass to qSortHelp as PivotP
46101 MOV EAX, EDX // EAX = nElem
46102 CALL @@qSortHelp
46103 POP EBX
46104 POP ECX
46105 POP ECX
46106 @@exit:
46107 POP EBP
46108 RET 4
46110 @@qSortHelp:
46111 PUSH EBX // EBX (in) = PivotP
46112 PUSH ESI // ESI = leftP
46113 PUSH EDI // EDI = rightP
46115 @@TailRecursion:
46116 CMP EAX, 2
46117 JG @@2
46118 JNE @@exit_qSortHelp
46119 LEA ECX, [EBX+1]
46120 MOV EDX, EBX
46121 CALL @@Compare
46122 JLE @@exit_qSortHelp
46123 @@swp_exit:
46124 CALL @@Swap
46125 @@exit_qSortHelp:
46126 POP EDI
46127 POP ESI
46128 POP EBX
46131 // ESI = leftP
46132 // EDI = rightP
46133 @@2: LEA EDI, [EAX+EBX-1]
46134 MOV ESI, EAX
46135 SHR ESI, 1
46136 ADD ESI, EBX
46137 MOV ECX, ESI
46138 MOV EDX, EDI
46139 CALL @@CompareLeSwap
46140 MOV EDX, EBX
46141 CALL @@Compare
46143 JG @@4
46144 CALL @@Swap
46145 JMP @@5
46146 @@4: MOV ECX, EBX
46147 MOV EDX, EDI
46148 CALL @@CompareLeSwap
46149 @@5:
46150 CMP EAX, 3
46151 JNE @@6
46152 MOV EDX, EBX
46153 MOV ECX, ESI
46154 JMP @@swp_exit
46155 @@6: // classic Horae algorithm
46157 PUSH EAX // EAX = pivotEnd
46158 LEA EAX, [EBX+1]
46159 MOV ESI, EAX
46160 @@repeat:
46161 MOV EDX, ESI
46162 MOV ECX, EBX
46163 CALL @@Compare
46164 JG @@while2
46165 @@while1:
46166 JNE @@7
46167 MOV EDX, ESI
46168 MOV ECX, EAX
46169 CALL @@Swap
46170 INC EAX
46171 @@7:
46172 CMP ESI, EDI
46173 JGE @@qBreak
46174 INC ESI
46175 JMP @@repeat
46176 @@while2:
46177 CMP ESI, EDI
46178 JGE @@until
46179 MOV EDX, EBX
46180 MOV ECX, EDI
46181 CALL @@Compare
46182 JGE @@8
46183 DEC EDI
46184 JMP @@while2
46185 @@8:
46186 MOV EDX, ESI
46187 MOV ECX, EDI
46188 PUSHFD
46189 CALL @@Swap
46190 POPFD
46191 JE @@until
46192 INC ESI
46193 DEC EDI
46194 @@until:
46195 CMP ESI, EDI
46196 JL @@repeat
46197 @@qBreak:
46198 MOV EDX, ESI
46199 MOV ECX, EBX
46200 CALL @@Compare
46201 JG @@9
46202 INC ESI
46203 @@9:
46204 PUSH EBX // EBX = PivotTemp
46205 PUSH ESI // ESI = leftTemp
46206 DEC ESI
46207 @@while3:
46208 CMP EBX, EAX
46209 JGE @@while3_break
46210 CMP ESI, EAX
46211 JL @@while3_break
46212 MOV EDX, EBX
46213 MOV ECX, ESI
46214 CALL @@Swap
46215 INC EBX
46216 DEC ESI
46217 JMP @@while3
46218 @@while3_break:
46219 POP ESI
46220 POP EBX
46222 MOV EDX, EAX
46223 POP EAX // EAX = nElem
46224 PUSH EDI // EDI = lNum
46225 MOV EDI, ESI
46226 SUB EDI, EDX
46227 ADD EAX, EBX
46228 SUB EAX, ESI
46230 PUSH EBX
46231 PUSH EAX
46232 CMP EAX, EDI
46233 JGE @@10
46235 MOV EBX, ESI
46236 CALL @@qSortHelp
46237 POP EAX
46238 MOV EAX, EDI
46239 POP EBX
46240 JMP @@11
46242 @@10: MOV EAX, EDI
46243 CALL @@qSortHelp
46244 POP EAX
46245 POP EBX
46246 MOV EBX, ESI
46247 @@11:
46248 POP EDI
46249 JMP @@TailRecursion
46251 @@Compare:
46252 PUSH EAX
46253 PUSH EDX
46254 PUSH ECX
46255 MOV EAX, [EBP-4]
46256 DEC EDX
46257 DEC ECX
46258 CALL dword ptr [EBP-8]
46259 POP ECX
46260 POP EDX
46261 TEST EAX, EAX
46262 POP EAX
46265 @@CompareLeSwap:
46266 CALL @@Compare
46267 JG @@ret
46269 @@Swap: PUSH EAX
46270 PUSH EDX
46271 PUSH ECX
46272 MOV EAX, [EBP-4]
46273 DEC EDX
46274 DEC ECX
46275 CALL dword ptr [SwapProc]
46276 POP ECX
46277 POP EDX
46278 TEST EAX, EAX
46279 POP EAX
46280 @@ret:
46283 end;
46284 {$ELSE ASM_VERSION} //Pascal
46285 procedure SortData( const Data: Pointer; const uNElem: Dword;
46286 const CompareFun: TCompareEvent;
46287 const SwapProc: TSwapEvent );
46288 { uNElem - number of elements to sort }
46290 function Compare( const e1, e2 : DWord ) : Integer;
46291 begin
46292 Result := CompareFun( Data, e1 - 1, e2 - 1 );
46293 end;
46295 procedure Swap( const e1, e2 : DWord );
46296 begin
46297 SwapProc( Data, e1 - 1, e2 - 1 );
46298 end;
46300 procedure qSortHelp(pivotP: Dword; nElem: Dword);
46301 label
46302 TailRecursion,
46303 qBreak;
46305 leftP, rightP, pivotEnd, pivotTemp, leftTemp: Dword;
46306 lNum: Dword;
46307 retval: integer;
46308 begin
46309 TailRecursion:
46310 if (nElem <= 2) then
46311 begin
46312 if (nElem = 2) then
46313 begin
46314 rightP := pivotP +1;
46315 retval := Compare(pivotP,rightP);
46316 if (retval > 0) then Swap(pivotP,rightP);
46317 end;
46318 exit;
46319 end;
46320 rightP := (nElem -1) + pivotP;
46321 leftP := (nElem shr 1) + pivotP;
46322 { sort pivot, left, and right elements for "median of 3" }
46323 retval := Compare(leftP,rightP);
46324 if (retval > 0) then Swap(leftP, rightP);
46325 retval := Compare(leftP,pivotP);
46327 if (retval > 0) then
46328 Swap(leftP, pivotP)
46329 else
46330 begin
46331 retval := Compare(pivotP,rightP);
46332 if retval > 0 then Swap(pivotP, rightP);
46333 end;
46334 if (nElem = 3) then
46335 begin
46336 Swap(pivotP, leftP);
46337 exit;
46338 end;
46339 { now for the classic Horae algorithm }
46340 pivotEnd := pivotP + 1;
46341 leftP := pivotEnd;
46342 repeat
46344 retval := Compare(leftP, pivotP);
46345 while (retval <= 0) do
46346 begin
46348 if (retval = 0) then
46349 begin
46350 Swap(leftP, pivotEnd);
46351 Inc(pivotEnd);
46352 end;
46353 if (leftP < rightP) then
46354 Inc(leftP)
46355 else
46356 goto qBreak;
46357 retval := Compare(leftP, pivotP);
46358 end; {while}
46359 while (leftP < rightP) do
46360 begin
46361 retval := Compare(pivotP, rightP);
46362 if (retval < 0) then
46363 Dec(rightP)
46365 else
46366 begin
46367 Swap(leftP, rightP);
46368 if (retval <> 0) then
46369 begin
46370 Inc(leftP);
46371 Dec(rightP);
46372 end;
46373 break;
46374 end;
46375 end; {while}
46377 until (leftP >= rightP);
46378 qBreak:
46379 retval := Compare(leftP,pivotP);
46380 if (retval <= 0) then Inc(leftP);
46382 leftTemp := leftP -1;
46383 pivotTemp := pivotP;
46384 while ((pivotTemp < pivotEnd) and (leftTemp >= pivotEnd)) do
46385 begin
46386 Swap(pivotTemp, leftTemp);
46387 Inc(pivotTemp);
46388 Dec(leftTemp);
46389 end; {while}
46390 lNum := (leftP - pivotEnd);
46391 nElem := ((nElem + pivotP) -leftP);
46393 if (nElem < lNum) then
46394 begin
46395 qSortHelp(leftP, nElem);
46396 nElem := lNum;
46398 else
46399 begin
46400 qSortHelp(pivotP, lNum);
46401 pivotP := leftP;
46402 end;
46403 goto TailRecursion;
46404 end; {qSortHelp }
46406 begin
46407 if (uNElem < 2) then exit; { nothing to sort }
46408 qSortHelp(1, uNElem);
46409 end;
46410 {$ENDIF ASM_VERSION}
46411 //[END SortData]
46413 //[FUNCTION CompareIntegers]
46414 {$IFDEF ASM_VERSION}
46415 function CompareIntegers( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46417 MOV EDX, [EAX+EDX*4]
46418 SUB EDX, [EAX+ECX*4]
46419 XCHG EAX, EDX
46420 end;
46421 {$ELSE ASM_VERSION} //Pascal
46422 function CompareIntegers( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46423 var I1, I2 : Integer;
46424 begin
46425 I1 := PInteger( DWORD( Sender ) + e1 * Sizeof( Integer ) )^;
46426 I2 := PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;
46427 Result := 0;
46428 if I1 < I2 then Result := -1
46429 else
46430 if I1 > I2 then Result := 1;
46431 end;
46432 {$ENDIF ASM_VERSION}
46433 //[END CompareIntegers]
46435 //[FUNCTION CompareDwords]
46436 {$IFDEF ASM_VERSION}
46437 function CompareDwords( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46439 MOV EDX, [EAX+EDX*4]
46440 SUB EDX, [EAX+ECX*4]
46441 XCHG EAX, EDX
46442 JNB @@1
46443 SBB EAX, EAX
46444 @@1:
46445 end;
46446 {$ELSE ASM_VERSION} //Pascal
46447 function CompareDwords( const Sender : Pointer; const e1, e2 : DWORD ) : Integer;
46448 var I1, I2 : DWord;
46449 begin
46450 I1 := PDWORD( DWORD( Sender ) + e1 * Sizeof( Integer ) )^;
46451 I2 := PDWORD( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;
46452 Result := 0;
46453 if I1 < I2 then Result := -1
46454 else
46455 if I1 > I2 then Result := 1;
46456 end;
46457 {$ENDIF ASM_VERSION}
46458 //[END CompareDwords]
46460 //[PROCEDURE SwapIntegers]
46461 {$IFDEF ASM_VERSION}
46462 procedure SwapIntegers( const Sender : Pointer; const e1, e2 : DWORD );
46464 LEA EDX, [EAX+EDX*4]
46465 LEA ECX, [EAX+ECX*4]
46466 MOV EAX, [EDX]
46467 XCHG EAX, [ECX]
46468 MOV [EDX], EAX
46469 end;
46470 {$ELSE ASM_VERSION} //Pascal
46471 procedure SwapIntegers( const Sender : Pointer; const e1, e2 : DWORD );
46472 var Tmp : Integer;
46473 begin
46474 Tmp := PInteger( DWORD( Sender ) + e1 * SizeOf( Integer ) )^;
46475 PInteger( DWORD( Sender ) + e1 * Sizeof( Integer ) )^ :=
46476 PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^;
46477 PInteger( DWORD( Sender ) + e2 * Sizeof( Integer ) )^ := Tmp;
46478 end;
46479 {$ENDIF ASM_VERSION}
46480 //[END SwapIntegers]
46482 //[procedure SortIntegerArray]
46483 procedure SortIntegerArray( var A : array of Integer );
46484 begin
46485 SortData( @A[ 0 ], High( A ) - Low( A ) + 1, @CompareIntegers, @SwapIntegers );
46486 end;
46488 //[procedure SortDwordArray]
46489 procedure SortDwordArray( var A : array of DWORD );
46490 begin
46491 SortData( @A[ 0 ], High( A ) - Low( A ) + 1, @CompareDwords, @SwapIntegers );
46492 end;
46495 { -- status bar implementation -- }
46497 //[FUNCTION _NewStatusbar]
46498 {$IFDEF ASM_VERSION}
46499 function _NewStatusbar( AParent: PControl ): PControl;
46500 const STAT_CLS_NAM: PChar = STATUSCLASSNAME;
46502 PUSH 0
46503 PUSH 0
46504 //PUSH EAX
46505 //CALL TControl.GetCanResize
46506 CMP [EAX].TControl.fSizeGrip, 0
46507 MOV ECX, WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or 3 or WS_VISIBLE
46508 //MOV CH, AL // SBARS_SIZEGRIP = $0100
46509 JZ @@1
46510 //SETNZ CH
46511 INC CH
46512 AND CL, not 3
46513 @@1:
46514 //POP EAX
46515 MOV EDX, [STAT_CLS_NAM]
46516 CALL _NewCommonControl
46517 PUSH EBX
46518 XCHG EBX, EAX
46519 PUSH EDI
46520 LEA EDI, [EBX].TControl.fBoundsRect
46521 XOR EAX, EAX
46522 STOSD
46523 STOSD
46524 STOSD
46525 STOSD
46526 MOV [EBX].TControl.fAlign, caBottom
46527 INC [EBX].TControl.fNotUseAlign
46528 POP EDI
46529 MOV EAX, EBX
46530 CALL InitCommonControlSizeNotify
46531 XCHG EAX, EBX
46532 POP EBX
46533 end;
46534 {$ELSE ASM_VERSION} //Pascal
46535 function _NewStatusbar( AParent: PControl ): PControl;
46536 var Style: DWORD;
46537 //R: TRect;
46538 begin
46539 Style := WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or 3 or WS_VISIBLE;
46540 {if AParent.CanResize then
46541 Style := Style or SBARS_SIZEGRIP;}
46542 if AParent.fSizeGrip then
46543 Style := (Style or SBARS_SIZEGRIP) and not 3;
46544 Result := _NewCommonControl( AParent, STATUSCLASSNAME,
46545 Style, FALSE, nil );
46547 with Result.fBoundsRect do
46548 begin
46549 Left := 0;
46550 Right := 0;
46551 Top := 0;
46552 Bottom := 0;
46553 end;
46554 Result.fAlign := caBottom;
46555 Result.fNotUseAlign := True;
46556 {$IFDEF TEST_VERSION}
46557 Result.fTag := DWORD( PChar( 'Status bar' ) );
46558 {$ENDIF}
46559 InitCommonControlSizeNotify( Result );
46560 //R := AParent.ClientRect;
46561 //AParent.Perform( WM_SIZING, WMSZ_TOPLEFT, Integer( @ R ) );
46562 //Result.AttachProc( WndProcEraseBkgnd );
46563 end;
46564 {$ENDIF ASM_VERSION}
46565 //[END _NewStatusbar]
46567 {$IFDEF ASM_VERSION}
46568 //[procedure TControl.SetStatusText]
46569 procedure TControl.SetStatusText(Index: Integer; Value: PChar);
46571 PUSHAD
46572 MOV EBX, EDX // EBX = Index
46573 MOV ESI, EAX // ESI = @Self
46575 PUSH Value // prepare value for call at the end of procedure
46576 PUSH EBX // prepare Index for call at the end of procedure
46578 MOV ECX, [ESI].fStatusCtl
46579 INC ECX
46580 LOOP @@status_created
46582 CALL GetClientHeight
46583 PUSH EAX // ch = old client height
46585 MOV EAX, ESI
46586 CALL _NewStatusBar
46587 MOV [ESI].fStatusCtl, EAX
46588 PUSH EAX //-----------v
46590 CALL TControl.GetWindowHandle
46591 MOV [ESI].fStatusWnd, EAX
46592 XCHG EDI, EAX
46593 POP EAX //-----------^
46595 XOR EDX, EDX
46596 PUSH EDX
46597 INC DH
46598 DEC EDX
46599 CMP EBX, EDX
46600 SETZ DL
46601 NEG EDX
46603 @@1: PUSH EDX
46604 PUSH SB_SIMPLE
46606 PUSH EAX
46607 CALL TControl.Perform
46609 ADD ESP, -16
46610 PUSH ESP
46611 PUSH [ESI].fStatusWnd
46612 CALL GetWindowRect
46613 POP EAX
46614 POP EDX
46615 POP EAX
46616 POP EAX
46617 SUB EAX, EDX
46618 MOV [ESI].fClientBottom, EAX
46620 POP EDX // ch
46622 PUSH 0
46623 PUSH 0
46624 PUSH WM_SIZE
46625 PUSH EDI
46627 MOV EAX, ESI
46628 CALL TControl.SetClientHeight
46630 CALL SendMessage
46632 @@status_created:
46633 CMP EBX, 255
46634 JGE @@not_simple
46636 PUSH 0
46637 PUSH 0
46638 PUSH SB_GETPARTS
46639 PUSH [ESI].fStatusWnd
46640 CALL SendMessage
46642 CMP EAX, EBX
46643 JG @@reset_simple
46645 MOV EAX, ESI
46646 CALL GetWidth
46648 MOV ECX, EBX
46649 INC ECX
46650 IDIV ECX
46651 MOV EDX, EAX
46653 ADD ESP, -1024
46654 MOV ECX, EBX
46655 MOV EDI, ESP
46656 JECXZ @@2
46658 @@store_loo:
46659 STOSD
46660 ADD EAX, EDX
46661 LOOP @@store_loo
46662 @@2:
46663 OR dword ptr [ESP+EBX*4], -1
46664 PUSH ESP
46665 INC EBX
46666 PUSH EBX
46667 PUSH SB_SETPARTS
46668 PUSH [ESI].fStatusWnd
46669 CALL SendMessage
46670 ADD ESP, 1024
46672 @@reset_simple:
46673 PUSH 0
46674 PUSH 0
46675 PUSH SB_SIMPLE
46676 PUSH [ESI].fStatusWnd
46677 CALL SendMessage
46679 @@not_simple:
46680 PUSH SB_SETTEXT
46681 PUSH [ESI].fStatusWnd
46682 CALL SendMessage
46683 POPAD
46684 end;
46685 {$ELSE ASM_VERSION} //Pascal
46686 procedure TControl.SetStatusText(Index: Integer; Value: PChar);
46687 var ch: Integer;
46688 R : TRect;
46689 N, I, L, W : Integer;
46690 WidthsBuf: array[ 0..254 ] of Integer;
46691 begin
46692 if fStatusCtl = nil then
46693 begin
46694 ch := GetClientHeight;
46695 fStatusCtl := _NewStatusBar( @Self );
46696 fStatusWnd := fStatusCtl.GetWindowHandle;
46697 fStatusCtl.Perform( SB_SIMPLE, Integer( LongBool( Index = 255 ) ), 0 );
46698 GetWindowRect( fStatusWnd, R );
46699 fClientBottom := R.Bottom - R.Top;
46700 SetClientHeight( ch );
46701 SendMessage( fStatusWnd, WM_SIZE, 0, 0 );
46702 end;
46703 if Index < 255 then
46704 begin
46705 N := SendMessage( fStatusWnd, SB_GETPARTS, 0, 0 );
46706 if N <= Index then
46707 begin
46708 W := Width;
46709 L := W div (Index + 1);
46710 W := L;
46711 for I := 0 to Index - 1 do
46712 begin
46713 WidthsBuf[ I ] := W;
46714 Inc( W, L );
46715 end;
46716 WidthsBuf[ Index ] := -1;
46717 SendMessage( fStatusWnd, SB_SETPARTS, Index + 1, Integer( @WidthsBuf[ 0 ] ) );
46718 end;
46719 SendMessage( fStatusWnd, SB_SIMPLE, 0, 0 );
46720 end;
46721 SendMessage( fStatusWnd, SB_SETTEXT, Index, Integer( Value ) );
46722 end;
46723 {$ENDIF ASM_VERSION}
46725 {$IFDEF ASM_VERSION}
46726 //[function TControl.GetStatusText]
46727 function TControl.GetStatusText( Index: Integer ): PChar;
46729 MOV ECX, [EAX].fStatusWnd
46730 JECXZ @@exit
46732 PUSH EBX
46733 PUSH ESI
46734 XCHG ESI, EAX // ESI = @Self
46735 MOV EBX, EDX // EBX = Index
46737 XOR EAX, EAX
46738 XCHG EAX, [ESI].fStatusTxt
46739 TEST EAX, EAX
46740 JZ @@1
46741 CALL System.@FreeMem
46742 @@1:
46743 XOR EAX, EAX
46745 MOV DL, WM_GETTEXTLENGTH
46746 PUSH WM_GETTEXT
46747 CMP EBX, 255
46748 JZ @@2
46749 POP EAX
46750 MOV EAX, EBX
46751 MOV DX, SB_GETTEXTLENGTH
46752 PUSH SB_GETTEXT
46753 @@2:
46754 MOV EBX, EAX
46756 PUSH 0
46757 PUSH EAX
46758 PUSH EDX
46759 PUSH [ESI].fStatusWnd
46760 CALL SendMessage
46761 TEST AX, AX
46762 JZ @@get_rslt
46764 PUSH EAX
46765 INC EAX
46766 CALL System.@GetMem
46767 POP EDX
46768 MOV [ESI].fStatusTxt, EAX
46769 MOV byte ptr [EAX+EDX], 0
46771 POP EDX // Msg
46772 PUSH EAX
46773 PUSH EBX
46774 PUSH EDX
46775 PUSH [ESI].fStatusWnd
46776 CALL SendMessage
46777 PUSH EDX
46778 @@get_rslt:
46779 POP EDX
46780 MOV ECX, [ESI].fStatusTxt
46781 POP ESI
46782 POP EBX
46784 @@exit: XCHG EAX, ECX
46785 end;
46786 {$ELSE ASM_VERSION} //Pascal
46787 function TControl.GetStatusText( Index: Integer ): PChar;
46788 var L, I: Integer;
46789 Msg: DWORD;
46790 begin
46791 Result := nil;
46792 if fStatusWnd = 0 then Exit;
46793 if fStatusTxt <> nil then
46794 FreeMem( fStatusTxt );
46795 fStatusTxt := nil;
46796 Msg := SB_GETTEXTLENGTH;
46797 I := Index;
46798 if Index = 255 then
46799 begin
46800 Msg := WM_GETTEXTLENGTH;
46801 I := 0;
46802 end;
46803 L := SendMessage( fStatusWnd, Msg, I, 0 ) and $FFFF;
46804 if L > 0 then
46805 begin
46806 GetMem( fStatusTxt, L + 1 );
46807 fStatusTxt[ L ] := #0;
46808 Msg := SB_GETTEXT;
46809 if Index = 255 then
46810 Msg := WM_GETTEXT;
46811 SendMessage( fStatusWnd, Msg, I, Integer( fStatusTxt ) );
46812 end;
46813 Result := fStatusTxt;
46814 end;
46815 {$ENDIF ASM_VERSION}
46817 {$IFDEF ASM_VERSION}
46818 //[procedure TControl.RemoveStatus]
46819 procedure TControl.RemoveStatus;
46821 MOV ECX, [EAX].fStatusCtl
46822 JECXZ @@exit
46823 PUSH EBX
46824 MOV EBX, EAX
46825 CALL GetClientHeight
46826 PUSH EAX
46828 MOV [EBX].fStatusWnd, EDX
46829 XCHG EAX, EDX
46830 XCHG [EBX].fStatusCtl, EAX
46831 CALL TControl.Free
46832 POP EAX
46834 MOV [EBX].fClientBottom, EDX
46835 XCHG EDX, EAX
46836 XCHG EAX, EBX
46837 POP EBX
46838 CALL SetClientHeight
46839 @@exit:
46840 end;
46841 {$ELSE ASM_VERSION} //Pascal
46842 procedure TControl.RemoveStatus;
46843 var ch: Integer;
46844 begin
46845 if fStatusCtl = nil then Exit;
46846 ch := ClientHeight;
46847 fStatusWnd := 0;
46848 fStatusCtl.Free;
46849 fStatusCtl := nil;
46850 fClientBottom := 0;
46851 ClientHeight := ch;
46852 end;
46853 {$ENDIF ASM_VERSION}
46855 {$IFDEF ASM_VERSION}
46856 //[function TControl.StatusPanelCount]
46857 function TControl.StatusPanelCount: Integer;
46859 MOV EAX, [EAX].fStatusWnd
46860 TEST EAX, EAX
46861 JZ @@exit
46862 PUSH 0
46863 PUSH 0
46864 PUSH SB_GETPARTS
46865 PUSH EAX
46866 CALL SendMessage
46867 @@exit:
46868 end;
46869 {$ELSE ASM_VERSION} //Pascal
46870 function TControl.StatusPanelCount: Integer;
46871 begin
46872 Result := 0;
46873 if fStatusWnd = 0 then Exit;
46874 Result := SendMessage( fStatusWnd, SB_GETPARTS, 0, 0 );
46875 end;
46876 {$ENDIF ASM_VERSION}
46878 {$IFDEF ASM_VERSION}
46879 //[function TControl.GetStatusPanelX]
46880 function TControl.GetStatusPanelX(Idx: Integer): Integer;
46882 MOV ECX, [EAX].fStatusWnd
46883 JECXZ @@exit
46884 PUSH EBX
46885 MOV EBX, EDX
46886 ADD ESP, -1024
46887 PUSH ESP
46888 XOR EDX, EDX
46889 DEC DL
46890 PUSH EDX
46891 MOV DX, SB_GETPARTS
46892 PUSH EDX
46893 PUSH ECX
46894 CALL SendMessage
46895 CMP EAX, EBX
46896 MOV ECX, [ESP+EBX*4]
46897 JG @@1
46898 XOR ECX, ECX
46899 @@1: ADD ESP, 1024
46900 POP EBX
46901 @@exit:
46902 XCHG EAX, ECX
46903 end;
46904 {$ELSE ASM_VERSION} //Pascal
46905 function TControl.GetStatusPanelX(Idx: Integer): Integer;
46906 var Buf: array[0..254] of Integer;
46907 N : Integer;
46908 begin
46909 Result := 0;
46910 if fStatusWnd = 0 then Exit;
46911 N := SendMessage( fStatusWnd, SB_GETPARTS, 255, Integer( @Buf[ 0 ] ) );
46912 if N <= Idx then Exit;
46913 Result := Buf[ Idx ];
46914 end;
46915 {$ENDIF ASM_VERSION}
46917 {$IFDEF ASM_VERSION}
46918 //[procedure TControl.SetStatusPanelX]
46919 procedure TControl.SetStatusPanelX(Idx: Integer; const Value: Integer);
46921 ADD ESP, -1024
46922 MOV EAX, [EAX].fStatusWnd
46923 TEST EAX, EAX
46924 JZ @@exit
46926 PUSH ESP
46927 PUSH EDX
46928 PUSH SB_SETPARTS
46929 PUSH EAX
46931 PUSH EDX
46932 PUSH ECX
46934 LEA EDX, [ESP+24]
46935 PUSH EDX
46936 PUSH 255
46937 PUSH SB_GETPARTS
46938 PUSH EAX
46939 CALL SendMessage
46941 POP ECX
46942 POP EDX
46943 CMP EAX, EDX
46944 JG @@1
46945 ADD ESP, 16
46946 JMP @@exit
46948 @@1: MOV [ESP+8], EAX
46949 MOV [ESP+16+EDX*4], ECX
46950 CALL SendMessage
46952 @@exit: ADD ESP, 1024
46953 end;
46954 {$ELSE ASM_VERSION} //Pascal
46955 procedure TControl.SetStatusPanelX(Idx: Integer; const Value: Integer);
46956 var Buf: array[0..254] of Integer;
46957 N : Integer;
46958 begin
46959 if fStatusWnd = 0 then Exit;
46960 N := SendMessage( fStatusWnd, SB_GETPARTS, 255, Integer( @Buf[ 0 ] ) );
46961 if N <= Idx then Exit;
46962 Buf[ Idx ] := Value;
46963 SendMessage( fStatusWnd, SB_SETPARTS, N, Integer( @Buf[ 0 ] ) );
46964 end;
46965 {$ENDIF ASM_VERSION}
46967 //[procedure TControl.SetColor1]
46968 procedure TControl.SetColor1(const Value: TColor);
46969 begin
46970 fColor1 := Value;
46971 Invalidate;
46972 end;
46974 //[procedure TControl.SetColor2]
46975 procedure TControl.SetColor2(const Value: TColor);
46976 begin
46977 fColor2 := Value;
46978 Invalidate;
46979 end;
46981 //[procedure TControl.SetGradientLayout]
46982 procedure TControl.SetGradientLayout(const Value: TGradientLayout);
46983 begin
46984 FGradientLayout := Value;
46985 Invalidate;
46986 end;
46988 //[procedure TControl.SetGradientStyle]
46989 procedure TControl.SetGradientStyle(const Value: TGradientStyle);
46990 begin
46991 FGradientStyle := Value;
46992 Invalidate;
46993 end;
47006 { -- Image List -- }
47009 {$IFDEF USE_CONSTRUCTORS}
47010 //[function NewImageList]
47011 function NewImageList( AOwner: PControl ): PImageList;
47012 begin
47013 new( Result, CreateImageList( AOwner ) );
47014 end;
47015 //[END NewImageList]
47016 {$ELSE not_USE_CONSTRUCTORS}
47017 //[function NewImageList]
47018 function NewImageList( AOwner: PControl ): PImageList;
47019 begin
47020 {*************} DoInitCommonControls( ICC_WIN95_CLASSES );
47022 New( Result, Create );
47024 {++}(*Result := TImageList.Create;*){--}
47025 Result.FAllocBy := 1;
47026 Result.FMasked := True;
47027 if AOwner = nil then exit;
47029 Result.FControl := AOwner;
47030 Result.fNext := PImageList( AOwner.fImageList );
47031 if AOwner.fImageList <> nil then
47032 PImageList( AOwner.fImageList ).fPrev := Result;
47033 Result.fBkColor := clNone;
47034 //ImageList_SetBkColor( Result.FHandle, CLR_NONE );
47035 AOwner.fImageList := Result;
47036 Result.FImgWidth := 32;
47037 Result.FImgHeight := 32;
47038 Result.FColors := ilcDefault;
47039 end;
47040 {$ENDIF}
47042 //[API ImageList_XXX]
47043 function ImageList_Create; stdcall; external cctrl name 'ImageList_Create';
47044 function ImageList_Destroy; external cctrl name 'ImageList_Destroy';
47045 function ImageList_GetImageCount; external cctrl name 'ImageList_GetImageCount';
47046 function ImageList_SetImageCount; external cctrl name 'ImageList_SetImageCount';
47047 function ImageList_Add; external cctrl name 'ImageList_Add';
47048 function ImageList_ReplaceIcon; external cctrl name 'ImageList_ReplaceIcon';
47049 function ImageList_SetBkColor; external cctrl name 'ImageList_SetBkColor';
47050 function ImageList_GetBkColor; external cctrl name 'ImageList_GetBkColor';
47051 function ImageList_SetOverlayImage; external cctrl name 'ImageList_SetOverlayImage';
47052 function ImageList_Draw; external cctrl name 'ImageList_Draw';
47053 function ImageList_Replace; external cctrl name 'ImageList_Replace';
47054 function ImageList_AddMasked; external cctrl name 'ImageList_AddMasked';
47055 function ImageList_DrawEx; external cctrl name 'ImageList_DrawEx';
47056 function ImageList_Remove; external cctrl name 'ImageList_Remove';
47057 function ImageList_GetIcon; external cctrl name 'ImageList_GetIcon';
47058 function ImageList_LoadImageA; external cctrl name 'ImageList_LoadImageA';
47059 function ImageList_LoadImageW; external cctrl name 'ImageList_LoadImageW';
47060 function ImageList_LoadImage; external cctrl name 'ImageList_LoadImageA';
47061 function ImageList_BeginDrag; external cctrl name 'ImageList_BeginDrag';
47062 function ImageList_EndDrag; external cctrl name 'ImageList_EndDrag';
47063 function ImageList_DragEnter; external cctrl name 'ImageList_DragEnter';
47064 function ImageList_DragLeave; external cctrl name 'ImageList_DragLeave';
47065 function ImageList_DragMove; external cctrl name 'ImageList_DragMove';
47066 function ImageList_SetDragCursorImage; external cctrl name 'ImageList_SetDragCursorImage';
47067 function ImageList_DragShowNolock; external cctrl name 'ImageList_DragShowNolock';
47068 function ImageList_GetDragImage; external cctrl name 'ImageList_GetDragImage';
47069 //function ImageList_Read; external cctrl name 'ImageList_Read';
47070 //function ImageList_Write; external cctrl name 'ImageList_Write';
47071 function ImageList_GetIconSize; external cctrl name 'ImageList_GetIconSize';
47072 function ImageList_SetIconSize; external cctrl name 'ImageList_SetIconSize';
47073 function ImageList_GetImageInfo; external cctrl name 'ImageList_GetImageInfo';
47074 function ImageList_Merge; external cctrl name 'ImageList_Merge';
47076 //[function ImageList_AddIcon]
47077 function ImageList_AddIcon(ImageList: HImageList; Icon: HIcon): Integer;
47078 begin
47079 Result := ImageList_ReplaceIcon(ImageList, -1, Icon);
47080 end;
47082 //[function Index2OverlayMask]
47083 function Index2OverlayMask(Index: Integer): Integer;
47084 begin
47085 Result := Index shl 8;
47086 end;
47088 { macros }
47089 //[procedure ImageList_RemoveAll]
47090 procedure ImageList_RemoveAll(ImageList: HImageList); stdcall;
47091 begin
47092 ImageList_Remove(ImageList, -1);
47093 end;
47095 //[function ImageList_ExtractIcon]
47096 function ImageList_ExtractIcon(Instance: THandle; ImageList: HImageList;
47097 Image: Integer): HIcon; stdcall;
47098 begin
47099 Result := ImageList_GetIcon(ImageList, Image, 0);
47100 end;
47102 //[function ImageList_LoadBitmap]
47103 function ImageList_LoadBitmap(Instance: THandle; Bmp: PChar;
47104 CX, Grow: Integer; Mask: TColorRef): HImageList; stdcall;
47105 begin
47106 Result := ImageList_LoadImage(Instance, Bmp, CX, Grow, Mask,
47107 IMAGE_BITMAP, 0);
47108 end;
47110 //[procedure FreeBmp]
47111 procedure FreeBmp( Bmp: HBitmap );
47112 begin
47113 DeleteObject( Bmp );
47114 end;
47116 //[function LoadBmp]
47117 function LoadBmp( Instance: Integer; Rsrc: PChar; MasterObj: PObj ): HBitmap;
47118 begin
47119 Result := LoadBitmap( Instance, Rsrc );
47120 MasterObj.Add2AutoFreeEx( TObjectMethod( MakeMethod( Pointer( Result ), @ FreeBmp ) ) );
47121 end;
47123 { TImageList }
47126 //[function TImageList.Add]
47127 function TImageList.Add(Bmp, Msk: HBitmap): Integer;
47128 begin
47129 Result := -1;
47130 if not HandleNeeded then Exit;
47131 Result := ImageList_Add( FHandle, Bmp, Msk );
47132 end;
47135 //[function TImageList.AddIcon]
47136 function TImageList.AddIcon(Ico: HIcon): Integer;
47137 {var Bmp : HBitmap;
47138 DC : HDC;}
47139 begin
47140 Result := -1;
47141 if ImgWidth = 0 then
47142 ImgWidth := 32;
47143 if ImgHeight = 0 then
47144 ImgHeight := 32;
47145 if not HandleNeeded then Exit;
47147 {DC := GetDC( 0 );
47148 Bmp := CreateCompatibleBitmap( DC, ImgWidth, ImgHeight );
47149 Result := AddMasked( Bmp, 0 );
47150 DeleteObject( Bmp );
47151 ReleaseDC( 0, DC );
47152 if Result >= 0 then
47153 ReplaceIcon( Result, Ico );}
47154 Result := ImageList_AddIcon( fHandle, Ico );
47155 end;
47158 //[function TImageList.AddMasked]
47159 function TImageList.AddMasked(Bmp: HBitmap; Color: TColor): Integer;
47160 begin
47161 Result := -1;
47162 if not HandleNeeded then Exit;
47163 Result := ImageList_AddMasked( FHandle, Bmp, Color2RGB( Color ) );
47164 end;
47167 //[procedure TImageList.Clear]
47168 procedure TImageList.Clear;
47169 begin
47170 Handle := 0;
47171 end;
47174 //[procedure TImageList.Delete]
47175 procedure TImageList.Delete(Idx: Integer);
47176 begin
47177 if FHandle = 0 then Exit;
47178 ImageList_Remove( FHandle, Idx );
47179 end;
47181 {$IFDEF ASM_VERSION}
47182 //[destructor TImageList.Destroy]
47183 destructor TImageList.Destroy;
47185 PUSH EAX
47186 XOR EDX, EDX
47187 CALL SetHandle
47188 POP EAX
47189 MOV EDX, [EAX].fNext
47190 MOV ECX, [EAX].fPrev
47191 TEST EDX, EDX
47192 JZ @@nonext
47193 MOV [EDX].fPrev, ECX
47194 @@nonext:
47195 JECXZ @@noprev
47196 MOV [ECX].fNext, EDX
47197 @@noprev:
47198 MOV ECX, [EAX].fControl
47199 JECXZ @@fin
47200 CMP [ECX].TControl.fImageList, EAX
47201 JNZ @@fin
47202 MOV [ECX].TControl.fImageList, EDX
47203 @@fin: CALL TObj.Destroy
47204 end;
47205 {$ELSE ASM_VERSION} //Pascal
47206 destructor TImageList.Destroy;
47207 begin
47208 Clear;
47209 if fNext <> nil then
47210 fNext.fPrev := fPrev;
47211 if fPrev <> nil then
47212 fPrev.fNext := fNext;
47213 if fControl <> nil then
47214 if PControl( fControl ).fImageList = @Self then
47215 PControl( fControl ).fImageList := fNext;
47216 inherited;
47217 end;
47218 {$ENDIF ASM_VERSION}
47221 //[procedure TImageList.Draw]
47222 procedure TImageList.Draw(Idx: Integer; DC: HDC; X, Y: Integer);
47223 begin
47224 if FHandle = 0 then Exit;
47225 ImageList_Draw( FHandle, Idx, DC, X, Y, GetDrawStyle );
47226 end;
47228 //[function TImageList.ExtractIcon]
47229 function TImageList.ExtractIcon(Idx: Integer): HIcon;
47230 begin
47231 Result := ImageList_ExtractIcon( 0, FHandle, Idx );
47232 end;
47234 //[function TImageList.ExtractIconEx]
47235 function TImageList.ExtractIconEx(Idx: Integer): HIcon;
47236 begin
47237 Result := ImageList_GetIcon( FHandle, Idx, GetDrawStyle );
47238 end;
47241 //[function TImageList.GetBitmap]
47242 function TImageList.GetBitmap: HBitmap;
47243 var II : TImageInfo;
47244 begin
47245 Result := 0;
47246 if FHandle = 0 then Exit;
47247 if ImageList_GetImageInfo( FHandle, 0, II ) then
47248 Result := II.hbmImage;
47249 end;
47252 //[function TImageList.GetBkColor]
47253 function TImageList.GetBkColor: TColor;
47254 begin
47255 Result := fBkColor;
47256 if FHandle = 0 then Exit;
47257 Result := ImageList_GetBkColor( FHandle );
47258 end;
47261 //[function TImageList.GetCount]
47262 function TImageList.GetCount: Integer;
47263 begin
47264 Result := 0;
47265 if FHandle <> 0 then
47266 Result := ImageList_GetImageCount( FHandle );
47267 end;
47270 //[function TImageList.GetDrawStyle]
47271 function TImageList.GetDrawStyle: DWord;
47272 begin
47273 Result := 0;
47274 if dsBlend25 in DrawingStyle then
47275 Result := Result or ILD_BLEND25;
47276 if dsBlend50 in DrawingStyle then
47277 Result := Result or ILD_BLEND50;
47278 if dsTransparent in DrawingStyle then
47279 Result := Result or ILD_TRANSPARENT
47280 else
47281 if dsMask in DrawingStyle then
47282 Result := Result or ILD_MASK
47283 {else
47284 Result := Result or ILD_NORMAL}; // ILD_NORMAL = 0
47285 end;
47287 {$IFDEF ASM_VERSION}
47288 //[function TImageList.GetHandle]
47289 function TImageList.GetHandle: THandle;
47291 PUSH EAX
47292 CALL HandleNeeded
47293 POP EAX
47294 MOV EAX, [EAX].FHandle
47295 end;
47296 {$ELSE ASM_VERSION} //Pascal
47297 function TImageList.GetHandle: THandle;
47298 begin
47299 HandleNeeded;
47300 Result := FHandle;
47301 end;
47302 {$ENDIF ASM_VERSION}
47305 //[function TImageList.GetMask]
47306 function TImageList.GetMask: HBitmap;
47307 var II : TImageInfo;
47308 begin
47309 Result := 0;
47310 if FHandle = 0 then Exit;
47311 if ImageList_GetImageInfo( FHandle, 0, II ) then
47312 Result := II.hbmMask;
47313 end;
47315 {$IFDEF ASM_noVERSION}
47316 //[function TImageList.HandleNeeded]
47317 function TImageList.HandleNeeded: Boolean;
47318 const ColorFlags : array[ TImageListColors ] of Byte = ( ILC_COLOR,
47319 ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24,
47320 ILC_COLOR32, ILC_COLORDDB );
47322 MOV ECX, [EAX].FHandle
47323 JECXZ @@make_handle
47324 MOV AL, 1
47326 @@make_handle:
47327 MOV ECX, [EAX].fImgWidth
47328 JECXZ @@ret_ECX
47329 MOV EDX, ECX
47330 MOV ECX, [EAX].fImgHeight
47331 JECXZ @@ret_ECX
47332 PUSH EBX
47333 XCHG EBX, EAX
47335 PUSH [EBX].FAllocBy
47336 PUSH 0
47337 MOVZX EAX, [EBX].FColors
47338 MOVZX EAX, byte ptr [ColorFlags+EAX]
47339 CMP [EBX].FMasked, 0
47340 JZ @@flags_ready
47341 {$IFDEF PARANOIA}
47342 DB $0C, $01
47343 {$ELSE}
47344 OR AL, 1
47345 {$ENDIF}
47346 @@flags_ready:
47347 PUSH EAX
47348 PUSH ECX
47349 PUSH EDX
47350 CALL ImageList_Create
47351 MOV [EBX].FHandle, EAX
47352 XCHG ECX, EAX
47353 POP EBX
47354 @@ret_ECX:
47355 TEST ECX, ECX
47356 SETNZ AL
47357 end;
47358 {$ELSE ASM_VERSION} //Pascal
47359 function TImageList.HandleNeeded: Boolean;
47360 const ColorFlags : array[ TImageListColors ] of Byte = ( ILC_COLOR,
47361 ILC_COLOR4, ILC_COLOR8, ILC_COLOR16, ILC_COLOR24,
47362 ILC_COLOR32, ILC_COLORDDB, 0 );
47363 var Flags : DWord;
47364 begin
47365 Result := True;
47366 if FHandle <> 0 then Exit;
47367 Result := False;
47368 if ImgWidth = 0 then Exit;
47369 if ImgHeight = 0 then Exit;
47370 Flags := ColorFlags[ FColors ];
47371 if Masked then
47372 Flags := Flags or ILC_MASK;
47373 FHandle := ImageList_Create( ImgWidth, ImgHeight, Flags, 0, FAllocBy );
47374 if fBkColor <> clNone then
47375 SetBkColor( fBkColor );
47376 Result := FHandle <> 0;
47377 end;
47378 {$ENDIF ASM_VERSION}
47381 //[function TImageList.ImgRect]
47382 function TImageList.ImgRect(Idx: Integer): TRect;
47383 var II : TImageInfo;
47384 begin
47385 Result := MakeRect( 0, 0, 0, 0 );
47386 if FHandle = 0 then Exit;
47387 if ImageList_GetImageInfo( FHandle, Idx, II ) then
47388 Result := II.rcImage;
47389 end;
47391 {$IFDEF ASM_noVERSION}
47392 //[function TImageList.LoadBitmap]
47393 function TImageList.LoadBitmap(ResourceName: PChar;
47394 TranspColor: TColor): Boolean;
47396 PUSH EBX
47397 XCHG EBX, EAX
47398 XCHG EAX, ECX //TranspColor
47399 PUSH EDX
47400 CMP EAX, clNone
47401 JNE @@2rgb
47402 OR EAX, -1
47403 JMP @@tranColorReady
47404 @@2rgb:
47405 CALL Color2RGB
47406 @@tranColorReady:
47407 POP EDX
47408 PUSH EAX
47409 PUSH [EBX].fAllocBy
47410 PUSH [EBX].fImgWidth
47411 PUSH EDX
47412 PUSH [hInstance]
47413 CALL ImageList_LoadBitmap
47414 TEST EAX, EAX
47415 JZ @@exit
47416 XCHG EDX, EAX
47417 XCHG EAX, EBX
47418 CALL SetHandle
47419 MOV AL, 1
47420 @@exit: POP EBX
47421 end;
47422 {$ELSE ASM_VERSION} //Pascal
47423 function TImageList.LoadBitmap(ResourceName: PChar;
47424 TranspColor: TColor): Boolean;
47425 var NewHandle : THandle;
47426 TranColr: TColor;
47427 begin
47428 TranColr := TranspColor;
47429 if TranColr = clNone then TranColr := TColor( CLR_NONE )
47430 else TranColr := Color2RGB( TranColr );
47431 NewHandle := ImageList_LoadBitmap( hInstance, ResourceName,
47432 ImgWidth, AllocBy, TranColr );
47433 //ImageList_GetIconSize( NewHandle, fImgWidth, fImgHeight );
47434 Result := NewHandle <> 0;
47435 if Result then
47436 Handle := NewHandle;
47437 ImageList_GetIconSize( fHandle, FImgWidth, FImgHeight );
47438 end;
47439 {$ENDIF ASM_VERSION}
47442 //[function TImageList.LoadFromFile]
47443 function TImageList.LoadFromFile(FileName: PChar; TranspColor: TColor;
47444 ImgType: TImageType): Boolean;
47445 const ImgTypes:array[ TImageType ] of DWord = ( IMAGE_BITMAP, IMAGE_ICON, IMAGE_CURSOR );
47446 var NewHandle : THandle;
47447 TranspFlag : DWord;
47448 begin
47449 TranspFlag := 0;
47450 if TranspColor <> clNone then
47451 TranspFlag := LR_LOADTRANSPARENT;
47452 NewHandle := ImageList_LoadImage( hInstance, FileName, ImgWidth, AllocBy, Color2RGB( TranspColor ),
47453 ImgTypes[ ImgType ], LR_LOADFROMFILE or TranspFlag );
47454 Result := NewHandle <> 0;
47455 if Result then
47456 Handle := NewHandle;
47457 end;
47460 //[function TImageList.LoadSystemIcons]
47461 function TImageList.LoadSystemIcons(SmallIcons: Boolean): Boolean;
47462 var NewHandle : THandle;
47463 FileInfo : TSHFileInfo;
47464 Flags : DWord;
47465 begin
47466 OleInit;
47467 Flags := SHGFI_SYSICONINDEX;
47468 if SmallIcons then
47469 Flags := Flags or SHGFI_SMALLICON;
47470 NewHandle := SHGetFileInfo( '', 0, FileInfo, Sizeof( FileInfo ), Flags );
47471 Result := NewHandle <> 0;
47472 if Result then
47473 begin
47474 Handle := NewHandle;
47475 FShareImages := True;
47476 end;
47477 end;
47480 //[function TImageList.Merge]
47481 function TImageList.Merge(Idx: Integer; ImgList2: PImageList; Idx2, X,
47482 Y: Integer): PImageList;
47483 var L : THandle;
47484 begin
47485 Result := nil;
47486 //if FHandle = 0 then Exit;
47487 L := ImageList_Merge( FHandle, Idx, ImgList2.Handle, Idx2, X, Y );
47488 if L <> 0 then
47489 begin
47490 Result := NewImageList( fControl );
47491 Result.Handle := L;
47492 end;
47493 end;
47496 //[function TImageList.Replace]
47497 function TImageList.Replace(Idx: Integer; Bmp, Msk: HBitmap): Boolean;
47498 begin
47499 Result := False;
47500 if FHandle = 0 then Exit;
47501 Result := ImageList_Replace( FHandle, Idx, Bmp, Msk );
47502 end;
47505 //[function TImageList.ReplaceIcon]
47506 function TImageList.ReplaceIcon(Idx: Integer; Ico: HIcon): Boolean;
47507 begin
47508 Result := False;
47509 if FHandle = 0 then Exit;
47510 Result := ImageList_ReplaceIcon( FHandle, Idx, Ico ) >= 0;
47511 end;
47514 //[procedure TImageList.SetAllocBy]
47515 procedure TImageList.SetAllocBy(const Value: Integer);
47516 begin
47517 if FHandle <> 0 then Exit;
47518 // AllocBy can be changed only before adding images
47519 // and creating image list handle
47520 FAllocBy := Value;
47521 end;
47524 //[procedure TImageList.SetBkColor]
47525 procedure TImageList.SetBkColor(const Value: TColor);
47526 begin
47527 fBkColor := Value;
47528 if fHandle <> 0 then
47529 ImageList_SetBkColor( FHandle, Color2RGB( Value ) );
47530 end;
47533 //[procedure TImageList.SetColors]
47534 procedure TImageList.SetColors(const Value: TImageListColors);
47535 begin
47536 if FHandle <> 0 then Exit;
47537 FColors := Value;
47538 end;
47540 {$IFDEF ASM_VERSION}
47541 //[procedure TImageList.SetHandle]
47542 procedure TImageList.SetHandle(const Value: THandle);
47544 PUSH EBX
47545 XCHG EBX, EAX
47546 MOV ECX, [EBX].FHandle
47547 CMP ECX, EDX
47548 JZ @@exit
47549 JECXZ @@set_handle
47550 CMP [EBX].fShareImages, 0
47551 JNZ @@set_handle
47552 PUSH EDX
47553 PUSH ECX
47554 CALL ImageList_Destroy
47555 POP EDX
47557 @@set_handle:
47558 MOV [EBX].FHandle, EDX
47559 TEST EDX, EDX
47560 JZ @@set_sz0
47561 LEA EAX, [EBX].FImgHeight
47562 PUSH EAX
47563 LEA EAX, [EBX].FImgWidth
47564 PUSH EAX
47565 PUSH EDX
47566 CALL ImageList_GetIconSize
47567 JMP @@exit
47569 @@set_sz0:
47570 MOV [EBX].fImgWidth, EDX
47571 MOV [EBX].fImgHeight, EDX
47573 @@exit:
47574 POP EBX
47575 end;
47576 {$ELSE ASM_VERSION} //Pascal
47577 procedure TImageList.SetHandle(const Value: THandle);
47578 begin
47579 if FHandle = Value then Exit;
47580 if (FHandle <> 0) and not FShareImages then
47581 ImageList_Destroy( FHandle );
47582 FHandle := Value;
47583 if FHandle <> 0 then
47584 ImageList_GetIconSize( FHandle, FImgWidth, FImgHeight )
47585 else
47586 begin
47587 FImgWidth := 0;
47588 FImgHeight := 0;
47589 end;
47590 //FBkColor := ImageList_GetBkColor( FHandle );
47591 end;
47592 {$ENDIF ASM_VERSION}
47594 //[procedure TImageList.SetImgHeight]
47595 procedure TImageList.SetImgHeight(const Value: Integer);
47596 begin
47597 if FHandle <> 0 then Exit;
47598 FImgHeight := Value;
47599 end;
47601 //[procedure TImageList.SetImgWidth]
47602 procedure TImageList.SetImgWidth(const Value: Integer);
47603 begin
47604 if FHandle <> 0 then Exit;
47605 FImgWidth := Value;
47606 end;
47608 //[procedure TImageList.SetMasked]
47609 procedure TImageList.SetMasked(const Value: Boolean);
47610 begin
47611 if FHandle <> 0 then Exit;
47612 FMasked := Value;
47613 end;
47616 //[function TImageList.GetOverlay]
47617 function TImageList.GetOverlay(Idx: TImgLOVrlayIdx): Integer;
47618 begin
47619 Result := fOverlay[ Idx ];
47620 end;
47622 //[procedure TImageList.SetOverlay]
47623 procedure TImageList.SetOverlay(Idx: TImgLOVrlayIdx; const Value: Integer);
47624 begin
47625 if ImageList_SetOverlayImage( fHandle, Value, Idx shl 8 ) then
47626 fOverlay[ Idx ] := Value;
47627 end;
47629 //[procedure TImageList.StretchDraw]
47630 procedure TImageList.StretchDraw(Idx: Integer; DC: HDC; const Rect: TRect);
47631 begin
47632 if FHandle = 0 then Exit;
47633 ImageList_DrawEx( FHandle, Idx, DC, Rect.Left, Rect.Top,
47634 Rect.Right- Rect.Left, Rect.Bottom-Rect.Top,
47635 BkColor, BlendColor, GetDrawStyle );
47636 end;
47639 //[function GetImgListSize]
47640 function GetImgListSize( Sender: PControl; Size: Integer ): PImageList;
47641 begin
47642 if Size > 16 then
47643 Result := Sender.fCtlImageListNormal
47644 else
47645 Result := Sender.fCtlImageListSml;
47646 if Result <> nil then
47647 begin
47648 if Result.fImgWidth = 0 then
47649 Result.ImgWidth := Size;
47650 if Result.fImgHeight = 0 then
47651 Result.ImgHeight := Size;
47652 //if (Result.FImgWidth <> Size) or (Result.FImgHeight <> Size) then
47653 // Result := nil;
47654 end;
47655 if Result = nil then
47656 begin
47657 Result := Sender.fImageList;
47658 while Result <> nil do
47659 begin
47660 if (Result.FImgWidth = Size) and (Result.FImgHeight = Size) then
47661 break;
47662 Result := Result.fNext;
47663 end;
47664 end;
47665 end;
47668 //[function TControl.GetImgListIdx]
47669 function TControl.GetImgListIdx(const Index: Integer): PImageList;
47670 begin
47671 if Index <> 0 then
47672 Result := GetImgListSize( @Self, Index )
47673 else
47674 begin
47675 Result := fCtlImgListState;
47676 if Result = nil then
47677 begin
47678 Result := fImageList;
47679 while Result <> nil do
47680 begin
47681 if (Result <> GetImgListIdx( 16 )) and (Result <> GetImgListIdx( 32 )) then
47682 break;
47683 Result := Result.fNext;
47684 end;
47685 end;
47686 end;
47687 end;
47690 //[procedure TControl.SetImgListIdx]
47691 procedure TControl.SetImgListIdx(const Index: Integer;
47692 const Value: PImageList);
47693 begin
47695 if Value <> nil then
47696 begin
47697 if Index <> 0 then
47698 if (Value.ImgWidth = 0) or (Value.ImgHeight = 0) then
47699 begin
47700 Value.ImgWidth := Index;
47701 Value.ImgHeight := Index;
47702 end;
47703 end;
47705 case Index of
47706 32: fCtlImageListNormal := Value;
47707 16: fCtlImageListSml := Value;
47708 else fCtlImgListState := Value;
47709 end;
47710 ApplyImageLists2Control( @Self );
47711 end;
47713 { -- list view -- }
47715 //[function WndProcEndLabelEdit]
47716 function WndProcEndLabelEdit( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
47717 var NMhdr: PNMHdr;
47718 LVDisp: PLVDispInfo;
47719 {$IFNDEF _FPC}
47720 {$IFNDEF _D2}
47721 {$IFDEF UNICODE_CTRLS}
47722 LVDispW: PLVDispInfoW;
47723 {$ENDIF UNICODE_CTRLS}
47724 {$ENDIF _D2}
47725 {$ENDIF _FPC}
47726 Flag: Boolean;
47727 begin
47728 Result := False;
47729 if Msg.message = WM_NOTIFY then
47730 begin
47731 NMHdr := Pointer( Msg.lParam );
47732 case NMHdr.code of
47733 LVN_ENDLABELEDIT {$IFDEF UNICODE_CTRLS}, LVN_ENDLABELEDITW {$ENDIF UNICODE_CTRLS}:
47734 begin
47735 LVDisp := Pointer( Msg.lParam );
47736 Result := True;
47737 if LVDisp.item.pszText = nil then Exit;
47738 Rslt := 1;
47739 if assigned( Self_.fOnEditLVItem ) then
47740 begin
47741 {$IFNDEF _FPC}
47742 {$IFNDEF _D2}
47743 {$IFDEF UNICODE_CTRLS}
47744 if NMHdr.code = LVN_ENDLABELEDITW then
47745 begin
47746 LVDispW := Pointer( LVDisp );
47747 Flag := Self_.fOnEditLVItem( Self_, LVDispW.item.iItem,
47748 LVDispW.item.iSubItem, PChar( LVDispW.item.pszText ) );
47749 end else
47750 {$ENDIF UNICODE_CTRLS}
47751 {$ENDIF _D2}
47752 {$ENDIF _FPC}
47753 Flag := Self_.fOnEditLVItem( Self_, LVDisp.item.iItem,
47754 LVDisp.item.iSubItem, LVDisp.item.pszText );
47755 if Flag then Rslt := 1
47756 else Rslt := 0;
47757 end;
47758 end;
47759 end;
47760 end;
47761 end;
47763 //[procedure TControl.SetOnEditLVItem]
47764 procedure TControl.SetOnEditLVItem(const Value: TOnEditLVItem);
47765 begin
47766 fOnEditLVITem := Value;
47767 AttachProc( WndProcEndLabelEdit );
47768 end;
47771 //[procedure TControl.LVColAdd]
47772 procedure TControl.LVColAdd(const aText: String; aalign: TTextAlign;
47773 aWidth: Integer);
47774 begin
47775 ////////////////////////////////////////////////////
47776 //LVColInsert( fLVColCount + 1, aText, aalign, aWidth );
47777 //////////////////////////////////////////////////////
47778 LVColInsert( fLVColCount, aText, aalign, aWidth );// 21.10.2001
47779 ////////////////////////////////////////////////////
47780 end;
47782 {$IFNDEF _FPC}
47783 {$IFNDEF _D2}
47784 //[procedure TControl.LVColAddW]
47785 procedure TControl.LVColAddW(const aText: WideString; aalign: TTextAlign;
47786 aWidth: Integer);
47787 begin
47788 LVColInsertW( fLVColCount, aText, aalign, aWidth );
47789 end;
47790 {$ENDIF _D2}
47791 {$ENDIF _FPC}
47793 //****************** changed by Mike Gerasimov
47794 //[procedure TControl.LVColInsert]
47795 procedure TControl.LVColInsert(ColIdx: Integer; const aText: String;
47796 aAlign: TTextAlign; aWidth: Integer);
47797 var LVColData: TLVColumn;
47798 begin
47799 LVColData.mask := LVCF_FMT or LVCF_TEXT;
47800 if ImageListSmall <> nil then
47801 LVColData.mask := LVColData.mask; // or LVCF_IMAGE ;
47802 LVColData.iImage := -1;
47803 LVColData.fmt := Ord( aAlign );
47804 if aWidth < 0 then
47805 begin
47806 aWidth := -aWidth;
47807 LVColData.fmt := LVColData.fmt or LVCFMT_BITMAP_ON_RIGHT;
47808 end;
47809 LVColData.cx := aWidth;
47810 if aWidth > 0 then
47811 LVColData.mask := LVColData.mask or LVCF_WIDTH;
47812 LVColData.pszText := PChar( aText );
47813 if Perform( LVM_INSERTCOLUMN, ColIdx, Integer( @LVColData ) ) >= 0 then
47814 Inc( fLVColCount );
47815 end;
47817 {$IFNDEF _FPC}
47818 {$IFNDEF _D2}
47819 //[procedure TControl.LVColInsertW]
47820 procedure TControl.LVColInsertW(ColIdx: Integer; const aText: WideString;
47821 aAlign: TTextAlign; aWidth: Integer);
47822 var LVColData: TLVColumnW;
47823 begin
47824 LVColData.mask := LVCF_FMT or LVCF_TEXT;
47825 if ImageListSmall <> nil then
47826 LVColData.mask := LVColData.mask; // or LVCF_IMAGE ;
47827 LVColData.iImage := -1;
47828 LVColData.fmt := Ord( aAlign );
47829 if aWidth < 0 then
47830 begin
47831 aWidth := -aWidth;
47832 LVColData.fmt := LVColData.fmt or LVCFMT_BITMAP_ON_RIGHT;
47833 end;
47834 LVColData.cx := aWidth;
47835 if aWidth > 0 then
47836 LVColData.mask := LVColData.mask or LVCF_WIDTH;
47837 LVColData.pszText := PWideChar( aText );
47838 if Perform( LVM_INSERTCOLUMNW, ColIdx, Integer( @LVColData ) ) >= 0 then
47839 Inc( fLVColCount );
47840 end;
47841 {$ENDIF _D2}
47842 {$ENDIF _FPC}
47844 //[function TControl.GetLVColText]
47845 function TControl.GetLVColText(Idx: Integer): String;
47846 var Buf: array[ 0..4095 ] of Char;
47847 LC: TLVColumn;
47848 begin
47849 LC.mask := LVCF_TEXT;
47850 LC.pszText := @ Buf[ 0 ];
47851 LC.cchTextMax := Sizeof( Buf );
47852 Buf[ 0 ] := #0;
47853 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
47854 Result := Buf;
47855 end;
47857 //[procedure TControl.SetLVColText]
47858 procedure TControl.SetLVColText(Idx: Integer; const Value: String);
47859 var LC: TLVColumn;
47860 begin
47861 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
47862 LC.mask := LVCF_TEXT;
47863 LC.pszText := '';
47864 if Value <> '' then
47865 LC.pszText := @ Value[ 1 ];
47866 Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );
47867 end;
47869 {$IFNDEF _FPC}
47870 {$IFNDEF _D2}
47871 //[function TControl.GetLVColTextW]
47872 function TControl.GetLVColTextW(Idx: Integer): WideString;
47873 var Buf: array[ 0..4095 ] of WideChar;
47874 LC: TLVColumnW;
47875 begin
47876 LC.mask := LVCF_TEXT;
47877 LC.pszText := @ Buf[ 0 ];
47878 LC.cchTextMax := High( Buf ) + 1;
47879 Buf[ 0 ] := #0;
47880 Perform( LVM_GETCOLUMNW, Idx, Integer( @ LC ) );
47881 Result := Buf;
47882 end;
47884 //[procedure TControl.SetLVColTextW]
47885 procedure TControl.SetLVColTextW(Idx: Integer; const Value: WideString);
47886 var LC: TLVColumnW;
47887 begin
47888 FillChar( LC, Sizeof( LC ), 0 );
47889 LC.mask := LVCF_TEXT;
47890 LC.pszText := '';
47891 if Value <> '' then
47892 LC.pszText := @ Value[ 1 ];
47893 Perform( LVM_SETCOLUMNW, Idx, Integer( @ LC ) );
47894 end;
47895 {$ENDIF _D2}
47896 {$ENDIF _FPC}
47898 //[function TControl.GetLVColalign]
47899 function TControl.GetLVColalign(Idx: Integer): TTextAlign;
47900 const Formats: array[ 0..2 ] of TTextAlign = ( taLeft, taRight, taCenter );
47901 var LC: TLVColumn;
47902 begin
47903 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
47904 LC.mask := LVCF_FMT;
47905 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
47906 Result := Formats[ LC.fmt and LVCFMT_JUSTIFYMASK ];
47907 end;
47909 //[procedure TControl.SetLVColalign]
47910 procedure TControl.SetLVColalign(Idx: Integer; const Value: TTextAlign);
47911 const FormatFlags: array[ TTextAlign ] of BYTE = ( LVCFMT_LEFT, LVCFMT_RIGHT,
47912 LVCFMT_CENTER );
47913 var LC: TLVColumn;
47914 begin
47915 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
47916 LC.mask := LVCF_FMT;
47917 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
47918 LC.fmt := LC.fmt and not LVCFMT_JUSTIFYMASK or FormatFlags[ Value ];
47919 Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );
47920 end;
47922 //[function TControl.GetLVColEx]
47923 function TControl.GetLVColEx(Idx: Integer; const Index: Integer): Integer;
47924 var LC: TLVColumn;
47925 begin
47926 FillChar( LC, Sizeof( LC ), 0 ); {Alexey (Lecha2002)}
47927 LC.mask := LoWord( Index );
47928 Perform( LVM_GETCOLUMN, Idx, Integer( @ LC ) );
47929 Result := PDWORD( Integer( @ LC ) + HiWord( Index ) )^;
47930 end;
47932 //********************** changed by Mike Gerasimov
47933 //[procedure TControl.SetLVColEx]
47934 procedure TControl.SetLVColEx(Idx: Integer; const Index: Integer;
47935 const Value: Integer);
47936 var LC: TLVColumn;
47937 begin
47938 FillChar(LC,SizeOf(LC),0); // Added Line
47939 LC.mask := LoWord( Index );
47940 if HiWord( Index ) = 24 then // Added Line
47941 begin // Added Line
47942 LC.mask := LC.mask or LVCF_FMT; // Added Line
47943 if Value <>-1 then // Added Line
47944 LC.fmt := LC.fmt or LVCFMT_IMAGE or LVCFMT_COL_HAS_IMAGES // Added Line
47945 else LC.mask := LC.mask and not LVCF_IMAGE; // + by non
47946 end;
47947 if (value<>-1)or(HiWord( Index )<>24) then // + by non
47948 PDWORD( Integer( @ LC ) + HiWord( Index ) )^ := Value;
47949 Perform( LVM_SETCOLUMN, Idx, Integer( @ LC ) );
47950 end;
47953 //[function TControl.LVAdd]
47954 function TControl.LVAdd(const aText: String; ImgIdx: Integer;
47955 State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer;
47956 Data: DWORD): Integer;
47957 begin
47958 Result := LVInsert( MaxInt {Count}, aText, ImgIdx, State, StateImgIdx, OverlayImgIdx, Data );
47959 end;
47962 //[function TControl.LVInsert]
47963 function TControl.LVInsert(Idx: Integer; const aText: String;
47964 ImgIdx: Integer; State: TListViewItemState; StateImgIdx, OverlayImgIdx: Integer;
47965 Data: DWORD): Integer;
47966 const
47967 LVM_REDRAWITEMS = LVM_FIRST + 21;
47968 var LVI: TLVItem;
47969 begin
47970 LVI.mask := LVIF_TEXT or LVIF_IMAGE or LVIF_PARAM or LVIF_STATE
47971 or LVIF_DI_SETITEM;
47972 LVI.iItem := Idx;
47973 LVI.iSubItem := 0;
47974 LVI.state := 0;
47975 if lvisBlend in State then
47976 LVI.state := LVIS_CUT;
47977 if lvisHighlight in State then
47978 LVI.state := LVI.state or LVIS_DROPHILITED;
47979 if lvisFocus in State then
47980 LVI.state := LVI.state or LVIS_FOCUSED;
47981 if lvisSelect in State then
47982 LVI.state := LVI.state or LVIS_SELECTED;
47983 LVI.stateMask := $FFFF;
47984 if StateImgIdx <> 0 then
47985 LVI.state := LVI.state or ((StateImgIdx and $F) shl 12);
47986 if OverlayImgIdx <> 0 then
47987 LVI.state := LVI.state or ((OverlayImgIdx and $F) shl 8);
47988 LVI.pszText := PChar( aText );
47989 LVI.iImage := ImgIdx;
47990 LVI.lParam := Data;
47991 Result := Perform( LVM_INSERTITEM, 0, Integer( @LVI ) );
47992 //Perform( LVM_REDRAWITEMS, Idx, Idx );
47993 end;
47996 //[procedure TControl.LVSetItem]
47997 procedure TControl.LVSetItem(Idx, Col: Integer; const aText: String;
47998 ImgIdx: Integer; State: TListViewItemState; StateImgIdx,
47999 OverlayImgIdx: Integer; Data: DWORD);
48000 var LVI: TLVItem;
48001 I: Integer;
48002 begin
48003 LVI.mask := LVIF_TEXT or {LVIF_STATE or} LVIF_DI_SETITEM;
48004 if Col = 0 then
48005 begin
48006 LVI.mask := LVIF_TEXT or LVIF_STATE or LVIF_PARAM
48007 or LVIF_DI_SETITEM;
48008 if ImgIdx <> I_SKIP then
48009 LVI.mask := LVI.mask or LVIF_IMAGE;
48010 end;
48011 if ImgIdx < I_SKIP then
48012 LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;
48013 LVI.iItem := Idx;
48014 LVI.iSubItem := Col;
48015 LVI.state := 0;
48016 if lvisBlend in State then
48017 LVI.state := LVIS_CUT;
48018 if lvisHighlight in State then
48019 LVI.state := LVI.state or LVIS_DROPHILITED;
48020 if lvisFocus in State then
48021 LVI.state := LVI.state or LVIS_FOCUSED;
48022 if lvisSelect in State then
48023 LVI.state := LVI.state or LVIS_SELECTED;
48024 LVI.stateMask := $FFFF;
48025 if StateImgIdx <> 0 then
48026 LVI.state := LVI.state or ((StateImgIdx and $F) shl 12);
48027 if StateImgIdx < 0 {= I_SKIP} then
48028 LVI.stateMask := $F0FF;
48029 if OverlayImgIdx <> 0 then
48030 LVI.state := LVI.state or ((OverlayImgIdx and $F) shl 8);
48031 if OverlayImgIdx < 0 {=I_SKIP} then
48032 LVI.stateMask := LVI.stateMask and $FFF;
48033 LVI.pszText := PChar( aText );
48034 LVI.iImage := ImgIdx;
48035 LVI.lParam := Data;
48036 I := Perform( LVM_SETITEM, 0, Integer( @LVI ) );
48037 if (I = 0) and (Col = 0) then
48038 Assert( False, 'Can not set item ' );
48039 end;
48042 //[procedure LVGetItem]
48043 procedure LVGetItem( Sender: PControl; Idx, Col: Integer; var LVI: TLVItem;
48044 TextBuf: PChar; TextBufSize: Integer );
48045 begin
48046 LVI.mask := LVIF_STATE or LVIF_PARAM or LVIF_IMAGE;
48047 if Col > 0 then
48048 if not (lvoSubItemImages in Sender.fLVOptions) then
48049 LVI.mask := LVIF_STATE or LVIF_PARAM;
48050 LVI.iItem := Idx;
48051 LVI.iSubItem := Col;
48052 LVI.pszText := TextBuf;
48053 LVI.cchTextMax := TextBufSize;
48054 if TextBufSize <> 0 then
48055 LVI.mask := LVI.mask or LVIF_TEXT;
48056 Sender.Perform( LVM_GETITEM, 0, Integer( @LVI ) );
48057 end;
48059 {$IFNDEF _FPC}
48060 {$IFNDEF _D2}
48061 //[procedure LVGetItemW]
48062 procedure LVGetItemW( Sender: PControl; Idx, Col: Integer; var LVI: TLVItemW;
48063 TextBuf: PWideChar; TextBufSize: Integer );
48064 begin
48065 LVI.mask := LVIF_STATE or LVIF_PARAM or LVIF_IMAGE;
48066 if Col > 0 then
48067 if not (lvoSubItemImages in Sender.fLVOptions) then
48068 LVI.mask := LVIF_STATE or LVIF_PARAM;
48069 LVI.iItem := Idx;
48070 LVI.iSubItem := Col;
48071 LVI.pszText := TextBuf;
48072 LVI.cchTextMax := TextBufSize;
48073 if TextBufSize <> 0 then
48074 LVI.mask := LVI.mask or LVIF_TEXT;
48075 Sender.Perform( LVM_GETITEMW, 0, Integer( @LVI ) );
48076 end;
48077 {$ENDIF _D2}
48078 {$ENDIF _FPC}
48081 //[function TControl.LVGetItemImgIdx]
48082 function TControl.LVGetItemImgIdx(Idx: Integer): Integer;
48083 var LVI: TLVItem;
48084 begin
48085 LVI.iImage := -1;//= Result if image is not assigned {Andrzej Kubaszek}
48086 LVGetItem( @Self, Idx, 0, LVI, nil, 0 );
48087 Result := LVI.iImage;
48088 end;
48091 //[procedure TControl.LVSetItemImgIdx]
48092 procedure TControl.LVSetItemImgIdx(Idx: Integer; const Value: Integer);
48093 var LVI: TLVItem;
48094 begin
48095 LVGetItem( @Self, Idx, 0, LVI, nil, 0 );
48096 LVI.iImage := Value;
48097 Perform( LVM_SETITEM, 0, Integer( @LVI ) );
48098 end;
48101 //[function TControl.LVGetItemText]
48102 function TControl.LVGetItemText(Idx, Col: Integer): String;
48103 var LVI: TLVItem;
48104 TextBuf: PChar;
48105 BufSize: DWORD;
48106 begin
48107 BufSize := 0;
48108 TextBuf := nil;
48109 repeat
48110 if TextBuf <> nil then
48111 FreeMem( TextBuf );
48112 BufSize := BufSize * 2 + 100; // to vary in asm version
48113 GetMem( TextBuf, BufSize );
48114 TextBuf[ 0 ] := #0;
48115 LVGetItem( @Self, Idx, Col, LVI, TextBuf, BufSize );
48116 until StrLen( TextBuf ) < BufSize - 1;
48117 Result := TextBuf;
48118 FreeMem( TextBuf );
48119 end;
48122 //[procedure TControl.LVSetItemText]
48123 procedure TControl.LVSetItemText(Idx, Col: Integer; const Value: String);
48124 var LVI: TLVItem;
48125 begin
48126 LVI.iSubItem := Col;
48127 LVI.pszText := PChar( Value );
48128 Perform( LVM_SETITEMTEXT, Idx, Integer( @LVI ) );
48129 end;
48131 {$IFNDEF _FPC}
48132 {$IFNDEF _D2}
48133 //[function TControl.LVGetItemTextW]
48134 function TControl.LVGetItemTextW(Idx, Col: Integer): WideString;
48135 var LVI: TLVItemW;
48136 TextBuf: PWideChar;
48137 BufSize: DWORD;
48138 begin
48139 BufSize := 0;
48140 TextBuf := nil;
48141 repeat
48142 if TextBuf <> nil then
48143 FreeMem( TextBuf );
48144 BufSize := BufSize * 2 + 100; // to vary in asm version
48145 GetMem( TextBuf, BufSize * 2 );
48146 TextBuf[ 0 ] := #0;
48147 LVGetItemW( @Self, Idx, Col, LVI, TextBuf, BufSize );
48148 until DWORD( WStrLen( TextBuf ) ) < BufSize - 1;
48149 Result := TextBuf;
48150 FreeMem( TextBuf );
48151 end;
48153 //[procedure TControl.LVSetItemTextW]
48154 procedure TControl.LVSetItemTextW(Idx, Col: Integer;
48155 const Value: WideString);
48156 var LVI: TLVItemW;
48157 begin
48158 LVI.iSubItem := Col;
48159 LVI.pszText := PWideChar( Value );
48160 Perform( LVM_SETITEMTEXTW, Idx, Integer( @LVI ) );
48161 end;
48162 {$ENDIF _D2}
48163 {$ENDIF _FPC}
48166 //[procedure TControl.LVColDelete]
48167 procedure TControl.LVColDelete(ColIdx: Integer);
48168 begin
48169 Perform( LVM_DELETECOLUMN, ColIdx, 0 );
48170 if fLVColCount > 0 then
48171 Dec( fLVColCount );
48172 end;
48175 //[procedure TControl.SetLVOptions]
48176 procedure TControl.SetLVOptions(const Value: TListViewOptions);
48177 begin
48178 if fLVOptions = Value then Exit;
48179 fLVOptions := Value;
48180 ApplyImageLists2ListView( @Self );
48181 PostMessage( fHandle, WM_SIZE, 0, 0 ); // to restore scrollers (otherwise its are lost)
48182 end;
48185 //[procedure TControl.SetLVStyle]
48186 procedure TControl.SetLVStyle(const Value: TListViewStyle);
48187 begin
48188 if fLVStyle = Value then Exit;
48189 fLVStyle := Value;
48190 ApplyImageLists2ListView( @Self );
48191 end;
48193 {$IFDEF ASM_VERSION}
48194 //[function TControl.Perform]
48195 function TControl.Perform(msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;
48197 PUSH [lParam]
48198 PUSH [wParam]
48199 PUSH [msgcode]
48200 MOV EAX, [EBP+8]
48201 CALL TControl.GetWindowHandle
48202 PUSH EAX
48203 CALL Windows.SendMessage
48204 end;
48205 {$ELSE ASM_VERSION} //Pascal
48206 function TControl.Perform(msgcode: DWORD; wParam, lParam: Integer): Integer; stdcall;
48207 begin
48208 Result := SendMessage( GetWindowHandle, msgcode, wParam, lParam );
48209 end;
48210 {$ENDIF ASM_VERSION}
48212 {$IFDEF ASM_VERSION}
48213 //[function TControl.Postmsg]
48214 function TControl.Postmsg(msgcode: DWORD; wParam, lParam: Integer): Boolean; stdcall;
48216 PUSH [lParam]
48217 PUSH [wParam]
48218 PUSH [msgcode]
48219 MOV EAX, [EBP+8]
48220 CALL TControl.GetWindowHandle
48221 PUSH EAX
48222 CALL Windows.PostMessage
48223 end;
48224 {$ELSE ASM_VERSION} //Pascal
48225 function TControl.Postmsg(msgcode: DWORD; wParam, lParam: Integer): Boolean; stdcall;
48226 begin
48227 Result := PostMessage( GetWindowHandle, msgcode, wParam, lParam );
48228 end;
48229 {$ENDIF ASM_VERSION}
48231 {$IFDEF ASM_VERSION}
48232 //[function TControl.GetChildCount]
48233 function TControl.GetChildCount: Integer;
48235 MOV EAX, [EAX].fChildren
48236 MOV EAX, [EAX].TList.fCount
48237 end;
48238 {$ELSE ASM_VERSION} //Pascal
48239 function TControl.GetChildCount: Integer;
48240 begin
48241 Result := fChildren.fCount;
48242 end;
48243 {$ENDIF ASM_VERSION}
48245 //[procedure TControl.LVDelete]
48246 procedure TControl.LVDelete(Idx: Integer);
48247 begin
48248 Perform( LVM_DELETEITEM, Idx, 0 );
48249 end;
48251 //[procedure TControl.LVEditItemLabel]
48252 procedure TControl.LVEditItemLabel(Idx: Integer);
48253 begin
48254 Perform( LVM_EDITLABEL, Idx, 0 );
48255 end;
48258 //[function TControl.LVItemRect]
48259 function TControl.LVItemRect(Idx: Integer; Part: TGetLVItemPart): TRect;
48260 const Parts: array[ TGetLVItemPart ] of Byte = (
48261 LVIR_BOUNDS, LVIR_ICON, LVIR_LABEL, LVIR_SELECTBOUNDS );
48262 begin
48263 Result := MakeRect( Parts[ Part ], 0, 0, 0 );
48264 if Perform( LVM_GETITEMRECT, Idx, Integer( @Result ) ) = 0 then
48265 Result := MakeRect( 0, 0, 0, 0 );
48266 end;
48268 //[function TControl.LVSubItemRect]
48269 function TControl.LVSubItemRect(Idx, ColIdx: Integer): TRect;
48270 var Hdr: HWnd;
48271 R, R1: TRect;
48272 ClassNameBuf: array[ 0..31 ] of Char;
48273 HdItem: THDItem;
48274 begin
48275 Result.Top := ColIdx; // + 1; error in MSDN ?
48276 Result.Left := LVIR_BOUNDS;
48277 if Perform( LVM_GETSUBITEMRECT, Idx, Integer( @Result ) ) <> 0 then
48278 Exit;
48279 Result := MakeRect( 0, 0, 0, 0 );
48280 if ColIdx > 0 then R := LVSubItemRect( Idx, ColIdx - 1 )
48281 else R := LVItemRect( Idx, lvipBounds );
48282 if (R.Left = 0) and (R.Right = 0) and
48283 (R.Top = 0) and (R.Bottom = 0) then Exit;
48284 Hdr := GetWindow( GetWindowHandle, GW_CHILD );
48285 if Hdr <> 0 then
48286 begin
48287 if GetClassName( Hdr, ClassNameBuf, 32 ) > 0 then
48288 if ClassNameBuf = 'SysHeader32' then
48289 begin
48290 if ColIdx > 0 then R.Left := R.Right
48291 else R.Left := 0;
48292 R1.Top := 0; R1.Left := 0;
48293 Windows.ClientToScreen( Hdr,{$IFDEF FPC} PPoint( @ R1.Left )^ {$ELSE} R1.TopLeft {$ENDIF} );
48294 Windows.ScreenToClient( fHandle, {$IFDEF FPC} PPoint( @ R1.Left )^ {$ELSE} R1.TopLeft {$ENDIF} );
48295 R1 := R;
48296 HdItem.Mask := HDI_WIDTH;
48297 if SendMessage( Hdr, HDM_GETITEM, ColIdx, Integer( @HdItem ) ) = 0 then Exit;
48298 R1.Right := R1.Left + HdItem.cxy;
48299 Result := R1;
48300 end;
48301 end;
48302 end;
48305 //[function TControl.LVGetItemPos]
48306 function TControl.LVGetItemPos(Idx: Integer): TPoint;
48307 begin
48308 Perform( LVM_GETITEMPOSITION, Idx, Integer( @Result ) );
48309 end;
48312 //[procedure TControl.LVSetItemPos]
48313 procedure TControl.LVSetItemPos(Idx: Integer; const Value: TPoint);
48314 begin
48315 Perform( LVM_SETITEMPOSITION32, Idx, Integer( @Value ) );
48316 end;
48319 //[function TControl.LVItemAtPos]
48320 function TControl.LVItemAtPos(X, Y: Integer): Integer;
48321 var Dummy: TWherePosLVItem;
48322 begin
48323 Result := LVItemAtPosEx( X, Y, Dummy );
48324 end;
48327 //[function TControl.LVItemAtPosEx]
48328 function TControl.LVItemAtPosEx(X, Y: Integer;
48329 var Where: TWherePosLVItem): Integer;
48330 var HTI: TLVHitTestInfo;
48331 begin
48332 HTI.pt.x := X;
48333 HTI.pt.y := Y;
48334 Perform( LVM_HITTEST, 0, Integer( @HTI ) );
48335 Result := HTI.iItem;
48336 Where := lvwpOnColumn;
48337 if HTI.flags = LVHT_ONITEMICON then
48338 Where := lvwpOnIcon
48339 else
48340 if HTI.flags = LVHT_ONITEMLABEL then
48341 Where := lvwpOnLabel
48342 else
48343 if HTI.flags = LVHT_ONITEMSTATEICON then
48344 Where := lvwpOnStateIcon
48345 else
48346 if HTI.flags = LVHT_ONITEM then
48347 Where := lvwpOnItem;
48348 end;
48350 //[procedure TControl.LVMakeVisible]
48351 procedure TControl.LVMakeVisible(Item: Integer; PartiallyOK: Boolean);
48352 begin
48353 if Item < 0 then Exit;
48354 Perform( LVM_ENSUREVISIBLE, Item, Integer( PartiallyOK ) );
48355 end;
48358 //[procedure TControl.LVSetColorByIdx]
48359 procedure TControl.LVSetColorByIdx(const Index: Integer;
48360 const Value: TColor);
48361 var MsgCode: Integer;
48362 ColorValue: TColor;
48363 begin
48364 MsgCode := Index + 1;
48365 case MsgCode of
48366 LVM_SETTEXTCOLOR: fTextColor := Value;
48367 LVM_SETTEXTBKCOLOR: fLVTextBkColor := Value;
48368 LVM_SETBKCOLOR: fColor := Value;
48369 end;
48370 ColorValue := Color2RGB( Value );
48371 Perform( MsgCode, 0, ColorValue );
48372 end;
48374 {$IFDEF F_P}
48375 //[function TControl.LVGetColorByIdx]
48376 function TControl.LVGetColorByIdx(const Index: Integer): TColor;
48377 begin
48378 CASE Index OF
48379 LVM_SETTEXTCOLOR: Result := fTextColor;
48380 LVM_SETTEXTBKCOLOR: Result := fLVTextBkColor;
48381 LVM_SETBKCOLOR: Result := fColor;
48382 END;
48383 end;
48384 {$ENDIF F_P}
48387 //[function TControl.GetIntVal]
48388 function TControl.GetIntVal(const Index: Integer): Integer;
48389 begin
48390 Result := GetItemVal( 0, Index );
48391 end;
48394 //[procedure TControl.SetIntVal]
48395 procedure TControl.SetIntVal(const Index, Value: Integer);
48396 begin
48397 SetItemVal( Value, Index, 0 );
48398 end;
48401 //[function TControl.GetItemVal]
48402 function TControl.GetItemVal(Item: Integer; const Index: Integer): Integer;
48403 begin
48404 Result := Perform( LoWord(Index), Item, 0 );
48405 end;
48407 {$IFDEF ASM_VERSION}
48408 //[procedure TControl.SetItemVal]
48409 procedure TControl.SetItemVal(Item: Integer; const Index: Integer; const Value: Integer);
48411 PUSH EAX
48412 PUSH [Value]
48413 PUSH EDX
48414 MOV EDX, ECX
48415 SHR EDX, 16
48416 JNZ @@1
48417 MOV EDX, ECX
48418 INC EDX
48419 @@1:
48420 MOV EBP, EDX
48421 AND EDX, 7FFFh
48422 PUSH EDX
48423 PUSH EAX
48424 CALL Perform
48425 MOV EAX, EBP
48426 ADD AX, AX
48427 POP EAX
48428 JNB @@2
48429 CALL Invalidate
48430 @@2:
48431 end;
48432 {$ELSE ASM_VERSION} //Pascal
48433 procedure TControl.SetItemVal(Item: Integer; const Index: Integer; const Value: Integer);
48434 var MsgCode: Integer;
48435 begin
48436 MsgCode := HiWord( Index );
48437 if MsgCode = 0 then
48438 MsgCode := Index + 1;
48439 Perform( MsgCode and $7FFF, Item, Value );
48440 if (MsgCode and $8000) <> 0 then
48441 Invalidate;
48442 end;
48443 {$ENDIF ASM_VERSION}
48445 //[procedure TControl.GetSBMinMax]
48446 function TControl.GetSBMinMax: TPoint;
48447 {$IFDEF _D2}
48448 var X, Y: Integer;
48449 {$ENDIF}
48450 begin
48451 if (Handle <> 0) then begin
48452 {$IFDEF _D2}
48453 GetScrollRange(Handle, SB_CTL, X, Y);
48454 Result.X := X;
48455 Result.Y := Y;
48456 {$ELSE}
48457 GetScrollRange(Handle, SB_CTL, Result.X, Result.Y);
48458 {$ENDIF}
48459 Dec(Result.Y, SBPageSize - 1);
48461 else
48462 Result := fSBMinMax;
48463 end;
48465 //[procedure TControl.GetSBPageSize]
48466 function TControl.GetSBPageSize: Integer;
48468 SI: TScrollInfo;
48469 begin
48470 FillChar(SI, SizeOf(SI), 0);
48471 SI.cbSize := SizeOf(SI);
48472 SI.fMask := SIF_PAGE;
48473 SBGetScrollInfo(SI);
48474 Result := SI.nPage;
48475 end;
48477 //[procedure TControl.GetSBPosition]
48478 function TControl.GetSBPosition: Integer;
48479 begin
48480 Result := GetScrollPos(Handle, SB_CTL);
48481 end;
48483 //[procedure TControl.SetSBMax]
48484 procedure TControl.SetSBMax(Value: Longint);
48486 P: TPoint;
48487 begin
48488 fSBMinMax.Y := Value;
48489 if (Handle <> 0) then begin
48490 P := SBMinMax;
48491 P.Y := Value;
48492 SBMinMax := P;
48493 end;
48494 end;
48496 //[procedure TControl.SetSBMin]
48497 procedure TControl.SetSBMin(Value: Longint);
48499 P: TPoint;
48500 begin
48501 fSBMinMax.X := Value;
48502 if (Handle <> 0) then begin
48503 P := SBMinMax;
48504 P.X := Value;
48505 SBMinMax := P;
48506 end;
48507 end;
48509 //[procedure TControl.SetSBPageSize]
48510 procedure TControl.SetSBPageSize(Value: Integer);
48512 SI: TScrollInfo;
48513 begin
48514 fSBPageSize := Value;
48515 if (Handle <> 0) then begin
48516 FillChar(SI, SizeOf(SI), 0);
48517 SI.cbSize := SizeOf(SI);
48518 SI.fMask := SIF_PAGE or SIF_RANGE;
48519 SBGetScrollInfo(SI);
48520 if (SI.nMax = 0) and (SI.nMin = 0) then
48521 SI.nMax := 1;
48522 SI.nMax := SI.nMax - Integer(SI.nPage) + Value;
48523 SI.nPage := Value;
48524 SBSetScrollInfo(SI);
48525 end;
48526 end;
48528 //[procedure TControl.SetSBPosition]
48529 procedure TControl.SetSBPosition(Value: Integer);
48530 begin
48531 fSBPosition := Value;
48532 if (Handle <> 0) then
48533 SetScrollPos(Handle, SB_CTL, Value, True);
48534 end;
48536 //[procedure TControl.SetSBMinMax]
48537 procedure TControl.SetSBMinMax(const Value: TPoint);
48538 begin
48539 GetSBMinMax;
48540 if (Handle <> 0) then
48541 SetScrollRange(Handle, SB_CTL, Value.X, Value.Y + SBPageSize - 1, True)
48542 else
48543 fSBMinMax := Value;
48544 end;
48546 //[procedure TControl.SBSetScrollInfo]
48547 function TControl.SBSetScrollInfo(const SI: TScrollInfo): Integer;
48548 begin
48549 Result := SetScrollInfo(Handle, SB_CTL, SI, True)
48550 end;
48552 //[procedure TControl.SBGetScrollInfo]
48553 function TControl.SBGetScrollInfo(var SI: TScrollInfo): Boolean;
48554 begin
48555 Result := Cardinal(GetScrollInfo(Handle, SB_CTL, SI)) <> 0;
48556 end;
48559 { -- OpenSaveDialog -- }
48562 //[function NewOpenSaveDialog]
48563 function NewOpenSaveDialog( const Title, StrtDir: String;
48564 Options: TOpenSaveOptions ): POpenSaveDialog;
48565 begin
48567 New( Result, Create );
48568 {+}{++}(*Result := POpenSaveDialog.Create;*){--}
48569 Result.FOptions := Options;
48570 if Options = [] then
48571 Result.FOptions := DefOpenSaveDlgOptions;
48572 Result.fOpenDialog := True;
48573 Result.FTitle := Title;
48574 Result.FInitialDir := StrtDir;
48575 end;
48576 //[END NewOpenSaveDialog]
48578 { TOpenSaveDialog }
48580 {$IFDEF ASM_VERSION}
48581 //[destructor TOpenSaveDialog.Destroy]
48582 destructor TOpenSaveDialog.Destroy;
48583 asm //cmd //opd
48584 PUSH EAX
48585 PUSH 0
48586 LEA EDX, [EAX].FFilter
48587 PUSH EDX
48588 LEA EDX, [EAX].FInitialDir
48589 PUSH EDX
48590 LEA EDX, [EAX].FDefExtension
48591 PUSH EDX
48592 LEA EDX, [EAX].FFileName
48593 PUSH EDX
48594 LEA EAX, [EAX].FTitle
48595 @@loo:
48596 CALL System.@LStrClr
48597 POP EAX
48598 TEST EAX, EAX
48599 JNZ @@loo
48600 POP EAX
48601 CALL TObj.Destroy
48602 end;
48603 {$ELSE ASM_VERSION} //Pascal
48604 destructor TOpenSaveDialog.Destroy;
48605 begin
48606 FFilter := '';
48607 FInitialDir := '';
48608 FDefExtension := '';
48609 FFileName := '';
48610 FTitle := '';
48611 {$IFDEF OpenSaveDialog_Extended}
48612 TemplateName := '';
48613 {$ENDIF}
48614 inherited;
48615 end;
48616 {$ENDIF ASM_VERSION}
48618 {$IFDEF ASM_VERSION}
48619 //[function TOpenSaveDialog.Execute]
48620 function TOpenSaveDialog.Execute: Boolean;
48622 PUSH EBX
48623 XCHG EBX, EAX
48625 XOR ECX, ECX
48626 {$IFDEF OpenSaveDialog_Extended}
48627 PUSH [EBX].TemplateName
48628 PUSH [EBX].HookProc
48629 {$ELSE}
48630 PUSH ECX // prepare lpTemplateName = nil
48631 PUSH ECX // prepare lpfnHook = nil
48632 {$ENDIF}
48633 PUSH EBX // prepare lCustData = @Self
48634 MOV EDX, [EBX].FDefExtension
48635 CALL EDX2PChar
48636 PUSH EDX // prepare lpstrDefExt = FDefExtension
48637 PUSH ECX // prepare nFileExtension, nFileOffset: Word = 0, 0
48638 // prepare flags:
48639 LEA EAX, [EBX].FOptions
48640 MOV EDX, Offset[@@OpenSaveFlags]
48641 {$IFDEF OpenSaveDialog_Extended}
48642 MOV CL, 14
48643 {$ELSE}
48644 MOV CL, 12
48645 {$ENDIF}
48646 CALL MakeFlags
48647 XOR ECX, ECX
48648 OR EAX, OFN_EXPLORER or OFN_LONGNAMES or OFN_ENABLESIZING
48649 PUSH EAX // push Flags
48650 PUSH [EBX].FTitle // prepare lpstrTitle
48651 PUSH [EBX].FInitialDir // prepare lpstrInitialDir
48652 PUSH ECX // prepare nMaxFileTitle = 0
48653 PUSH ECX // prepare lpstrFileTitle = nil
48654 TEST AH, 2 // MultiSelect?
48655 MOV EAX, 65520
48656 JNZ @@1
48657 MOV AX, MAX_PATH+2
48658 @@1: PUSH EAX // prepare nMaxFile
48659 CALL System.@GetMem
48660 POP ECX
48661 PUSH ECX
48662 PUSH EAX // prepare lpStrFile
48663 XOR EDX, EDX
48665 @@2: //MOV [EAX], DL // clear it initially {Vadim Petrov: it is necessary}
48666 //INC EAX
48667 //LOOP @@2
48669 MOV EDX, [EBX].fFileName // no, fill it initilly by FileName
48670 CALL EDX2PChar
48671 DEC ECX // added 5 october 2003 to prevent possible error if FileName too big
48672 CALL StrLCopy
48673 XOR EDX, EDX
48675 PUSH [EBX].FFilterIndex // prepare nFilterIndex
48676 PUSH EDX // prepare nMaxCustFilter
48677 PUSH EDX // prepare lpstrCustomFilter
48678 PUSH EDX // prepare lpstrFilter = nil
48679 MOV EAX, ESP
48680 OR EDX, [EBX].FFilter
48681 JZ @@5
48683 MOV ECX, offset[@@0]
48684 CALL System.@LStrCat3 // prepare lpStrFilter = FFilter + #0
48685 POP EAX
48686 PUSH EAX
48687 XOR EDX, EDX
48688 @@3: INC EAX // filter is not starting from ';' or '|'...
48689 CMP [EAX], DL
48690 JZ @@5
48691 CMP byte ptr [EAX], '|'
48692 JNZ @@3
48693 @@4: MOV [EAX], DL
48694 JMP @@3
48695 @@OpenSaveFlags:
48696 DD OFN_CREATEPROMPT, OFN_EXTENSIONDIFFERENT, OFN_FILEMUSTEXIST
48697 DD OFN_HIDEREADONLY, OFN_NOCHANGEDIR, OFN_NODEREFERENCELINKS
48698 DD OFN_ALLOWMULTISELECT, OFN_NONETWORKBUTTON, OFN_NOREADONLYRETURN
48699 DD OFN_OVERWRITEPROMPT, OFN_PATHMUSTEXIST, OFN_READONLY, OFN_NOVALIDATE
48700 {$IFDEF OpenSaveDialog_Extended}
48701 DD OFN_ENABLETEMPLATE, OFN_ENABLEHOOK
48702 {$ENDIF}
48704 DD -1, 1
48705 @@0: DB 0
48708 @@5:
48709 PUSH [hInstance] // prepare hInstance
48711 MOV ECX, [EBX].TControl.fWnd
48712 INC ECX
48713 LOOP @@6
48714 MOV ECX, [Applet]
48715 JECXZ @@6
48716 MOV ECX, [ECX].TControl.fHandle
48717 @@6: PUSH ECX // prepare hWndOwner
48718 PUSH 76 // prepare lStructSize
48720 PUSH ESP
48721 CMP [EBX].FOpenDialog, DL
48722 JZ @@7
48723 CALL GetOpenFileName
48724 JMP @@8
48725 @@7: CALL GetSaveFileName
48726 @@8:
48727 PUSH EAX
48728 XOR EDX, EDX
48729 TEST EAX, EAX
48730 JZ @@10
48732 MOV EAX, [ESP+4].TOpenFileName.nFilterIndex
48733 MOV [EBX].FFilterIndex, EAX
48735 MOV EAX, [ESP+4].TOpenFileName.lpstrFile
48736 MOV EDX, EAX
48737 XOR ECX, ECX
48739 TEST [EBX].FOptions, 1 shl OSAllowMultiSelect
48740 JZ @@10
48742 DEC EAX
48743 @@9: INC EAX
48744 CMP byte ptr [EAX], CL
48745 JNZ @@9
48746 CMP byte ptr [EAX+1], CL
48747 JZ @@10
48748 MOV byte ptr [EAX], 13
48749 JMP @@9
48751 @@10:
48752 LEA EAX, [EBX].FFileName
48753 CALL System.@LStrFromPChar
48754 MOV EAX, [ESP+4].TOpenFileName.lpstrFile
48755 CALL System.@FreeMem // v1.86 +AK
48757 LEA EAX, [ESP+4].TOpenFileName.lpstrFilter
48758 CALL System.@LStrClr
48760 POP EAX
48761 ADD ESP, 76
48762 POP EBX
48763 end;
48764 {$ELSE ASM_VERSION} //Pascal
48765 function TOpenSaveDialog.Execute: Boolean;
48766 const OpenSaveFlags: array[ TOpenSaveOption ] of Integer = (
48767 OFN_CREATEPROMPT,
48768 OFN_EXTENSIONDIFFERENT,
48769 OFN_FILEMUSTEXIST,
48770 OFN_HIDEREADONLY,
48771 OFN_NOCHANGEDIR,
48772 OFN_NODEREFERENCELINKS,
48773 OFN_ALLOWMULTISELECT,
48774 OFN_NONETWORKBUTTON,
48775 OFN_NOREADONLYRETURN,
48776 OFN_OVERWRITEPROMPT,
48777 OFN_PATHMUSTEXIST,
48778 OFN_READONLY,
48779 OFN_NOVALIDATE
48780 //{$IFDEF OpenSaveDialog_Extended}
48782 OFN_ENABLETEMPLATE,
48783 OFN_ENABLEHOOK
48784 //{$ENDIF}
48787 Ofn : TOpenFilename;
48788 Fltr : String;
48789 TempFilename : String;
48791 Function MakeFilter(s : string) : String;
48793 format of filter for API call is following:
48794 'text files'#0'*.txt'#0
48795 'bitmap files'#0'*.bmp'#0#0
48797 var Str: PChar;
48798 begin
48799 Result := s;
48800 if Result='' then
48801 exit;
48802 Result:=Result+#0; {Delphi string always end on #0 is this is #0#0}
48803 Str := PChar( Result );
48804 while Str^ <> #0 do
48805 begin
48806 if Str^ = '|' then
48807 Str^ := #0;
48808 Inc( Str );
48809 end;
48810 end;
48812 begin
48813 Fillchar( ofn, sizeof( ofn ), 0 );
48815 ofn.lStructSize:= 76; //to provide correct work in Win9x
48816 //sizeof(ofn); - by suggestion of Michael Morozov, 28-Nov-2001
48817 if fWnd <> 0 then
48818 ofn.hWndOwner := fWnd
48819 else
48820 if assigned(applet) then
48821 ofn.hwndOwner:=applet.Handle;
48823 ofn.hInstance:=HInstance;
48825 Fltr:=MakeFilter(FFilter);
48826 if Fltr <> '' then
48827 ofn.lpstrFilter:=pchar(Fltr);
48829 //ofn.lpstrCustomFilter:=nil;
48830 //ofn.nMaxCustFilter:=0;
48831 ofn.nFilterIndex:=FFilterIndex;
48833 if OSAllowMultiSelect in FOptions then
48834 ofn.nMaxFile:=High(word)-14 // by V.K. (exchanged condition)
48835 else
48836 ofn.nMaxFile:=MAX_PATH+2;
48838 TempFileName:=StringOfChar(#0,ofn.nMaxFile); {Vadim Petrov}
48839 ofn.lpstrFile:=StrLCopy(pchar(TempFileName), pchar(fFileName),
48840 Min(ofn.nMaxFile,Length(fFileName)));
48842 ofn.lpstrInitialDir:=Pointer(FInitialDir);
48843 ofn.lpstrTitle:=Pointer(FTitle);
48844 ofn.Flags := MakeFlags( @FOptions, OpenSaveFlags )
48845 or OFN_EXPLORER or OFN_LONGNAMES or OFN_ENABLESIZING;
48847 ofn.lpstrDefExt:=PChar(FDefExtension);
48848 ofn.lCustData:=integer(@self);
48849 {$IFDEF OpenSaveDialog_Extended}
48850 ofn.lpTemplateName := PChar( TemplateName );
48851 ofn.lpfnHook := HookProc;
48852 {$ELSE}
48853 ofn.lpTemplateName:=nil;
48854 ofn.lpfnHook:=nil;
48855 {$ENDIF}
48856 if fOpenDialog then
48857 result:=GetOpenFileName(ofn)
48858 else
48859 result:=GetSaveFileName(ofn);
48860 if result then begin
48861 fFilterIndex := ofn.nFilterIndex; // by Vadim
48862 if OSAllowMultiSelect in foptions then begin
48863 FFileName:=copy(TempFileName, 1, pos(#0#0, tempfilename)-1);
48864 while pos(#0, ffilename) > 0 do begin
48865 FFilename[pos(#0, ffilename)]:=#13;
48866 end;
48867 end else
48868 FFileName:=copy(tempFileName, 1, pos(#0, TempFilename)
48869 -1 // by X.Y.B.
48871 end else
48872 FFilename:='';
48873 end;
48874 {$ENDIF ASM_VERSION}
48876 { -- OpenDirDialog -- }
48879 //[function NewOpenDirDialog]
48880 function NewOpenDirDialog( const Title: String; Options: TOpenDirOptions ):
48881 POpenDirDialog;
48882 begin
48884 New( Result, Create );
48885 {+}{++}(*Result := POpenDirDialog.Create;*){--}
48886 Result.FOptions := [ odOnlySystemDirs ];
48887 if Options <> [] then
48888 Result.FOptions := Options;
48889 Result.FTitle := Title;
48890 end;
48891 //[END NewOpenDirDialog]
48893 { TOpenDirDialog }
48895 {$IFDEF ASM_VERSION}
48896 //[destructor TOpenDirDialog.Destroy]
48897 destructor TOpenDirDialog.Destroy;
48898 asm //cmd //opd
48899 PUSH EAX
48900 PUSH 0
48901 LEA EDX, [EAX].FTitle
48902 PUSH EDX
48903 LEA EDX, [EAX].FInitialPath
48904 PUSH EDX
48905 LEA EAX, [EAX].FStatusText
48906 @@loo: CALL System.@LStrClr
48907 POP EAX
48908 TEST EAX, EAX
48909 JNZ @@loo
48910 POP EAX
48911 CALL TObj.Destroy
48912 end;
48913 {$ELSE ASM_VERSION} //Pascal
48914 destructor TOpenDirDialog.Destroy;
48915 begin
48916 FTitle := '';
48917 FInitialPath := '';
48918 FStatusText := '';
48919 inherited;
48920 end;
48921 {$ENDIF ASM_VERSION}
48923 type
48924 {$IFNDEF _D2}
48925 (*IMalloc = interface(IUnknown)
48926 ['{00000002-0000-0000-C000-000000000046}']
48927 function Alloc(cb: Longint): Pointer; stdcall;
48928 function Realloc(pv: Pointer; cb: Longint): Pointer; stdcall;
48929 procedure Free(pv: Pointer); stdcall;
48930 function GetSize(pv: Pointer): Longint; stdcall;
48931 function DidAlloc(pv: Pointer): Integer; stdcall;
48932 procedure HeapMinimize; stdcall;
48933 end;*)
48934 {$ENDIF}
48936 PSHItemID = ^TSHItemID;
48937 TSHItemID = packed record
48938 cb: Word; { Size of the ID (including cb itself) }
48939 abID: array[0..0] of Byte; { The item ID (variable length) }
48940 end;
48942 PItemIDList = ^TItemIDList;
48943 TItemIDList = record
48944 mkid: TSHItemID;
48945 end;
48947 PBrowseInfo = ^TBrowseInfo;
48948 TBrowseInfo = record
48949 hwndOwner: HWND;
48950 pidlRoot: PItemIDList;
48951 pszDisplayName: PAnsiChar; { Return display name of item selected. }
48952 lpszTitle: PAnsiChar; { text to go in the banner over the tree. }
48953 ulFlags: UINT; { Flags that control the return stuff }
48954 lpfn: Pointer; //TFNBFFCallBack;
48955 lParam: LPARAM; { extra info that's passed back in callbacks }
48956 iImage: Integer; { output var: where to return the Image index. }
48957 end;
48959 //[API SHXXXXXXXXXX]
48960 function SHBrowseForFolder(var lpbi: TBrowseInfo): PItemIDList; stdcall;
48961 external 'shell32.dll' name 'SHBrowseForFolderA';
48962 function SHGetPathFromIDList(pidl: PItemIDList; pszPath: PChar): BOOL; stdcall;
48963 external shell32 name 'SHGetPathFromIDListA';
48965 function CoTaskMemAlloc(cb : DWORD) : pointer; stdcall; external 'ole32.dll'
48966 name 'CoTaskMemAlloc';
48968 procedure CoTaskMemFree(pv: Pointer); stdcall; external 'ole32.dll'
48969 name 'CoTaskMemFree';
48971 const
48972 BIF_RETURNONLYFSDIRS = $0001; { For finding a folder to start document searching }
48973 BIF_DONTGOBELOWDOMAIN = $0002; { For starting the Find Computer }
48974 BIF_STATUSTEXT = $0004;
48975 BIF_RETURNFSANCESTORS = $0008;
48976 BIF_EDITBOX = $0010;
48977 BIF_VALIDATE = $0020; { insist on valid result (or CANCEL) }
48978 BIF_NEWDIALOGSTYLE = $0040; { Use the new dialog layout with the ability to resize }
48979 { Caller needs to call OleInitialize() before using this API (c) JVCL }
48980 BIF_BROWSEFORCOMPUTER = $1000; { Browsing for Computers. }
48981 BIF_BROWSEFORPRINTER = $2000; { Browsing for Printers }
48982 BIF_BROWSEINCLUDEFILES = $4000; { Browsing for Everything }
48984 BFFM_INITIALIZED = 1;
48985 BFFM_SELCHANGED = 2;
48987 BFFM_SETSTATUSTEXT = WM_USER + 100;
48988 BFFM_ENABLEOK = WM_USER + 101;
48989 BFFM_SETSELECTION = WM_USER + 102;
48992 {$IFDEF ASM_VERSION} // WndOwner
48993 //[function TOpenDirDialog.Execute]
48994 function TOpenDirDialog.Execute: Boolean;
48996 PUSH EBX
48997 XCHG EBX, EAX
48999 XOR ECX, ECX
49000 PUSH ECX // prepare iImage = 0
49001 PUSH EBX // prepare lParam = @Self
49002 PUSH [EBX].FCallBack // prepare lpfn = FCallBack
49003 LEA EAX, [EBX].FOptions
49004 MOV EDX, Offset[@@FlagsArray]
49005 MOV CL, 8
49006 CALL MakeFlags
49007 PUSH EAX // prepare ulFlags = Options
49008 PUSH [EBX].FTitle // prepare lpszTitle
49009 LEA EAX, [EBX].FBuf
49010 PUSH EAX // prepare pszDisplayName
49011 PUSH 0 // prepare pidlRoot
49012 MOV ECX, [EBX].fWnd
49013 INC ECX
49014 LOOP @@1
49015 MOV ECX, Applet
49016 JECXZ @@1
49017 MOV ECX, [ECX].TControl.fHandle
49018 @@1: PUSH ECX // prepare hwndOwner
49020 PUSH ESP
49021 CALL SHBrowseForFolder
49022 ADD ESP, 32
49023 TEST EAX, EAX
49024 JZ @@exit
49026 PUSH EAX
49028 LEA EDX, [EBX].FBuf
49029 PUSH EDX
49030 PUSH EAX
49031 CALL SHGetPathFromIDList
49033 CALL CoTaskMemFree
49035 MOV AL, 1
49036 JMP @@fin
49038 @@FlagsArray:
49039 DD BIF_BROWSEFORCOMPUTER, BIF_BROWSEFORPRINTER, BIF_DONTGOBELOWDOMAIN
49040 DD BIF_RETURNFSANCESTORS, BIF_RETURNONLYFSDIRS, BIF_STATUSTEXT
49041 DD BIF_BROWSEINCLUDEFILES, BIF_EDITBOX, BIF_NEWDIALOGSTYLE
49043 @@exit: XOR EAX, EAX
49044 @@fin:
49045 POP EBX
49046 end;
49047 {$ELSE ASM_VERSION} //Pascal
49048 function TOpenDirDialog.Execute: Boolean;
49049 const FlagsArray: array[ TOpenDirOption ] of Integer =
49050 ( BIF_BROWSEFORCOMPUTER, BIF_BROWSEFORPRINTER, BIF_DONTGOBELOWDOMAIN,
49051 BIF_RETURNFSANCESTORS, BIF_RETURNONLYFSDIRS, BIF_STATUSTEXT,
49052 BIF_BROWSEINCLUDEFILES, BIF_EDITBOX, BIF_NEWDIALOGSTYLE );
49053 var BI : TBrowseInfo;
49054 Browse : PItemIdList;
49055 begin
49056 Result := False;
49057 if WndOwner <> 0 then
49058 BI.hwndOwner := WndOwner
49059 else
49060 if assigned( Applet ) then
49061 BI.hwndOwner := Applet.Handle
49062 else
49063 BI.hwndOwner := 0;
49064 BI.pidlRoot := nil;
49065 BI.pszDisplayName := @FBuf[ 0 ];
49066 BI.lpszTitle := PChar( Title );
49067 BI.ulFlags := MakeFlags( @FOptions, FlagsArray );
49068 BI.lpfn := FCallBack;
49069 BI.lParam := Integer( @Self );
49070 Browse := SHBrowseForFolder( BI );
49071 if Browse <> nil then
49072 begin
49073 SHGetPathFromIDList( Browse, @FBuf[ 0 ] );
49074 CoTaskMemFree( Browse );
49075 Result := True;
49076 end;
49077 end;
49078 {$ENDIF ASM_VERSION}
49080 //[function TOpenDirDialog.GetInitialPath]
49081 function TOpenDirDialog.GetInitialPath: String;
49082 begin
49083 Result := IncludeTrailingPathDelimiter( fInitialPath );
49084 end;
49086 //[function TOpenDirDialog.GetPath]
49087 function TOpenDirDialog.GetPath: String;
49088 begin
49089 Result := FBuf;
49090 end;
49092 //[FUNCTION OpenDirSelChangeCallBack]
49093 {$IFDEF ASM_VERSION}
49094 function OpenDirSelChangeCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ):
49095 Integer; stdcall;
49097 MOV EAX, [lpData]
49098 MOV ECX, [EAX].TOpenDirDialog.FOnSelChanged.TMethod.Code
49099 JECXZ @@exit
49101 LEA EDX, [EAX].TOpenDirDialog.FBuf
49102 PUSH EDX
49103 PUSH [lParam]
49104 CALL SHGetPathFromIDList
49106 //EnableOK := 0;
49107 //Self_.FOnSelChanged( Self_, Self_.FBuf, EnableOK, Self_.FStatusText );
49109 MOV EDX, [lpData]
49110 LEA ECX, [EDX].TOpenDirDialog.FBuf
49111 PUSH 0
49112 PUSH ESP
49113 LEA EAX, [EDX].TOpenDirDialog.FStatusText
49114 PUSH EAX
49115 MOV EAX, [EDX].TOpenDirDialog.FOnSelChanged.TMethod.Data
49116 CALL dword ptr [EDX].TOpenDirDialog.FOnSelChanged.TMethod.Code
49117 POP ECX
49118 JECXZ @@1
49120 INC ECX
49121 PUSH ECX
49122 PUSH 0
49123 PUSH BFFM_ENABLEOK
49124 PUSH [Wnd]
49125 CALL SendMessage
49126 @@1:
49127 MOV EDX, [lpData]
49128 MOV ECX, [EDX].TOpenDirDialog.FStatusText
49129 JECXZ @@exit
49131 PUSH ECX
49132 PUSH 0
49133 PUSH BFFM_SETSTATUSTEXT
49134 PUSH [Wnd]
49135 CALL SendMessage
49137 @@exit: XOR EAX, EAX
49138 end;
49139 {$ELSE ASM_VERSION} //Pascal
49140 function OpenDirSelChangeCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ):
49141 Integer; stdcall;
49142 var _Self_: POpenDirDialog;
49143 EnableOK: Integer;
49144 begin
49145 _Self_ := Pointer( lpData );
49146 if assigned( _Self_.FOnSelChanged ) then
49147 begin
49148 SHGetPathFromIDList( PItemIDList( lParam ), @ _Self_.FBuf[ 0 ] );
49149 EnableOK := 0;
49150 _Self_.FOnSelChanged( _Self_, _Self_.FBuf, EnableOK, _Self_.FStatusText );
49151 if EnableOK <> 0 then
49152 SendMessage( Wnd, BFFM_ENABLEOK, 0, EnableOK + 1 );
49153 if _Self_.FStatusText <> '' then
49154 SendMessage( Wnd, BFFM_SETSTATUSTEXT, 0, Integer( PChar( _Self_.FStatusText ) ) );
49155 end;
49156 Result := 0;
49157 end;
49158 {$ENDIF ASM_VERSION}
49159 //[END OpenDirSelChangeCallBack]
49161 //[FUNCTION OpenDirCallBack]
49162 {$IFDEF ASM_VERSION}
49163 function OpenDirCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ): Integer;
49164 stdcall;
49166 MOV EAX, [Wnd]
49167 MOV EDX, [lpData]
49168 MOV ECX, [Msg]
49169 LOOP @@chk_sel_chg
49170 // Msg = 1 -> BFFM_Initialized
49172 MOV ECX, [EDX].TOpenDirDialog.FCenterProc
49173 JECXZ @@1
49174 PUSH EDX
49175 CALL ECX
49176 POP EDX
49177 @@1: MOV ECX, [EDX].TOpenDirDialog.FInitialPath
49178 JECXZ @@exit
49179 PUSH ECX
49180 PUSH 1
49181 PUSH BFFM_SETSELECTION
49182 PUSH [Wnd]
49183 CALL SendMessage
49184 JMP @@exit
49186 @@chk_sel_chg:
49187 LOOP @@exit
49188 // Msg = 2 -> BFFM_SelChanged
49190 MOV ECX, [EDX].TOpenDirDialog.FDoSelChanged
49191 JECXZ @@exit
49192 POP EBP
49193 JMP ECX
49195 @@exit: XOR EAX, EAX
49196 end;
49197 {$ELSE ASM_VERSION} //Pascal
49198 function OpenDirCallBack( Wnd: HWnd; Msg: DWORD; lParam, lpData: LParam ): Integer;
49199 stdcall;
49200 var Self_ : POpenDirDialog;
49201 begin
49202 Self_ := Pointer( lpData );
49203 if Msg = BFFM_INITIALIZED then
49204 begin
49205 if assigned( Self_.FCenterProc ) then
49206 Self_.FCenterProc( Wnd );
49207 if Self_.FInitialPath <> '' then
49208 SendMessage( Wnd, BFFM_SETSELECTION, 1, Integer( PChar( Self_.FInitialPath ) ) );
49210 else
49211 if Msg = BFFM_SELCHANGED then
49212 begin
49213 if assigned( Self_.FDoSelChanged ) then
49214 Self_.FDoSelChanged( Wnd, Msg, lParam, lpData );
49215 end;
49216 Result := 0;
49217 end;
49218 {$ENDIF ASM_VERSION}
49219 //[END OpenDirCallBack]
49221 //[PROCEDURE OpenDirDlgCenter]
49222 {$IFDEF ASM_VERSION}
49223 procedure OpenDirDlgCenter( Wnd: HWnd );
49225 PUSH EBX
49226 MOV EBX, EAX
49228 ADD ESP, -16
49229 PUSH ESP
49230 PUSH EAX
49231 CALL GetWindowRect
49232 POP EDX // EDX = Left
49233 POP ECX // ECX = Top
49234 POP EAX // EAX = Right
49235 SUB EAX, EDX // EAX = W
49236 POP EDX // EDX = Bottom
49237 SUB EDX, ECX // EDX = H
49238 XOR ECX, ECX
49239 INC ECX
49240 PUSH ECX // prepare True
49241 PUSH EDX // prepare H
49242 PUSH EAX // prepare W
49244 INC ECX
49245 @@1:
49246 PUSH ECX
49248 DEC ECX
49249 PUSH ECX
49250 CALL GetSystemMetrics
49252 POP ECX
49253 SUB EAX, [ESP+4]
49254 SAR EAX, 1
49255 PUSH EAX
49257 LOOP @@1
49260 PUSH SM_CYSCREEN
49261 CALL GetSystemMetrics
49262 SUB EAX, [ESP+4]
49263 SAR EAX, 1
49264 PUSH EAX
49266 PUSH SM_CXSCREEN
49267 CALL GetSystemMetrics
49268 SUB EAX, [ESP+4]
49269 SAR EAX, 1
49270 PUSH EAX
49273 PUSH EBX
49274 CALL MoveWindow
49275 POP EBX
49276 end;
49277 {$ELSE ASM_VERSION} //Pascal
49278 procedure OpenDirDlgCenter( Wnd: HWnd );
49279 var R: TRect;
49280 W, H: Integer;
49281 begin
49282 GetWindowRect( Wnd, R );
49283 W := R.Right - R.Left;
49284 H := R.Bottom - R.Top;
49285 R.Left := (GetSystemMetrics( SM_CXSCREEN ) - W) div 2;
49286 R.Top := (GetSystemMetrics( SM_CYSCREEN ) - H) div 2;
49287 MoveWindow( Wnd, R.Left, R.Top, W, H, True );
49288 end;
49289 {$ENDIF ASM_VERSION}
49290 //[END OpenDirDlgCenter]
49292 {$IFDEF ASM_VERSION}
49293 //[procedure TOpenDirDialog.SetCenterOnScreen]
49294 procedure TOpenDirDialog.SetCenterOnScreen(const Value: Boolean);
49296 MOV [EAX].FCenterOnScreen, DL
49297 MOVZX ECX, DL
49298 JECXZ @@1
49299 MOV ECX, Offset[OpenDirDlgCenter]
49300 @@1: MOV [EAX].FCenterProc, ECX
49301 end;
49302 {$ELSE ASM_VERSION} //Pascal
49303 procedure TOpenDirDialog.SetCenterOnScreen(const Value: Boolean);
49304 var P: procedure( Wnd: HWnd );
49305 begin
49306 FCenterOnScreen := Value;
49307 P := nil;
49308 if Value then
49309 P := @OpenDirDlgCenter;
49310 FCenterProc := P;
49311 end;
49312 {$ENDIF ASM_VERSION}
49314 //[procedure TOpenDirDialog.SetInitialPath]
49315 procedure TOpenDirDialog.SetInitialPath(const Value: String);
49316 begin
49317 FCallBack := @OpenDirCallBack;
49318 FInitialPath := ExcludeTrailingPathDelimiter( Value );
49319 if (FInitialPath <> '') and
49320 (FInitialPath[ Length( FInitialPath ) ] = ':') then
49321 FInitialPath := IncludeTrailingPathDelimiter( Value );
49322 end;
49324 //[procedure TOpenDirDialog.SetOnSelChanged]
49325 procedure TOpenDirDialog.SetOnSelChanged(const Value: TOnODSelChange);
49326 begin
49327 FOnSelChanged := Value;
49328 FCallBack := @OpenDirCallBack;
49329 FDoSelChanged := @OpenDirSelChangeCallBack;
49330 end;
49333 type
49334 PByteArray =^TByteArray;
49335 TByteArray = array[Word]of Byte;
49337 //[API CreateMappedBitmap]
49338 function CreateMappedBitmap(Instance: THandle; Bitmap: Integer;
49339 Flags: UINT; ColorMap: PColorMap; NumMaps: Integer): HBitmap; stdcall;
49340 external cctrl name 'CreateMappedBitmap';
49342 //[function CreateMappedBitmapEx]
49343 function CreateMappedBitmapEx(Instance: THandle; BmpRsrcName: PChar; Flags:
49344 Cardinal; ColorMap: PColorMap; NumMaps: Integer): HBitmap;
49345 var bi: TBITMAPINFO;
49346 DC, tmcl: Cardinal;
49347 Bits: PByteArray;
49348 i, j, k, CO, bps: Integer;
49349 tm: array [1..4] of byte absolute tmcl;
49350 bm: Windows.TBITMAP;
49351 CM: PColorMap;
49352 DW: HWnd;
49353 begin
49354 Result := LoadBitmap( Instance, BmpRsrcName );
49355 if Result = 0 then
49356 begin
49357 {$IFDEF DEBUG}
49358 ShowMessage( 'Can not load bitmap ' + BmpRsrcName + ', error ' +
49359 Int2Str( GetLastError ) + ': ' + SysErrorMessage( GetLastError ) );
49360 {$ENDIF}
49361 Exit;
49362 end;
49363 DW := GetDesktopWindow;
49364 DC := GetDC(DW);
49365 FillChar( bm, SizeOf(bm), 0 );
49366 GetObject( Result, SizeOf( bm ), @bm );
49368 FillChar( bi, SizeOf( bi ), 0 );
49369 bi.bmiHeader.biSize := SizeOf( bi.bmiHeader );
49370 bi.bmiHeader.biWidth := bm.bmWidth;
49371 bi.bmiHeader.biHeight := -bm.bmHeight;
49372 bi.bmiHeader.biPlanes := 1;
49373 bi.bmiHeader.biBitCount := 24;
49374 // BitCout - always 24 for easy algorythm
49375 bi.bmiHeader.biCompression:=BI_RGB;
49376 bps := CalcScanLineSize( @bi.bmiHeader );
49378 GetMem( Bits, bps * bm.bmHeight );
49379 GetDIBits( DC, Result, 0, bm.bmHeight, @Bits[0], bi, DIB_RGB_COLORS );
49380 DeleteObject( Result );
49382 for i := 0 to bm.bmHeight - 1 do begin
49383 for j := 0 to bm.bmWidth - 1 do begin
49384 CO := bps * i + 3 * j;
49385 for k := 0 to NumMaps - 1 do begin
49386 CM := Pointer( Integer( ColorMap ) + SizeOf( TColorMap ) * k );
49387 if RGB( Bits[CO+2], Bits[CO+1], Bits[CO] ) = CM.cFrom then
49388 begin
49389 tmcl := CM.cTo;
49390 tm[4]:=tm[1];
49391 tm[1]:=tm[3];
49392 tm[3]:=tm[4];
49393 Move( tmcl, Bits[CO], 3);
49394 end;
49395 end;
49396 end;
49397 end;
49398 Result := CreateDIBitmap( DC, bi.bmiHeader, CBM_INIT, @Bits[0], bi,
49399 DIB_RGB_COLORS );
49400 ReleaseDC( DW, DC );
49401 FreeMem( Bits );
49402 end;
49405 //[function LoadMappedBitmap]
49406 function LoadMappedBitmap( hInst: THandle; BmpResID: Integer; const Map: array of TColor )
49407 : HBitmap;
49408 var Map2Pass: Pointer;
49409 begin
49410 Map2Pass := nil;
49411 if High( Map ) > 0 then
49412 Map2Pass := PColorMap( @Map[ 0 ] );
49413 Result := CreateMappedBitmap( hInst, BmpResID, 0, Map2Pass, (High( Map ) + 1) div 2 );
49414 end;
49416 //[function LoadMappedBitmapEx]
49417 function LoadMappedBitmapEx( MasterObj: PObj; hInst: THandle; BmpResName: PChar; const Map: array of TColor )
49418 : HBitmap;
49419 var Map2Pass: Pointer;
49420 begin
49421 Map2Pass := nil;
49422 if High( Map ) > 0 then
49423 Map2Pass := PColorMap( @Map[ 0 ] );
49424 Result := CreateMappedBitmapEx( hInst, BmpResName, 0, Map2Pass, (High( Map ) + 1) div 2 );
49425 if MasterObj <> nil then
49426 MasterObj.Add2AutoFreeEx( TObjectMethod( MakeMethod( Pointer( Result ), @ FreeBmp ) ) );
49427 end;
49429 { -- Toolbar -- }
49431 {$IFDEF ASM_noVERSION} // width
49432 //[procedure TControl.TBAddBitmap]
49433 procedure TControl.TBAddBitmap(Bitmap: HBitmap);
49434 const szBI = sizeof(TBitmapInfo);
49436 TEST EDX, EDX
49437 JZ @@exit
49438 JGE @@1
49439 CMP EDX, -6
49440 JL @@1
49442 NEG EDX
49443 DEC EDX
49444 PUSH EDX
49445 PUSH -1
49446 XOR EDX, EDX
49447 JMP @@2
49449 @@1: PUSH EDX // AB.hInst = Bitmap
49450 PUSH 0 // AB.nID = 0
49452 PUSH EAX // > @Self
49453 ADD ESP, -szBI
49454 PUSH ESP
49455 PUSH szBI
49456 PUSH EDX
49457 CALL GetObject
49458 TEST EAX, EAX
49459 JG @@11
49461 ADD ESP, szBI
49462 JMP @@exit
49464 @@11: MOV EAX, [ESP].TBitmapInfo.bmiHeader.biWidth
49465 MOV ECX, [ESP].TBitmapInfo.bmiHeader.biHeight
49466 TEST ECX, ECX
49467 JGE @@12
49468 NEG ECX
49469 @@12: ADD ESP, szBI
49470 CDQ // EDX = 0
49471 DIV ECX // EAX = N
49472 XCHG EAX, [ESP] // > N
49473 PUSH EAX // > @Self
49475 MOV EDX, ECX
49476 SHL EDX, 16
49477 OR ECX, EDX
49479 PUSH EDX
49480 PUSH EDX
49481 PUSH TB_AUTOSIZE
49482 PUSH EAX
49484 PUSH ECX
49485 PUSH EDX
49486 PUSH TB_SETBITMAPSIZE
49487 PUSH EAX
49488 CALL Perform
49489 CALL Perform
49490 POP EAX
49491 POP EDX
49493 @@2: PUSH ESP
49494 PUSH EDX
49495 PUSH TB_ADDBITMAP
49496 PUSH EAX
49497 CALL Perform
49498 POP ECX
49499 POP ECX
49500 @@exit:
49501 end;
49502 {$ELSE ASM_VERSION} //Pascal
49503 procedure TControl.TBAddBitmap(Bitmap: HBitmap);
49504 const NstdBitmaps: array[ 0..5 ] of DWORD = ( 15, 15, 0, 0, 13, 13 );
49505 var BI: TBitmapInfo;
49506 AB: TTBAddBitmap;
49507 N, W: Integer;
49508 begin
49509 if Bitmap = 0 then Exit;
49510 if (Integer( Bitmap ) >= -10) and (Integer( Bitmap ) <= -1) then
49511 begin
49512 AB.hInst := THandle(-1);
49513 AB.nID := -Integer(Bitmap) - 1;
49514 N := 0; //NstdBitmaps[ AB.nID ]; // (this value is ignored)
49516 else
49517 if GetObject( Bitmap, sizeof( TBitmapInfo ), @BI ) > 0 then
49518 begin
49519 AB.hInst := 0;
49520 AB.nID := Bitmap;
49521 W := fTBBtnImgWidth;
49522 if W = 0 then
49523 W := Abs( BI.bmiHeader.biHeight );
49524 N := BI.bmiHeader.biWidth div W;
49525 Perform( TB_SETBITMAPSIZE, 0, MAKELONG( W, Abs(BI.bmiHeader.biHeight )) );
49526 Perform( TB_AUTOSIZE, 0, 0 );
49528 else Exit;
49529 Perform( TB_ADDBITMAP, N, Integer( @AB ) );
49530 end;
49531 {$ENDIF ASM_VERSION}
49533 var ToolbarsIDcmd: Integer = 100;
49534 {$IFDEF ASM_VERSION}
49535 //[function TControl.TBAddInsButtons]
49536 function TControl.TBAddInsButtons(Idx: Integer; const Buttons: array of PChar;
49537 const BtnImgIdxArray: array of Integer): Integer; stdcall;
49539 { [EBP+$8] = @Self
49540 [EBP+$C] = Idx
49541 [EBP+$10] = Buttons
49542 [EBP+$14] = High(Butons)
49543 [EBP+$18] = BtnImgIdxArray
49544 [EBP+$1C] = High(BtnImgIdxArray)
49546 PUSH EBX
49547 PUSH ESI
49548 PUSH EDI
49549 OR EBX, -1
49550 MOV EAX, 20
49551 MOV ECX, [EBP+$14]
49552 CMP ECX, EBX
49553 JLE @@fin
49554 INC ECX
49555 MUL ECX
49556 CALL System.@GetMem
49557 PUSH EAX // save AB to FreeMem after
49558 MOV EDX, EBX
49559 DEC EDX // nBmp := -2
49561 MOV ECX, [EBP+$14]
49562 INC ECX
49563 JZ @@exit
49565 MOV ECX, [EBP+$1C]
49566 INC ECX
49567 JZ @@1
49568 MOV ECX, [BtnImgIdxArray]
49569 MOV EDX, [ECX]
49570 DEC EDX // nBmp := BtnImgIdxArray[ 0 ] - 1
49571 @@1: MOV ECX, [EBP+$14]
49572 INC ECX
49573 MOV ESI, [Buttons]
49574 MOV EDI, EAX // EDI = PAB
49575 PUSH 0 // N:=0 in [EBP-$14]
49576 // -- impossible?-- JZ @@break
49577 @@loop:
49578 LODSD
49579 TEST EAX, EAX
49580 JZ @@break
49581 //CMP byte ptr [EAX], 0
49582 //JZ @@break
49583 PUSH ECX
49585 CMP word ptr [EAX], '-'
49586 JNE @@2
49588 OR EAX, -1
49589 STOSD
49590 //INC EAX //=0
49591 MOV EAX, [ToolbarsIDcmd]
49592 TEST EBX, EBX
49593 {$IFDEF USE_CMOV}
49594 CMOVL EBX, EAX
49595 {$ELSE}
49596 JGE @@b0
49597 MOV EBX, EAX
49598 @@b0: {$ENDIF}
49600 //INC [ToolbarsIDcmd]
49601 STOSD
49602 XOR EAX, EAX
49603 INC AH // TBSTYLE_SEP = 1
49604 STOSD
49605 DEC AH
49606 STOSD
49607 DEC EAX
49608 JMP @@3
49610 DD -1, 1
49611 @@0: DB 0
49613 @@2:
49614 INC EDX // Inc( nBmp )
49615 PUSH EAX
49617 MOV EAX, [EBP+$1C]
49618 MOV ECX, [EBP-$14]
49619 CMP EAX, ECX
49620 MOV EAX, EDX
49621 JL @@21
49622 MOV EAX, [BtnImgIdxArray]
49623 MOV EAX, [EAX+ECX*4]
49624 @@21: STOSD
49626 TEST EDX, EDX
49627 JGE @@2a
49628 DEC EDX
49629 @@2a:
49631 MOV EAX, [ToolbarsIDcmd]
49632 //INC [ToolbarsIDcmd]
49633 STOSD
49634 TEST EBX, EBX
49635 {$IFDEF USE_CMOV}
49636 CMOVL EBX, EAX
49637 {$ELSE}
49638 JGE @@210
49639 MOV EBX, EAX
49640 @@210: {$ENDIF}
49642 POP ECX
49643 MOV AX, $1004 // AL=fsState=_ENABLED, AH=fsStyle=_AUTOSIZE
49644 CMP byte ptr [ECX], '^'
49645 JNE @@22
49646 MOV AH, TBSTYLE_DROPDOWN or TBSTYLE_AUTOSIZE
49647 INC ECX
49648 @@22: CMP byte ptr [ECX], '-'
49649 JZ @@23
49650 CMP byte ptr [ECX], '+'
49651 JNZ @@24
49652 MOV AL, TBSTATE_ENABLED or TBSTATE_CHECKED
49653 @@23: INC ECX
49654 OR AH, TBSTYLE_CHECK
49655 CMP byte ptr [ECX], '!'
49656 JNZ @@24
49657 OR AH, TBSTYLE_GROUP
49658 INC ECX
49659 @@24: STOSD
49660 MOV EAX, [EBP+8]
49661 STOSD
49662 OR EAX, -1
49663 CMP word ptr [ECX], ' '
49664 JZ @@3
49665 CMP byte ptr [ECX], 0
49666 JZ @@3
49668 PUSH EDX
49669 PUSH 0
49670 MOV EDX, ECX
49671 MOV EAX, ESP
49672 CALL System.@LStrFromPChar
49673 MOV EAX, ESP
49674 MOV EDX, offset[@@0]
49675 CALL System.@LStrCat
49676 PUSH dword ptr [ESP]
49677 PUSH 0
49678 PUSH TB_ADDSTRING
49679 PUSH dword ptr [EBP+8]
49680 CALL Perform
49681 STOSD
49683 CALL RemoveStr
49684 POP EDX
49685 JMP @@30
49687 @@3: STOSD
49688 @@30: INC dword ptr [EBP-$14]
49689 INC [ToolbarsIDcmd]
49690 POP ECX
49691 DEC ECX
49692 JNZ @@loop
49693 @@break:
49694 POP ECX
49695 JECXZ @@exit
49696 PUSH dword ptr [ESP]
49697 MOV EAX, [Idx]
49698 TEST EAX, EAX
49699 JGE @@31
49701 PUSH ECX
49702 PUSH TB_ADDBUTTONS
49703 JMP @@32
49704 @@31:
49705 PUSH EAX
49706 PUSH TB_INSERTBUTTON
49707 @@32:
49708 PUSH dword ptr [EBP+8]
49709 CALL Perform
49710 @@exit:
49711 POP EAX
49712 //TEST EAX, EAX
49713 //JZ @@fin
49714 CALL System.@FreeMem
49716 @@fin:
49717 POP EDI
49718 POP ESI
49719 XCHG EAX, EBX
49720 POP EBX
49721 end;
49722 {$ELSE ASM_VERSION} //Pascal
49723 function TControl.TBAddInsButtons(Idx: Integer; const Buttons: array of PChar;
49724 const BtnImgIdxArray: array of Integer): Integer; stdcall;
49726 function AddInsButtons: Integer;
49727 type TTBBtnArray = array[ 0..100000 ] of TTBButton;
49728 PTBBtnArray = ^TTBBtnArray;
49729 var AB: PTBBtnArray;
49730 I, N, nBmp: Integer;
49731 PAB: PTBButton;
49732 Str: PChar;
49733 begin
49734 Result := -1;
49735 AB := nil;
49736 if High( Buttons ) >= 0 then
49737 GetMem( AB, Sizeof( TTBButton ) * (High(Buttons) + 1) );
49738 N := 0;
49739 PAB := @AB[ 0 ];
49740 nBmp := -2;
49741 if High(BtnImgIdxArray) >= 0 then
49742 nBmp := BtnImgIdxArray[ 0 ] - 1;
49743 for I:= 0 to High( Buttons ) do
49744 begin
49745 if Buttons[ I ] = nil then break;
49747 {if High( BtnImgIdxArray ) >= 0 then
49748 if I > High( BtnImgIdxArray ) then
49749 nBmp := -3;}
49751 if Buttons[ I ] = {$IFDEF F_P}''+{$ENDIF} '-' then
49752 begin
49753 PAB.iBitmap := -1;
49754 //PAB.idCommand := 0;
49755 PAB.fsState := 0;
49756 PAB.fsStyle := TBSTYLE_SEP;
49757 PAB.iString := -1;
49759 else
49760 begin
49761 Str := Buttons[ I ];
49762 Inc( nBmp );
49763 PAB.iBitmap := nBmp;
49764 if nBmp < 0 then
49765 Dec( nBmp );
49766 if High( BtnImgIdxArray ) >= N then
49767 PAB.iBitmap := BtnImgIdxArray[ N ];
49768 {PAB.idCommand := ToolbarsIDcmd;
49769 if Result < 0 then Result := PAB.idCommand;
49770 Inc( ToolbarsIDcmd );}
49771 PAB.fsState := TBSTATE_ENABLED;
49772 PAB.fsStyle := TBSTYLE_BUTTON or TBSTYLE_AUTOSIZE;
49773 if Str^ = '^' then
49774 begin
49775 PAB.fsStyle := TBSTYLE_DROPDOWN or TBSTYLE_AUTOSIZE;
49776 Inc( Str );
49777 end;
49778 if Str^ in [ '-', '+' ] then
49779 begin
49780 PAB.fsStyle := PAB.fsStyle or TBSTYLE_CHECK;
49781 if Str^ = '+' then
49782 PAB.fsState := PAB.fsState or TBSTATE_CHECKED;
49783 Inc( Str );
49784 if Str^ = '!' then
49785 begin
49786 PAB.fsStyle := PAB.fsStyle or TBSTYLE_GROUP;
49787 Inc( Str );
49788 end;
49789 end;
49790 if (Str = {$IFDEF F_P}''+{$ENDIF} ' ') or (Str^ = #0) then
49791 PAB.iString := -1
49792 //Perform( TB_ADDSTRING, 0, Integer( PChar( '' + #0 ) ) )
49793 // an experiment: is it possible to remove space right to image
49794 // without setting tboTextBottom option (non compatible with FixFlatXP)
49795 // answer: seems not possible.
49796 else
49797 PAB.iString :=
49798 Perform( TB_ADDSTRING, 0, Integer( PChar( '' + Str + #0 ) ) );
49799 end;
49801 PAB.idCommand := ToolbarsIDcmd;
49802 if Result < 0 then Result := PAB.idCommand;
49803 Inc( ToolbarsIDcmd );
49805 PAB.dwData := Integer( @Self );
49806 Inc( N );
49807 Inc( PAB );
49808 end;
49809 if N > 0 then
49810 begin
49811 if Idx < 0 then
49812 Perform( TB_ADDBUTTONS, N, Integer( @AB[ 0 ] ) )
49813 else
49814 Perform( TB_INSERTBUTTON, Idx, Integer( @AB[ 0 ] ) );
49815 end;
49816 if AB <> nil then
49817 FreeMem( AB );
49818 end;
49819 begin
49820 if High( Buttons ) < 0 then
49821 Result := -1
49822 else
49823 Result := AddInsButtons;
49824 end;
49825 {$ENDIF ASM_VERSION}
49827 {$IFDEF ASM_VERSION}
49828 //[function TControl.TBAddButtons]
49829 function TControl.TBAddButtons(const Buttons: array of PChar;
49830 const BtnImgIdxArray: array of Integer): Integer;
49832 PUSH dword ptr [EBP+8]
49833 PUSH dword ptr [EBP+12]
49834 PUSH ECX
49835 PUSH EDX
49836 PUSH -1
49837 PUSH EAX
49838 CALL TBAddInsButtons
49839 end;
49840 {$ELSE ASM_VERSION} //Pascal
49841 function TControl.TBAddButtons(const Buttons: array of PChar;
49842 const BtnImgIdxArray: array of Integer): Integer;
49843 begin
49844 Result := TBAddInsButtons( -1, Buttons, BtnImgIdxArray );
49845 end;
49846 {$ENDIF ASM_VERSION}
49849 //[function TControl.TBInsertButtons]
49850 function TControl.TBInsertButtons(BeforeIdx: Integer;
49851 Buttons: array of PChar; BtnImgIdxArray: array of Integer): Integer;
49852 var I, J, K: Integer;
49853 begin
49854 J := -1;
49855 Result := -1;
49856 for I := 0 to High( Buttons ) do
49857 begin
49858 if I <= High( BtnImgIdxArray ) then
49859 J := BtnImgIdxArray[ I ]
49860 else
49861 if J >= 0 then Inc( J );
49862 K := TBAddInsButtons( BeforeIdx, [ Buttons[ I ], '' ], [ J ] );
49863 if Result < 0 then Result := K;
49864 end;
49865 end;
49867 //[function GetTBBtnGoodID]
49868 function GetTBBtnGoodID( Toolbar: PControl; BtnIDorIdx: Integer ): Integer;
49869 // change by Alexander Pravdin (to fix toolbar with separator first):
49870 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
49871 var Btn1st, i: Integer; btn: TTBButton;
49872 begin
49873 Result := BtnIDorIdx;
49874 Btn1st := 0;
49875 for i := 0 to Toolbar.TBButtonCount - 1 do begin
49876 Toolbar.Perform( TB_GETBUTTON, i, Integer( @btn ) );
49877 if btn.fsStyle <> TBSTYLE_SEP then begin
49878 Btn1st := i;
49879 Break;
49880 end;
49881 end;
49882 if Result < Toolbar.TBIndex2Item( Btn1st ) then
49883 Result := Toolbar.TBIndex2Item( Result );
49884 end;
49886 type
49887 TTBButtonEvent = packed Record
49888 BtnID: DWORD;
49889 Event: TOnToolbarButtonClick;
49890 end;
49891 PTBButtonEvent = ^TTBButtonEvent;
49893 //[procedure TControl.TBFreeTBevents]
49894 procedure TControl.TBFreeTBevents;
49895 begin
49896 fTBevents.Release;
49897 end;
49899 //[function WndProcToolbarButtonsClicks]
49900 function WndProcToolbarButtonsClicks( TB: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
49901 var Notify: PTBNotify;
49902 I: Integer;
49903 Event: PTBButtonEvent;
49904 begin
49905 Result := FALSE;
49906 if Msg.message = WM_NOTIFY then
49907 begin
49908 Notify := Pointer( Msg.lParam );
49909 if Notify.hdr.code = NM_CLICK then
49910 begin
49911 for I := TB.fTBevents.fCount-1 downto 0 do
49912 begin
49913 Event := TB.fTBevents.fItems[ I ];
49914 if Integer( Event.BtnID ) = Notify.iItem then
49915 begin
49916 if Assigned( Event.Event ) then
49917 begin
49918 TB.RefInc;
49919 Rslt := DefWindowProc( Msg.hwnd, Msg.message, Msg.wParam, Msg.lParam );
49920 Event.Event( TB, Event.BtnID );
49921 //Rslt := TB.CallDefWndProc( Msg );
49922 TB.RefDec;
49923 Result := TRUE;
49924 Exit;
49925 end;
49926 break;
49927 end;
49928 end;
49929 end;
49930 end;
49931 end;
49933 //[procedure TControl.TBAssignEvents]
49934 procedure TControl.TBAssignEvents(BtnID: Integer;
49935 Events: array of TOnToolbarButtonClick);
49936 var I: Integer;
49937 EventRec: PTBButtonEvent;
49938 begin
49939 if fTBevents = nil then
49940 begin
49941 fTBevents := NewList;
49942 Add2AutoFreeEx( TBFreeTBevents );
49943 AttachProc( WndProcToolbarButtonsClicks );
49944 end;
49945 BtnID := GetTBBtnGoodID( @Self, BtnID );
49946 for I := 0 to High( Events ) do
49947 begin
49948 GetMem( EventRec, Sizeof( TTBButtonEvent ) );
49949 fTBevents.Add( EventRec );
49950 EventRec.Event := Events[ I ];
49951 EventRec.BtnID := BtnID;
49952 Inc( BtnID );
49953 end;
49954 end;
49956 //[procedure TControl.TBResetImgIdx]
49957 procedure TControl.TBResetImgIdx( BtnID, BtnCount: Integer );
49958 begin
49959 while BtnCount > 0 do
49960 begin
49961 TBButtonImage[ BtnID ] := -2;
49962 Inc( BtnID );
49963 Dec( BtnCount );
49964 end;
49965 end;
49968 //[function TControl.TBGetButtonVisible]
49969 function TControl.TBGetButtonVisible(BtnID: Integer): Boolean;
49970 begin
49971 Result := Perform( TB_ISBUTTONHIDDEN, GetTBBtnGoodID( @ Self, BtnID ), 0 ) = 0;
49972 end;
49975 //[function TControl.TBItem2Index]
49976 function TControl.TBItem2Index(BtnID: Integer): Integer;
49977 begin
49978 Result := Perform( TB_COMMANDTOINDEX, BtnID, 0 );
49979 end;
49982 //[procedure TControl.TBSetButtonVisible]
49983 procedure TControl.TBSetButtonVisible(BtnID: Integer;
49984 const Value: Boolean);
49985 begin
49986 BtnID := GetTBBtnGoodID( @Self, BtnID );
49987 Perform( TB_HIDEBUTTON, BtnID, Integer( not Value ) );
49988 end;
49990 {$IFDEF ASM_VERSION}
49991 //[function TControl.TBGetBtnStt]
49992 function TControl.TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;
49994 PUSH 0
49995 PUSH ECX
49996 PUSH EAX
49997 CALL GetTBBtnGoodID
49998 POP EDX
49999 POP ECX
50000 PUSH EAX
50001 ADD ECX, 8
50002 PUSH ECX
50003 PUSH EDX
50004 CALL Perform
50005 TEST EAX, EAX
50006 SETNZ AL
50007 end;
50008 {$ELSE ASM_VERSION} //Pascal
50009 function TControl.TBGetBtnStt(BtnID: Integer; const Index: Integer): Boolean;
50010 begin
50011 BtnID := GetTBBtnGoodID( @Self, BtnID );
50012 Result := Perform( Index + 8, BtnID, 0 ) <> 0;
50013 end;
50014 {$ENDIF ASM_VERSION}
50017 //[procedure TControl.TBSetBtnStt]
50018 procedure TControl.TBSetBtnStt(BtnID: Integer; const Index: Integer; const Value: Boolean);
50019 begin
50020 BtnID := GetTBBtnGoodID( @Self, BtnID );
50021 Perform( Index, BtnID, Integer( Value ) );
50022 end;
50024 {$IFDEF ASM_VERSION}
50025 //[function TControl.TBIndex2Item]
50026 function TControl.TBIndex2Item(Idx: Integer): Integer;
50027 //*/////////////////////////////////////////////////////
50028 const //
50029 _sizeof_TTBButton = sizeof( TTBButton ); //
50030 //*/////////////////////////////////////////////////////
50032 //*/////////////////////////////////////////////////////
50033 // ADD ESP, -sizeof(TTBButton)
50034 //*/////////////////////////////////////////////////////
50035 ADD ESP, -_sizeof_TTBButton //
50036 //*/////////////////////////////////////////////////////
50037 PUSH ESP
50038 PUSH EDX
50039 PUSH TB_GETBUTTON
50040 PUSH EAX
50041 CALL Perform
50042 TEST EAX, EAX
50043 MOV EAX, [ESP].TTBButton.idCommand
50044 JNZ @@1
50045 OR EAX, -1
50046 //*/////////////////////////////////////////////////////
50047 //@@1: ADD ESP, sizeof( TTBButton )
50048 //*/////////////////////////////////////////////////////
50049 @@1: ADD ESP, _sizeof_TTBButton //
50050 //*/////////////////////////////////////////////////////
50051 end;
50052 {$ELSE ASM_VERSION} //Pascal
50053 function TControl.TBIndex2Item(Idx: Integer): Integer;
50054 var ButtonInfo: TTBButton;
50055 begin
50056 Result := -1;
50057 if Perform( TB_GETBUTTON, Idx, Integer( @ButtonInfo ) ) <> 0 then
50058 Result := ButtonInfo.idCommand;
50059 end;
50060 {$ENDIF ASM_VERSION}
50062 //[procedure TControl.TBConvertIdxArray2ID]
50063 procedure TControl.TBConvertIdxArray2ID(const IdxVars: array of PDWORD);
50064 var i: Integer;
50065 begin
50066 for i := 0 to High( IdxVars ) do
50067 IdxVars[ i ]^ := TBIndex2Item( IdxVars[ I ]^ );
50068 end;
50070 {$IFDEF ASM_VERSION}
50071 //[function TControl.TBGetButtonText]
50072 function TControl.TBGetButtonText( BtnID: Integer ): String;
50074 PUSH ECX
50075 ADD ESP, -1024
50076 PUSH ESP
50077 PUSH EAX
50078 CALL GetTBBtnGoodID
50079 POP EDX
50080 PUSH EAX
50081 PUSH TB_GETBUTTONTEXT
50082 PUSH EDX
50083 CALL Perform
50084 TEST EAX, EAX
50085 JLE @@2
50086 MOV EDX, ESP
50087 JMP @@1
50088 @@2: XOR EDX, EDX
50089 @@1: MOV EAX, [ESP+1024]
50090 CALL System.@LStrFromPChar
50091 ADD ESP, 1028
50092 end;
50093 {$ELSE ASM_VERSION} //Pascal
50094 function TControl.TBGetButtonText( BtnID: Integer ): String;
50095 var Buffer: array[ 0..1023 ] of Char;
50096 begin
50097 BtnID := GetTBBtnGoodID( @Self, BtnID );
50098 if Perform( TB_GETBUTTONTEXT, BtnID, Integer( @Buffer[ 0 ] ) ) > 0 then
50099 Result := Buffer
50100 else
50101 Result := '';
50102 end;
50103 {$ENDIF ASM_VERSION}
50106 //[function TControl.TBGetButtonRect]
50107 function TControl.TBGetButtonRect(BtnID: Integer): TRect;
50108 begin
50109 BtnID := GetTBBtnGoodID( @Self, BtnID );
50110 Perform( TB_GETITEMRECT, TBItem2Index( BtnID ), Integer( @Result ) );
50111 end;
50114 //[function TControl.TBGetRows]
50115 function TControl.TBGetRows: Integer;
50116 begin
50117 Result := 1;
50118 UpdateWndStyles;
50119 if (TBSTYLE_WRAPABLE and fStyle) <> 0 then
50120 Result := Perform( TB_GETROWS, 0, 0 );
50121 end;
50124 //[procedure TControl.TBSetRows]
50125 procedure TControl.TBSetRows(const Value: Integer);
50126 begin
50127 Perform( TB_SETROWS, Value, 0 );
50128 end;
50130 //[function TControl.TBMoveBtn]
50131 function TControl.TBMoveBtn(FromIdx, ToIdx: Integer): Boolean;
50132 var btn: TTBButton;
50133 begin
50134 Perform(TB_GETBUTTON,FromIdx,integer(@btn));
50135 Result := Perform(TB_DELETEBUTTON,FromIdx,0) <> 0;
50136 if Result then
50137 Perform(TB_INSERTBUTTON,ToIdx,integer(@btn));
50138 end;
50140 {$IFDEF ASM_VERSION}
50141 //[procedure TControl.TBSetTooltips]
50142 procedure TControl.TBSetTooltips(BtnID1st: Integer;
50143 Tooltips: array of PChar);
50145 PUSH EBX
50146 PUSH ESI
50147 MOV ESI, ECX
50148 MOV EBX, EAX
50149 PUSHAD
50150 MOV ECX, [EBX].fTBttCmd
50151 INC ECX
50152 LOOP @@1
50153 CALL NewList
50154 MOV [EBX].fTBttCmd, EAX
50155 CALL NewStrList
50156 MOV [EBX].fTBttTxt, EAX
50157 @@1: POPAD
50158 MOV ECX, [EBP+8]
50159 INC ECX
50160 JZ @@exit
50161 @@loop:
50162 PUSH ECX
50163 PUSH EDX
50164 PUSH 0
50165 LODSD
50166 MOV EDX, EAX
50167 MOV EAX, ESP
50168 CALL System.@LStrFromPChar
50170 MOV EDX, [ESP+4]
50171 MOV EAX, [EBX].fTBttCmd
50172 CALL TList.IndexOf
50173 TEST EAX, EAX
50174 JGE @@2
50176 MOV EDX, [ESP+4]
50177 MOV EAX, [EBX].fTBttCmd
50178 CALL TList.Add
50179 POP EDX
50180 PUSH EDX
50181 MOV EAX, [EBX].fTBttTxt
50182 CALL TStrList.Add
50183 JMP @@3
50185 @@2:
50186 MOV EDX, EAX
50187 POP ECX
50188 PUSH ECX
50189 MOV EAX, [EBX].fTBttTxt
50190 CALL TStrList.Put
50191 @@3:
50192 CALL RemoveStr
50194 POP EDX
50195 POP ECX
50196 INC EDX
50197 LOOP @@loop
50198 @@exit:
50199 POP ESI
50200 POP EBX
50201 end;
50202 {$ELSE ASM_VERSION} //Pascal
50203 procedure TControl.TBSetTooltips(BtnID1st: Integer;
50204 Tooltips: array of PChar);
50205 var I, J: Integer;
50206 begin
50207 if not assigned( fTBttCmd ) then
50208 begin
50209 fTBttCmd := NewList;
50210 fTBttTxt := NewStrList;
50211 end;
50212 for I:= 0 to High( Tooltips ) do
50213 begin
50214 J := fTBttCmd.IndexOf( Pointer( BtnID1st ) );
50215 if J < 0 then
50216 begin
50217 fTBttCmd.Add( Pointer( BtnID1st ) );
50218 fTBttTxt.Add( Tooltips[ I ] );
50220 else
50221 fTBttTxt.Items[ J ] := Tooltips[ I ];
50222 Inc( BtnID1st );
50223 end;
50224 end;
50225 {$ENDIF ASM_VERSION}
50227 {$IFDEF ASM_VERSION}
50228 //[function TControl.TBButtonAtPos]
50229 function TControl.TBButtonAtPos(X, Y: Integer): Integer;
50231 PUSH EAX
50232 CALL TBBtnIdxAtPos
50233 TEST EAX, EAX
50234 MOV EDX, EAX
50235 POP EAX
50236 JGE TBIndex2Item
50237 MOV EAX, EDX
50238 end;
50239 {$ELSE ASM_VERSION} //Pascal
50240 function TControl.TBButtonAtPos(X, Y: Integer): Integer;
50241 var I: Integer;
50242 begin
50243 I := TBBtnIdxAtPos( X, Y );
50244 if I >= 0 then
50245 I := TBIndex2Item( I );
50246 Result := I;
50247 end;
50248 {$ENDIF ASM_VERSION}
50250 {$IFDEF ASM_VERSION}
50251 //[function TControl.TBBtnIdxAtPos]
50252 function TControl.TBBtnIdxAtPos(X, Y: Integer): Integer;
50254 PUSH EBX
50255 PUSH ECX
50256 PUSH EDX
50257 MOV EBX, EAX
50258 CALL GetItemsCount
50259 MOV ECX, EAX
50260 JECXZ @@fin
50261 @@1: PUSH ECX
50262 ADD ESP, -16
50263 PUSH ESP
50264 DEC ECX
50265 PUSH ECX
50266 PUSH TB_GETITEMRECT
50267 PUSH EBX
50268 CALL Perform
50269 MOV EDX, ESP
50270 LEA EAX, [ESP+20]
50271 CALL PointInRect
50272 ADD ESP, 16
50273 POP ECX
50274 TEST AL, AL
50275 {$IFDEF USE_CMOV}
50276 CMOVNZ EAX, ECX
50277 {$ELSE}
50278 JZ @@2
50279 MOV EAX, ECX
50280 JMP @@fin
50281 @@2: {$ENDIF}
50282 JNZ @@fin
50284 LOOP @@1
50285 @@fin: DEC EAX
50286 POP EDX
50287 POP EDX
50288 POP EBX
50289 end;
50290 {$ELSE ASM_VERSION} //Pascal
50291 function TControl.TBBtnIdxAtPos(X, Y: Integer): Integer;
50292 var I: Integer;
50293 R: TRect;
50294 P: TPoint;
50295 begin
50296 P := MakePoint( X, Y );
50297 for I := TBButtonCount - 1 downto 0 do
50298 begin
50299 Perform( TB_GETITEMRECT, I, Integer( @R ) );
50300 if PointInRect( P, R ) then
50301 begin
50302 Result := I;
50303 Exit;
50304 end;
50305 end;
50306 Result := -1;
50307 end;
50308 {$ENDIF ASM_VERSION}
50310 //[function TControl.TBButtonSeparator]
50311 function TControl.TBButtonSeparator(BtnID: Integer): Boolean;
50312 var B: TTBButton;
50313 begin
50314 Perform( TB_GETBUTTON, TBItem2Index( GetTBBtnGoodID( @Self, BtnID )
50315 ), Integer( @B ) ) ;
50316 Result := B.fsStyle = TBSTYLE_SEP;
50317 end;
50322 //[procedure TControl.TBDeleteButton]
50323 procedure TControl.TBDeleteButton(BtnID: Integer);
50324 begin
50325 BtnID := GetTBBtnGoodID( @Self, BtnID );
50326 Perform( TB_DELETEBUTTON, TBItem2Index( BtnID ), 0 );
50327 end;
50330 //[procedure TControl.TBDeleteBtnByIdx]
50331 procedure TControl.TBDeleteBtnByIdx(Idx: Integer);
50332 begin
50333 Perform( TB_DELETEBUTTON, Idx, 0 );
50334 end;
50337 //[procedure TControl.Clear]
50338 procedure TControl.Clear;
50339 begin
50340 fCommandActions.aClear( @Self );
50341 end;
50343 {$IFDEF ASM_noVERSION}
50344 //[function TControl.TBGetBtnImgIdx]
50345 function TControl.TBGetBtnImgIdx(BtnID: Integer): Integer;
50346 const szTBButton = sizeof( TTBButton );
50348 ADD ESP, -szTBButton
50349 PUSH ESP
50350 PUSH EAX
50351 CALL TBItem2Index
50352 POP EDX
50353 PUSH EAX
50354 PUSH TB_GETBUTTON
50355 PUSH EDX
50356 CALL Perform
50357 POP EAX
50358 ADD ESP, szTBButton-4
50359 end;
50360 {$ELSE ASM_VERSION} //Pascal
50361 function TControl.TBGetBtnImgIdx(BtnID: Integer): Integer;
50362 var B: TTBButton;
50363 begin
50364 Perform( TB_GETBUTTON, TBItem2Index( GetTBBtnGoodID( @Self, BtnID ) ), Integer( @B ) );
50365 Result := B.iBitmap;
50366 end;
50367 {$ENDIF ASM_VERSION}
50370 //[procedure TControl.TBSetBtnImgIdx]
50371 procedure TControl.TBSetBtnImgIdx(BtnID: Integer; const Value: Integer);
50372 begin
50373 Perform( TB_CHANGEBITMAP, GetTBBtnGoodID( @Self, BtnID ), Value );
50374 end;
50376 {$IFDEF ASM_VERSION}
50377 //[procedure TControl.TBSetButtonText]
50378 procedure TControl.TBSetButtonText(BtnID: Integer; const Value: String);
50380 PUSH 0
50381 PUSH ECX
50382 PUSH EAX
50383 CALL GetTBBtnGoodID
50384 POP EDX
50386 ADD ESP, -16
50387 PUSH TBIF_TEXT
50388 PUSH 32 //Sizeof( TTBButtonInfo )
50389 PUSH ESP
50390 PUSH EAX
50391 PUSH TB_SETBUTTONINFO
50392 PUSH EDX
50393 CALL Perform
50394 ADD ESP, 32 //sizeof( TTBButtonInfo )
50395 end;
50396 {$ELSE ASM_VERSION} //Pascal
50397 procedure TControl.TBSetButtonText(BtnID: Integer; const Value: String);
50398 var BI: TTBButtonInfo;
50399 begin
50400 BtnID := GetTBBtnGoodID( @Self, BtnID );
50401 BI.cbSize := Sizeof( BI );
50402 BI.dwMask := TBIF_TEXT;
50403 BI.pszText := PChar( Value );
50404 Perform( TB_SETBUTTONINFO, BtnID, Integer( @BI ) );
50405 end;
50406 {$ENDIF ASM_VERSION}
50408 {$IFDEF ASM_VERSION}
50409 //[function TControl.TBGetBtnWidth]
50410 function TControl.TBGetBtnWidth(BtnID: Integer): Integer;
50412 ADD ESP, -16
50413 MOV ECX, ESP
50414 CALL TBGetButtonRect
50415 POP EDX
50416 POP ECX
50417 POP EAX
50418 SUB EAX, EDX
50419 POP EDX
50420 end;
50421 {$ELSE ASM_VERSION} //Pascal
50422 function TControl.TBGetBtnWidth(BtnID: Integer): Integer;
50423 var R: TRect;
50424 begin
50425 R := TBButtonRect[ BtnID ];
50426 Result := R.Right - R.Left;
50427 end;
50428 {$ENDIF ASM_VERSION}
50430 {$IFDEF ASM_VERSION}
50431 //[procedure TControl.TBSetBtnWidth]
50432 procedure TControl.TBSetBtnWidth(BtnID: Integer; const Value: Integer);
50434 PUSH EBX
50435 MOV EBX, ECX
50437 PUSH EAX
50438 CALL GetTBBtnGoodID
50439 POP EDX
50441 ADD ESP, -24
50442 PUSH TBIF_SIZE or TBIF_STYLE
50443 PUSH 32
50444 MOV ECX, ESP
50446 PUSH ECX
50447 PUSH EAX
50448 PUSH TB_SETBUTTONINFO
50449 PUSH EDX
50451 PUSH ECX
50452 PUSH EAX
50453 PUSH TB_GETBUTTONINFO
50454 PUSH EDX
50455 CALL Perform
50457 MOV [ESP+16+18], BX
50458 AND byte ptr [ESP+16].TTBButtonInfo.fsStyle, not TBSTYLE_AUTOSIZE
50459 CALL Perform
50460 ADD ESP, 32
50461 POP EBX
50462 end;
50463 {$ELSE ASM_VERSION} //Pascal
50464 procedure TControl.TBSetBtnWidth(BtnID: Integer; const Value: Integer);
50465 var BI: TTBButtonInfo;
50466 begin
50467 BI.cbSize := Sizeof( BI );
50468 BI.dwMask := TBIF_SIZE or TBIF_STYLE;
50469 BtnID := GetTBBtnGoodID( @Self, BtnID );
50470 Perform( TB_GETBUTTONINFO, BtnID, Integer( @BI ) );
50471 BI.cx := Value;
50472 BI.fsStyle := BI.fsStyle and not TBSTYLE_AUTOSIZE;
50473 Perform( TB_SETBUTTONINFO, BtnID, Integer( @BI ) );
50474 end;
50475 {$ENDIF ASM_VERSION}
50477 //[procedure TControl.TBSetBtMinMaxWidth]
50478 procedure TControl.TBSetBtMinMaxWidth(const Idx: Integer; const Value: Integer);
50479 begin
50480 case Idx of
50481 0: FTBBtMinWidth := Value;
50482 1: FTBBtMaxWidth := Value;
50483 end;
50484 Perform( TB_SETBUTTONWIDTH, 0, FTBBtMaxWidth or (FTBBtMinWidth shl 16) );
50485 end;
50487 {$IFDEF F_P}
50488 //[function TControl.TBGetBtMinMaxWidth]
50489 function TControl.TBGetBtMinMaxWidth(const Idx: Integer): Integer;
50490 begin
50491 CASE Idx OF
50492 0: Result := FTBBtMinWidth;
50493 1: Result := FTBBtMaxWidth;
50494 END;
50495 end;
50496 {$ENDIF F_P}
50498 //[procedure TControl.SetDroppedDown]
50499 procedure TControl.SetDroppedDown(const Value: Boolean);
50500 begin
50501 //fDropped := Value;
50502 Perform( CB_SHOWDROPDOWN, Integer( Value ), 0 );
50503 end;
50505 {$IFDEF ASM_VERSION}
50506 //[procedure TControl.AddDirList]
50507 procedure TControl.AddDirList(const Filemask: String; Attrs: DWORD);
50509 CALL EDX2PChar
50510 PUSH EDX
50511 PUSH ECX
50512 MOVZX ECX, [EAX].fCommandActions.aDir
50513 JECXZ @@exit
50514 PUSH ECX
50515 PUSH EAX
50516 CALL Perform
50518 @@exit:
50519 POP ECX
50520 POP ECX
50521 end;
50522 {$ELSE ASM_VERSION} //Pascal
50523 procedure TControl.AddDirList(const Filemask: String; Attrs: DWORD);
50524 begin
50525 if fCommandActions.aDir <> 0 then
50526 Perform( fCommandActions.aDir, Attrs, Integer( PChar( Filemask ) ) );
50527 end;
50528 {$ENDIF ASM_VERSION}
50530 //[FUNCTION WndProcShowModal]
50531 {$IFDEF ASM_VERSION}
50532 function WndProcShowModal( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
50534 CMP word ptr [EDX].TMsg.message, WM_CLOSE
50535 JNZ @@ret_false
50536 {//++++++ AP
50537 PUSH EBX
50538 MOV EBX, 1
50539 CMP [EAX].TControl.fOnClose.TMethod.Code, 0
50540 JZ @@AP1
50541 PUSH EAX
50542 PUSH EDX
50543 PUSH ECX
50544 XCHG EDX, EAX
50545 PUSH EBX
50546 MOV ECX, ESP
50547 MOV EAX, [EDX].TControl.fOnClose.TMethod.Data
50548 CALL dword ptr [EDX].TControl.fOnClose.TMethod.Code
50549 POP EBX
50550 POP ECX
50551 POP EDX
50552 POP EAX
50553 @@AP1:
50554 //------ AP}
50556 XCHG EDX, EAX
50557 XOR EAX, EAX
50558 CMP [EDX].TControl.fModalResult, EAX
50559 JNZ @@1
50560 OR [EDX].TControl.fModalResult, -1
50561 @@1:
50562 {//++++++ AP
50563 TEST BL, BL
50564 JNZ @@AP2
50565 MOV [EDX].TControl.fModalResult, 0
50566 @@AP2:
50567 POP EBX
50568 //------ AP}
50570 MOV [ECX], EAX
50571 INC EAX
50573 @@ret_false:
50574 XOR EAX, EAX
50576 end;
50577 {$ELSE ASM_VERSION} //Pascal
50578 function WndProcShowModal( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
50579 //var Accept: Boolean; // {Alexander Pravdin, AP}
50580 begin
50581 if Msg.message = WM_CLOSE then
50582 begin
50583 //++++++++ {AP} +++++++++++++++++++++++++++++++++++++++++++++++++++++++//
50584 {Accept := True; //
50585 if Assigned( Self_.fOnClose ) then Self_.fOnClose( Self_, Accept ); //
50586 }//-------- {AP} ----------------------------------------------------//
50587 if Self_.ModalResult = 0 then { (Sergey Shishmintzev) }
50588 Self_.ModalResult := -1;
50589 //++++++++ {AP} +++++++++++++++++++++++++++++++++++++++++++++++++++++++//
50590 {if not Accept then //
50591 Self_.ModalResult := 0; //íå çàêðûâàåì ôîðìó, îñòàâëÿÿ å¸ íà ýêðàíå//
50592 }//-------- {AP} ----------------------------------------------------//
50593 Rslt := 0;
50594 Result := True; // Do not process !
50596 else
50597 Result := False;
50598 end;
50599 {$ENDIF ASM_VERSION}
50600 //[END WndProcShowModal]
50602 //[function WndProcFixModal]
50603 // by TR"]F
50604 function WndProcFixModal( Self_: PControl; var Msg: TMsg; var Rslt:
50605 Integer ): Boolean;
50606 const HTERROR = $FFFE;
50607 LBtnDown = $201;
50608 LBtnUp = $202;
50609 RBtnDown = $204;
50610 RBtnUp = $205;
50611 WeelDown = $207;
50612 WeelUp = $208;
50613 begin
50614 Result := false;
50615 if (Msg.message = WM_SETCURSOR) then
50616 if (LoWord(Msg.lParam) = HTERROR) then
50617 if (HiWord(Msg.lParam) >= LBtnDown) and
50618 (HiWord(Msg.lParam) <= RBtnUp) then
50619 begin
50620 if Applet.fModalForm <> nil then
50621 SetForegroundWindow(Applet.fModalForm.Handle);
50622 Rslt := 1;
50623 Result := TRUE;
50624 end;
50625 end;
50626 //[END WndProcFixModal]
50628 {$IFDEF ASM_noVERSION}
50629 //[function TControl.ShowModal]
50630 function TControl.ShowModal: Integer;
50632 MOV ECX, [EAX].fParent
50633 JECXZ @@show
50634 MOVZX ECX, [EAX].fIsControl
50635 JECXZ @@show_modal
50636 @@show:
50637 CALL Show
50638 XOR EAX, EAX
50640 @@show_modal:
50641 PUSHAD
50643 MOV EBX, EAX
50644 MOV EDI, [Applet]
50646 XOR EBP, EBP // CurCtl = nil
50648 MOV EAX, [EDI].fCurrentControl
50649 CMP [EDI].TControl.FIsApplet, 0
50650 {$IFDEF USE_CMOV}
50651 CMOVZ EAX, EDI
50652 {$ELSE}
50653 JNZ @@curctrl_save
50654 MOV EAX, EDI
50655 @@curctrl_save:
50656 {$ENDIF}
50658 PUSH EAX
50660 MOV EDX, offset[WndProcShowModal]
50661 PUSH EDX
50663 MOV EAX, EBX
50664 CALL TControl.AttachProc
50665 XOR EDX, EDX
50666 MOV [EBX].fModalResult, EDX
50668 CALL NewList
50669 XCHG EAX, EBP
50671 XOR ECX, ECX
50672 INC ECX
50673 MOV ESI, EDI
50675 CMP [EDI].TControl.FIsApplet, 0
50676 JZ @@isapplet
50678 MOV EBP, [EDI].fCurrentControl // CurCtl = Applet.fCurrentControl
50680 MOV ESI, [EDI].fChildren
50681 MOV ECX, [ESI].TList.fCount
50682 MOV ESI, [ESI].TList.fItems
50684 @@1loo: LODSD
50686 @@isapplet:
50688 PUSH ECX
50689 CMP EAX, EBX
50690 JE @@1nx
50691 PUSH EAX
50692 CALL GetEnabled
50693 TEST AL, AL
50694 POP EAX
50695 JZ @@1nx
50696 PUSH EAX
50697 MOV DL, 0
50698 CALL SetEnabled
50699 POP EDX
50700 MOV EAX, EBP
50701 CALL TList.Add
50702 @@1nx: POP ECX
50703 LOOP @@1loo
50705 INC [EBX].fModal
50706 MOV EAX, [Applet]
50707 MOV [EAX].fModalForm, EBX
50709 MOV EAX, EBX
50710 CALL Show
50712 @@msgloo:
50713 MOVZX ECX, [AppletTerminated]
50714 OR ECX, [EBX].fModalResult
50715 JNZ @@e_msgloo
50716 CALL WaitMessage
50717 MOV EAX, EDI
50718 CALL ProcessMessages
50719 {$IFNDEF NOT_USE_OnIdle}
50720 MOV EAX, EBX
50721 CALL [ProcessIdle]
50722 {$ENDIF}
50723 JMP @@msgloo
50725 @@e_msgloo:
50726 POP EDX
50727 MOV EAX, EBX
50728 CALL TControl.DetachProc
50730 DEC [EBX].fModal
50731 MOV EAX, [Applet]
50732 XOR ECX, ECX
50733 MOV [EAX].fModalForm, ECX
50735 MOV ECX, [EBP].TList.fCount
50736 JECXZ @@2end
50737 MOV ESI, [EBP].TList.fItems
50739 @@2loo: LODSD
50740 PUSH ECX
50741 MOV DL, 1
50742 CALL TControl.SetEnabled
50743 POP ECX
50744 LOOP @@2loo
50746 @@2end:
50747 MOV EAX, EBP
50748 CALL TObj.Free
50750 POP ECX
50751 JECXZ @@exit
50752 PUSH 0
50753 PUSH WA_ACTIVE
50754 PUSH WM_ACTIVATE
50755 PUSH [ECX].fHandle
50756 CALL PostMessage
50758 TEST EBP, EBP // CurCtl = nil ?
50759 JZ @@exit
50760 MOV EAX, EBP
50761 MOV DL, 1
50762 CALL TControl.SetFocused
50764 @@exit:
50765 POPAD
50766 MOV EAX, [EAX].fModalResult
50767 end;
50768 {$ELSE ASM_VERSION} //Pascal
50769 {$IFDEF USE_SHOWMODALPARENTED_ALWAYS}
50770 function TControl.ShowModal: Integer;
50771 begin
50772 Result := ShowModalParented(Applet);
50773 end;
50774 {$ELSE not USE_SHOWMODALPARENTED_ALWAYS}
50775 function TControl.ShowModal: Integer;
50776 var FL: PList;
50777 var CurForm: PControl;
50778 I: Integer;
50779 F: PControl;
50780 CurCtl: PControl; // { Alexander Pravdin }
50781 begin
50782 Result := 0;
50783 if (fIsControl) or (fParent = nil) then
50784 begin
50785 Show;
50786 Exit;
50787 end;
50788 AttachProc( WndProcShowModal );
50789 CurForm := Applet.fCurrentControl;
50790 FL := NewList;
50791 CurCtl := nil; // { Alexander Pravdin }
50793 if Applet.IsApplet then
50794 for I := 0 to Applet.ChildCount - 1 do
50795 begin
50796 F := Applet.fChildren.Items[ I ];
50797 if F <> @Self then
50798 if F.Enabled then
50799 begin
50800 FL.Add( F );
50801 F.Enabled := FALSE;
50802 {$IFNDEF NOT_FIX_MODAL}
50803 F.AttachProc(WndProcFixModal); {**************}
50804 {$ENDIF}
50805 end;
50807 else
50808 begin
50809 CurForm := Applet;
50810 if Applet.Enabled then
50811 begin
50812 FL.Add( Applet );
50813 CurCtl := Applet.fCurrentControl; { Alexander Pravdin }
50814 Applet.Enabled := FALSE;
50815 {$IFNDEF NOT_FIX_MODAL}
50816 Applet.AttachProc(WndProcFixModal); {**************}
50817 {$ENDIF}
50818 end;
50819 end;
50821 Inc( fModal );
50822 Applet.fModalForm := @ Self;
50823 Enabled := TRUE;
50825 Show;
50826 ModalResult := 0;
50827 while not AppletTerminated and (ModalResult = 0) do
50828 begin
50829 WaitMessage;
50830 Applet.ProcessMessages;
50831 {$IFNDEF NOT_USE_OnIdle}
50832 ProcessIdle( @Self );
50833 {$ENDIF}
50834 end;
50836 Dec( fModal );
50837 Applet.fModalForm := nil;
50839 DetachProc( WndProcShowModal );
50840 for I := 0 to FL.Count - 1 do
50841 begin
50842 F := FL.Items[ I ];
50843 {$IFNDEF NOT_FIX_MODAL}
50844 F.DetachProc(WndProcFixModal); {**************}
50845 {$ENDIF}
50846 F.Enabled := TRUE;
50847 //EnableWindow( F.Handle, TRUE );
50848 //F.Perform( WM_ENABLE, 1, 0 );
50849 end;
50850 FL.Free;
50852 if CurForm <> nil then
50853 PostMessage( CurForm.Handle, WM_ACTIVATE, WA_ACTIVE, 0 );
50854 if CurCtl <> nil then CurCtl.SetFocused( TRUE ); { Alexander Pravdin }
50856 Result := ModalResult;
50857 end;
50858 {$ENDIF USE_SHOWMODALPARENTED_ALWAYS}
50859 {$ENDIF ASM_VERSION}
50861 //[function TControl.ShowModalParented]
50862 {$IFNDEF NEW_MODAL}
50863 function TControl.ShowModalParented( const AParent: PControl ): Integer;
50864 begin
50865 Result := 0;
50866 end;
50867 {$ELSE NEW_MODAL defined}
50868 function TControl.ShowModalParented( const AParent: PControl ): Integer;
50870 FL: PList;
50871 OldMF, F: PControl;
50872 I: Integer;
50873 begin
50874 Result := 0;
50875 if ( AParent = nil ) then Exit;
50877 Inc( fModal );
50878 FL := NewList;
50879 OldMF := AParent.fModalForm;
50880 AParent.fModalForm := @Self;
50882 if AParent.fIsApplet or ( AParent.IsMainWindow and AParent.fIsForm ) then
50883 begin
50884 for I := 0 to AParent.ChildCount - 1 do
50885 begin
50886 F := AParent.fChildren.Items[ I ];
50887 if ( F <> @Self ) and F.fIsForm and F.fEnabled and F.fVisible then
50888 begin
50889 FL.Add( F );
50890 F.Enabled := FALSE;
50891 {$IFNDEF NOT_FIX_MODAL}
50892 F.AttachProc(WndProcFixModal); {**************}
50893 {$ENDIF}
50894 end;
50895 end;
50896 end;
50898 if AParent.fIsForm and AParent.Enabled then
50899 begin
50900 FL.Add( AParent );
50901 AParent.Enabled := FALSE;
50902 end;
50904 ModalResult := 0;
50905 Show;
50906 while not AppletTerminated and ( ModalResult = 0 ) do
50907 begin
50908 WaitMessage;
50909 AParent.ProcessMessages;
50910 {$IFNDEF NOT_USE_OnIdle}
50911 ProcessIdle( @Self );
50912 {$ENDIF}
50913 end;
50915 AParent.fModalForm := OldMF;
50916 Dec( fModal );
50917 for I := 0 to FL.Count - 1 do
50918 begin
50919 PControl( FL.Items[ I ] ).Enabled := True;
50920 {$IFNDEF NOT_FIX_MODAL}
50921 F.DetachProc(WndProcFixModal); {**************}
50922 {$ENDIF}
50923 end;
50924 FL.Free;
50925 Hide;
50926 Result := ModalResult;
50927 end;
50928 {$ENDIF NEW_MODAL}
50930 //[function DisableWindows]
50931 function DisableWindows( W: hwnd; LPARAM: Integer ): Bool; stdcall;
50932 var FL: PList;
50933 Buf: array[ 0..127 ] of Char;
50934 begin
50935 FL := Pointer( LPARAM );
50936 if IsWindowEnabled( W ) and (W <> FL.Tag) then
50937 begin
50938 GetClassName( W, @ Buf[ 0 ], Sizeof( Buf ) );
50939 if Buf <> 'ComboLBox' then
50940 begin
50941 FL.Add( Pointer( W ) );
50942 EnableWindow( W, FALSE );
50943 end;
50944 end;
50945 Result := TRUE;
50946 end;
50948 //[function TControl.ShowModalEx]
50949 function TControl.ShowModalEx: Integer;
50950 var FL: PList;
50951 var CurForm: PControl;
50952 I: Integer;
50953 W: HWnd;
50954 CurCtl: PControl; { Alexander Pravdin }
50955 begin
50956 Result := 0;
50957 if (fIsControl) or (fParent = nil) then
50958 begin
50959 Show;
50960 Exit;
50961 end;
50962 AttachProc( WndProcShowModal );
50963 CurForm := Applet.fCurrentControl;
50964 FL := NewList;
50965 FL.Tag := fHandle;
50967 // ++++ { Alexander Pravdin }
50968 if not Applet.fIsApplet then CurCtl := Applet.fCurrentControl
50969 else CurCtl := nil;
50970 // ----
50971 CreateWindow;
50973 EnumThreadWindows( GetCurrentThreadID, @ DisableWindows, Integer( FL ) );
50974 Enabled := TRUE;
50976 Inc( fModal );
50977 Applet.fModalForm := @ Self;
50978 Show;
50979 ModalResult := 0;
50980 while not AppletTerminated and (ModalResult = 0) do
50981 begin
50982 WaitMessage;
50983 Applet.ProcessMessages;
50984 {$IFNDEF NOT_USE_OnIdle}
50985 ProcessIdle( @Self );
50986 {$ENDIF}
50987 end;
50989 Dec( fModal );
50990 Applet.fModalForm := @ Self;
50992 DetachProc( WndProcShowModal );
50994 for I := 0 to FL.Count - 1 do
50995 begin
50996 W := THandle( FL.Items[ I ] );
50997 EnableWindow( W, TRUE );
50998 end;
50999 FL.Free;
51001 if CurForm <> nil then
51002 PostMessage( CurForm.Handle, WM_ACTIVATE, WA_ACTIVE, 0 );
51003 if CurCtl <> nil then CurCtl.SetFocused( True ); { Alexander Pravdin }
51004 Result := ModalResult;
51005 end;
51007 //[function TControl.GetModal]
51008 function TControl.GetModal: Boolean;
51009 begin
51010 Result := fModal > 0;
51011 end;
51013 {$IFDEF USE_SETMODALRESULT}
51014 //[procedure TControl.SetModalResult]
51015 procedure TControl.SetModalResult( const Value: Integer );
51016 begin
51017 //if fModal <= 0 then Exit;
51018 fModalResult := Value;
51019 if Value <> 0 then
51020 PostMessage( GetWindowHandle, 0, 0, 0 );
51021 end;
51022 {$ENDIF}
51025 //////////////////////////////////////////////////////////////////
51027 // T I M E R
51029 //////////////////////////////////////////////////////////////////
51031 var TimerOwnerWnd: PControl;
51032 TimerCount: Integer = 0;
51034 { -- Constructor of timer -- }
51036 //[function NewTimer]
51037 function NewTimer( Interval: Integer ): PTimer;
51038 begin
51040 New( Result, Create );
51041 {+}{++}(*Result := PTimer.Create;*){--}
51042 if Interval <= 0 then Interval := 1000;
51043 Result.fInterval := Interval;
51044 Inc( TimerCount );
51045 end;
51046 //[END NewTimer]
51048 { -- Timer procedure -- }
51050 //[FUNCTION TimerProc]
51051 {$IFDEF ASM_VERSION}
51052 function TimerProc( Wnd : HWnd; Msg : Integer; T : PTimer; CurrentTime : DWord ): Integer;
51053 stdcall;
51054 asm //cmd //opd
51055 MOV EDX, T
51056 MOV ECX, [EDX].TTimer.fOnTimer.TMethod.Code
51057 JECXZ @@exit
51058 MOV EAX, [EDX].TTimer.fOnTimer.TMethod.Data
51059 CALL ECX
51060 @@exit: XOR EAX, EAX
51061 end;
51062 {$ELSE ASM_VERSION} //Pascal
51063 function TimerProc( Wnd : HWnd; Msg : Integer; T : PTimer; CurrentTime : DWord ): Integer;
51064 stdcall;
51065 begin
51066 if Assigned( T.fOnTimer ) then
51067 T.fOnTimer( T );
51068 Result := 0;
51069 end;
51070 {$ENDIF ASM_VERSION}
51071 //[END TimerProc]
51073 { TTimer }
51075 {$IFDEF ASM_VERSION}
51076 //[destructor TTimer.Destroy]
51077 destructor TTimer.Destroy;
51079 PUSH EAX
51080 XOR EDX, EDX
51081 CALL TTimer.SetEnabled
51082 POP EAX
51083 CALL TObj.Destroy
51084 DEC [TimerCount]
51085 JNZ @@exit
51086 XOR EAX, EAX
51087 XCHG EAX, [TimerOwnerWnd]
51088 CALL TObj.Free
51089 @@exit:
51090 end;
51091 {$ELSE ASM_VERSION} //Pascal
51092 destructor TTimer.Destroy;
51093 begin
51094 Enabled := False;
51095 inherited;
51096 Dec( TimerCount );
51097 if TimerCount = 0 then
51098 begin
51099 TimerOwnerWnd.Free;
51100 TimerOwnerWnd := nil;
51101 end;
51102 end;
51103 {$ENDIF ASM_VERSION}
51105 {$IFDEF ASM_VERSION}
51106 //[procedure TTimer.SetEnabled]
51107 procedure TTimer.SetEnabled(const Value: Boolean);
51109 PUSH EBX
51110 XCHG EBX, EAX
51112 CMP [EBX].fEnabled, DL
51113 JZ @@exit
51115 MOV [EBX].fEnabled, DL
51117 TEST DL, DL
51118 JZ @@disable
51120 MOV ECX, [TimerOwnerWnd]
51121 INC ECX
51122 LOOP @@owner_ready
51124 INC ECX
51125 MOV EDX, offset[EmptyString]
51126 XOR EAX, EAX
51127 CALL _NewWindowed
51128 MOV [TimerOwnerWnd], EAX
51129 MOV [EAX].TControl.fStyle, 0
51130 INC [EAX].TControl.fIsControl
51131 XCHG ECX, EAX
51133 @@owner_ready:
51135 PUSH offset[TimerProc]
51136 PUSH [EBX].fInterval
51137 PUSH EBX
51138 XCHG EAX, ECX
51139 CALL TControl.GetWindowHandle
51140 PUSH EAX
51141 CALL SetTimer
51142 MOV [EBX].fHandle, EAX
51144 JMP @@exit
51146 @@disable:
51147 XOR ECX, ECX
51148 XCHG ECX, [EBX].TTimer.fHandle
51149 JECXZ @@exit
51151 PUSH ECX
51152 MOV EAX, [TimerOwnerWnd]
51153 PUSH [EAX].TControl.fHandle
51154 CALL KillTimer
51156 @@exit:
51157 POP EBX
51158 end;
51159 {$ELSE ASM_VERSION} //Pascal
51160 procedure TTimer.SetEnabled(const Value: Boolean);
51161 begin
51162 if FEnabled = Value then Exit;
51163 fEnabled := Value;
51164 if Value then
51165 begin
51166 if TimerOwnerWnd = nil then
51167 begin
51168 TimerOwnerWnd := _NewWindowed( nil, '', TRUE );
51169 TimerOwnerWnd.fStyle := 0;
51170 TimerOwnerWnd.fIsControl := TRUE;
51171 end;
51172 fHandle := SetTimer( TimerOwnerWnd.GetWindowHandle, Integer( @Self ),
51173 fInterval, @TimerProc );
51175 else
51176 begin
51177 if fHandle <> 0 then
51178 begin
51179 KillTimer( TimerOwnerWnd.fHandle, fHandle );
51180 fHandle := 0;
51181 end;
51182 end;
51183 end;
51184 {$ENDIF ASM_VERSION}
51186 {$IFDEF ASM_VERSION}
51187 //[procedure TTimer.SetInterval]
51188 procedure TTimer.SetInterval(const Value: Integer);
51190 CMP EDX, [EAX].fInterval
51191 JE @@exit
51192 MOV [EAX].fInterval, EDX
51193 PUSH dword ptr [EAX].fEnabled
51194 PUSH EAX
51195 XOR EDX, EDX
51196 CALL SetEnabled
51197 POP EAX
51198 POP EDX
51199 CALL SetEnabled
51200 @@exit:
51201 end;
51202 {$ELSE ASM_VERSION} //Pascal
51203 procedure TTimer.SetInterval(const Value: Integer);
51204 var WasEnabled : Boolean;
51205 begin
51206 if fInterval = Value then Exit;
51207 fInterval := Value;
51208 WasEnabled := Enabled;
51209 Enabled := False;
51210 Enabled := WasEnabled;
51211 end;
51212 {$ENDIF ASM_VERSION}
51215 { TMMTimer }
51217 { ------------ declarations moved here from MMSystem -------------------- }
51218 const
51219 TIME_ONESHOT = 0; { program timer for single event }
51220 TIME_PERIODIC = 1; { program for continuous periodic event }
51221 TIME_CALLBACK_FUNCTION = $0000; { callback is function }
51222 TIME_CALLBACK_EVENT_SET = $0010; { callback is event - use SetEvent }
51223 TIME_CALLBACK_EVENT_PULSE = $0020; { callback is event - use PulseEvent }
51225 type
51226 TFNTimeCallBack = procedure(uTimerID, uMessage: UINT;
51227 dwUser, dw1, dw2: DWORD) stdcall;
51228 //[API timeSetEvent]
51229 function timeSetEvent(uDelay, uResolution: UINT;
51230 lpFunction: TFNTimeCallBack; dwUser: DWORD; uFlags: UINT): THandle; stdcall;
51231 external 'winmm.dll' name 'timeSetEvent';
51232 function timeKillEvent(uTimerID: UINT): Integer; stdcall;
51233 external 'winmm.dll' name 'timeKillEvent';
51234 { ----------------------------------------------------------------------- }
51236 //[procedure MMTimerCallback]
51237 procedure MMTimerCallback(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD);
51238 stdcall;
51239 var MMTimer: PMMTimer;
51240 begin
51241 MMTimer := Pointer( dwUser );
51242 if Assigned( MMTimer.FOnTimer ) then
51243 MMTimer.fOnTimer( MMTimer );
51244 end;
51246 //[function NewMMTimer]
51247 function NewMMTimer( Interval: Integer ): PMMTimer;
51248 begin
51250 New( Result, Create );
51251 {+} {++}(* Result := PMMTimer.Create; *){--}
51252 Result.fInterval := Interval;
51253 Result.FPeriodic := TRUE;
51254 end;
51255 //[END NewMMTimer]
51257 //[destructor TMMTimer.Destroy]
51258 destructor TMMTimer.Destroy;
51259 begin
51260 Enabled := FALSE;
51261 Inc( TimerCount );
51262 inherited;
51263 end;
51265 //[procedure TMMTimer.SetEnabled]
51266 procedure TMMTimer.SetEnabled(const Value: Boolean);
51267 begin
51268 if Value xor (fHandle <> 0) then
51269 begin
51270 if fHandle = 0 then
51271 fHandle := timeSetEvent( Interval, Resolution, MMTimerCallback, DWORD( @ Self ),
51272 Integer( Periodic ) or TIME_CALLBACK_FUNCTION )
51273 else
51274 begin
51275 timeKillEvent( fHandle );
51276 fHandle := 0;
51277 end;
51278 end;
51279 fEnabled := Value;
51280 end;
51292 ////////////////////////////////////////////////////////////////////////
51295 // t B I T M A P
51298 ///////////////////////////////////////////////////////////////////////
51300 { -- bitmap -- }
51302 //[FUNCTION PrepareBitmapHeader]
51303 {$IFDEF ASM_VERSION}
51304 function PrepareBitmapHeader( W, H, BitsPerPixel: Integer ): PBitmapInfo;
51305 const szIH = sizeof(TBitmapInfoHeader);
51306 szHd = szIH + 256 * Sizeof(TRGBQuad);
51308 PUSH EDI
51310 PUSH ECX // BitsPerPixel
51311 PUSH EDX // H
51312 PUSH EAX // W
51314 MOV EAX, szHd
51315 CALL AllocMem
51317 MOV EDI, EAX
51318 XCHG ECX, EAX
51320 XOR EAX, EAX
51321 MOV AL, szIH
51322 STOSD // biSize = Sizeof( TBitmapInfoHeader )
51323 POP EAX // ^ W
51324 STOSD // -> biWidth
51325 POP EAX // ^ H
51326 STOSD // -> biHeight
51327 XOR EAX, EAX
51328 INC EAX
51329 STOSW // 1 -> biPlanes
51330 POP EAX // ^ BitsPerPixel
51331 STOSW // -> biBitCount
51333 XCHG EAX, ECX // EAX = Result
51334 POP EDI
51335 end;
51336 {$ELSE ASM_VERSION} //Pascal
51337 function PrepareBitmapHeader( W, H, BitsPerPixel: Integer ): PBitmapInfo;
51338 begin
51339 Assert( W > 0, 'Width must be >0' );
51340 Assert( H > 0, 'Height must be >0' );
51342 Result := AllocMem( 256*Sizeof(TRGBQuad)+Sizeof(TBitmapInfoHeader) );
51343 Assert( Result <> nil, 'No memory' );
51345 Result.bmiHeader.biSize := Sizeof( TBitmapInfoHeader );
51346 Result.bmiHeader.biWidth := W;
51347 Result.bmiHeader.biHeight := H; // may be, -H ?
51348 Result.bmiHeader.biPlanes := 1;
51349 Result.bmiHeader.biBitCount := BitsPerPixel;
51350 //Result.bmiHeader.biCompression := BI_RGB; // BI_RGB = 0
51351 end;
51352 {$ENDIF ASM_VERSION}
51353 //[END PrepareBitmapHeader]
51355 const
51356 BitsPerPixel_By_PixelFormat: array[ TPixelFormat ] of Byte =
51357 ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );
51359 //[FUNCTION Bits2PixelFormat]
51360 {$IFDEF ASM_VERSION}
51361 function Bits2PixelFormat( BitsPerPixel: Integer ): TPixelFormat;
51363 PUSH ESI
51364 MOV ESI, offset[ BitsPerPixel_By_PixelFormat + 1 ]
51365 XOR ECX, ECX
51366 XCHG EDX, EAX
51367 @@loo: INC ECX
51368 LODSB
51369 CMP AL, DL
51370 JZ @@exit
51371 TEST AL, AL
51372 JNZ @@loo
51373 @@exit: XCHG EAX, ECX
51374 POP ESI
51375 end;
51376 {$ELSE ASM_VERSION} //Pascal
51377 function Bits2PixelFormat( BitsPerPixel: Integer ): TPixelFormat;
51378 var I: TPixelFormat;
51379 begin
51380 for I := High(I) downto Low(I) do
51381 if BitsPerPixel = BitsPerPixel_By_PixelFormat[ I ] then
51382 begin
51383 Result := I;
51384 Exit;
51385 end;
51386 Result := pfDevice;
51387 end;
51388 {$ENDIF ASM_VERSION}
51389 //[END Bits2PixelFormat]
51391 //[procedure DummyDetachCanvas]
51392 procedure DummyDetachCanvas( Sender: PBitmap );
51393 begin
51394 end;
51396 //[FUNCTION _NewBitmap]
51397 {$IFDEF ASM_VERSION}
51398 function _NewBitmap( W, H: Integer ): PBitmap;
51399 begin
51400 New( Result, Create );
51401 Result.fDetachCanvas := DummyDetachCanvas;
51402 Result.fWidth := W;
51403 Result.fHeight := H;
51404 end;
51405 {$ENDIF ASM_VERSION}
51406 //[END _NewBitmap]
51408 //[FUNCTION NewBitmap]
51409 {$IFDEF ASM_VERSION}
51410 function NewBitmap( W, H: Integer ): PBitmap;
51412 PUSH EAX
51413 PUSH EDX
51414 CALL _NewBitmap
51415 POP EDX
51416 POP ECX
51417 PUSH EAX
51418 INC [EAX].TBitmap.fHandleType
51419 JECXZ @@exit
51420 TEST EDX, EDX
51421 JZ @@exit
51422 PUSH EBX
51423 PUSH EAX
51424 PUSH EDX
51425 PUSH ECX
51426 PUSH 0
51427 CALL GetDC
51428 PUSH EAX
51429 XCHG EBX, EAX
51430 CALL CreateCompatibleBitmap
51431 POP EDX
51432 MOV [EDX].TBitmap.fHandle, EAX
51433 PUSH EBX
51434 PUSH 0
51435 CALL ReleaseDC
51436 POP EBX
51437 @@exit: POP EAX
51438 end;
51439 {$ELSE ASM_VERSION} //Pascal
51440 function NewBitmap( W, H: Integer ): PBitmap;
51441 var DC: HDC;
51442 begin
51444 New( Result, Create );
51445 {+}{++}(*Result := PBitmap.Create;*){--}
51446 Result.fHandleType := bmDDB;
51447 Result.fDetachCanvas := DummyDetachCanvas;
51448 Result.fWidth := W;
51449 Result.fHeight := H;
51450 if (W <> 0) and (H <> 0) then
51451 begin
51452 //DC := CreateCompatibleDC( 0 );
51453 DC := GetDC( 0 );
51454 Result.fHandle := CreateCompatibleBitmap( DC, W, H );
51455 Assert( Result.fHandle <> 0, 'Can not create bitmap handle' );
51456 //DeleteDC( DC );
51457 ReleaseDC( 0, DC );
51458 end;
51459 end;
51460 {$ENDIF ASM_VERSION}
51461 //[END NewBitmap]
51463 const InitColors: array[ 0..17 ] of DWORD = ( $F800, $7E0, $1F, 0, $800000, $8000,
51464 $808000, $80, $800080, $8080, $808080, $C0C0C0, $FF0000, $FF00, $FFFF00, $FF,
51465 $FF00FF, $FFFF );
51466 //[PROCEDURE PreparePF16bit]
51467 {$IFDEF ASM_VERSION}
51468 procedure PreparePF16bit( DIBHeader: PBitmapInfo );
51469 const szBIH = sizeof(TBitmapInfoHeader);
51471 MOV byte ptr [EAX].TBitmapInfoHeader.biCompression, BI_BITFIELDS
51472 ADD EAX, szBIH
51473 XCHG EDX, EAX
51474 MOV EAX, offset[InitColors]
51475 XOR ECX, ECX
51476 MOV CL, 19*4
51477 CALL System.Move
51478 end;
51479 {$ELSE ASM_VERSION} //Pascal
51480 procedure PreparePF16bit( DIBHeader: PBitmapInfo );
51481 begin
51482 DIBHeader.bmiHeader.biCompression := BI_BITFIELDS;
51483 Move( InitColors[ 0 ], DIBHeader.bmiColors[ 0 ], 19*Sizeof(TRGBQUAD) );
51484 end;
51485 {$ENDIF ASM_VERSION}
51486 //[END PreparePF16bit]
51488 //[FUNCTION NewDIBBitmap]
51489 {$IFDEF ASM_VERSION}
51490 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;
51492 PUSH EBX
51494 PUSH ECX
51495 PUSH EDX
51496 PUSH EAX
51497 CALL _NewBitmap
51498 XCHG EBX, EAX
51499 POP EAX //W
51500 POP EDX //H
51501 POP ECX //PixelFormat
51503 TEST EAX, EAX
51504 JZ @@exit
51505 TEST EDX, EDX
51506 JZ @@exit
51508 PUSH EAX
51509 MOVZX EAX, CL
51510 JMP @@loadBitsPixel
51511 @@loadDefault:
51512 MOVZX EAX, [DefaultPixelFormat]
51513 @@loadBitsPixel:
51514 MOVZX ECX, byte ptr [ BitsPerPixel_By_PixelFormat + EAX ]
51515 JECXZ @@loadDefault
51516 MOV [EBX].TBitmap.fNewPixelFormat, AL
51517 {$IFDEF PARANOIA}
51518 DB $3C, pf16bit
51519 {$ELSE}
51520 CMP AL, pf16bit
51521 {$ENDIF}
51522 POP EAX
51524 PUSHFD
51525 CALL PrepareBitmapHeader
51526 MOV [EBX].TBitmap.fDIBHeader, EAX
51527 POPFD
51528 JNZ @@2
51530 CALL PreparePF16bit
51532 @@2:
51533 MOV EAX, EBX
51534 CALL TBitmap.GetScanLineSize
51535 MOV EDX, [EBX].TBitmap.fHeight
51536 MUL EDX
51537 MOV [EBX].TBitmap.fDIBSize, EAX
51538 CALL AllocMem
51539 MOV [EBX].TBitmap.fDIBBits, EAX
51540 @@exit:
51541 XCHG EAX, EBX
51542 POP EBX
51543 end;
51544 {$ELSE ASM_VERSION} //Pascal
51545 function NewDIBBitmap( W, H: Integer; PixelFormat: TPixelFormat ): PBitmap;
51546 const BitsPerPixel: array[ TPixelFormat ] of Byte = ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );
51547 var BitsPixel: Integer;
51548 //AField: PDWORD;
51549 //DC0 : HDC;
51550 begin
51552 New( Result, Create );
51553 {+}{++}(*Result := PBitmap.Create;*){--}
51554 Result.fDetachCanvas := DummyDetachCanvas;
51555 Result.fWidth := W;
51556 Result.fHeight := H;
51557 if (W <> 0) and (H <> 0) then
51558 begin
51559 BitsPixel := BitsPerPixel[ PixelFormat ];
51560 if BitsPixel = 0 then
51561 begin
51562 Result.fNewPixelFormat := DefaultPixelFormat;
51563 BitsPixel := BitsPerPixel[DefaultPixelFormat];
51565 else
51566 Result.fNewPixelFormat := PixelFormat;
51567 ASSERT( Result.fNewPixelFormat in [ pf1bit..pf32bit ], 'Strange pixel format' );
51568 Result.fDIBHeader := PrepareBitmapHeader( W, H, BitsPixel );
51569 if PixelFormat = pf16bit then
51570 begin
51571 PreparePF16bit( Result.fDIBHeader );
51573 Result.fDIBHeader.bmiHeader.biCompression := BI_BITFIELDS;
51574 AField := @Result.fDIBHeader.bmiColors[ 0 ];
51575 AField^ := $F800; Inc( AField );
51576 AField^ := $07E0; Inc( AField );
51577 AField^ := $001F; Inc( AField );
51578 DC0 := CreateCompatibleDC( 0 );
51579 GetSystemPaletteEntries( DC0, 0, 16, AField^ );
51580 DeleteDC( DC0 );
51582 end;
51584 Result.fDIBSize := Result.ScanLineSize * H;
51585 Result.fDIBBits := AllocMem( Result.fDIBSize );
51586 ASSERT( Result.fDIBBits <> nil, 'No memory' );
51587 end;
51588 end;
51589 {$ENDIF ASM_VERSION}
51590 //[END NewDIBBitmap]
51592 { TBitmap }
51594 {$IFDEF ASM_VERSION}
51595 //[procedure TBitmap.ClearData]
51596 procedure TBitmap.ClearData;
51598 PUSH EBX
51599 MOV EBX, EAX
51600 CALL [EBX].fDetachCanvas
51601 XOR ECX, ECX
51602 XCHG ECX, [EBX].fHandle
51603 JECXZ @@1
51604 PUSH ECX
51605 CALL DeleteObject
51606 XOR ECX, ECX
51607 MOV [EBX].fDIBBits, ECX
51608 @@1: XCHG ECX, [EBX].fDIBBits
51609 JECXZ @@2
51610 XCHG EAX, ECX
51611 CALL System.@FreeMem
51612 @@2: XOR ECX, ECX
51613 XCHG ECX, [EBX].fDIBHeader
51614 JECXZ @@3
51615 XCHG EAX, ECX
51616 CALL System.@FreeMem
51617 @@3: XOR EAX, EAX
51618 MOV [EBX].fScanLineSize, EAX
51619 MOV [EBX].fGetDIBPixels, EAX
51620 MOV [EBX].fSetDIBPixels, EAX
51621 XCHG EAX, EBX
51622 POP EBX
51623 CALL ClearTransImage
51624 end;
51625 {$ELSE ASM_VERSION} //Pascal
51626 procedure TBitmap.ClearData;
51627 begin
51628 fDetachCanvas( @Self );
51629 if fHandle <> 0 then
51630 begin
51631 DeleteObject( fHandle );
51632 fHandle := 0;
51633 fDIBBits := nil;
51634 //fDIBHeader := nil;
51635 end;
51636 if fDIBBits <> nil then
51637 begin
51638 FreeMem( fDIBBits );
51639 fDIBBits := nil;
51640 end;
51641 if fDIBHeader <> nil then
51642 begin
51643 FreeMem( fDIBHeader );
51644 fDIBHeader := nil;
51645 end;
51646 fScanLineSize := 0;
51647 fGetDIBPixels := nil;
51648 fSetDIBPixels := nil;
51649 ClearTransImage;
51650 end;
51651 {$ENDIF ASM_VERSION}
51653 {$IFDEF ASM_VERSION}
51654 //[procedure TBitmap.Clear]
51655 procedure TBitmap.Clear;
51657 PUSH EAX
51658 CALL RemoveCanvas
51659 POP EAX
51660 PUSH EAX
51661 CALL ClearData
51662 POP EAX
51663 XOR EDX, EDX
51664 MOV [EAX].fWidth, EDX
51665 MOV [EAX].fHeight, EDX
51666 MOV [EAX].fDIBAutoFree, DL
51667 end;
51668 {$ELSE ASM_VERSION} //Pascal
51669 procedure TBitmap.Clear;
51670 begin
51671 RemoveCanvas;
51672 ClearData;
51673 fWidth := 0;
51674 fHeight := 0;
51675 fDIBAutoFree := FALSE;
51676 end;
51677 {$ENDIF ASM_VERSION}
51679 //[function TBitmap.GetBoundsRect]
51680 function TBitmap.GetBoundsRect: TRect;
51681 begin
51682 Result := MakeRect( 0, 0, Width, Height );
51683 end;
51685 {$IFDEF ASM_VERSION}
51686 //[destructor TBitmap.Destroy]
51687 destructor TBitmap.Destroy;
51689 PUSH EAX
51690 CALL Clear
51691 POP EAX
51692 CALL TObj.Destroy
51693 end;
51694 {$ELSE ASM_VERSION} //Pascal
51695 destructor TBitmap.Destroy;
51696 begin
51697 Clear;
51698 inherited;
51699 end;
51700 {$ENDIF ASM_VERSION}
51702 //[function TBitmap.BitsPerPixel]
51703 function TBitmap.BitsPerPixel: Integer;
51704 var B: tagBitmap;
51705 begin
51706 CASE PixelFormat OF
51707 pf1bit: Result := 1;
51708 pf4bit: Result := 4;
51709 pf8bit: Result := 8;
51710 pf15bit: Result := 15;
51711 pf16bit: Result := 16;
51712 pf24bit: Result := 24;
51713 pf32bit: Result := 32;
51714 else begin
51715 Result := 0;
51716 if fHandle <> 0 then
51717 if GetObject( fHandle, Sizeof( B ), @B ) > 0 then
51718 Result := B.bmBitsPixel * B.bmPlanes;
51719 end;
51720 END;
51721 end;
51723 {$IFDEF ASM_VERSION}
51724 //[procedure TBitmap.Draw]
51725 procedure TBitmap.Draw(DC: HDC; X, Y: Integer);
51726 const szBitmap = sizeof( tagBitmap );
51727 asm // [EBP+8] = Y
51728 PUSH EDX // [EBP-4] = DC
51729 PUSH ECX // [EBP-8] = X
51730 PUSH EBX
51731 PUSH ESI
51732 @@try_again:
51733 MOV EBX, EAX
51734 CALL GetEmpty // GetEmpty must be assembler version !
51735 JZ @@exit
51737 MOV ECX, [EBX].fHandle
51738 JECXZ @@2
51740 //MOV EAX, EBX
51741 //CALL [EBX].fDetachCanvas // detached in StartDC
51743 ADD ESP, -szBitmap
51744 PUSH ESP
51745 PUSH szBitmap
51746 PUSH [EBX].fHandle
51747 CALL GetObject
51748 TEST EAX, EAX
51749 MOV ESI, [ESP].tagBitmap.bmHeight
51750 {$IFDEF USE_CMOV}
51751 CMOVZ ESI, [EBX].fHeight
51752 {$ELSE}
51753 JNZ @@1
51754 MOV ESI, [EBX].fHeight
51755 @@1: {$ENDIF}
51757 ADD ESP, szBitmap
51758 CALL StartDC
51760 PUSH SRCCOPY
51761 PUSH 0
51762 PUSH 0
51763 PUSH EAX
51764 CALL @@prepare
51765 CALL BitBlt
51766 CALL FinishDC
51767 JMP @@exit
51769 @@prepare:
51770 XCHG ESI, [ESP]
51771 PUSH [EBX].fWidth
51772 PUSH Y
51773 PUSH dword ptr [EBP-8]
51774 PUSH dword ptr [EBP-4]
51775 JMP ESI
51777 @@2:
51778 MOV ECX, [EBX].fDIBHeader
51779 JECXZ @@exit
51781 MOV ESI, [ECX].TBitmapInfoHeader.biHeight
51782 TEST ESI, ESI
51783 JGE @@20
51784 NEG ESI
51785 @@20:
51786 PUSH SRCCOPY
51787 PUSH DIB_RGB_COLORS
51788 PUSH ECX
51789 PUSH [EBX].fDIBBits
51790 PUSH ESI
51791 PUSH [EBX].fWidth
51792 PUSH 0
51793 PUSH 0
51794 CALL @@prepare
51795 CALL StretchDIBits
51796 TEST EAX, EAX
51797 JNZ @@exit
51798 MOV EAX, EBX
51799 CALL GetHandle
51800 TEST EAX, EAX
51801 XCHG EAX, EBX
51802 JNZ @@try_again
51803 @@exit:
51804 POP ESI
51805 POP EBX
51806 MOV ESP, EBP
51807 end;
51808 {$ELSE ASM_VERSION} //Pascal
51809 procedure TBitmap.Draw(DC: HDC; X, Y: Integer);
51811 DCfrom, DC0: HDC;
51812 oldBmp: HBitmap;
51813 oldHeight: Integer;
51814 B: tagBitmap;
51815 label
51816 TRYAgain;
51817 begin
51818 TRYAgain:
51819 if Empty then Exit;
51820 if fHandle <> 0 then
51821 begin
51822 fDetachCanvas( @Self );
51823 oldHeight := fHeight;
51824 if GetObject( fHandle, sizeof( B ), @B ) <> 0 then
51825 oldHeight := B.bmHeight;
51826 ASSERT( oldHeight > 0, 'oldHeight must be > 0' );
51828 DC0 := GetDC( 0 );
51829 DCfrom := CreateCompatibleDC( DC0 );
51830 ReleaseDC( 0, DC0 );
51832 oldBmp := SelectObject( DCfrom, fHandle );
51833 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
51835 BitBlt( DC, X, Y, fWidth, oldHeight, DCfrom, 0, 0, SRCCOPY );
51836 {$IFDEF CHK_BITBLT} Chk_BitBlt; {$ENDIF}
51838 SelectObject( DCfrom, oldBmp );
51839 DeleteDC( DCfrom );
51841 else
51842 if fDIBBits <> nil then
51843 begin
51844 oldHeight := Abs(fDIBHeader.bmiHeader.biHeight);
51845 ASSERT( oldHeight > 0, 'oldHeight must be > 0' );
51846 ASSERT( fWidth > 0, 'Width must be > 0' );
51847 if StretchDIBits( DC, X, Y, fWidth, oldHeight, 0, 0, fWidth, oldHeight,
51848 fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY ) = 0 then
51849 begin
51850 if GetHandle <> 0 then
51851 goto TRYAgain;
51852 end;
51853 end;
51854 end;
51855 {$ENDIF ASM_VERSION}
51857 {$IFDEF ASM_VERSION}
51858 //[procedure TBitmap.StretchDraw]
51859 procedure TBitmap.StretchDraw(DC: HDC; const Rect: TRect);
51861 PUSH EBX
51862 PUSH EDI
51863 PUSH EBP
51864 MOV EBP, ESP
51865 PUSH EDX
51866 PUSH ECX
51867 MOV EBX, EAX
51868 CALL GetEmpty
51869 JZ @@exit
51871 MOV ECX, [EBX].fHandle
51872 JECXZ @@2
51874 @@0:
51875 CALL StartDC
51876 PUSH SRCCOPY
51877 PUSH [EBX].fHeight
51878 PUSH [EBX].fWidth
51879 PUSH 0
51880 PUSH 0
51881 PUSH EAX
51883 CALL @@prepare
51884 CALL StretchBlt
51885 CALL FinishDC
51886 JMP @@exit
51888 @@prepare:
51889 POP EDI
51890 MOV EAX, [EBP-8]
51891 MOV EDX, [EAX].TRect.Bottom
51892 MOV ECX, [EAX].TRect.Top
51893 SUB EDX, ECX
51894 PUSH EDX
51895 MOV EDX, [EAX].TRect.Right
51896 MOV EAX, [EAX].TRect.Left
51897 SUB EDX, EAX
51898 PUSH EDX
51899 PUSH ECX
51900 PUSH EAX
51901 PUSH dword ptr [EBP-4]
51902 JMP EDI
51905 @@2: MOV ECX, [EBX].fDIBHeader
51906 JECXZ @@exit
51908 PUSH SRCCOPY
51909 PUSH DIB_RGB_COLORS
51910 PUSH ECX
51911 PUSH [EBX].fDIBBits
51912 PUSH [EBX].fHeight
51913 PUSH [EBX].fWidth
51914 PUSH 0
51915 PUSH 0
51916 CALL @@prepare
51917 CALL StretchDIBits
51918 TEST EAX, EAX
51919 JG @@exit
51921 MOV EAX, EBX
51922 CALL GetHandle
51923 MOV ECX, [EBX].fHandle
51924 JECXZ @@exit
51925 JMP @@0
51927 @@exit: MOV ESP, EBP
51928 POP EBP
51929 POP EDI
51930 POP EBX
51931 end;
51932 {$ELSE ASM_VERSION} //Pascal
51933 procedure TBitmap.StretchDraw(DC: HDC; const Rect: TRect);
51934 var DCfrom: HDC;
51935 oldBmp: HBitmap;
51936 label DrawHandle;
51937 begin
51938 if Empty then Exit;
51939 DrawHandle:
51940 if fHandle <> 0 then
51941 begin
51942 fDetachCanvas( @Self );
51943 DCfrom := CreateCompatibleDC( 0 );
51944 oldBmp := SelectObject( DCfrom, fHandle );
51945 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
51946 StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left,
51947 Rect.Bottom - Rect.Top, DCfrom, 0, 0, fWidth, fHeight,
51948 SRCCOPY );
51949 SelectObject( DCfrom, oldBmp );
51950 DeleteDC( DCfrom );
51952 else
51953 if fDIBBits <> nil then
51954 begin
51955 if StretchDIBits( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left,
51956 Rect.Bottom - Rect.Top, 0, 0, fWidth, fHeight,
51957 fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY )<=0 then
51958 begin
51959 if GetHandle <> 0 then
51960 goto DrawHandle;
51961 end;
51962 end;
51963 end;
51964 {$ENDIF ASM_VERSION}
51966 //[procedure TBitmap.DrawMasked]
51967 procedure TBitmap.DrawMasked(DC: HDC; X, Y: Integer; Mask: HBitmap);
51968 begin
51969 StretchDrawMasked( DC, MakeRect( X, Y, X + fWidth, Y + fHeight ), Mask );
51970 end;
51972 {$IFDEF ASM_VERSION}
51973 //[procedure TBitmap.DrawTransparent]
51974 procedure TBitmap.DrawTransparent(DC: HDC; X, Y: Integer; TranspColor: TColor);
51976 PUSH ECX
51977 MOV ECX, TranspColor
51978 INC ECX
51979 MOV ECX, [Y]
51980 JNZ @@2
51981 XCHG ECX, [ESP]
51982 CALL Draw
51983 JMP @@exit
51984 @@2:
51985 ADD ECX, [EAX].fHeight
51986 PUSH ECX
51987 MOV ECX, [EBP-4]
51988 ADD ECX, [EAX].fWidth
51989 PUSH ECX
51990 PUSH [Y]
51991 PUSH dword ptr [EBP-4]
51992 MOV ECX, ESP
51993 PUSH [TranspColor]
51994 CALL StretchDrawTransparent
51995 @@exit:
51996 MOV ESP, EBP
51997 end;
51998 {$ELSE ASM_VERSION} //Pascal
51999 procedure TBitmap.DrawTransparent(DC: HDC; X, Y: Integer; TranspColor: TColor);
52000 begin
52001 if TranspColor = clNone then
52002 Draw( DC, X, Y )
52003 else
52004 StretchDrawTransparent( DC, MakeRect( X, Y, X + fWidth, Y + fHeight ),
52005 TranspColor );
52006 end;
52007 {$ENDIF ASM_VERSION}
52009 {$IFDEF ASM_VERSION}
52010 //[procedure TBitmap.StretchDrawTransparent]
52011 procedure TBitmap.StretchDrawTransparent(DC: HDC; const Rect: TRect; TranspColor: TColor);
52013 PUSH EBX
52014 XCHG EBX, EAX
52015 MOV EAX, [TranspColor]
52016 INC EAX
52017 MOV EAX, EBX
52018 JNZ @@2
52019 CALL StretchDraw
52020 JMP @@exit
52021 @@2:
52022 PUSH EDX
52023 PUSH ECX
52024 CALL GetHandle
52025 TEST EAX, EAX
52026 JZ @@exit2
52028 MOV EAX, [TranspColor]
52029 CALL Color2RGB
52030 MOV ECX, [EBX].fTransMaskBmp
52031 JECXZ @@makemask0
52032 CMP EAX, [EBX].fTransColor
52033 JE @@3
52034 @@makemask0:
52035 MOV [EBX].fTransColor, EAX
52036 INC ECX
52037 LOOP @@20
52038 //MOV EAX, [EBX].fWidth
52039 //MOV EDX, [EBX].fHeight
52040 XOR EAX, EAX // pass height = 0
52041 // absolutely no matter what to pass as width
52042 CALL NewBitmap
52043 MOV [EBX].fTransMaskBmp, EAX
52044 @@20:
52045 MOV EAX, [EBX].fTransMaskBmp
52046 PUSH EAX
52047 MOV EDX, EBX
52048 CALL Assign
52049 POP EAX
52050 MOV EDX, [EBX].fTransColor
52051 CALL Convert2Mask
52052 @@3:
52053 MOV EAX, [EBX].fTransMaskBmp
52054 CALL GetHandle
52055 POP ECX
52056 POP EDX
52057 PUSH EAX
52058 XCHG EAX, EBX
52059 CALL StretchDrawMasked
52060 JMP @@exit
52061 @@exit2:
52062 POP ECX
52063 POP EDX
52064 @@exit:
52065 POP EBX
52066 end;
52067 {$ELSE ASM_VERSION} //Pascal
52068 procedure TBitmap.StretchDrawTransparent(DC: HDC; const Rect: TRect; TranspColor: TColor);
52069 begin
52070 if TranspColor = clNone then
52071 StretchDraw( DC, Rect )
52072 else
52073 begin
52074 if GetHandle = 0 then Exit;
52075 TranspColor := Color2RGB( TranspColor );
52076 if (fTransMaskBmp = nil) or (fTransColor <> TranspColor) then
52077 begin
52078 if fTransMaskBmp = nil then
52079 fTransMaskBmp := NewBitmap( 0, 0 {fWidth, fHeight} );
52080 fTransColor := TranspColor;
52081 // Create here mask bitmap:
52082 fTransMaskBmp.Assign( @Self );
52083 fTransMaskBmp.Convert2Mask( TranspColor );
52084 end;
52085 StretchDrawMasked( DC, Rect, fTransMaskBmp.Handle );
52086 end;
52087 end;
52088 {$ENDIF ASM_VERSION}
52090 const
52091 ROP_DstCopy = $00AA0029;
52092 {$IFDEF ASM_VERSION}
52093 //[procedure TBitmap.StretchDrawMasked]
52094 procedure TBitmap.StretchDrawMasked(DC: HDC; const Rect: TRect; Mask: HBitmap);
52096 PUSH EDX // [EBP-4] = DC
52097 PUSH ECX // [EBP-8] = Rect
52098 PUSH EBX // save EBX
52099 MOV EBX, EAX
52100 PUSH ESI // save ESI
52101 CALL GetHandle
52102 TEST EAX, EAX
52103 JZ @@to_exit
52105 PUSH 0
52106 CALL CreateCompatibleDC
52107 PUSH EAX // [EBP-20] = MaskDC
52109 PUSH [Mask]
52110 PUSH EAX
52111 CALL SelectObject
52112 PUSH EAX // [EBP-24] = Save4Mask
52114 CALL StartDC // [EBP-28] = DCfrom; [EBP-32] = Save4From
52116 PUSH [EBX].fHeight
52117 PUSH [EBX].fWidth
52118 PUSH EAX
52119 CALL CreateCompatibleBitmap
52120 PUSH EAX // [EBP-36] = MemBmp
52122 PUSH 0
52123 CALL CreateCompatibleDC
52124 PUSH EAX // [EBP-40] = MemDC
52126 PUSH dword ptr [EBP-36] //MemBmp
52127 PUSH EAX
52128 CALL SelectObject
52129 PUSH EAX // [EBP-44] = Save4Mem
52131 PUSH SRCCOPY
52132 MOV EAX, [EBP-20] //MaskDC
52133 CALL @@stretch1
52135 PUSH SRCERASE
52136 MOV EAX, [EBP-28] //DCfrom
52137 CALL @@stretch1
52139 PUSH 0
52140 PUSH dword ptr [EBP-4] //DC
52141 CALL SetTextColor
52142 PUSH EAX // [EBP-48] = crText
52144 PUSH $FFFFFF
52145 PUSH dword ptr [EBP-4] //DC
52146 CALL Windows.SetBkColor
52147 PUSH EAX // [EBP-52] = crBack
52149 PUSH SRCAND
52150 MOV EAX, [EBP-20] //MaskDC
52151 CALL @@stretch2
52153 PUSH SRCINVERT
52154 MOV EAX, [EBP-40] //MemDC
52155 CALL @@stretch2
52157 PUSH dword ptr [EBP-4] //DC
52158 CALL Windows.SetBkColor
52160 PUSH dword ptr [EBP-4] //DC
52161 CALL SetTextColor
52163 MOV ESI, offset[FinishDC]
52164 CALL ESI
52165 CALL DeleteObject // DeleteObject( MemBmp )
52167 CALL ESI
52169 CALL ESI
52170 @@to_exit:
52172 JC @@exit
52174 @@stretch1:
52175 POP ESI
52176 PUSH [EBX].fHeight
52177 PUSH [EBX].fWidth
52178 XOR EDX, EDX
52179 PUSH EDX
52180 PUSH EDX
52181 PUSH EAX
52182 PUSH [EBX].fHeight
52183 PUSH [EBX].fWidth
52184 PUSH EDX
52185 PUSH EDX
52186 PUSH dword ptr [EBP-40] //MemDC
52187 JMP @@stretch3
52189 @@stretch2:
52190 POP ESI
52191 PUSH [EBX].fHeight
52192 PUSH [EBX].fWidth
52193 PUSH 0
52194 PUSH 0
52195 PUSH EAX
52196 MOV EAX, [EBP-8] //Rect
52197 MOV EDX, [EAX].TRect.Bottom
52198 MOV ECX, [EAX].TRect.Top
52199 SUB EDX, ECX
52200 PUSH EDX
52201 MOV EDX, [EAX].TRect.Right
52202 MOV EAX, [EAX].TRect.Left
52203 SUB EDX, EAX
52204 PUSH EDX
52205 PUSH ECX
52206 PUSH EAX
52207 PUSH dword ptr [EBP-4] //DC
52208 @@stretch3:
52209 CALL StretchBlt
52210 JMP ESI
52212 @@exit:
52213 POP ESI
52214 POP EBX
52215 MOV ESP, EBP
52216 end;
52217 {$ELSE ASM_VERSION} //Pascal
52218 procedure TBitmap.StretchDrawMasked(DC: HDC; const Rect: TRect; Mask: HBitmap);
52220 DCfrom, MemDC, MaskDC: HDC;
52221 MemBmp: HBITMAP;
52222 Save4From, Save4Mem, Save4Mask: THandle;
52223 crText, crBack: TColorRef;
52224 //SavePal: HPALETTE;
52225 begin
52226 if GetHandle = 0 then Exit;
52227 fDetachCanvas( @Self );
52228 //SavePal := 0;
52230 DCfrom := CreateCompatibleDC( 0 );
52231 Save4From := SelectObject( DCfrom, fHandle );
52232 ASSERT( Save4From <> 0, 'Can not select source bitmap to DC' );
52233 MaskDC := CreateCompatibleDC( 0 );
52234 Save4Mask := SelectObject( MaskDC, Mask );
52235 ASSERT( Save4Mask <> 0, 'Can not select mask bitmap to DC' );
52236 MemDC := CreateCompatibleDC( 0 );
52237 //try
52238 MemBmp := CreateCompatibleBitmap( DCfrom, fWidth, fHeight );
52239 Save4Mem := SelectObject( MemDC, MemBmp );
52240 ASSERT( Save4Mem <> 0, 'Can not select memory bitmap to DC' );
52241 //SavePal := SelectPalette(DCfrom, SystemPalette16, False);
52242 //SelectPalette(DCfrom, SavePal, False);
52243 //if SavePal <> 0 then
52244 // SavePal := SelectPalette(MemDC, SavePal, True)
52245 //else
52246 // SavePal := SelectPalette(MemDC, SystemPalette16, True);
52247 //RealizePalette(MemDC);
52249 StretchBlt( MemDC, 0, 0, fWidth, fHeight, MaskDC, 0, 0, fWidth, fHeight, SrcCopy);
52250 StretchBlt( MemDC, 0, 0, fWidth, fHeight, DCfrom, 0, 0, fWidth, fHeight, SrcErase);
52251 crText := SetTextColor(DC, $0);
52252 crBack := Windows.SetBkColor(DC, $FFFFFF);
52253 StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top,
52254 MaskDC, 0, 0, fWidth, fHeight, SrcAnd);
52255 StretchBlt( DC, Rect.Left, Rect.Top, Rect.Right - Rect.Left, Rect.Bottom - Rect.Top,
52256 MemDC, 0, 0, fWidth, fHeight, SrcInvert);
52257 Windows.SetBkColor( DC, crBack);
52258 SetTextColor( DC, crText);
52260 if Save4Mem <> 0 then
52261 SelectObject( MemDC, Save4Mem );
52262 DeleteObject(MemBmp);
52263 //finally
52264 //if SavePal <> 0 then SelectPalette(MemDC, SavePal, False);
52265 DeleteDC(MemDC);
52266 SelectObject( DCfrom, Save4From );
52267 DeleteDC( DCfrom );
52268 SelectObject( MaskDC, Save4Mask );
52269 DeleteDC( MaskDC );
52270 //end;
52271 end;
52272 {$ENDIF ASM_VERSION}
52274 //[procedure ApplyBitmapBkColor2Canvas]
52275 procedure ApplyBitmapBkColor2Canvas( Sender: PBitmap );
52276 begin
52277 if Sender.fCanvas = nil then Exit;
52278 Sender.fCanvas.Brush.Color := Sender.BkColor;
52279 end;
52281 //[PROCEDURE DetachBitmapFromCanvas]
52282 {$IFDEF ASM_VERSION}
52283 procedure DetachBitmapFromCanvas( Sender: PBitmap );
52285 XOR ECX, ECX
52286 XCHG ECX, [EAX].TBitmap.fCanvasAttached
52287 JECXZ @@exit
52288 PUSH ECX
52289 MOV EAX, [EAX].TBitmap.fCanvas
52290 PUSH [EAX].TCanvas.fHandle
52291 CALL SelectObject
52292 @@exit:
52293 end;
52294 {$ELSE ASM_VERSION} //Pascal
52295 procedure DetachBitmapFromCanvas( Sender: PBitmap );
52296 begin
52297 if Sender.fCanvasAttached = 0 then Exit;
52298 SelectObject( Sender.fCanvas.fHandle, Sender.fCanvasAttached );
52299 Sender.fCanvasAttached := 0;
52300 end;
52301 {$ENDIF ASM_VERSION}
52302 //[END DetachBitmapFromCanvas]
52304 {$IFDEF ASM_VERSION}
52305 //[function TBitmap.GetCanvas]
52306 function TBitmap.GetCanvas: PCanvas;
52308 PUSH EBX
52309 MOV EBX, EAX
52310 CALL GetEmpty
52311 JZ @@exit
52312 MOV EAX, EBX
52313 CALL GetHandle
52314 TEST EAX, EAX
52315 JZ @@exit
52316 MOV ECX, [EBX].fCanvas
52317 INC ECX
52318 LOOP @@ret_Canvas
52320 MOV [EBX].fApplyBkColor2Canvas, offset[ApplyBitmapBkColor2Canvas]
52321 PUSH 0
52322 CALL CreateCompatibleDC
52323 CALL NewCanvas
52324 MOV [EBX].fCanvas, EAX
52325 MOV [EAX].TCanvas.fOnChange.TMethod.Code, offset[CanvasChanged]
52326 MOV [EAX].TCanvas.fOnChange.TMethod.Data, EBX
52327 CALL TCanvas.GetBrush
52328 XOR EDX, EDX
52329 MOV ECX, [EBX].fBkColor
52330 CALL TGraphicTool.SetInt
52332 @@ret_Canvas:
52333 MOV EAX, [EBX].fCanvas
52334 MOV ECX, [EAX].TCanvas.fHandle
52335 INC ECX
52336 LOOP @@attach_Canvas
52337 PUSH EAX
52338 MOV [EBX].fCanvasAttached, ECX
52339 PUSH ECX
52340 CALL CreateCompatibleDC
52341 XCHG EDX, EAX
52342 POP EAX
52343 CALL TCanvas.SetHandle
52345 @@attach_Canvas:
52346 MOV ECX, [EBX].fCanvasAttached
52347 INC ECX
52348 LOOP @@2
52349 PUSH [EBX].fHandle
52350 MOV EAX, [EBX].fCanvas
52351 CALL TCanvas.GetHandle
52352 PUSH EAX
52353 CALL SelectObject
52354 MOV [EBX].fCanvasAttached, EAX
52356 @@2: MOV [EBX].fDetachCanvas, offset[DetachBitmapFromCanvas]
52357 MOV EAX, [EBX].fCanvas
52358 @@exit: POP EBX
52359 end;
52360 {$ELSE ASM_VERSION} //Pascal
52361 function TBitmap.GetCanvas: PCanvas;
52362 var DC: HDC;
52363 begin
52364 Result := nil;
52365 if Empty then Exit;
52366 if GetHandle = 0 then Exit;
52367 if fCanvas = nil then
52368 begin
52369 fApplyBkColor2Canvas := ApplyBitmapBkColor2Canvas;
52370 DC := CreateCompatibleDC( 0 );
52371 fCanvas := NewCanvas( DC );
52372 fCanvas.fIsPaintDC := FALSE;
52373 fCanvas.OnChange := CanvasChanged;
52374 fCanvas.Brush.Color := fBkColor;
52375 end;
52376 Result := fCanvas;
52378 if fCanvas.fHandle = 0 then
52379 begin
52380 DC := CreateCompatibleDC( 0 );
52381 fCanvas.Handle := DC;
52382 fCanvasAttached := 0;
52383 end;
52385 if fCanvasAttached = 0 then
52386 begin
52387 fCanvasAttached := SelectObject( fCanvas.Handle, fHandle );
52388 ASSERT( fCanvasAttached <> 0, 'Can not select bitmap to DC of Canvas' );
52389 end;
52390 fDetachCanvas := DetachBitmapFromCanvas;
52391 end;
52392 {$ENDIF ASM_VERSION}
52394 {$IFDEF ASM_VERSION}
52395 //[function TBitmap.GetEmpty]
52396 function TBitmap.GetEmpty: Boolean;
52398 PUSH ECX
52399 MOV ECX, [EAX].fWidth
52400 JECXZ @@1
52401 MOV ECX, [EAX].fHeight
52402 @@1: TEST ECX, ECX
52403 POP ECX
52404 SETZ AL
52405 end;
52406 {$ELSE ASM_VERSION} //Pascal
52407 function TBitmap.GetEmpty: Boolean;
52408 begin
52409 Result := (fWidth = 0) or (fHeight = 0);
52410 ASSERT( (fWidth >= 0) and (fHeight >= 0), 'Bitmap dimensions can be negative' );
52411 end;
52412 {$ENDIF ASM_VERSION}
52414 {$IFDEF ASM_noVERSION}
52415 //[function TBitmap.GetHandle]
52416 function TBitmap.GetHandle: HBitmap;
52418 PUSH EBX
52419 MOV EBX, EAX
52420 CALL GetEmpty
52421 JZ @@exit
52422 MOV ECX, [EBX].fHandle
52423 INC ECX
52424 LOOP @@exit
52426 MOV ECX, [EBX].fDIBBits
52427 JECXZ @@exit
52429 PUSH ECX
52430 PUSH 0
52431 CALL GetDC
52432 PUSH EAX
52433 PUSH 0
52434 PUSH 0
52435 LEA EDX, [EBX].fDIBBits
52436 PUSH EDX
52437 PUSH DIB_RGB_COLORS
52438 PUSH [EBX].fDIBHeader
52439 PUSH EAX
52440 CALL CreateDIBSection
52441 MOV [EBX].fHandle, EAX
52442 PUSH 0
52443 CALL ReleaseDC
52444 POP EAX
52445 PUSH EAX
52446 MOV EDX, [EBX].fDIBBits
52447 MOV ECX, [EBX].fDIBSize
52448 CALL System.Move
52449 POP EAX
52450 CMP [EBX].fDIBAutoFree, 0
52451 JNZ @@freed
52452 CALL System.@FreeMem
52453 @@freed:MOV [EBX].fDIBAutoFree, 1
52454 XOR EAX, EAX
52455 MOV [EBX].fGetDIBPixels, EAX
52456 MOV [EBX].fSetDIBPixels, EAX
52458 @@exit: MOV EAX, [EBX].fHandle
52459 POP EBX
52460 end;
52461 {$ELSE ASM_VERSION} //Pascal
52462 function TBitmap.GetHandle: HBitmap;
52463 var OldBits: Pointer;
52464 DC0: HDC;
52465 {$IFDEF DEBUG}
52466 B: tagBitmap;
52467 {$ENDIF}
52468 begin
52469 Result := 0;
52470 if Empty then Exit;
52471 if fHandle = 0 then
52472 begin
52473 if fDIBBits <> nil then
52474 begin
52475 OldBits := fDIBBits;
52476 DC0 := GetDC( 0 );
52478 fDIBBits := nil;
52479 //fDIBHeader.bmiHeader.biCompression := 0;
52480 fHandle := CreateDIBSection( DC0, fDIBHeader^, DIB_RGB_COLORS,
52481 fDIBBits, 0, 0 );
52482 {$IFDEF DEBUG}
52483 if fHandle = 0 then
52484 ShowMessage( 'Can not create DIB section, error: ' + Int2Str( GetLastError ) +
52485 ', ' + SysErrorMessage( GetLastError ) );
52486 GetObject( fHandle, Sizeof( B ), @ B );
52487 {$ELSE}
52488 ASSERT( fHandle <> 0, 'Can not create DIB section, error: ' + Int2Str( GetLastError ) +
52489 ', ' + SysErrorMessage( GetLastError ) );
52490 {$ENDIF}
52491 ReleaseDC( 0, DC0 );
52492 if fHandle <> 0 then
52493 begin
52494 Move( OldBits^, fDIBBits^, fDIBSize );
52495 if not fDIBAutoFree then
52496 FreeMem( OldBits );
52497 fDIBAutoFree := TRUE;
52499 fGetDIBPixels := nil;
52500 fSetDIBPixels := nil;
52502 else
52503 fDIBBits := OldBits;
52504 end;
52505 end;
52506 Result := fHandle;
52507 end;
52508 {$ENDIF ASM_VERSION}
52510 //[function TBitmap.GetHandleAllocated]
52511 function TBitmap.GetHandleAllocated: Boolean;
52512 begin
52513 Result := fHandle <> 0;
52514 end;
52516 {$IFDEF ASM_VERSION}
52517 //[procedure TBitmap.LoadFromFile]
52518 procedure TBitmap.LoadFromFile(const Filename: String);
52520 PUSH EAX
52521 XCHG EAX, EDX
52522 CALL NewReadFileStream
52523 XCHG EDX, EAX
52524 POP EAX
52525 PUSH EDX
52526 CALL LoadFromStream
52527 POP EAX
52528 CALL TObj.Free
52529 end;
52530 {$ELSE ASM_VERSION} //Pascal
52531 procedure TBitmap.LoadFromFile(const Filename: String);
52532 var Strm: PStream;
52533 begin
52534 Strm := NewReadFileStream( Filename );
52535 LoadFromStream( Strm );
52536 Strm.Free;
52537 end;
52538 {$ENDIF ASM_VERSION}
52540 //[procedure TBitmap.LoadFromResourceID]
52541 procedure TBitmap.LoadFromResourceID(Inst: DWORD; ResID: Integer);
52542 begin
52543 LoadFromResourceName( Inst, MAKEINTRESOURCE( ResID ) );
52544 end;
52546 {$IFDEF ASM_VERSION}
52547 //[procedure TBitmap.LoadFromResourceName]
52548 procedure TBitmap.LoadFromResourceName(Inst: DWORD; ResName: PChar);
52550 PUSH EBX
52551 MOV EBX, EAX
52552 PUSHAD
52553 CALL Clear
52554 POPAD
52555 XOR EAX, EAX
52556 PUSH ECX
52557 MOVZX ECX, [EBX].fHandleType
52558 INC ECX
52559 LOOP @@1
52560 MOV AH, LR_CREATEDIBSECTION shr 8 // = $2000
52561 @@1: MOV AL, LR_DEFAULTSIZE // = $40
52562 POP ECX
52563 PUSH EAX
52564 PUSH 0
52565 PUSH 0
52566 PUSH IMAGE_BITMAP
52567 PUSH ECX
52568 PUSH EDX
52569 CALL LoadImage
52570 TEST EAX, EAX
52571 JZ @@exit
52572 XCHG EDX, EAX
52573 XCHG EAX, EBX
52574 CALL SetHandle
52575 @@exit: POP EBX
52576 end;
52577 {$ELSE ASM_VERSION} //Pascal
52578 procedure TBitmap.LoadFromResourceName(Inst: DWORD; ResName: PChar);
52579 var ResHandle: HBitmap;
52580 Flg: DWORD;
52581 begin
52582 Clear;
52583 //ResHandle := LoadBitmap( Inst, ResName );
52584 Flg := 0;
52585 if fHandleType = bmDIB then
52586 Flg := LR_CREATEDIBSECTION;
52587 ResHandle := LoadImage( Inst, ResName, IMAGE_BITMAP, 0, 0,
52588 LR_DEFAULTSIZE or Flg );
52589 if ResHandle = 0 then Exit;
52590 //Handle := CopyImage( ResHandle, IMAGE_BITMAP, 0, 0, LR_COPYRETURNORG );
52591 Handle := ResHandle;
52592 end;
52593 {$ENDIF ASM_VERSION}
52595 {$IFDEF F_P}
52596 type
52597 TBITMAPFILEHEADER = packed record
52598 bfType: Word;
52599 bfSize: DWORD;
52600 bfReserved1: Word;
52601 bfReserved2: Word;
52602 bfOffBits: DWORD;
52603 end;
52604 {$ENDIF}
52606 {$IFDEF ASM_noVERSION} // error + 16Colors->swap(Gray,Silver) + Core
52607 //[procedure TBitmap.LoadFromStream]
52608 procedure TBitmap.LoadFromStream(Strm: PStream);
52609 type tBFH = TBitmapFileHeader;
52610 tBIH = TBitmapInfoHeader;
52611 const szBIH = Sizeof( tBIH );
52612 szBFH = Sizeof( tBFH );
52614 PUSH EBX
52615 PUSH ESI
52616 MOV EBX, EAX
52617 PUSH EDX
52618 CALL Clear
52619 POP ESI
52620 MOV EAX, ESI
52621 CALL TStream.GetPosition
52622 PUSH EAX // [EBP+4] = Strm.Pos (starting pos)
52623 PUSH EBP
52624 MOV EBP, ESP
52625 ADD ESP, -(szBIH + szBFH)
52627 // reading bitmap
52628 XOR ECX, ECX
52629 MOV [EBX].fHandleType, CL
52630 MOV CL, szBFH
52631 MOV EDX, ESP
52632 PUSH ECX
52633 MOV EAX, ESI
52634 CALL TStream.Read
52635 POP ECX
52636 SUB ECX, EAX
52637 JNZ @@eread1
52639 CMP [ESP].tBFH.bfType, $4D42
52640 JE @@1
52641 MOV EDX, [EBP+4]
52642 MOV EAX, ESI
52643 CALL TStream.Seek
52644 XOR EAX, EAX
52645 XOR EDX, EDX
52646 JMP @@2
52648 @@1:
52649 MOV EDX, [ESP].tBFH.bfSize
52650 MOV EAX, [ESP].tBFH.bfOffBits
52651 @@2:
52652 PUSH EDX // Push Size
52653 PUSH EAX // Push Off
52654 XOR ECX, ECX
52655 MOV CL, szBIH
52656 LEA EDX, [EBP-szBIH]
52657 MOV EAX, ESI
52658 PUSH ECX
52659 CALL TStream.Read // read BIH
52660 POP ECX
52661 @@eread1:
52662 XOR ECX, EAX
52663 JNZ @@eread
52665 MOVZX EAX, [EBP-szBIH].tBIH.biBitCount
52666 MOVZX EDX, [EBP-szBIH].tBIH.biPlanes
52667 MUL EDX
52668 CALL Bits2PixelFormat
52669 {$IFDEF PARANOIA}
52670 DB $3C, pf15bit
52671 {$ELSE}
52672 CMP AL, pf15bit
52673 {$ENDIF}
52674 JNZ @@no15bit
52675 CMP [EBP-szBIH].tBIH.biCompression, 0
52676 JZ @@no15bit
52677 INC AL // AL = pf16bit
52678 @@no15bit:
52679 MOV [EBX].fNewPixelFormat, AL
52681 MOV EAX, szBIH + 1024
52682 CALL System.@GetMem
52683 MOV [EBX].fDIBHeader, EAX
52684 XCHG EDX, EAX
52685 LEA EAX, [EBP-szBIH]
52686 XOR ECX, ECX
52687 MOV CL, szBIH
52688 CALL System.Move
52690 MOV EAX, [EBP-szBIH].tBIH.biWidth
52691 MOV [EBX].fWidth, EAX
52692 MOV EAX, [EBP-szBIH].tBIH.biHeight
52693 TEST EAX, EAX
52694 JGE @@20
52695 NEG EAX
52696 @@20: MOV [EBX].fHeight, EAX
52698 MOV EAX, EBX
52699 CALL GetScanLineSize
52700 MOV EDX, [EBX].fHeight
52701 MUL EDX
52702 MOV [EBX].fDIBSize, EAX
52703 CALL AllocMem
52704 MOV [EBX].fDIBBits, EAX
52706 MOVZX EAX, [EBP-szBIH].tBIH.biBitCount
52707 {$IFDEF PARANOIA}
52708 DB $3C, 8
52709 {$ELSE}
52710 CMP AL, 8
52711 {$ENDIF}
52712 JA @@3
52713 MOV AL, 4
52714 MOVZX ECX, [EBP-szBIH].tBIH.biBitCount
52715 SAL EAX, CL
52716 XCHG ECX, EAX
52717 @@3:
52718 CMP [EBX].TBitmap.fNewPixelFormat, pf16bit
52719 JNE @@30
52720 XOR ECX, ECX
52721 MOV CL, 12 // ColorCount = 12
52722 @@30:
52723 POP EAX // EAX = off
52724 TEST EAX, EAX
52725 JLE @@4
52726 SUB EAX, szBFH + szBIH
52727 CMP EAX, ECX
52728 JZ @@4
52729 XCHG ECX, EAX
52730 @@4:
52731 JECXZ @@5
52732 PUSH ECX
52733 MOV EDX, [EBX].fDIBHeader
52734 ADD EDX, szBIH
52735 MOV EAX, ESI
52736 CALL TStream.Read
52737 POP ECX
52738 XOR EAX, ECX
52739 JNZ @@eread
52740 @@5:
52741 MOV ECX, [EBX].fDIBSize
52742 @@7:
52743 PUSH ECX
52744 MOV EAX, ESI
52745 CALL TStream.GetPosition
52746 PUSH EAX
52747 MOV EAX, ESI
52748 CALL TStream.GetSize
52749 POP EDX
52750 SUB EAX, EDX
52751 POP ECX // Size = fDIBSize
52752 CMP EAX, ECX // Strm.Size - Strm.Position > Size ?
52753 JL @@8
52754 XCHG ECX, EAX
52755 @@8:
52756 // ++++++++++++++ 26-Oct-2003 VK see comment in Pascal
52757 MOV EAX, [EBX].fDIBSize
52758 CMP ECX, EAX
52759 JGE @@9
52760 SUB EAX, ECX
52761 PUSH EAX
52762 MOV EAX, ESI
52763 PUSH ECX
52764 CALL TStream.GetPosition
52765 POP ECX
52766 POP EDX
52767 CMP EDX, EAX
52768 JG @@9
52770 MOV EAX, ESI
52771 NEG EDX
52772 XOR ECX, ECX
52773 INC ECX
52774 CALL TStream.Seek
52776 MOV ECX, [EBX].fDIBSize
52777 @@9:
52778 // ++++++++++++++
52780 PUSH ECX
52781 MOV EDX, [EBX].fDIBBits
52782 MOV EAX, ESI
52783 CALL TStream.Read
52784 POP ECX
52785 XOR EAX, ECX
52786 POP EAX // Strm.Size - Position
52787 POP ECX // fDIBSize
52788 //JNZ @@eread
52790 // end of reading bitmap
52791 @@eread:
52792 MOV ESP, EBP
52793 POP EBP
52794 POP EDX
52795 JZ @@exit
52796 // not success:
52797 XCHG EAX, ESI
52798 XOR ECX, ECX // ECX = spBegin
52799 CALL TStream.Seek
52800 XCHG EAX, EBX
52801 CALL Clear
52802 @@exit: POP ESI
52803 POP EBX
52804 end;
52805 {$ELSE ASM_VERSION} //Pascal
52806 procedure TBitmap.LoadFromStream(Strm: PStream);
52807 type
52808 TColorsArray = array[ 0..15 ] of TColor;
52809 PColorsArray = ^TColorsArray;
52810 PColor = ^TColor;
52811 var Pos : Integer;
52812 BFH : TBitmapFileHeader;
52814 function ReadBitmap : Boolean;
52815 var Size, Size1: Integer;
52816 BCH: TBitmapCoreHeader;
52817 RGBSize: DWORD;
52818 C: PColor;
52819 Off, HdSz, ColorCount: DWORD;
52820 begin
52821 fHandleType := bmDIB;
52822 Result := False;
52823 if Strm.Read( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;
52824 Off := 0; Size := 0;
52825 if BFH.bfType <> $4D42 then
52826 Strm.Seek( Pos, spBegin )
52827 else
52828 begin
52829 Off := BFH.bfOffBits - Sizeof( BFH );
52830 Size := BFH.bfSize; // don't matter, just <> 0 is good
52831 //Size := Min( BFH.bfSize, Strm.Size - Strm.Position );
52832 end;
52833 RGBSize := 4;
52834 HdSz := Sizeof( TBitmapInfoHeader );
52835 fDIBHeader := AllocMem( 256*sizeof(TRGBQuad) + HdSz );
52836 if Strm.Read( fDIBHeader.bmiHeader.biSize, Sizeof( DWORD ) ) <> Sizeof( DWORD ) then
52837 Exit;
52838 if fDIBHeader.bmiHeader.biSize = HdSz then
52839 begin
52840 if Strm.Read( fDIBHeader.bmiHeader.biWidth, HdSz - Sizeof( DWORD ) ) <>
52841 HdSz - Sizeof( DWORD ) then
52842 Exit;
52844 else
52845 if fDIBHeader.bmiHeader.biSize = Sizeof( TBitmapCoreHeader ) then
52846 begin
52847 RGBSize := 3;
52848 HdSz := Sizeof( TBitmapCoreHeader );
52849 if Strm.Read( BCH.bcWidth, HdSz - Sizeof( DWORD ) ) <>
52850 HdSz - Sizeof( DWORD ) then
52851 Exit;
52852 fDIBHeader.bmiHeader.biSize := Sizeof( TBitmapInfoHeader );
52853 fDIBHeader.bmiHeader.biWidth := BCH.bcWidth;
52854 fDIBHeader.bmiHeader.biHeight := BCH.bcHeight;
52855 fDIBHeader.bmiHeader.biPlanes := BCH.bcPlanes;
52856 fDIBHeader.bmiHeader.biBitCount := BCH.bcBitCount;
52858 else Exit;
52859 fNewPixelFormat := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount
52860 * fDIBHeader.bmiHeader.biPlanes );
52861 if (fNewPixelFormat = pf15bit) and (fDIBHeader.bmiHeader.biCompression <> BI_RGB) then
52862 begin
52863 ASSERT( fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS, 'Unsupported bitmap format' );
52864 //fNewPixelFormat := pf16bit;
52865 end;
52866 fWidth := fDIBHeader.bmiHeader.biWidth;
52867 ASSERT( fWidth > 0, 'Bitmap width must be > 0' );
52868 fHeight := Abs(fDIBHeader.bmiHeader.biHeight);
52869 ASSERT( fHeight > 0, 'Bitmap height must be > 0' );
52871 fDIBSize := ScanLineSize * fHeight;
52872 fDIBBits := AllocMem( fDIBSize );
52873 ASSERT( fDIBBits <> nil, 'No memory' );
52875 ColorCount := 0;
52876 if fDIBHeader.bmiHeader.biBitCount <= 8 then
52877 ColorCount := (1 shl fDIBHeader.bmiHeader.biBitCount) * RGBSize
52878 else if fNewPixelFormat in [pf15bit,pf16bit] then
52879 ColorCount := 12;
52881 if Off > 0 then
52882 begin
52883 Off := Off - HdSz;
52884 if (Off <> ColorCount) then
52885 if not(fNewPixelFormat in [pf15bit,pf16bit])
52886 or (Off = 0) //+++ to fix loading 15- and 16-bit bmps with mask omitted
52887 then
52888 ColorCount := Off;
52889 end;
52890 if ColorCount <> 0 then
52891 begin
52892 if Off >= ColorCount then
52893 Off := Off - ColorCount;
52894 if RGBSize = 4 then
52895 begin
52896 if Strm.Read( fDIBheader.bmiColors[ 0 ], ColorCount )
52897 <> DWORD( ColorCount ) then Exit;
52899 else
52900 begin
52901 C := @ fDIBHeader.bmiColors[ 0 ];
52902 while ColorCount > 0 do
52903 begin
52904 if Strm.Read( C^, RGBSize ) <> RGBSize then Exit;
52905 Dec( ColorCount, RGBSize );
52906 Inc( C );
52907 end;
52908 end;
52909 end;
52910 if Off > 0 then
52911 Strm.Seek( Off, spCurrent );
52913 if Size = 0 then
52914 Size := fDIBSize //ScanLineSize * fHeight
52915 else
52916 Size := Min( {Size - Sizeof( TBitmapFileHeader ) - Sizeof( TBitmapInfoHeader )
52917 - ColorCount} fDIBSize, Strm.Size - Strm.Position );
52919 Size1 := Min( Size, fDIBSize );
52921 // +++++++++++++++++++ 26-Oct-2003 by VK
52922 if (Size1 < fDIBSize)
52923 and (DWORD( fDIBSize - Size1 ) <= Strm.Position) then
52924 begin
52925 Strm.Seek( Size1 - fDIBSize, spCurrent );
52926 Size1 := fDIBSize;
52927 end;
52928 // +++++++++++++++++++ to fix some "incorrect" bitmaps while loading
52930 if Strm.Read( fDIBBits^, Size1 ) <> DWORD( Size1 ) then Exit;
52931 if Size > Size1 then
52932 Strm.Seek( Size - Size1, spCurrent );
52934 Result := True;
52935 end;
52936 {var ColorsArray: PColorsArray;
52937 DC: HDC;
52938 Old: HBitmap;}
52939 begin
52940 Clear;
52941 Pos := Strm.Position;
52942 if not ReadBitmap then
52943 begin
52944 Strm.Seek( Pos, spBegin );
52945 Clear;
52946 end;
52947 {else
52948 begin
52949 if (fDIBBits <> nil) and (fDIBHeader.bmiHeader.biBitCount >= 4) then
52950 begin
52951 ColorsArray := @ fDIBHeader.bmiColors[ 0 ];
52952 if ColorsArray[ 7 ] = $C0C0C0 then
52953 if ColorsArray[ 8 ] = $808080 then
52954 if GetHandle <> 0 then
52955 begin
52956 DC := CreateCompatibleDC( 0 );
52957 Old := SelectObject( DC, fHandle );
52958 SetDIBColorTable( DC, 0, 16, fDIBHeader.bmiColors[ 0 ] );
52959 SelectObject( DC, Old );
52960 DeleteDC( DC );
52961 end;
52962 end;
52963 end;}
52964 end;
52965 {$ENDIF ASM_VERSION}
52967 ////////////////// bitmap RLE-decoding and loading - by Vyacheslav A. Gavrik
52969 //[procedure DecodeRLE4]
52970 procedure DecodeRLE4(Bmp:PBitmap;Data:Pointer); // by Vyacheslav A. Gavrik
52971 procedure OddMove(Src,Dst:PByte;Size:Integer);
52972 begin
52973 if Size=0 then Exit;
52974 repeat
52975 Dst^:=(Dst^ and $F0)or(Src^ shr 4);
52976 Inc(Dst);
52977 Dst^:=(Dst^ and $0F)or(Src^ shl 4);
52978 Inc(Src);
52979 Dec(Size);
52980 until Size=0;
52981 end;
52982 procedure OddFill(Mem:PByte;Size,Value:Integer);
52983 begin
52984 Value:=(Value shr 4)or(Value shl 4);
52985 Mem^:=(Mem^ and $F0)or(Value and $0F);
52986 Inc(Mem);
52987 if Size>1 then FillChar(Mem^,Size,Value);
52988 Mem^:=(Mem^ and $0F)or(Value and $F0);
52989 end;
52991 pb: PByte;
52992 x,y,z,i: Integer;
52993 begin
52994 pb:=Data; x:=0; y:=0;
52995 if Bmp.fScanLineSize = 0 then
52996 Bmp.ScanLineSize;
52997 while y<Bmp.Height do
52998 begin
52999 if pb^=0 then
53000 begin
53001 Inc(pb);
53002 z:=pb^;
53003 case pb^ of
53004 0: begin
53005 Inc(y);
53006 x:=0;
53007 end;
53008 1: Break;
53009 2: begin
53010 Inc(pb); Inc(x,pb^);
53011 Inc(pb); Inc(y,pb^);
53012 end;
53013 else
53014 begin
53015 Inc(pb);
53016 i:=(z+1)shr 1;
53017 if(z and 2)=2 then Inc(i);
53018 if((x and 1)=1)and(x+i<Bmp.Width)then
53019 OddMove(pb,@PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],i)
53020 else
53021 Move(pb^,PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],i);
53022 Inc(pb,i-1);
53023 Inc(x,z);
53024 end;
53025 end;
53026 end else
53027 begin
53028 z:=pb^;
53029 Inc(pb);
53030 if((x and 1)=1)and(x+z<Bmp.Width)then
53031 OddFill(@PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],z shr 1,pb^)
53032 else
53033 FillChar(PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x shr 1],z shr 1,pb^);
53034 Inc(x,z);
53035 end;
53036 Inc(pb);
53037 end;
53038 end;
53040 //[procedure DecodeRLE8]
53041 procedure DecodeRLE8(Bmp:PBitmap;Data:Pointer); // by Vyacheslav A. Gavrik
53043 pb: PByte;
53044 x,y,z,i: Integer;
53045 begin
53046 pb:=Data; y:=0; x:=0;
53047 if Bmp.fScanLineSize = 0 then
53048 Bmp.ScanLineSize;
53050 while y<Bmp.Height do
53051 begin
53052 if pb^=0 then
53053 begin
53054 Inc(pb);
53055 case pb^ of
53056 0: begin
53057 Inc(y);
53058 x:=0;
53059 end;
53060 1: Break;
53061 2: begin
53062 Inc(pb); Inc(x,pb^);
53063 Inc(pb); Inc(y,pb^);
53064 end;
53065 else
53066 begin
53067 i:=pb^;
53068 z:=(i+1)and(not 1);
53069 Inc(pb);
53070 Move(pb^,PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x],z);
53071 Inc(pb,z-1);
53072 Inc(x,i);
53073 end;
53074 end;
53075 end else
53076 begin
53077 i:=pb^; Inc(pb);
53078 FillChar(PByteArray(Integer( Bmp.fDIBBits ) + Bmp.fScanLineSize * y)[x],i,pb^);
53079 Inc(x,i);
53080 end;
53081 Inc(pb);
53082 end;
53083 end;
53085 //[function TBitmap.LoadFromFileEx]
53086 function TBitmap.LoadFromFileEx(const Filename: String): Boolean; // by Vyacheslav A. Gavrik
53087 var Strm: PStream;
53088 begin
53089 Strm := NewReadFileStream( Filename );
53090 Result := LoadFromStreamEx(Strm);
53091 Strm.Free;
53092 end;
53094 //[function TBitmap.LoadFromStreamEx]
53095 function TBitmap.LoadFromStreamEx(Strm: PStream): Boolean; // by Vyacheslav A. Gavrik
53096 var Pos : Integer;
53098 function ReadBitmap : Boolean;
53099 var Off, Size, ColorCount: Integer;
53100 BFH : TBitmapFileHeader;
53101 BFHValid: Boolean;
53102 Buffer: Pointer;
53103 begin
53104 fHandleType := bmDIB;
53105 Result := False;
53106 BFHValid := FALSE;
53107 if Strm.Read( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;
53108 Off := 0; Size := 0;
53109 if BFH.bfType <> $4D42 then
53110 Strm.Seek( Pos, spBegin )
53111 else
53112 begin
53113 BFHValid := TRUE;
53114 Off := BFH.bfOffBits;
53115 Size := Strm.GetSize;
53116 end;
53117 GetMem( fDIBHeader, 256*sizeof(TRGBQuad) + sizeof(TBitmapInfoHeader) );
53118 if Strm.Read( fDIBHeader^, Sizeof(TBitmapInfoHeader) ) <> Sizeof(TBitmapInfoHeader) then
53119 Exit;
53120 //if fDIBHeader.bmiHeader.biCompression = BI_RGB then
53121 {if fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS then
53122 //BI_RGB here????
53123 Strm.Read( fDIBHeader.bmiColors[ 0 ], 3 * Sizeof( DWORD ) );}
53125 fNewPixelFormat := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount
53126 * fDIBHeader.bmiHeader.biPlanes );
53128 fWidth := fDIBHeader.bmiHeader.biWidth;
53129 ASSERT( fWidth > 0, 'Bitmap width must be > 0' );
53130 fHeight := Abs(fDIBHeader.bmiHeader.biHeight);
53131 ASSERT( fHeight > 0, 'Bitmap height must be > 0' );
53133 fDIBSize := ScanLineSize * fHeight;
53134 GetMem( fDIBBits, fDIBSize );
53135 ASSERT( fDIBBits <> nil, 'No memory' );
53136 ASSERT( (fDIBHeader.bmiHeader.biCompression and
53137 (BI_RLE8 or BI_RLE4 or BI_RLE8 or BI_BITFIELDS) <> 0) or
53138 (fDIBHeader.bmiHeader.biCompression = BI_RGB),
53139 'Unknown compression algorithm');
53141 ColorCount := 0;
53142 if fDIBHeader.bmiHeader.biBitCount <= 8 then
53143 ColorCount := (1 shl fDIBHeader.bmiHeader.biBitCount) * Sizeof( TRGBQuad )
53144 else if fNewPixelFormat in [ pf16bit ] then
53145 ColorCount := 12;
53147 if Off > 0 then
53148 begin
53149 Off := Off - SizeOf( TBitmapFileHeader ) - Sizeof( TBitmapInfoHeader );
53150 if Off <> ColorCount then
53151 ColorCount := Off;
53152 end;
53153 if fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS then
53154 begin
53155 PDWORD( DWORD( @ fDIBHeader.bmiColors[ 0 ] ) + 8 )^ := ( $00001F );
53156 PDWORD( DWORD( @ fDIBHeader.bmiColors[ 0 ] ) + 4 )^ := ( $0007E0 );
53157 TColor( fDIBHeader.bmiColors[ 0 ] ) := ( $00F800 );
53158 end;
53160 if ColorCount <> 0 then
53161 if Strm.Read( fDIBheader.bmiColors[ 0 ], ColorCount )
53162 <> DWORD( ColorCount ) then Exit;
53164 if not BFHValid then
53165 Size := fDIBSize
53166 else
53167 if(fDIBHeader.bmiHeader.biCompression = BI_RLE8)
53168 or (fDIBHeader.bmiHeader.biCompression=BI_RLE4) then
53169 Size := BFH.bfSize - BFH.bfOffBits
53170 else
53171 begin
53172 if Integer( Strm.Size - BFH.bfOffBits) - Pos > Integer(Size) then
53173 Size := fDIBSize
53174 else
53175 Size := Strm.Size - BFH.bfOffBits - DWORD( Pos );
53176 end;
53178 if (fDIBHeader.bmiHeader.biCompression = BI_RGB) or
53179 (fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS) then
53180 begin
53181 if Strm.Read( fDIBBits^, Size ) <> DWORD( Size ) then
53182 //Exit;
53184 else
53185 begin
53186 GetMem(Buffer,Size);
53187 if Strm.Read(Buffer^,Size) <> DWORD( Size ) then Exit;
53189 if fDIBHeader.bmiHeader.biCompression=BI_RLE8 then
53190 DecodeRLE8(@Self,Buffer)
53191 else
53192 DecodeRLE4(@Self,Buffer);
53194 fDIBHeader.bmiHeader.biCompression := BI_RGB;
53195 FreeMem(Buffer);
53196 end;
53198 Result := True;
53199 end;
53200 begin
53201 Clear;
53202 Pos := Strm.Position;
53203 result := ReadBitmap;
53204 if not result then
53205 begin
53206 Strm.Seek( Pos, spBegin );
53207 Clear;
53208 end;
53209 end;
53211 ///////////////////////////
53213 {$IFDEF ASM_VERSION}
53214 //[function TBitmap.ReleaseHandle]
53215 function TBitmap.ReleaseHandle: HBitmap;
53217 PUSH EBX
53218 MOV EBX, EAX
53219 XOR EDX, EDX
53220 CALL SetHandleType
53221 MOV EAX, EBX
53222 CALL GetHandle
53223 TEST EAX, EAX
53224 JZ @@exit
53226 CMP [EBX].fDIBAutoFree, 0
53227 JZ @@1
53228 MOV EAX, [EBX].fDIBSize
53229 PUSH EAX
53230 CALL System.@GetMem
53231 MOV EDX, EAX
53232 XCHG EAX, [EBX].fDIBBits
53233 POP ECX
53234 CALL System.Move
53235 @@1:
53236 XOR EAX, EAX
53237 MOV [EBX].fDIBAutoFree, AL
53238 XCHG EAX, [EBX].fHandle
53240 @@exit: POP EBX
53241 end;
53242 {$ELSE ASM_VERSION} //Pascal
53243 function TBitmap.ReleaseHandle: HBitmap;
53244 var OldBits: Pointer;
53245 begin
53246 HandleType := bmDIB;
53247 Result := GetHandle;
53248 if Result = 0 then Exit; // only when bitmap is empty
53249 if fDIBAutoFree then
53250 begin
53251 OldBits := fDIBBits;
53252 GetMem( fDIBBits, fDIBSize );
53253 Move( OldBits^, fDIBBits^, fDIBSize );
53254 fDIBAutoFree := FALSE;
53255 end;
53256 fHandle := 0;
53257 end;
53258 {$ENDIF ASM_VERSION}
53260 {$IFDEF ASM_VERSION}
53261 //[procedure TBitmap.SaveToFile]
53262 procedure TBitmap.SaveToFile(const Filename: String);
53264 PUSH EAX
53265 PUSH EDX
53266 CALL GetEmpty
53267 POP EAX
53268 JZ @@exit
53269 CALL NewWriteFileStream
53270 XCHG EDX, EAX
53271 POP EAX
53272 PUSH EDX
53273 CALL SaveToStream
53274 POP EAX
53275 CALL TObj.Free
53276 PUSH EAX
53277 @@exit: POP EAX
53278 end;
53279 {$ELSE ASM_VERSION} //Pascal
53280 procedure TBitmap.SaveToFile(const Filename: String);
53281 var Strm: PStream;
53282 begin
53283 if Empty then Exit;
53284 Strm := NewWritefileStream( Filename );
53285 SaveToStream( Strm );
53286 Strm.Free;
53287 end;
53288 {$ENDIF ASM_VERSION}
53290 {$IFDEF ASM_VERSION}
53291 //[procedure TBitmap.SaveToStream]
53292 procedure TBitmap.SaveToStream(Strm: PStream);
53293 type tBFH = TBitmapFileHeader;
53294 tBIH = TBitmapInfoHeader;
53295 const szBIH = Sizeof( tBIH );
53296 szBFH = Sizeof( tBFH );
53298 PUSH EBX
53299 PUSH ESI
53300 MOV EBX, EAX
53301 MOV ESI, EDX
53302 CALL GetEmpty
53303 JZ @@exit
53304 MOV EAX, ESI
53305 CALL TStream.GetPosition
53306 PUSH EAX
53308 MOV EAX, EBX
53309 XOR EDX, EDX // EDX = bmDIB
53310 CALL SetHandleType
53311 XOR EAX, EAX
53312 MOV EDX, [EBX].fDIBHeader
53313 MOVZX ECX, [EDX].TBitmapInfoHeader.biBitCount
53314 CMP CL, 8
53315 JG @@1
53316 MOV AL, 4
53317 SHL EAX, CL
53318 @@1:
53319 PUSH EAX // ColorsSize
53320 LEA ECX, [EAX + szBFH + szBIH]
53321 CMP [EDX].TBitmapInfoHeader.biCompression, 0
53322 JZ @@10
53323 ADD ECX, 74
53324 @@10:
53325 PUSH ECX // BFH.bfOffBits
53326 PUSH 0
53327 ADD ECX, [EBX].fDIBSize
53328 PUSH ECX
53329 MOV CX, $4D42
53330 PUSH CX
53331 XOR ECX, ECX
53332 MOV EDX, ESP
53333 MOV CL, szBFH
53334 PUSH ECX
53335 MOV EAX, ESI
53336 CALL TStream.Write
53337 POP ECX
53338 ADD ESP, szBFH
53339 XOR EAX, ECX
53340 POP ECX // ColorsSize
53341 JNZ @@ewrite
53343 MOV EDX, [EBX].fDIBHeader
53344 CMP [EDX].TBitmapInfoHeader.biCompression, 0
53345 JZ @@11
53346 ADD ECX, 74
53347 @@11:
53349 ADD ECX, szBIH
53350 PUSH ECX
53351 MOV EAX, ESI
53352 CALL TStream.Write
53353 POP ECX
53354 XOR EAX, ECX
53355 JNZ @@ewrite
53357 MOV ECX, [EBX].fDIBSize
53358 MOV EDX, [EBX].fDIBBits
53359 MOV EAX, ESI
53360 PUSH ECX
53361 CALL TStream.Write
53362 POP ECX
53363 XOR EAX, ECX
53365 @@ewrite:
53366 POP EDX
53367 JZ @@exit
53368 XCHG EAX, ESI
53369 XOR ECX, ECX
53370 CALL TStream.Seek
53371 @@exit:
53372 POP ESI
53373 POP EBX
53374 end;
53375 {$ELSE ASM_VERSION} //Pascal
53376 procedure TBitmap.SaveToStream(Strm: PStream);
53377 var BFH : TBitmapFileHeader;
53378 Pos : Integer;
53379 function WriteBitmap : Boolean;
53380 var ColorsSize, BitsSize, Size : Integer;
53381 begin
53382 Result := False;
53383 if Empty then Exit;
53384 HandleType := bmDIB; // convert to DIB if DDB
53385 FillChar( BFH, Sizeof( BFH ), 0 );
53386 ColorsSize := 0;
53387 with fDIBHeader.bmiHeader do
53388 if biBitCount <= 8 then
53389 ColorsSize := (1 shl biBitCount) * Sizeof( TRGBQuad )
53390 {else
53391 if biCompression <> 0 then
53392 ColorsSize := 12};
53393 BFH.bfOffBits := Sizeof( BFH ) + Sizeof( TBitmapInfoHeader ) + ColorsSize;
53394 BitsSize := fDIBSize; //ScanLineSize * fHeight;
53395 BFH.bfSize := BFH.bfOffBits + DWord( BitsSize );
53396 BFH.bfType := $4D42; // 'BM';
53397 if fDIBHeader.bmiHeader.biCompression <> 0 then
53398 begin
53399 ColorsSize := 12 + 16*sizeof(TRGBQuad);
53400 Inc( BFH.bfOffBits, ColorsSize );
53401 end;
53402 if Strm.Write( BFH, Sizeof( BFH ) ) <> Sizeof( BFH ) then Exit;
53403 Size := Sizeof( TBitmapInfoHeader ) + ColorsSize;
53404 if Strm.Write( fDIBHeader^, Size ) <> DWORD(Size) then Exit;
53405 if Strm.Write( fDIBBits^, BitsSize ) <> DWord( BitsSize ) then Exit;
53406 Result := True;
53407 end;
53408 begin
53409 Pos := Strm.Position;
53410 if not WriteBitmap then
53411 Strm.Seek( Pos, spBegin );
53412 end;
53413 {$ENDIF ASM_VERSION}
53415 {$IFDEF ASM_VERSION}
53416 //[procedure TBitmap.SetHandle]
53417 procedure TBitmap.SetHandle(const Value: HBitmap);
53418 const szB = sizeof( tagBitmap );
53419 szDIB = sizeof( TDIBSection );
53420 szBIH = sizeof( TBitmapInfoHeader ); // = 40
53422 PUSH EBX
53423 MOV EBX, EAX
53424 PUSH EDX
53425 CALL Clear
53426 POP ECX
53427 JECXZ @@exit
53428 PUSH ECX
53430 ADD ESP, -szDIB
53431 PUSH ESP
53432 PUSH szDIB
53433 PUSH ECX
53434 CALL GetObject
53435 CMP EAX, szDIB
53436 JNZ @@ddb
53438 MOV [EBX].fHandleType, 0
53439 MOV EAX, [ESP].TDIBSection.dsBm.bmWidth
53440 MOV [EBX].fWidth, EAX
53441 MOV EDX, [ESP].TDIBSection.dsBm.bmHeight
53442 MOV [EBX].fHeight, EDX
53443 MOVZX ECX, [ESP].TDIBSection.dsBmih.biBitCount
53444 CALL PrepareBitmapHeader
53445 MOV [EBX].fDIBHeader, EAX
53446 XCHG EDX, EAX
53447 LEA EAX, [ESP].TDIBSection.dsBmih
53448 MOV ECX, 12+szBIH
53449 CALL System.Move
53451 MOV EDX, [ESP].TDIBSection.dsBm.bmBits
53452 MOV [EBX].fDIBBits, EDX
53453 MOV EDX, [ESP].TDIBSection.dsBmih.biSizeImage
53454 MOV [EBX].fDIBSize, EDX
53455 MOV [EBX].fDIBAutoFree, 1
53456 ADD ESP, szDIB
53457 POP [EBX].fHandle
53458 JMP @@exit
53460 @@ddb:
53461 MOV ECX, [ESP+szDIB]
53462 PUSH ESP
53463 PUSH szB
53464 PUSH ECX
53465 CALL GetObject
53466 POP EDX
53467 POP EDX // bmWidth
53468 POP ECX // bmHeight
53469 ADD ESP, szDIB-12
53470 TEST EAX, EAX
53471 JZ @@exit
53472 MOV [EBX].fWidth, EDX
53473 MOV [EBX].fHeight, ECX
53474 POP dword ptr [EBX].fHandle
53475 MOV [EBX].fHandleType, 1
53476 @@exit: POP EBX
53477 end;
53478 {$ELSE ASM_VERSION} //Pascal
53479 procedure TBitmap.SetHandle(const Value: HBitmap);
53480 var B: tagBitmap;
53481 Dib: TDIBSection;
53482 begin
53483 Clear;
53484 if Value = 0 then Exit;
53485 if GetObject( Value, Sizeof( Dib ), @ Dib ) = Sizeof( Dib ) then
53486 begin
53487 fHandle := Value;
53488 fHandleType := bmDIB;
53489 fDIBHeader := PrepareBitmapHeader( Dib.dsBm.bmWidth, Dib.dsBm.bmHeight,
53490 Dib.dsBmih.biBitCount );
53491 fDIBHeader.bmiHeader := Dib.dsBmih;
53492 Move( Dib.dsBitfields, fDIBHeader.bmiColors, 3 * 4 );
53493 fWidth := Dib.dsBm.bmWidth;
53494 fHeight := Dib.dsBm.bmHeight;
53495 fDIBBits := Dib.dsBm.bmBits;
53496 fDIBSize := Dib.dsBmih.biSizeImage;
53497 fDIBAutoFree := true;
53499 else
53500 begin
53501 if GetObject( Value, Sizeof( B ), @B ) = 0 then Exit;
53502 fHandle := Value;
53503 fWidth := B.bmWidth;
53504 fHeight := B.bmHeight;
53505 fHandleType := bmDDB;
53506 end;
53507 end;
53508 {$ENDIF ASM_VERSION}
53510 //[procedure TBitmap.SetWidth]
53511 procedure TBitmap.SetWidth(const Value: Integer);
53512 begin
53513 if fWidth = Value then Exit;
53514 fWidth := Value;
53515 FormatChanged;
53516 end;
53518 {$IFDEF ASM_VERSION}
53519 //[procedure TBitmap.SetHeight]
53520 procedure TBitmap.SetHeight(const Value: Integer);
53522 CMP EDX, [EAX].fHeight
53523 JE @@exit
53524 PUSHAD
53525 XOR EDX, EDX
53526 INC EDX
53527 CALL SetHandleType
53528 POPAD
53529 MOV [EAX].fHeight, EDX
53530 CALL FormatChanged
53531 @@exit:
53532 end;
53533 {$ELSE ASM_VERSION} //Pascal
53534 procedure TBitmap.SetHeight(const Value: Integer);
53535 begin
53536 if fHeight = Value then Exit;
53538 HandleType := bmDDB;
53539 // Not too good, but provides correct changing of height
53540 // preserving previous image
53542 fHeight := Value;
53543 FormatChanged;
53544 end;
53545 {$ENDIF ASM_VERSION}
53547 {$IFDEF ASM_VERSION}
53548 //[procedure TBitmap.SetPixelFormat]
53549 procedure TBitmap.SetPixelFormat(Value: TPixelFormat);
53551 PUSH EBX
53552 MOV EBX, EAX
53553 //////////////////////
53554 CALL GetEmpty // if Empty then Exit;
53555 JZ @@exit //
53556 MOV EAX, EBX //
53557 //////////////////////
53558 PUSH EDX
53559 CALL GetPixelFormat
53560 POP EDX
53561 CMP EAX, EDX
53562 JE @@exit
53563 TEST EDX, EDX
53564 MOV EAX, EBX
53565 JNE @@2
53566 // Value = pfDevice (=0)
53567 POP EBX
53568 INC EDX // EDX = bmDDB
53569 JMP SetHandleType
53570 @@2:
53571 MOV [EBX].fNewPixelFormat, DL
53572 CMP DL, pf16bit
53573 JNZ @@3
53574 DEC EDX
53575 @@3: PUSH EDX
53576 XOR EDX, EDX
53577 CALL SetHandleType
53578 MOV EAX, [EBX].fDIBHeader
53579 MOVZX EAX, [EAX].TBitmapInfoHeader.biBitCount
53580 CALL Bits2PixelFormat
53581 POP EDX
53582 CMP AL, DL
53583 XCHG EAX, EBX
53584 @@exit:
53585 POP EBX
53586 JNE FormatChanged
53587 end;
53588 {$ELSE ASM_VERSION} //Pascal
53589 procedure TBitmap.SetPixelFormat(Value: TPixelFormat);
53590 begin
53591 if PixelFormat = Value then Exit;
53592 if Empty then Exit;
53593 if Value = pfDevice then
53594 HandleType := bmDDB
53595 else
53596 begin
53597 fNewPixelFormat := Value;
53598 //if Value = pf16bit then Value := pf15bit;
53599 HandleType := bmDIB;
53600 if Value <> Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount ) then
53601 FormatChanged;
53602 end;
53603 end;
53604 {$ENDIF ASM_VERSION}
53606 //[FUNCTION CalcScanLineSize]
53607 {$IFDEF ASM_VERSION}
53608 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;
53610 MOVZX EDX, [EAX].TBitmapInfoHeader.biBitCount
53611 MOV EAX, [EAX].TBitmapInfoHeader.biWidth
53612 MUL EDX
53613 ADD EAX, 31
53614 SHR EAX, 3
53615 AND EAX, -4
53616 end;
53617 {$ELSE ASM_VERSION} //Pascal
53618 function CalcScanLineSize( Header: PBitmapInfoHeader ): Integer;
53619 begin
53620 //Result := ((Header.biBitCount * Header.biWidth + 31)
53621 // shr 5) * 4;
53622 Result := ((Header.biBitCount * Header.biWidth + 31) shr 3) and $FFFFFFFC;
53623 end;
53624 {$ENDIF ASM_VERSION}
53625 //[END CalcScanLineSize]
53627 //[PROCEDURE FillBmpWithBkColor]
53628 {$IFDEF ASM_VERSION}
53629 procedure FillBmpWithBkColor( Bmp: PBitmap; DC2: HDC; oldWidth, oldHeight: Integer );
53631 PUSH EBX
53632 PUSH ESI
53633 XCHG EAX, EBX
53634 PUSH EDX // [EBP-12] = DC2
53635 PUSH ECX // [EBP-16] = oldWidth
53636 MOV EAX, [EBX].TBitmap.fBkColor
53637 CALL Color2RGB
53638 TEST EAX, EAX
53639 JZ @@exit
53640 XCHG ESI, EAX // ESI = Color2RGB( Bmp.fBkColor )
53641 MOV EAX, EBX
53642 CALL TBitmap.GetHandle
53643 TEST EAX, EAX
53644 JZ @@exit
53645 PUSH EAX //fHandle
53646 PUSH dword ptr [EBP-12] //DC2
53647 CALL SelectObject
53648 PUSH EAX // [EBP-20] = oldBmp
53649 PUSH ESI
53650 CALL CreateSolidBrush
53651 XCHG ESI, EAX // ESI = Br
53652 PUSH [EBX].TBitmap.fHeight
53653 PUSH [EBX].TBitmap.fWidth
53654 MOV EAX, [oldHeight]
53655 MOV EDX, [EBP-16] //oldWidth
53656 CMP EAX, [EBX].TBitmap.fHeight
53657 JL @@fill
53658 CMP EDX, [EBX].TBitmap.fWidth
53659 JGE @@nofill
53660 @@fill: CMP EAX, [EBX].TBitmap.fHeight
53661 JNE @@1
53662 XOR EAX, EAX
53663 @@1:
53664 CMP EDX, [EBX].TBitmap.fWidth
53665 JNZ @@2
53667 @@2: PUSH EAX
53668 PUSH EDX
53670 MOV EDX, ESP
53671 PUSH ESI
53672 PUSH EDX
53673 PUSH dword ptr [EBP-12] //DC2
53674 CALL Windows.FillRect
53675 POP ECX
53676 POP ECX
53677 @@nofill:
53678 POP ECX
53679 POP ECX
53680 PUSH ESI //Br
53681 CALL DeleteObject
53682 PUSH dword ptr [EBP-12] //DC2
53683 CALL SelectObject
53684 @@exit:
53685 POP ECX
53686 POP EDX
53687 POP ESI
53688 POP EBX
53689 end;
53690 {$ELSE ASM_VERSION} //Pascal
53691 procedure FillBmpWithBkColor( Bmp: PBitmap; DC2: HDC; oldWidth, oldHeight: Integer );
53692 var oldBmp: HBitmap;
53693 R: TRect;
53694 Br: HBrush;
53695 begin
53696 with Bmp{-}^{+} do
53697 if Color2RGB( fBkColor ) <> 0 then
53698 if (oldWidth < fWidth) or (oldHeight < fHeight) then
53699 if GetHandle <> 0 then
53700 begin
53701 oldBmp := SelectObject( DC2, fHandle );
53702 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
53703 Br := CreateSolidBrush( Color2RGB( fBkColor ) );
53704 R := MakeRect( oldWidth, oldHeight, fWidth, fHeight );
53705 if oldWidth = fWidth then
53706 R.Left := 0;
53707 if oldHeight = fHeight then
53708 R.Top := 0;
53709 Windows.FillRect( DC2, R, Br );
53710 DeleteObject( Br );
53711 SelectObject( DC2, oldBmp );
53712 end;
53713 end;
53714 {$ENDIF ASM_VERSION}
53715 //[END FillBmpWithBkColor]
53717 const BitCounts: array[ TPixelFormat ] of Byte = ( 0, 1, 4, 8, 16, 16, 24, 32, 0 );
53718 {$IFDEF ASM_VERSION}
53719 //[procedure TBitmap.FormatChanged]
53720 procedure TBitmap.FormatChanged;
53721 type tBIH = TBitmapInfoHeader;
53722 tBmp = tagBitmap;
53723 const szBIH = Sizeof( tBIH );
53724 szBmp = Sizeof( tBmp );
53726 PUSH EAX
53727 CALL GetEmpty
53728 POP EAX
53729 JZ @@exit
53730 PUSHAD
53731 MOV EBX, EAX
53732 CALL [EBX].fDetachCanvas
53733 XOR EAX, EAX
53734 MOV [EBX].fScanLineSize, EAX
53735 MOV [EBX].fGetDIBPixels, EAX
53736 MOV [EBX].fSetDIBPixels, EAX
53737 MOV ESI, [EBX].fWidth // ESI := oldWidth
53738 MOV EDI, [EBX].fHeight // EDI := oldHeight
53739 MOV ECX, [EBX].fDIBBits
53740 JECXZ @@noDIBBits
53741 MOV EAX, [EBX].fDIBHeader
53742 MOV ESI, [EAX].TBitmapInfo.bmiHeader.biWidth
53743 MOV EDI, [EAX].TBitmapInfo.bmiHeader.biHeight
53744 TEST EDI, EDI
53745 JGE @@1
53746 NEG EDI
53747 @@1: JMP @@createDC2
53748 @@noDIBBits:
53749 MOV ECX, [EBX].fHandle
53750 JECXZ @@createDC2
53751 ADD ESP, -24 // -szBmp
53752 PUSH ESP
53753 PUSH 24 //szBmp
53754 PUSH ECX
53755 CALL GetObject
53756 XCHG ECX, EAX
53757 JECXZ @@2
53758 MOV ESI, [ESP].tBmp.bmWidth
53759 MOV EDI, [ESP].tBmp.bmHeight
53760 @@2: ADD ESP, 24 //szBmp
53761 @@createDC2:
53762 PUSH 0
53763 CALL CreateCompatibleDC
53764 PUSH EAX // > DC2
53765 CMP [EBX].fHandleType, bmDDB
53766 JNE @@DIB_handle_type
53767 PUSH 0
53768 CALL GetDC
53769 PUSH EAX // > DC0
53770 PUSH [EBX].fHeight
53771 PUSH [EBX].fWidth
53772 PUSH EAX
53773 CALL CreateCompatibleBitmap
53774 XCHG EBP, EAX // EBP := NewHandle
53775 PUSH 0
53776 CALL ReleaseDC // <
53777 POP EDX
53778 PUSH EDX // EDX := DC2
53779 PUSH EBP
53780 PUSH EDX
53781 CALL SelectObject
53782 PUSH EAX // > OldBmp
53783 PUSH [EBX].fHeight // prepare Rect(0,0,fWidth,fHeight)
53784 PUSH [EBX].fWidth
53785 PUSH 0
53786 PUSH 0
53787 MOV EAX, [EBX].fBkColor
53788 CALL Color2RGB
53789 PUSH EAX
53790 CALL CreateSolidBrush
53791 MOV EDX, ESP
53792 PUSH EAX // > Br
53793 PUSH EAX
53794 PUSH EDX
53795 PUSH dword ptr [ESP+32] // (DC2)
53796 CALL Windows.FillRect
53797 CALL DeleteObject // <
53798 ADD ESP, 16 // remove Rect
53799 MOV ECX, [EBX].fDIBBits
53800 JECXZ @@draw
53801 PUSH dword ptr [ESP+4] // (DC2)
53802 CALL SelectObject // < (OldBmp)
53803 PUSH DIB_RGB_COLORS // : DIB_RGB_COLORS
53804 PUSH [EBX].fDIBHeader // : fDIBHeader
53805 PUSH [EBX].fDIBBits // : fDIBBits
53806 PUSH [EBX].fHeight // : fHeight
53807 PUSH 0 // : 0
53808 PUSH EBP // : NewHandle
53809 PUSH dword ptr [ESP+24] // (DC2)
53810 CALL SetDIBits
53811 JMP @@clearData
53812 @@draw:
53813 MOV EDX, [ESP+4]
53814 PUSH EDX // prepare DC2 for SelectObject
53815 MOV EAX, EBX
53816 XOR ECX, ECX
53817 PUSH ECX
53818 CALL Draw
53819 CALL SelectObject
53820 @@clearData:
53821 MOV EAX, EBX
53822 CALL ClearData
53823 MOV [EBX].fHandle, EBP
53825 JMP @@fillBkColor
53827 @@DIB_handle_type: // [ESP] = DC2
53828 MOVZX EAX, [EBX].fNewPixelFormat
53829 @@getBitsPixel:
53830 XCHG ECX, EAX
53831 MOV CL, [ECX] + offset BitCounts
53832 MOVZX EAX, [DefaultPixelFormat]
53833 JECXZ @@getBitsPixel
53834 XOR EBP, EBP // NewHandle := 0
53835 MOV EAX, [EBX].fWidth // EAX := fWidth
53836 MOV EDX, [EBX].fHeight // EDX := fHeight
53837 CALL PrepareBitmapHeader
53838 PUSH EAX // > NewHeader
53839 CMP [EBX].fNewPixelFormat, pf16bit
53840 JNE @@newHeaderReady
53841 CALL PreparePF16bit
53842 @@newHeaderReady:
53843 POP EAX
53844 PUSH EAX
53845 CALL CalcScanLineSize
53846 MOV EDX, [EBX].fHeight
53847 MUL EDX
53848 PUSH EAX // > sizeBits
53850 {$IFDEF _FP}
53851 CALL GetMem
53852 {$ELSE}
53853 CALL System.@GetMem
53854 {$ENDIF}
53855 PUSH EAX // > NewBits
53856 PUSH DIB_RGB_COLORS
53857 PUSH dword ptr [ESP+12] // (NewHeader)
53858 PUSH EAX
53859 MOV EAX, [EBX].fHeight
53860 CMP EAX, EDI
53861 {$IFDEF USE_CMOV}
53862 CMOVG EAX, EDI
53863 {$ELSE}
53864 JLE @@3
53865 MOV EAX, EDI
53866 @@3: {$ENDIF}
53868 PUSH EAX
53869 PUSH 0
53870 MOV EAX, EBX
53871 CALL GetHandle
53872 PUSH EAX
53873 PUSH dword ptr [ESP+36] // (DC2)
53874 CALL GetDIBits
53876 MOV EDX, [EBX].fHeight
53877 CMP EDX, EDI
53878 {$IFDEF USE_CMOV}
53879 CMOVG EDX, EDI
53880 {$ELSE}
53881 JLE @@30
53882 MOV EDX, EDI
53883 @@30: {$ENDIF}
53885 CMP EAX, EDX
53886 JE @@2clearData
53888 POP EAX
53889 {$IFDEF _FP}
53890 CALL FreeMem
53891 {$ELSE}
53892 CALL System.@FreeMem
53893 {$ENDIF}
53895 XOR EAX, EAX
53896 PUSH EAX
53898 MOV EDX, ESP // EDX = @NewBits
53899 MOV ECX, [ESP+8] // ECX = @NewHeader
53900 PUSH EAX // -> 0
53901 PUSH EAX // -> 0
53902 PUSH EDX // -> @NewBits
53903 PUSH DIB_RGB_COLORS // -> DIB_RGB_COLORS
53904 PUSH ECX // -> @NewHeader
53905 PUSH dword ptr [ESP+32] // -> DC2
53906 CALL CreateDIBSection
53908 XOR ESI, -1 // use OldWidth to store NewDIBAutoFree flag
53910 XCHG EBP, EAX // EBP := NewHandle
53911 PUSH EBP
53912 PUSH dword ptr [ESP+16] // -> DC2
53913 CALL SelectObject
53914 PUSH EAX // save oldBmp
53915 MOV EDX, [ESP+16] // DC2 -> EDX (DC)
53916 XOR ECX, ECX // 0 -> ECX (X)
53917 PUSH ECX // 0 -> stack (Y)
53918 MOV EAX, EBX
53919 CALL TBitmap.Draw
53920 PUSH dword ptr [ESP+16] // -> DC2
53921 CALL SelectObject
53923 @@2clearData:
53924 MOV EAX, EBX
53925 CALL ClearData
53927 POP [EBX].fDIBBits
53928 POP [EBX].fDIBSize
53929 POP [EBX].fDIBHeader
53930 MOV [EBX].fHandle, EBP
53932 TEST ESI, ESI
53933 MOV [EBX].fDIBAutoFree, 0
53934 JGE @@noDIBautoFree
53935 INC [EBX].fDIBAutoFree
53936 @@noDIBautoFree:
53938 @@fillBkColor:
53939 MOV ECX, [EBX].fFillWithBkColor
53940 JECXZ @@deleteDC2
53941 POP EDX // (DC2)
53942 PUSH EDX
53943 PUSH EDI
53944 XCHG ECX, ESI
53945 XCHG EAX, EBX
53946 CALL ESI
53947 @@deleteDC2:
53948 CALL DeleteDC
53949 POPAD
53950 @@exit:
53951 end;
53952 {$ELSE ASM_VERSION} //Pascal
53953 procedure TBitmap.FormatChanged;
53954 // This method is used whenever Width, Height, PixelFormat or HandleType
53955 // properties are changed.
53956 // Old image will be drawn here to a new one (excluding cases when
53957 // old width or height was 0, and / or new width or height is 0).
53958 // To avoid inserting this code into executable, try not to change
53959 // properties Width / Height of bitmat after it is created using
53960 // NewBitmap( W, H ) function or after it is loaded from file, stream
53961 // or resource.
53963 var B: tagBitmap;
53964 oldBmp, NewHandle: HBitmap;
53965 DC0, DC2: HDC;
53966 NewHeader: PBitmapInfo;
53967 NewBits: Pointer;
53968 oldHeight, oldWidth, sizeBits, bitsPixel: Integer;
53969 Br: HBrush;
53970 N: Integer;
53971 NewDIBAutoFree: Boolean;
53972 Hndl: THandle;
53973 begin
53974 if Empty then Exit;
53975 NewDIBAutoFree := FALSE;
53976 fDetachCanvas( @Self );
53977 fScanLineSize := 0;
53978 fGetDIBPixels := nil;
53979 fSetDIBPixels := nil;
53981 oldWidth := fWidth;
53982 oldHeight := fHeight;
53983 if fDIBBits <> nil then
53984 begin
53985 oldWidth := fDIBHeader.bmiHeader.biWidth;
53986 oldHeight := Abs(fDIBHeader.bmiHeader.biHeight);
53988 else
53989 if fHandle <> 0 then
53990 begin
53991 if GetObject( fHandle, Sizeof( B ), @ B ) <> 0 then
53992 begin
53993 oldWidth := B.bmWidth;
53994 oldHeight := B.bmHeight;
53995 end;
53996 end;
53998 DC2 := CreateCompatibleDC( 0 );
54000 if fHandleType = bmDDB then
54001 begin
54002 // New HandleType is bmDDB: old bitmap can be copied using Draw method
54003 DC0 := GetDC( 0 );
54004 NewHandle := CreateCompatibleBitmap( DC0, fWidth, fHeight );
54005 ASSERT( NewHandle <> 0, 'Can not create DDB' );
54006 ReleaseDC( 0, DC0 );
54008 oldBmp := SelectObject( DC2, NewHandle );
54009 ASSERT( oldBmp <> 0, 'Can not select bitmap to DC' );
54011 Br := CreateSolidBrush( Color2RGB( fBkColor ) );
54012 FillRect( DC2, MakeRect( 0, 0, fWidth, fHeight ), Br );
54013 DeleteObject( Br );
54015 if fDIBBits <> nil then
54016 begin
54017 SelectObject( DC2, oldBmp );
54018 SetDIBits( DC2, NewHandle, 0, fHeight, fDIBBits, fDIBHeader^, DIB_RGB_COLORS );
54020 else
54021 begin
54022 Draw( DC2, 0, 0 );
54023 SelectObject( DC2, oldBmp );
54024 end;
54026 ClearData; // Image is cleared but fWidth and fHeight are preserved
54027 fHandle := NewHandle;
54029 else
54030 begin
54031 // New format is DIB. GetDIBits applied to transform old data to new one.
54032 bitsPixel := BitCounts[ fNewPixelFormat ];
54033 if bitsPixel = 0 then
54034 begin
54035 bitsPixel := BitCounts[DefaultPixelFormat];
54036 end;
54038 NewHandle := 0;
54039 NewHeader := PrepareBitmapHeader( fWidth, fHeight, bitsPixel );
54040 if fNewPixelFormat = pf16bit then
54041 PreparePF16bit( NewHeader );
54043 sizeBits := CalcScanLineSize( @NewHeader.bmiHeader ) * fHeight;
54045 GetMem( NewBits, sizeBits );
54046 ASSERT( NewBits <> nil, 'No memory' );
54048 Hndl := GetHandle;
54049 if Hndl = 0 then Exit;
54050 N :=
54051 GetDIBits( DC2, Hndl, 0, Min( fHeight, oldHeight ),
54052 NewBits, NewHeader^, DIB_RGB_COLORS );
54053 //Assert( N = Min( fHeight, oldHeight ), 'Can not get all DIB bits' );
54054 if N <> Min( fHeight, oldHeight ) then
54055 begin
54056 FreeMem( NewBits );
54057 NewBits := nil;
54058 NewHandle := CreateDIBSection( DC2, NewHeader^, DIB_RGB_COLORS, NewBits, 0, 0 );
54059 NewDIBAutoFree := TRUE;
54060 ASSERT( NewHandle <> 0, 'Can not create DIB secion for pf16bit bitmap' );
54061 oldBmp := SelectObject( DC2, NewHandle );
54062 ASSERT( oldBmp <> 0, 'Can not select pf16bit to DC' );
54063 Draw( DC2, 0, 0 );
54064 SelectObject( DC2, oldBmp );
54065 end;
54067 ClearData;
54068 fDIBSize := sizeBits;
54069 fDIBBits := NewBits;
54070 fDIBHeader := NewHeader;
54071 fHandle := NewHandle;
54072 fDIBAutoFree := NewDIBAutoFree;
54074 end;
54076 if Assigned( fFillWithBkColor ) then
54077 fFillWithBkColor( @Self, DC2, oldWidth, oldHeight );
54079 DeleteDC( DC2 );
54081 end;
54082 {$ENDIF ASM_VERSION}
54084 {$IFDEF ASM_VERSION}
54085 //[function TBitmap.GetScanLine]
54086 function TBitmap.GetScanLine(Y: Integer): Pointer;
54088 MOV ECX, [EAX].fDIBHeader
54089 JECXZ @@exit
54090 MOV ECX, [ECX].TBitmapInfoHeader.biHeight
54091 TEST ECX, ECX
54092 JL @@1
54094 SUB ECX, EDX
54095 DEC ECX
54096 MOV EDX, ECX
54098 @@1: MOV ECX, [EAX].fScanLineSize
54099 INC ECX
54100 PUSH [EAX].fDIBBits
54101 LOOP @@2
54103 PUSH EDX
54104 CALL GetScanLineSize
54105 POP EDX
54106 XCHG ECX, EAX
54108 @@2: XCHG EAX, ECX
54109 MUL EDX
54110 POP ECX
54111 ADD ECX, EAX
54113 @@exit: XCHG EAX, ECX
54114 end;
54115 {$ELSE ASM_VERSION} //Pascal
54116 function TBitmap.GetScanLine(Y: Integer): Pointer;
54117 begin
54118 ASSERT( (Y >= 0) {and (Y < fHeight)}, 'ScanLine index out of bounds' );
54119 ASSERT( fDIBBits <> nil, 'No bits available' );
54120 Result := nil;
54121 if fDIBHeader = nil then Exit;
54123 if fDIBHeader.bmiHeader.biHeight > 0 then
54124 Y := fHeight - 1 - Y;
54125 if fScanLineSize = 0 then
54126 ScanLineSize;
54128 Result := Pointer( Integer( fDIBBits ) + fScanLineSize * Y );
54129 end;
54130 {$ENDIF ASM_VERSION}
54132 {$IFDEF ASM_VERSION}
54133 //[function TBitmap.GetScanLineSize]
54134 function TBitmap.GetScanLineSize: Integer;
54136 MOV ECX, [EAX].fDIBHeader
54137 JECXZ @@exit
54139 PUSH EAX
54140 XCHG EAX, ECX
54141 CALL CalcScanLineSize
54142 XCHG ECX, EAX
54143 POP EAX
54144 MOV [EAX].fScanLineSize, ECX
54146 @@exit: XCHG EAX, ECX
54147 end;
54148 {$ELSE ASM_VERSION} //Pascal
54149 function TBitmap.GetScanLineSize: Integer;
54150 begin
54151 Result := 0;
54152 if fDIBHeader = nil then Exit;
54153 FScanLineSize := CalcScanLineSize( @fDIBHeader.bmiHeader );
54154 Result := FScanLineSize;
54155 end;
54156 {$ENDIF ASM_VERSION}
54158 {$IFDEF ASM_VERSION}
54159 //[procedure TBitmap.CanvasChanged]
54160 procedure TBitmap.CanvasChanged( Sender : PObj );
54162 PUSH EAX
54164 XCHG EAX, EDX
54165 CALL TCanvas.GetBrush
54166 MOV EDX, [EAX].TGraphicTool.fData.Color
54168 POP EAX
54169 MOV [EAX].fBkColor, EAX
54170 CALL ClearTransImage
54171 end;
54172 {$ELSE ASM_VERSION} //Pascal
54173 procedure TBitmap.CanvasChanged( Sender : PObj );
54174 begin
54175 fBkColor := PCanvas( Sender ).Brush.Color;
54176 ClearTransImage;
54177 end;
54178 {$ENDIF ASM_VERSION}
54180 {$IFDEF ASM_VERSION}
54181 //[procedure TBitmap.Dormant]
54182 procedure TBitmap.Dormant;
54184 PUSH EAX
54185 CALL RemoveCanvas
54186 POP EAX
54187 MOV ECX, [EAX].fHandle
54188 JECXZ @@exit
54189 CALL ReleaseHandle
54190 PUSH EAX
54191 CALL DeleteObject
54192 @@exit:
54193 end;
54194 {$ELSE ASM_VERSION} //Pascal
54195 procedure TBitmap.Dormant;
54196 begin
54197 RemoveCanvas;
54198 if fHandle <> 0 then
54199 DeleteObject( ReleaseHandle );
54200 end;
54201 {$ENDIF ASM_VERSION}
54203 {$IFDEF ASM_VERSION}
54204 //[procedure TBitmap.SetBkColor]
54205 procedure TBitmap.SetBkColor(const Value: TColor);
54207 CMP [EAX].fBkColor, EDX
54208 JE @@exit
54209 MOV [EAX].fBkColor, EDX
54210 MOV [EAX].fFillWithBkColor, offset[FillBmpWithBkColor]
54211 MOV ECX, [EAX].fApplyBkColor2Canvas
54212 JECXZ @@exit
54213 CALL ECX
54214 @@exit:
54215 end;
54216 {$ELSE ASM_VERSION} //Pascal
54217 procedure TBitmap.SetBkColor(const Value: TColor);
54218 begin
54219 if fBkColor = Value then Exit;
54220 fBkColor := Value;
54221 fFillWithBkColor := FillBmpWithBkColor;
54222 if Assigned( fApplyBkColor2Canvas ) then
54223 fApplyBkColor2Canvas( @Self );
54224 end;
54225 {$ENDIF ASM_VERSION}
54227 {$IFDEF ASM_VERSION}
54228 //[function TBitmap.Assign]
54229 function TBitmap.Assign(SrcBmp: PBitmap): Boolean;
54230 const szBIH = sizeof(TBitmapInfoHeader);
54232 PUSHAD
54233 XCHG EBX, EAX
54234 @@clear:
54235 MOV ESI, EDX
54236 MOV EAX, EBX
54237 CALL Clear
54238 MOV EAX, ESI
54239 OR EAX, EAX
54240 JZ @@exit
54241 CALL GetEmpty
54242 JZ @@exit
54243 MOV EAX, [ESI].fWidth
54244 MOV [EBX].fWidth, EAX
54245 MOV EAX, [ESI].fHeight
54246 MOV [EBX].fHeight, EAX
54247 MOVZX ECX, [ESI].fHandleType
54248 MOV [EBX].fHandleType, CL
54249 JECXZ @@fmtDIB
54251 DEC ECX // ECX = 0
54252 PUSH ECX
54253 PUSH ECX
54254 PUSH ECX
54255 PUSH ECX //IMAGE_BITMAP=0
54256 PUSH [ESI].fHandle
54257 CALL CopyImage
54258 MOV [EBX].fHandle, EAX
54259 TEST EAX, EAX
54260 XCHG EDX, EAX
54261 JZ @@clear
54262 JMP @@exit
54264 @@fmtDIB:
54265 XCHG EAX, ECX
54266 MOV AX, szBIH+1024
54267 PUSH EAX
54268 CALL System.@GetMem
54269 MOV [EBX].fDIBHeader, EAX
54270 XCHG EDX, EAX
54271 POP ECX
54272 MOV EAX, [ESI].fDIBHeader
54273 CALL System.Move
54274 MOV EAX, [ESI].fDIBSize
54275 MOV [EBX].fDIBSize, EAX
54276 PUSH EAX
54277 CALL System.@GetMem
54278 MOV [EBX].fDIBBits, EAX
54279 XCHG EDX, EAX
54280 POP ECX
54281 MOV EAX, [ESI].fDIBBits
54282 CALL System.Move
54284 INC EBX // reset "ZF"
54286 @@exit:
54287 POPAD
54288 SETNZ AL
54289 end;
54290 {$ELSE ASM_VERSION} //Pascal
54291 function TBitmap.Assign(SrcBmp: PBitmap): Boolean;
54292 begin
54293 Clear;
54294 Result := False;
54295 if SrcBmp = nil then Exit;
54296 if SrcBmp.Empty then Exit;
54297 fWidth := SrcBmp.fWidth;
54298 fHeight := SrcBmp.fHeight;
54299 fHandleType := SrcBmp.fHandleType;
54300 if SrcBmp.fHandleType = bmDDB then
54301 begin
54302 fHandle := CopyImage( SrcBmp.fHandle, IMAGE_BITMAP, 0, 0, 0 {LR_COPYRETURNORG} );
54303 ASSERT( fHandle <> 0, 'Can not copy bitmap image' );
54304 Result := fHandle <> 0;
54305 if not Result then Clear;
54307 else
54308 begin
54309 GetMem( fDIBHeader, Sizeof(TBitmapInfoHeader) + 256*sizeof(TRGBQuad) );
54310 ASSERT( fDIBHeader <> nil, 'No memory' );
54311 Move( SrcBmp.fDIBHeader^, fDIBHeader^, Sizeof(TBitmapInfoHeader) + 256*sizeof(TRGBQuad) );
54312 fDIBSize := SrcBmp.fDIBSize;
54313 GetMem( fDIBBits, fDIBSize );
54314 ASSERT( fDIBBits <> nil, 'No memory' );
54315 Move( SrcBmp.fDIBBits^, fDIBBits^, fDIBSize );
54316 //fDIBAutoFree := TRUE;
54317 Result := True;
54318 end;
54319 end;
54320 {$ENDIF ASM_VERSION}
54322 {$IFDEF ASM_VERSION}
54323 //[procedure TBitmap.RemoveCanvas]
54324 procedure TBitmap.RemoveCanvas;
54326 PUSH EAX
54327 CALL [EAX].fDetachCanvas
54328 POP EDX
54329 XOR EAX, EAX
54330 XCHG EAX, [EDX].fCanvas
54331 CALL TObj.Free
54332 end;
54333 {$ELSE ASM_VERSION} //Pascal
54334 procedure TBitmap.RemoveCanvas;
54335 begin
54336 fDetachCanvas( @Self );
54337 fCanvas.Free;
54338 fCanvas := nil;
54339 end;
54340 {$ENDIF ASM_VERSION}
54342 {$IFDEF ASM_VERSION}
54343 //[function TBitmap.DIBPalNearestEntry]
54344 function TBitmap.DIBPalNearestEntry(Color: TColor): Integer;
54345 const szBIH = sizeof(TBitmapInfoHeader);
54347 PUSH EBX
54348 PUSH ESI
54349 PUSH EDI
54350 XCHG ESI, EAX
54351 XCHG EAX, EDX
54352 CALL Color2RGBQuad
54353 XCHG EDI, EAX
54354 MOV EAX, ESI
54355 CALL GetDIBPalEntryCount
54356 XCHG ECX, EAX
54357 XOR EAX, EAX
54358 JECXZ @@exit
54360 MOV ESI, [ESI].fDIBHeader
54361 ADD ESI, szBIH
54362 XOR EDX, EDX
54363 PUSH EDX
54364 DEC DX
54366 @@loo: LODSD
54367 XOR EAX, EDI
54368 MOV EBX, EAX
54369 SHR EBX, 16
54370 MOV BH, 0
54371 ADD AL, AH
54372 MOV AH, 0
54373 ADC AX, BX
54374 CMP AX, DX
54375 JAE @@1
54376 MOV DX, AX
54377 POP EBX
54378 PUSH EDX // save better index (in high order word)
54379 @@1: ADD EDX, $10000 // increment index
54380 LOOP @@loo
54382 XCHG EAX, ECX
54383 POP AX
54384 POP AX
54385 @@exit:
54386 POP EDI
54387 POP ESI
54388 POP EBX
54389 end;
54390 {$ELSE ASM_VERSION} //Pascal
54391 function TBitmap.DIBPalNearestEntry(Color: TColor): Integer;
54392 var I, Diff, D: Integer;
54393 C : Integer;
54394 begin
54395 Color := TColor( Color2RGBQuad( Color ) );
54396 Result := 0;
54397 Diff := MaxInt;
54398 for I := 0 to DIBPalEntryCount - 1 do
54399 begin
54400 C := Color xor PInteger( Integer( @fDIBHeader.bmiColors[ 0 ] )
54401 + I * Sizeof( TRGBQuad ) )^;
54402 D := TRGBQuad( C ).rgbBlue + TRGBQuad( C ).rgbGreen + TRGBQuad( C ).rgbRed;
54403 if D < Diff then
54404 begin
54405 Diff := D;
54406 Result := I;
54407 end;
54408 end;
54409 end;
54410 {$ENDIF ASM_VERSION}
54412 {$IFDEF ASM_VERSION}
54413 //[function TBitmap.GetDIBPalEntries]
54414 function TBitmap.GetDIBPalEntries(Idx: Integer): TColor;
54415 const szBIH = sizeof(TBitmapInfoHeader);
54417 MOV ECX, [EAX].fDIBHeader
54418 JECXZ @@exit
54420 MOV ECX, [EAX+szBIH+EDX*4]
54421 INC ECX
54423 @@exit: DEC ECX
54424 XCHG EAX, ECX
54425 end;
54426 {$ELSE ASM_VERSION} //Pascal
54427 function TBitmap.GetDIBPalEntries(Idx: Integer): TColor;
54428 begin
54429 Result := TColor(-1);
54430 if fDIBBits = nil then Exit;
54431 ASSERT( PixelFormat in [pf1bit..pf8bit], 'Format has no DIB palette entries available' );
54432 ASSERT( (Idx >= 0) and (Idx < (1 shl fDIBHeader.bmiHeader.biBitCount)),
54433 'DIB palette index out of bounds' );
54434 Result := PDWORD( Integer( @fDIBHeader.bmiColors[ 0 ] )
54435 + Idx * Sizeof( TRGBQuad ) )^;
54436 end;
54437 {$ENDIF ASM_VERSION}
54439 {$IFDEF ASM_VERSION}
54440 //[function TBitmap.GetDIBPalEntryCount]
54441 function TBitmap.GetDIBPalEntryCount: Integer;
54443 PUSH EAX
54444 CALL GetEmpty
54445 POP EAX
54446 JZ @@ret0
54447 CALL GetPixelFormat
54448 MOVZX ECX, AL
54449 MOV EAX, ECX
54450 LOOP @@1
54451 // pf1bit:
54452 INC EAX
54454 @@1:
54455 LOOP @@2
54456 // pf4bit:
54457 MOV AL, 16
54459 @@2:
54460 LOOP @@ret0
54461 // pf8bit:
54462 XOR EAX, EAX
54463 INC AH
54465 @@ret0:
54466 XOR EAX, EAX
54467 end;
54468 {$ELSE ASM_VERSION} //Pascal
54469 function TBitmap.GetDIBPalEntryCount: Integer;
54470 begin
54471 Result := 0;
54472 if Empty then Exit;
54473 case PixelFormat of
54474 pf1bit: Result := 2;
54475 pf4bit: Result := 16;
54476 pf8bit: Result := 256;
54477 else;
54478 end;
54479 end;
54480 {$ENDIF ASM_VERSION}
54482 //[procedure TBitmap.SetDIBPalEntries]
54483 procedure TBitmap.SetDIBPalEntries(Idx: Integer; const Value: TColor);
54484 begin
54485 if fDIBBits = nil then Exit;
54486 Dormant;
54487 PDWORD( Integer( @fDIBHeader.bmiColors[ 0 ] )
54488 + Idx * Sizeof( TRGBQuad ) )^ := Color2RGB( Value );
54489 end;
54491 //[procedure TBitmap.SetHandleType]
54492 procedure TBitmap.SetHandleType(const Value: TBitmapHandleType);
54493 {var B: tagBitmap;
54494 DC0: HDC;}
54495 begin
54496 if fHandleType = Value then Exit;
54497 //++++++++++++++++ ?????????
54498 {if fHandleType = bmDDB then
54499 if PixelFormat = pfDevice then
54500 begin
54501 DC0 := GetDC( 0 );
54502 fNewPixelFormat := Bits2PixelFormat( GetDeviceCaps( DC0, BITSPIXEL ) );
54503 ReleaseDC( 0, DC0 );
54505 else
54506 if FHandle <> 0 then
54507 begin
54508 if GetObject( FHandle, Sizeof( B ), @ B ) > 0 then
54509 fNewPixelFormat := Bits2PixelFormat( B.bmPlanes * B.bmBitsPixel );
54510 end;}
54511 //----------------
54512 fHandleType := Value;
54513 FormatChanged;
54514 end;
54516 //[function TBitmap.GetPixelFormat]
54517 function TBitmap.GetPixelFormat: TPixelFormat;
54518 begin
54519 if (HandleType = bmDDB) or (fDIBBits = nil) then
54520 Result := pfDevice
54521 else
54522 begin
54523 Result := Bits2PixelFormat( fDIBHeader.bmiHeader.biBitCount );
54524 if (Result = pf15bit) and (fDIBHeader.bmiHeader.biCompression <> 0) then
54525 begin
54526 Assert( fDIBHeader.bmiHeader.biCompression = BI_BITFIELDS, 'Unsupported bitmap format' );
54527 Result := pf16bit;
54528 end;
54529 end;
54530 end;
54532 {$IFDEF ASM_VERSION}
54533 //[procedure TBitmap.ClearTransImage]
54534 procedure TBitmap.ClearTransImage;
54536 OR [EAX].fTransColor, -1
54537 XOR EDX, EDX
54538 XCHG [EAX].fTransMaskBmp, EDX
54539 XCHG EAX, EDX
54540 CALL TObj.Free
54541 end;
54542 {$ELSE ASM_VERSION} //Pascal
54543 procedure TBitmap.ClearTransImage;
54544 begin
54545 fTransColor := clNone;
54546 fTransMaskBmp.Free;
54547 fTransMaskBmp := nil;
54548 end;
54549 {$ENDIF ASM_VERSION}
54551 {$IFDEF ASM_VERSION}
54552 //[procedure TBitmap.Convert2Mask]
54553 procedure TBitmap.Convert2Mask(TranspColor: TColor);
54555 PUSH EBX
54556 PUSH ESI
54557 MOV EBX, EAX
54558 MOV ESI, EDX
54559 CALL GetHandle
54560 TEST EAX, EAX
54561 JZ @@exit
54563 PUSH 0
54564 PUSH 1
54565 PUSH 1
54566 PUSH [EBX].fHeight
54567 PUSH [EBX].fWidth
54568 CALL CreateBitmap
54569 PUSH EAX // MonoHandle
54570 PUSH 0
54571 CALL CreateCompatibleDC
54572 POP EDX
54573 PUSH EDX
54574 PUSH EAX // MonoDC
54576 PUSH EDX
54577 PUSH EAX
54578 CALL SelectObject
54579 PUSH EAX // SaveMono
54581 CALL StartDC // DCfrom, SaveFrom
54582 XCHG EAX, ESI
54583 CALL Color2RGB
54584 PUSH EAX // Color2RGB(TranspColor)
54585 PUSH dword ptr [ESP+8] //DCfrom
54586 CALL Windows.SetBkColor
54587 PUSH EAX // SaveBkColor
54589 PUSH SRCCOPY
54590 PUSH 0
54591 PUSH 0
54592 PUSH dword ptr [ESP+12+4+4] //DCfrom
54593 PUSH [EBX].fHeight
54594 PUSH [EBX].fWidth
54595 PUSH 0
54596 PUSH 0
54597 PUSH dword ptr [ESP+32+16] //MonoDC
54598 CALL BitBlt
54600 PUSH dword ptr [ESP+8] //DCfrom
54601 CALL Windows.SetBkColor // ESP-> SaveFrom
54602 CALL FinishDC // ESP-> SaveMono
54603 CALL FinishDC // ESP-> MonoHandle
54605 MOV EAX, EBX
54606 CALL ClearData
54607 POP [EBX].fHandle
54608 MOV [EBX].fHandleType, bmDDB
54609 @@exit:
54610 POP ESI
54611 POP EBX
54612 end;
54613 {$ELSE ASM_VERSION} //Pascal
54614 procedure TBitmap.Convert2Mask(TranspColor: TColor);
54615 var MonoHandle: HBitmap;
54616 SaveMono, SaveFrom: THandle;
54617 MonoDC, {DC0,} DCfrom: HDC;
54618 SaveBkColor: TColorRef;
54619 begin
54620 if GetHandle = 0 then Exit;
54621 fDetachCanvas( @Self );
54622 ///DC0 := GetDC( 0 );
54623 MonoHandle := CreateBitmap( fWidth, fHeight, 1, 1, nil );
54624 ASSERT( MonoHandle <> 0, 'Can not create monochrome bitmap' );
54625 MonoDC := CreateCompatibleDC( 0 );
54626 SaveMono := SelectObject( MonoDC, MonoHandle );
54627 ASSERT( SaveMono <> 0, 'Can not select bitmap to DC' );
54628 DCfrom := CreateCompatibleDC( 0 );
54629 SaveFrom := SelectObject( DCfrom, fHandle );
54630 ASSERT( SaveFrom <> 0, 'Can not select source bitmap to DC' );
54631 TranspColor := Color2RGB( TranspColor );
54632 SaveBkColor := Windows.SetBkColor( DCfrom, TranspColor );
54633 BitBlt( MonoDC, 0, 0, fWidth, fHeight, DCfrom, 0, 0, SRCCOPY );
54634 {$IFDEF CHK_BITBLT} Chk_BitBlt; {$ENDIF}
54635 Windows.SetBkColor( DCfrom, SaveBkColor );
54636 SelectObject( DCfrom, SaveFrom );
54637 DeleteDC( DCfrom );
54638 SelectObject( MonoDC, SaveMono );
54639 DeleteDC( MonoDC );
54640 ///ReleaseDC( 0, DC0 );
54641 ClearData;
54642 fHandle := MonoHandle;
54643 fHandleType := bmDDB;
54644 end;
54645 {$ENDIF ASM_VERSION}
54647 //[procedure TBitmap.Invert]
54648 procedure TBitmap.Invert;
54649 begin
54650 //BitBlt( Canvas.Handle, 0, 0, Width, Height, Canvas.Handle, 0, 0, DSTINVERT )
54651 InvertRect(Canvas.Handle, BoundsRect);
54652 end;
54654 //[procedure TBitmap.DIBDrawRect]
54655 procedure TBitmap.DIBDrawRect( DC: HDC; X, Y: Integer; const R: TRect );
54656 begin
54657 if fDIBBits = nil then Exit;
54658 StretchDIBits( DC, X, Y, R.Right - R.Left, R.Bottom - R.Top,
54659 R.Left, fHeight - R.Bottom, R.Right - R.Left, R.Bottom - R.Top,
54660 fDIBBits, fDIBHeader^, DIB_RGB_COLORS, SRCCOPY );
54661 end;
54663 //[PROCEDURE _PrepareBmp2Rotate]
54664 {$IFDEF ASM_VERSION}
54665 procedure _PrepareBmp2Rotate;
54666 const szBIH = sizeof(TBitmapInfoHeader);
54668 { <- BL = increment to height }
54669 XCHG EDI, EAX
54670 MOV ESI, EDX // ESI = SrcBmp
54672 XCHG EAX, EDX
54673 CALL TBitmap.GetPixelFormat
54674 MOVZX ECX, AL
54675 PUSH ECX
54677 MOV EDX, [ESI].TBitmap.fWidth
54678 MOVZX EBX, BL
54679 ADD EDX, EBX
54681 MOV EAX, [ESI].TBitmap.fHeight
54682 CALL NewDIBBitmap
54683 STOSD
54684 XCHG EDI, EAX
54686 MOV EAX, [ESI].TBitmap.fDIBHeader
54687 ADD EAX, szBIH
54688 MOV EDX, [EDI].TBitmap.fDIBHeader
54689 ADD EDX, szBIH
54690 XOR ECX, ECX
54691 MOV CH, 4
54692 CALL System.Move
54694 MOV EAX, EDI
54695 XOR EDX, EDX
54696 CALL TBitmap.GetScanLine
54697 MOV EBX, [EDI].TBitmap.fWidth
54698 DEC EBX // EBX = DstBmp.fWidth - 1
54699 XCHG EDI, EAX // EDI = DstBmp.ScanLine[ 0 ]
54701 XOR EDX, EDX
54702 INC EDX
54703 CALL TBitmap.GetScanLine
54704 XCHG EDX, EAX
54705 SUB EDX, EDI // EDX = BytesPerDstLine
54707 MOV EBP, [ESI].TBitmap.fWidth
54708 DEC EBP // EBP = SrcBmp.fWidth - 1
54710 POP ECX // ECX = PixelFormat
54711 end;
54712 {$ENDIF ASM_VERSION}
54713 //[END _PrepareBmp2Rotate]
54715 //[PROCEDURE _RotateBitmapMono]
54716 {$IFDEF ASM_VERSION}
54717 procedure _RotateBitmapMono( var DstBmp: PBitmap; SrcBmp: PBitmap );
54718 const szBIH = sizeof(TBitmapInfoHeader);
54720 PUSHAD
54721 MOV BL, 7
54722 CALL _PrepareBmp2Rotate
54724 SHR EBP, 3
54725 SHL EBP, 8 // EBP = (WBytes-1) * 256
54727 MOV ECX, EBX // ECX and 7 = Shf
54728 SHR EBX, 3
54729 ADD EDI, EBX // EDI = Dst
54731 XOR EBX, EBX // EBX = temp mask
54732 XOR EAX, EAX // Y = 0
54733 @@looY:
54734 PUSH EAX
54735 PUSH EDI // Dst1 = Dst (Dst1 in EDI, Dst saved)
54736 PUSH ESI // SrcBmp
54738 PUSH EDX //BytesPerDstLine
54739 PUSH ECX //Shf
54741 XCHG EDX, EAX
54742 XCHG EAX, ESI
54743 CALL TBitmap.GetScanLine
54744 XCHG ESI, EAX // ESI = Src
54746 POP ECX // CL = Shf
54747 AND ECX, 7 // ECX = Shf
54748 OR ECX, EBP // ECX = (Wbytes-1)*8 + Shf
54749 POP EDX // EDX = BytesPerDstLine
54751 MOV BH, $80
54752 SHR EBX, CL // BH = mask, BL = mask & Tmp
54753 @@looX:
54754 XOR EAX, EAX
54756 LODSB
54758 MOV AH, AL
54759 SHR EAX, CL
54760 OR EAX,$01000000
54762 @@looBits:
54763 MOV BL, AH
54764 AND BL, BH
54765 OR [EDI], BL
54766 ADD EDI, EDX
54767 ADD EAX, EAX
54768 JNC @@looBits
54770 SUB ECX, 256
54771 JGE @@looX
54773 POP ESI // ESI = SrcBmp
54774 POP EDI // EDI = Dst
54775 POP EAX // EAX = Y
54777 ADD ECX, 256-1
54778 JGE @@1
54779 DEC EDI
54780 @@1:
54781 INC EAX
54782 CMP EAX, [ESI].TBitmap.fHeight
54783 JL @@looY
54785 POPAD
54786 end;
54787 {$ELSE ASM_VERSION} //Pascal
54788 procedure _RotateBitmapMono( var DstBmp: PBitmap; SrcBmp: PBitmap );
54789 var X, Y, Z, Shf, Wbytes, BytesPerDstLine: Integer;
54790 Src, Dst, Dst1: PByte;
54791 Tmp: Byte;
54792 begin
54794 DstBmp := NewDIBBitmap( SrcBmp.fHeight, (SrcBmp.fWidth + 7) and not 7, pf1bit );
54795 Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 2 * Sizeof( TRGBQuad ) );
54797 // Calculate ones:
54798 Dst := DstBmp.ScanLine[ 0 ];
54799 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
54800 Wbytes := (SrcBmp.fWidth + 7) shr 3;
54802 Inc( Dst, (DstBmp.fWidth - 1) shr 3 );
54803 Shf := (DstBmp.fWidth - 1) and 7;
54805 // Rotating bits:
54806 for Y := 0 to SrcBmp.fHeight - 1 do
54807 begin
54808 Src := SrcBmp.ScanLine[ Y ];
54809 Dst1 := Dst;
54810 for X := Wbytes downto 1 do
54811 begin
54812 Tmp := Src^;
54813 Inc( Src );
54814 for Z := 8 downto 1 do
54815 begin
54816 Dst1^ := Dst1^ or ( (Tmp and $80) shr Shf );
54817 Tmp := Tmp shl 1;
54818 Inc( Dst1, BytesPerDstLine );
54819 end;
54820 end;
54821 Dec( Shf );
54822 if Shf < 0 then
54823 begin
54824 Shf := 7;
54825 Dec( Dst );
54826 end;
54827 end;
54828 end;
54829 {$ENDIF ASM_VERSION}
54830 //[END _RotateBitmapMono]
54832 //[PROCEDURE _RotateBitmap4bit]
54833 {$IFDEF ASM_VERSION}
54834 procedure _RotateBitmap4bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
54835 const szBIH = sizeof(TBitmapInfoHeader);
54837 PUSHAD
54838 MOV BL, 1
54839 CALL _PrepareBmp2Rotate
54841 SHR EBP, 1 // EBP = WBytes - 1
54842 SHL EBP, 8 // EBP = (WBytes - 1) * 256
54844 // EBX = DstBmp.fWidth - 1
54845 MOV ECX, EBX
54846 SHL ECX, 2 // ECX and 7 = Shf (0 or 4)
54847 SHR EBX, 1
54848 ADD EDI, EBX // EDI = Dst
54850 XOR EAX, EAX // Y = 0
54851 XOR EBX, EBX
54853 @@looY:
54854 PUSH EAX // save Y
54855 PUSH EDI // Dst1 = Dst (Dst1 in EDI, Dst saved)
54856 PUSH ESI // SrcBmp
54858 PUSH EDX // BytesPerDstLine
54859 PUSH ECX // Shf
54861 XCHG EDX, EAX
54862 XCHG EAX, ESI
54863 CALL TBitmap.GetScanLine
54864 XCHG ESI, EAX // ESI = Src
54866 POP ECX
54867 AND ECX, 7 // CL = Shf
54868 OR ECX, EBP // ECX = (WBytes-1)*256 + Shf
54869 POP EDX // EDX = BytesPerDstLine
54871 MOV BH, $F0
54872 SHR EBX, CL // shift mask right 4 or 0
54874 @@looX:
54875 XOR EAX, EAX
54876 LODSB
54877 MOV AH, AL
54878 SHR EAX, CL
54880 MOV BL, AH
54881 AND BL, BH
54882 OR [EDI], BL
54883 ADD EDI, EDX
54885 SHL EAX, 4
54886 AND AH, BH
54887 OR [EDI], AH
54888 ADD EDI, EDX
54890 SUB ECX, 256
54891 JGE @@looX
54893 POP ESI // ESI = SrcBmp
54894 POP EDI // EDI = Dst
54895 POP EAX // EAX = Y
54897 ADD ECX, 256 - 4
54898 JGE @@1
54900 DEC EDI
54901 @@1:
54902 INC EAX
54903 CMP EAX, [ESI].TBitmap.fHeight
54904 JL @@looY
54906 POPAD
54907 end;
54908 {$ELSE ASM_VERSION} //Pascal
54909 procedure _RotateBitmap4bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
54910 var X, Y, Shf, Wbytes, BytesPerDstLine: Integer;
54911 Src, Dst, Dst1: PByte;
54912 Tmp: Byte;
54913 begin
54915 DstBmp := NewDIBBitmap( SrcBmp.fHeight, (SrcBmp.fWidth + 1) and not 1, pf4bit );
54916 Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 16 * Sizeof( TRGBQuad ) );
54918 // Calculate ones:
54919 Dst := DstBmp.ScanLine[ 0 ];
54920 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
54921 Wbytes := (SrcBmp.fWidth + 1) shr 1;
54923 Inc( Dst, (DstBmp.fWidth - 1) shr 1 );
54924 Shf := ((DstBmp.fWidth - 1) and 1) shl 2;
54926 // Rotating bits:
54927 for Y := 0 to SrcBmp.fHeight - 1 do
54928 begin
54929 Src := SrcBmp.ScanLine[ Y ];
54930 Dst1 := Dst;
54931 for X := Wbytes downto 1 do
54932 begin
54933 Tmp := Src^;
54934 Inc( Src );
54935 Dst1^ := Dst1^ or ( (Tmp and $F0) shr Shf );
54936 Inc( Dst1, BytesPerDstLine );
54937 Dst1^ := Dst1^ or ( ((Tmp shl 4) and $F0) shr Shf );
54938 Inc( Dst1, BytesPerDstLine );
54939 end;
54940 Dec( Shf, 4 );
54941 if Shf < 0 then
54942 begin
54943 Shf := 4;
54944 Dec( Dst );
54945 end;
54946 end;
54947 end;
54948 {$ENDIF ASM_VERSION}
54949 //[END _RotateBitmap4bit]
54951 //[PROCEDURE _RotateBitmap8bit]
54952 {$IFDEF ASM_VERSION}
54953 procedure _RotateBitmap8bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
54954 const szBIH = sizeof(TBitmapInfoHeader);
54956 PUSHAD
54957 XOR EBX, EBX
54958 CALL _PrepareBmp2Rotate
54960 ADD EDI, EBX // EDI = Dst
54962 MOV EBX, EDX // EBX = BytesPerDstLine
54963 DEC EBX
54964 MOV EBP, ESI // EBP = SrcBmp
54966 XOR EDX, EDX // Y = 0
54968 @@looY:
54969 PUSH EDX
54970 PUSH EDI
54972 MOV EAX, EBP
54973 CALL TBitmap.GetScanLine
54974 XCHG ESI, EAX
54975 MOV ECX, [EBP].TBitmap.fWidth
54977 @@looX:
54978 MOVSB
54979 ADD EDI, EBX
54980 LOOP @@looX
54982 POP EDI
54983 POP EDX
54985 DEC EDI
54986 INC EDX
54987 CMP EDX, [EBP].TBitmap.fHeight
54988 JL @@looY
54990 POPAD
54991 end;
54992 {$ELSE ASM_VERSION} //Pascal
54993 procedure _RotateBitmap8bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
54994 var X, Y, Wbytes, BytesPerDstLine: Integer;
54995 Src, Dst, Dst1: PByte;
54996 Tmp: Byte;
54997 begin
54999 DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );
55000 Move( SrcBmp.fDIBHeader.bmiColors[ 0 ], DstBmp.fDIBHeader.bmiColors[ 0 ], 256 * Sizeof( TRGBQuad ) );
55002 // Calculate ones:
55003 Wbytes := SrcBmp.fWidth;
55004 Dst := DstBmp.ScanLine[ 0 ];
55005 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55007 Inc( Dst, DstBmp.fWidth - 1 );
55009 // Rotating bits:
55010 for Y := 0 to SrcBmp.fHeight - 1 do
55011 begin
55012 Src := SrcBmp.ScanLine[ Y ];
55013 Dst1 := Dst;
55014 for X := Wbytes downto 1 do
55015 begin
55016 Tmp := Src^;
55017 Inc( Src );
55018 Dst1^ := Tmp;
55019 Inc( Dst1, BytesPerDstLine );
55020 end;
55021 Dec( Dst );
55022 end;
55024 end;
55025 {$ENDIF ASM_VERSION}
55026 //[END _RotateBitmap8bit]
55028 //[PROCEDURE _RotateBitmap16bit]
55029 {$IFDEF ASM_VERSION}
55030 procedure _RotateBitmap16bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55032 PUSHAD
55033 XOR EBX, EBX
55034 CALL _PrepareBmp2Rotate
55036 ADD EBX, EBX
55037 ADD EDI, EBX // EDI = Dst
55038 MOV EBX, EDX // EBX = BytesPerDstLine
55039 DEC EBX
55040 DEC EBX
55041 MOV EBP, ESI // EBP = SrcBmp
55043 XOR EDX, EDX // Y = 0
55045 @@looY:
55046 PUSH EDX
55047 PUSH EDI
55049 MOV EAX, EBP
55050 CALL TBitmap.GetScanLine
55051 XCHG ESI, EAX
55052 MOV ECX, [EBP].TBitmap.fWidth
55054 @@looX:
55055 MOVSW
55056 ADD EDI, EBX
55057 LOOP @@looX
55059 POP EDI
55060 POP EDX
55062 DEC EDI
55063 DEC EDI
55064 INC EDX
55065 CMP EDX, [EBP].TBitmap.fHeight
55066 JL @@looY
55068 POPAD
55069 end;
55070 {$ELSE ASM_VERSION} //Pascal
55071 procedure _RotateBitmap16bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55072 var X, Y, Wwords, BytesPerDstLine: Integer;
55073 Src, Dst, Dst1: PWord;
55074 Tmp: Word;
55075 begin
55077 DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );
55079 // Calculate ones:
55080 Wwords := SrcBmp.fWidth;
55081 Dst := DstBmp.ScanLine[ 0 ];
55082 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55084 Inc( Dst, DstBmp.fWidth - 1 );
55086 // Rotating bits:
55087 for Y := 0 to SrcBmp.fHeight - 1 do
55088 begin
55089 Src := SrcBmp.ScanLine[ Y ];
55090 Dst1 := Dst;
55091 for X := Wwords downto 1 do
55092 begin
55093 Tmp := Src^;
55094 Inc( Src );
55095 Dst1^ := Tmp;
55096 Inc( PByte(Dst1), BytesPerDstLine );
55097 end;
55098 Dec( Dst );
55099 end;
55101 end;
55102 {$ENDIF ASM_VERSION}
55103 //[END _RotateBitmap16bit]
55105 //[PROCEDURE _RotateBitmap2432bit]
55106 {$IFDEF ASM_VERSION}
55107 procedure _RotateBitmap2432bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55109 PUSHAD
55110 XOR EBX, EBX
55111 CALL _PrepareBmp2Rotate
55113 SUB ECX, pf24bit
55114 JNZ @@10
55115 LEA EBX, [EBX+EBX*2]
55116 JMP @@11
55117 @@10:
55118 LEA EBX, [EBX*4]
55119 @@11: ADD EDI, EBX // EDI = Dst
55121 MOV EBX, EDX // EBX = BytesPerDstLine
55122 DEC EBX
55123 DEC EBX
55124 DEC EBX
55126 MOV EBP, ESI // EBP = SrcBmp
55128 XOR EDX, EDX // Y = 0
55130 @@looY:
55131 PUSH EDX
55132 PUSH EDI
55133 PUSH ECX // ECX = 0 if pf24bit (1 if pf32bit)
55135 MOV EAX, EBP
55136 CALL TBitmap.GetScanLine
55137 XCHG ESI, EAX
55138 MOV ECX, [EBP].TBitmap.fWidth
55139 POP EAX
55140 PUSH EAX
55142 @@looX:
55143 MOVSW
55144 MOVSB
55145 ADD ESI, EAX
55146 ADD EDI, EBX
55147 LOOP @@looX
55149 POP ECX
55150 POP EDI
55151 POP EDX
55153 DEC EDI
55154 DEC EDI
55155 DEC EDI
55156 SUB EDI, ECX
55157 INC EDX
55158 CMP EDX, [EBP].TBitmap.fHeight
55159 JL @@looY
55161 POPAD
55162 end;
55163 {$ELSE ASM_VERSION} //Pascal
55164 procedure _RotateBitmap2432bit( var DstBmp: PBitmap; SrcBmp: PBitmap );
55165 var X, Y, Wwords, BytesPerDstLine, IncW: Integer;
55166 Src, Dst, Dst1: PDWord;
55167 Tmp: DWord;
55168 begin
55170 DstBmp := NewDIBBitmap( SrcBmp.fHeight, SrcBmp.fWidth, SrcBmp.PixelFormat );
55172 // Calculate ones:
55173 IncW := 4;
55174 if DstBmp.PixelFormat = pf24bit then
55175 IncW := 3;
55176 Wwords := SrcBmp.fWidth;
55177 Dst := DstBmp.ScanLine[ 0 ];
55178 BytesPerDstLine := Integer( DstBmp.ScanLine[ 1 ]) - Integer( Dst );
55180 Inc( PByte(Dst), (DstBmp.fWidth - 1) * IncW );
55182 // Rotating bits:
55183 for Y := 0 to SrcBmp.fHeight - 1 do
55184 begin
55185 Src := SrcBmp.ScanLine[ Y ];
55186 Dst1 := Dst;
55187 for X := Wwords downto 1 do
55188 begin
55189 Tmp := Src^ and $FFFFFF;
55190 Inc( PByte(Src), IncW );
55191 Dst1^ := Dst1^ or Tmp;
55192 Inc( PByte(Dst1), BytesPerDstLine );
55193 end;
55194 Dec( PByte(Dst), IncW );
55195 end;
55197 end;
55198 {$ENDIF ASM_VERSION}
55199 //[END _RotateBitmap2432bit]
55201 type
55202 TRotateBmpRefs = packed record
55203 proc_RotateBitmapMono: procedure( var Dst: PBitmap; Src: PBitmap );
55204 proc_RotateBitmap4bit: procedure( var Dst: PBitmap; Src: PBitmap );
55205 proc_RotateBitmap8bit: procedure( var Dst: PBitmap; Src: PBitmap );
55206 proc_RotateBitmap16bit: procedure( var Dst: PBitmap; Src: PBitmap );
55207 proc_RotateBitmap2432bit: procedure( var Dst: PBitmap; Src: PBitmap );
55208 end;
55211 RotateProcs: TRotateBmpRefs;
55213 //[PROCEDURE _RotateBitmapRight]
55214 {$IFDEF ASM_VERSION}
55215 procedure _RotateBitmapRight( SrcBmp: PBitmap );
55217 PUSH EBX
55218 PUSH EDI
55219 MOV EBX, EAX
55220 CMP [EBX].TBitmap.fHandleType, bmDIB
55221 JNZ @@exit
55223 CALL TBitmap.GetPixelFormat
55224 MOVZX ECX, AL
55225 LOOP @@not1bit
55226 MOV EAX, [RotateProcs.proc_RotateBitmapMono]
55227 @@not1bit:
55228 LOOP @@not4bit
55229 MOV EAX, [RotateProcs.proc_RotateBitmap4bit]
55230 @@not4bit:
55231 LOOP @@not8bit
55232 MOV EAX, [RotateProcs.proc_RotateBitmap8bit]
55233 @@not8bit:
55234 LOOP @@not15bit
55235 INC ECX
55236 @@not15bit:
55237 LOOP @@not16bit
55238 MOV EAX, [RotateProcs.proc_RotateBitmap16bit]
55239 @@not16bit:
55240 LOOP @@not24bit
55241 INC ECX
55242 @@not24bit:
55243 LOOP @@not32bit
55244 MOV EAX, [RotateProcs.proc_RotateBitmap2432bit]
55245 @@not32bit:
55246 TEST EAX, EAX
55247 JZ @@exit
55249 PUSH ECX
55250 XCHG ECX, EAX
55251 MOV EAX, ESP
55252 MOV EDX, EBX
55253 CALL ECX
55255 POP EDI
55256 MOV EAX, [EBX].TBitmap.fWidth
55257 CMP EAX, [EDI].TBitmap.fHeight
55258 JGE @@noCutHeight
55260 MOV EDX, [EDI].TBitmap.fScanLineSize
55261 MUL EDX
55262 MOV [EDI].TBitmap.fDIBSize, EAX
55264 MOV EDX, [EDI].TBitmap.fDIBHeader
55265 MOV EDX, [EDX].TBitmapInfoHeader.biHeight
55266 TEST EDX, EDX
55267 JL @@noCorrectImg
55269 PUSH EAX
55271 MOV EDX, [EDI].TBitmap.fHeight
55272 DEC EDX
55273 MOV EAX, EDI
55274 CALL TBitmap.GetScanLine
55275 PUSH EAX
55277 MOV EDX, [EBX].TBitmap.fWidth
55278 DEC EDX
55279 MOV EAX, EDI
55280 CALL TBitmap.GetScanLine
55281 POP EDX
55283 POP ECX
55284 CALL System.Move
55286 @@noCorrectImg:
55287 MOV EAX, [EBX].TBitmap.fWidth
55288 MOV [EDI].TBitmap.fHeight, EAX
55289 MOV EDX, [EDI].TBitmap.fDIBHeader
55290 MOV [EDX].TBitmapInfoHeader.biHeight, EAX
55292 @@noCutHeight:
55293 MOV EAX, EBX
55294 CALL TBitmap.ClearData
55296 XOR EAX, EAX
55297 XCHG EAX, [EDI].TBitmap.fDIBHeader
55298 XCHG [EBX].TBitmap.fDIBHeader, EAX
55300 XCHG EAX, [EDI].TBitmap.fDIBBits
55301 XCHG [EBX].TBitmap.fDIBBits, EAX
55303 MOV AL, [EDI].TBitmap.fDIBAutoFree
55304 MOV [EBX].TBitmap.fDIBAutoFree, AL
55306 MOV EAX, [EDI].TBitmap.fDIBSize
55307 MOV [EBX].TBitmap.fDIBSize, EAX
55309 MOV EAX, [EDI].TBitmap.fWidth
55310 MOV [EBX].TBitmap.fWidth, EAX
55312 MOV EAX, [EDI].TBitmap.fHeight
55313 MOV [EBX].TBitmap.fHeight, EAX
55315 XCHG EAX, EDI
55316 CALL TObj.Free
55317 @@exit:
55318 POP EDI
55319 POP EBX
55320 end;
55321 {$ELSE ASM_VERSION} //Pascal
55322 procedure _RotateBitmapRight( SrcBmp: PBitmap );
55323 var DstBmp: PBitmap;
55324 RotateProc: procedure( var DstBmp: PBitmap; SrcBmp: PBitmap );
55325 begin
55326 if SrcBmp.fHandleType <> bmDIB then Exit;
55328 case SrcBmp.PixelFormat of
55329 pf1bit: RotateProc := RotateProcs.proc_RotateBitmapMono;
55330 pf4bit: RotateProc := RotateProcs.proc_RotateBitmap4bit;
55331 pf8bit: RotateProc := RotateProcs.proc_RotateBitmap8bit;
55332 pf15bit, pf16bit: RotateProc := RotateProcs.proc_RotateBitmap16bit;
55333 else RotateProc := RotateProcs.proc_RotateBitmap2432bit;
55334 end;
55336 if not Assigned( RotateProc ) then Exit;
55337 RotateProc( DstBmp, SrcBmp );
55339 if DstBmp.fHeight > SrcBmp.fWidth then
55340 begin
55341 DstBmp.fDIBSize := DstBmp.fScanLineSize * SrcBmp.fWidth;
55342 //if DWORD( DstBmp.ScanLine[ 0 ] ) > DWORD( DstBmp.ScanLine[ 1 ] ) then
55343 if DstBmp.fDIBHeader.bmiHeader.biHeight > 0 then
55344 Move( DstBmp.ScanLine[ SrcBmp.fWidth - 1 ]^, DstBmp.ScanLine[ DstBmp.fHeight - 1 ]^,
55345 DstBmp.fDIBSize );
55346 DstBmp.fHeight := SrcBmp.fWidth;
55347 DstBmp.fDIBHeader.bmiHeader.biHeight := DstBmp.fHeight;
55348 end;
55350 SrcBmp.ClearData;
55352 //SrcBmp.fNewPixelFormat := DstBmp.PixelFormat;
55353 SrcBmp.fDIBHeader := DstBmp.fDIBHeader;
55354 DstBmp.fDIBHeader := nil;
55356 SrcBmp.fDIBBits := DstBmp.fDIBBits;
55357 DstBmp.fDIBBits := nil;
55358 SrcBmp.fDIBAutoFree := DstBmp.fDIBAutoFree;
55360 SrcBmp.fDIBSize := DstBmp.fDIBSize;
55362 SrcBmp.fWidth := DstBmp.fWidth;
55363 SrcBmp.fHeight := DstBmp.fHeight;
55364 DstBmp.Free;
55365 end;
55366 {$ENDIF ASM_VERSION}
55367 //[END _RotateBitmapRight]
55369 //[procedure TBitmap.RotateRight]
55370 procedure TBitmap.RotateRight;
55371 const AllRotators: TRotateBmpRefs = (
55372 proc_RotateBitmapMono: _RotateBitmapMono;
55373 proc_RotateBitmap4bit: _RotateBitmap4bit;
55374 proc_RotateBitmap8bit: _RotateBitmap8bit;
55375 proc_RotateBitmap16bit: _RotateBitmap16bit;
55376 proc_RotateBitmap2432bit: _RotateBitmap2432bit );
55377 begin
55378 RotateProcs := AllRotators;
55379 _RotateBitmapRight( @Self );
55380 end;
55382 //[procedure _RotateBitmapLeft]
55383 procedure _RotateBitmapLeft( Src: PBitmap );
55384 begin
55385 _RotateBitmapRight( Src );
55386 _RotateBitmapRight( Src );
55387 _RotateBitmapRight( Src );
55388 end;
55390 //[procedure TBitmap.RotateLeft]
55391 procedure TBitmap.RotateLeft;
55392 begin
55393 RotateRight;
55394 _RotateBitmapRight( @Self );
55395 _RotateBitmapRight( @Self );
55396 end;
55398 //[procedure TBitmap.RotateLeftMono]
55399 procedure TBitmap.RotateLeftMono;
55400 begin
55401 if PixelFormat <> pf1bit then Exit;
55402 RotateProcs.proc_RotateBitmapMono := _RotateBitmapMono;
55403 _RotateBitmapRight( @Self );
55404 end;
55406 //[procedure TBitmap.RotateRightMono]
55407 procedure TBitmap.RotateRightMono;
55408 begin
55409 if PixelFormat <> pf1bit then Exit;
55410 RotateProcs.proc_RotateBitmapMono := _RotateBitmapMono;
55411 _RotateBitmapLeft( @Self );
55412 end;
55414 //[procedure TBitmap.RotateLeft16bit]
55415 procedure TBitmap.RotateLeft16bit;
55416 begin
55417 if PixelFormat <> pf16bit then Exit;
55418 RotateProcs.proc_RotateBitmap16bit := _RotateBitmap16bit;
55419 _RotateBitmapLeft( @Self );
55420 end;
55422 //[procedure TBitmap.RotateLeft4bit]
55423 procedure TBitmap.RotateLeft4bit;
55424 begin
55425 if PixelFormat <> pf4bit then Exit;
55426 RotateProcs.proc_RotateBitmap4bit := _RotateBitmap4bit;
55427 _RotateBitmapLeft( @Self );
55428 end;
55430 //[procedure TBitmap.RotateLeft8bit]
55431 procedure TBitmap.RotateLeft8bit;
55432 begin
55433 if PixelFormat <> pf8bit then Exit;
55434 RotateProcs.proc_RotateBitmap8bit := _RotateBitmap8bit;
55435 _RotateBitmapLeft( @Self );
55436 end;
55438 //[procedure TBitmap.RotateLeftTrueColor]
55439 procedure TBitmap.RotateLeftTrueColor;
55440 begin
55441 if not (PixelFormat in [ pf24bit, pf32bit ]) then Exit;
55442 RotateProcs.proc_RotateBitmap2432bit := _RotateBitmap2432bit;
55443 _RotateBitmapLeft( @Self );
55444 end;
55446 //[procedure TBitmap.RotateRight16bit]
55447 procedure TBitmap.RotateRight16bit;
55448 begin
55449 if PixelFormat <> pf16bit then Exit;
55450 RotateProcs.proc_RotateBitmap16bit := _RotateBitmap16bit;
55451 _RotateBitmapRight( @Self );
55452 end;
55454 //[procedure TBitmap.RotateRight4bit]
55455 procedure TBitmap.RotateRight4bit;
55456 begin
55457 if PixelFormat <> pf4bit then Exit;
55458 RotateProcs.proc_RotateBitmap4bit := _RotateBitmap4bit;
55459 _RotateBitmapRight( @Self );
55460 end;
55462 //[procedure TBitmap.RotateRight8bit]
55463 procedure TBitmap.RotateRight8bit;
55464 begin
55465 if PixelFormat <> pf8bit then Exit;
55466 RotateProcs.proc_RotateBitmap8bit := _RotateBitmap8bit;
55467 _RotateBitmapRight( @Self );
55468 end;
55470 //[procedure TBitmap.RotateRightTrueColor]
55471 procedure TBitmap.RotateRightTrueColor;
55472 begin
55473 if not (PixelFormat in [ pf24bit, pf32bit ]) then Exit;
55474 RotateProcs.proc_RotateBitmap2432bit := _RotateBitmap2432bit;
55475 _RotateBitmapRight( @Self );
55476 end;
55478 {$IFDEF ASM_VERSION}
55479 //[function TBitmap.GetPixels]
55480 function TBitmap.GetPixels(X, Y: Integer): TColor;
55482 PUSH EBX
55483 MOV EBX, EAX
55484 PUSH ECX
55485 PUSH EDX
55486 CALL GetEmpty
55487 PUSHFD
55488 OR EAX, -1
55489 POPFD
55490 JZ @@exit
55492 CALL StartDC
55493 PUSH dword ptr [ESP+12]
55494 PUSH dword ptr [ESP+12]
55495 PUSH EAX
55496 CALL Windows.GetPixel
55497 XCHG EBX, EAX
55498 CALL FinishDC
55499 XCHG EAX, EBX
55500 @@exit:
55501 POP EDX
55502 POP EDX
55503 POP EBX
55504 end;
55505 {$ELSE ASM_VERSION} //Pascal
55506 function TBitmap.GetPixels(X, Y: Integer): TColor;
55507 var DC: HDC;
55508 Save: THandle;
55509 begin
55510 Result := clNone;
55511 //if GetHandle = 0 then Exit;
55512 if Empty then Exit;
55513 fDetachCanvas( @Self );
55514 DC := CreateCompatibleDC( 0 );
55515 Save := SelectObject( DC, GetHandle );
55516 ASSERT( Save <> 0, 'Can not select bitmap to DC' );
55517 Result := Windows.GetPixel( DC, X, Y );
55518 SelectObject( DC, Save );
55519 DeleteDC( DC );
55520 end;
55521 {$ENDIF ASM_VERSION}
55523 {$IFDEF ASM_VERSION}
55524 //[procedure TBitmap.SetPixels]
55525 procedure TBitmap.SetPixels(X, Y: Integer; const Value: TColor);
55527 PUSH EBX
55528 MOV EBX, EAX
55529 PUSH ECX
55530 PUSH EDX
55531 CALL GetEmpty
55532 JZ @@exit
55534 CALL StartDC
55535 MOV EAX, Value
55536 CALL Color2RGB
55537 PUSH EAX
55538 PUSH dword ptr [ESP+16]
55539 PUSH dword ptr [ESP+16]
55540 PUSH dword ptr [ESP+16]
55541 CALL Windows.SetPixel
55542 CALL FinishDC
55543 @@exit:
55544 POP EDX
55545 POP ECX
55546 POP EBX
55547 end;
55548 {$ELSE ASM_VERSION} //Pascal
55549 procedure TBitmap.SetPixels(X, Y: Integer; const Value: TColor);
55550 var DC: HDC;
55551 Save: THandle;
55552 begin
55553 //if GetHandle = 0 then Exit;
55554 if Empty then Exit;
55555 fDetachCanvas( @Self );
55556 DC := CreateCompatibleDC( 0 );
55557 Save := SelectObject( DC, GetHandle );
55558 ASSERT( Save <> 0, 'Can not select bitmap to DC' );
55559 Windows.SetPixel( DC, X, Y, Color2RGB( Value ) );
55560 SelectObject( DC, Save );
55561 DeleteDC( DC );
55562 end;
55563 {$ENDIF ASM_VERSION}
55565 //[FUNCTION _GetDIBPixelsPalIdx]
55566 {$IFDEF ASM_VERSION}
55567 function _GetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer ): TColor;
55568 const szBIH = Sizeof(TBitmapInfoHeader);
55570 PUSH EBX
55571 PUSH EDI
55572 PUSH EDX
55573 XCHG EBX, EAX
55575 XCHG EAX, EDX
55576 MOV EDI, [EBX].TBitmap.fPixelsPerByteMask
55577 INC EDI
55579 DIV EDI
55580 DEC EDI
55581 XCHG ECX, EAX // EAX = Y, ECX = X div (Bmp.fPixeldPerByteMask+1)
55583 MOV EDX, [EBX].TBitmap.fScanLineDelta
55584 IMUL EDX
55586 ADD EAX, [EBX].TBitmap.fScanLine0
55587 MOVZX EAX, byte ptr[EAX+ECX]
55589 POP EDX
55590 MOV ECX, [EBX].TBitmap.fPixelsPerByteMask
55591 AND EDX, ECX
55592 SUB ECX, EDX
55594 PUSH EAX
55595 MOV EDI, [EBX].TBitmap.fDIBHeader
55596 MOVZX EAX, [EDI].TBitmapInfoHeader.biBitCount
55597 MUL ECX
55598 XCHG ECX, EAX
55599 POP EAX
55600 SHR EAX, CL
55601 AND EAX, [EBX].TBitmap.fPixelMask
55603 MOV EAX, [EDI+szBIH+EAX*4]
55604 CALL Color2RGBQuad
55606 POP EDI
55607 POP EBX
55608 end;
55609 {$ELSE ASM_VERSION} //Pascal
55610 function _GetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer ): TColor;
55611 var Pixel: Byte;
55612 begin
55613 Pixel := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta
55614 + (X div (Bmp.fPixelsPerByteMask + 1)) )^;
55615 Pixel := ( Pixel shr ( (Bmp.fPixelsPerByteMask - (X and Bmp.fPixelsPerByteMask))
55616 * Bmp.fDIBHeader.bmiHeader.biBitCount ) )
55617 and Bmp.fPixelMask;
55618 Result := TColor( Color2RGBQuad( TColor( PRGBQuad( DWORD(@Bmp.fDIBHeader.bmiColors[ 0 ])
55619 + Pixel * Sizeof( TRGBQuad ) )^ ) ) );
55620 end;
55621 {$ENDIF ASM_VERSION}
55622 //[END _GetDIBPixelsPalIdx]
55624 //[FUNCTION _GetDIBPixels16bit]
55625 {$IFDEF ASM_VERSION}
55626 function _GetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer ): TColor;
55628 PUSH [EAX].TBitmap.fPixelMask
55629 PUSH EDX // X
55630 PUSH EAX
55631 MOV EAX, [EAX].TBitmap.fScanLineDelta
55632 IMUL ECX
55633 POP EDX
55634 ADD EAX, [EDX].TBitmap.fScanLine0
55635 POP ECX
55636 MOVZX EAX, word ptr [EAX+ECX*2]
55637 POP EDX
55638 CMP DL, 15
55639 JNE @@16bit
55641 MOV EDX, EAX
55642 SHR EDX, 7
55643 SHL EAX, 6
55644 MOV DH, AH
55645 AND DH, $F8
55646 SHL EAX, 13
55647 JMP @@1516bit
55649 @@16bit:
55650 MOV DL, AH
55651 SHL EAX, 5
55652 MOV DH, AH
55653 SHL EAX, 14
55654 @@1516bit:
55655 AND EAX, $F80000
55656 OR EAX, EDX
55657 AND AX, $FCF8
55658 end;
55659 {$ELSE ASM_VERSION} //Pascal
55660 function _GetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer ): TColor;
55661 var Pixel: Word;
55662 begin
55663 Pixel := PWord( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X * 2 )^;
55664 if Bmp.fPixelMask = 15 then
55665 Result := (Pixel shr 7) and $F8 or (Pixel shl 6) and $F800
55666 or (Pixel shl 19) and $F80000
55667 else
55668 Result := (Pixel shr 8) and $F8 or (Pixel shl 5) and $FC00
55669 or (Pixel shl 19) and $F80000;
55670 end;
55671 {$ENDIF ASM_VERSION}
55672 //[END _GetDIBPixels16bit]
55674 //[FUNCTION _GetDIBPixelsTrueColor]
55675 {$IFDEF ASM_VERSION}
55676 function _GetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer ): TColor;
55678 PUSH EBX
55679 XCHG EBX, EAX
55680 PUSH EDX
55681 MOV EAX, [EBX].TBitmap.fScanLineDelta
55682 IMUL ECX
55683 XCHG ECX, EAX
55684 POP EDX
55685 MOV EAX, [EBX].TBitmap.fBytesPerPixel
55686 MUL EDX
55687 ADD EAX, [EBX].TBitmap.fScanLine0
55688 MOV EAX, [EAX+ECX]
55689 AND EAX, $FFFFFF
55690 CALL Color2RGBQuad
55691 POP EBX
55692 end;
55693 {$ELSE ASM_VERSION} //Pascal
55694 function _GetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer ): TColor;
55695 var Pixel: DWORD;
55696 begin
55697 Pixel := PDWORD( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta +
55698 X * Bmp.fBytesPerPixel )^ and $FFFFFF;
55699 Result := TColor( Color2RGBQuad( TColor( Pixel ) ) );
55700 end;
55701 {$ENDIF ASM_VERSION}
55702 //[END _GetDIBPixelsTrueColor]
55704 {$IFDEF ASM_VERSION}
55705 //[function TBitmap.GetDIBPixels]
55706 function TBitmap.GetDIBPixels(X, Y: Integer): TColor;
55708 CMP word ptr [EAX].fGetDIBPixels+2, 0
55709 JNZ @@assigned
55711 // if not assigned, this preparing will be performed for first call:
55712 CMP [EAX].fHandleType, bmDDB
55713 JZ @@GetPixels
55715 PUSHAD
55716 MOV EBX, EAX
55717 XOR EDX, EDX
55718 CALL GetScanLine
55719 MOV [EBX].fScanLine0, EAX
55720 XOR EDX, EDX
55721 INC EDX
55722 MOV EAX, EBX
55723 CALL GetScanLine
55724 SUB EAX, [EBX].fScanLine0
55725 MOV [EBX].fScanLineDelta, EAX
55726 MOV EAX, EBX
55727 CALL GetPixelFormat
55728 MOVZX ECX, AL
55729 MOV DX, $0F00
55730 MOV byte ptr [EBX].fBytesPerPixel, 4
55731 XOR EAX, EAX
55732 LOOP @@if4bit
55733 MOV DX, $0107
55734 JMP @@1bit4bit8bit
55735 @@if4bit:
55736 LOOP @@if8bit
55737 INC EDX // MOV DX, $0F01
55738 JMP @@1bit4bit8bit
55739 @@if8bit:
55740 LOOP @@if15bit
55741 MOV DH, $FF //MOV DX, $FF00
55742 @@1bit4bit8bit:
55743 MOV EAX, offset[_GetDIBPixelsPalIdx]
55744 @@if15bit:
55745 LOOP @@if16bit
55746 //MOV DH, $0F
55747 DEC DH
55748 INC ECX
55749 @@if16bit:
55750 LOOP @@if24bit
55751 INC DH
55752 MOV EAX, offset[_GetDIBPixels16bit]
55753 @@if24bit:
55754 LOOP @@if32bit
55755 DEC [EBX].fBytesPerPixel
55756 INC ECX
55757 DEC EDX
55758 @@if32bit:
55759 LOOP @@iffin
55760 INC EDX
55761 MOV EAX, offset[_GetDIBPixelsTrueColor]
55762 @@iffin:
55763 MOV byte ptr [EBX].fPixelMask, DH
55764 MOV byte ptr [EBX].fPixelsPerByteMask, DL
55765 MOV [EBX].fGetDIBPixels, EAX
55766 TEST EAX, EAX
55767 POPAD
55768 @@GetPixels:
55769 JZ GetPixels
55771 @@assigned:
55772 JMP [EAX].fGetDIBPixels
55773 end;
55774 {$ELSE ASM_VERSION} //Pascal
55775 function TBitmap.GetDIBPixels(X, Y: Integer): TColor;
55776 begin
55777 if not Assigned( fGetDIBPixels ) then
55778 begin
55779 if fHandleType = bmDIB then
55780 begin
55781 fScanLine0 := ScanLine[ 0 ];
55782 fScanLineDelta := Integer(ScanLine[ 1 ]) - Integer(fScanLine0);
55783 case PixelFormat of
55784 pf1bit:
55785 begin
55786 fPixelMask := $01;
55787 fPixelsPerByteMask := 7;
55788 fGetDIBPixels := _GetDIBPixelsPalIdx;
55789 end;
55790 pf4bit:
55791 begin
55792 fPixelMask := $0F;
55793 fPixelsPerByteMask := 1;
55794 fGetDIBPixels := _GetDIBPixelsPalIdx;
55795 end;
55796 pf8bit:
55797 begin
55798 fPixelMask := $FF;
55799 fPixelsPerByteMask := 0;
55800 fGetDIBPixels := _GetDIBPixelsPalIdx;
55801 end;
55802 pf15bit:
55803 begin
55804 fPixelMask := 15;
55805 fGetDIBPixels := _GetDIBPixels16bit;
55806 end;
55807 pf16bit:
55808 begin
55809 fPixelMask := 16;
55810 fGetDIBPixels := _GetDIBPixels16bit;
55811 end;
55812 pf24bit:
55813 begin
55814 fPixelsPerByteMask := 0;
55815 fBytesPerPixel := 3;
55816 fGetDIBPixels := _GetDIBPixelsTrueColor;
55817 end;
55818 pf32bit:
55819 begin
55820 fPixelsPerByteMask := 1;
55821 fBytesPerPixel := 4;
55822 fGetDIBPixels := _GetDIBPixelsTrueColor;
55823 end;
55824 else;
55825 end;
55826 end;
55827 if not Assigned( fGetDIBPixels ) then
55828 begin
55829 Result := Pixels[ X, Y ];
55830 Exit;
55831 end;
55832 end;
55833 Result := fGetDIBPixels( @Self, X, Y );
55834 end;
55835 {$ENDIF ASM_VERSION}
55837 //[PROCEDURE _SetDIBPixels1bit]
55838 {$IFDEF ASM_VERSION}
55839 procedure _SetDIBPixels1bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
55841 PUSH EDX
55842 PUSH [EAX].TBitmap.fScanLine0
55843 PUSH ECX
55844 PUSH [EAX].TBitmap.fScanLineDelta
55845 MOV EAX, Value
55846 CALL Color2RGB
55847 MOV EDX, EAX
55848 SHR EAX, 16
55849 ADD AL, DL
55850 ADC AL, DH
55851 CMP EAX, 170
55852 SETGE CL
55853 AND ECX, 1
55854 SHL ECX, 7
55855 POP EAX
55856 POP EDX
55857 IMUL EDX
55858 POP EDX
55859 ADD EAX, EDX
55860 POP EDX
55861 PUSH ECX
55862 MOV ECX, EDX
55863 SHR EDX, 3
55864 ADD EAX, EDX
55865 AND ECX, 7
55866 MOV DX, $FF7F
55867 SHR EDX, CL
55868 AND byte ptr [EAX], DL
55869 POP EDX
55870 SHR EDX, CL
55871 OR byte ptr [EAX], DL
55872 end;
55873 {$ELSE ASM_VERSION} //Pascal
55874 procedure _SetDIBPixels1bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
55875 var Pixel: Byte;
55876 Pos: PByte;
55877 Shf: Integer;
55878 begin
55879 Value := Color2RGB( Value );
55880 if ((Value shr 16) and $FF) + ((Value shr 8) and $FF) + (Value and $FF)
55881 < 255 * 3 div 2 then Pixel := 0 else Pixel := $80;
55882 Pos := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X div 8 );
55883 Shf := X and 7;
55884 Pos^ := Pos^ and ($FF7F shr Shf) or (Pixel shr Shf);
55885 end;
55886 {$ENDIF ASM_VERSION}
55887 //[END _SetDIBPixels1bit]
55889 //[PROCEDURE _SetDIBPixelsPalIdx]
55890 {$IFDEF ASM_VERSION}
55891 procedure _SetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer; Value: TColor );
55893 XCHG EAX, EBP
55894 PUSH EDX // -> X
55895 PUSH ECX // -> Y
55896 MOV ECX, [EBP].TBitmap.fPixelsPerByteMask
55897 INC ECX
55898 XCHG EAX, EDX
55900 DIV ECX
55901 XCHG ECX, EAX // ECX = X div (fPixelsPerByteMask+1)
55902 POP EAX // <- Y
55903 MOV EDX, [EBP].TBitmap.fScanLineDelta
55904 IMUL EDX
55905 ADD ECX, EAX
55906 ADD ECX, [EBP].TBitmap.fScanLine0 // ECX = Pos
55907 PUSH ECX // -> Pos
55909 MOV EDX, [ESP+16] // Value
55910 MOV EAX, EBP
55911 CALL TBitmap.DIBPalNearestEntry // EAX = Pixel
55913 POP ECX // <- Pos
55914 POP EDX // <- X
55916 PUSH EAX // -> Pixel
55918 MOV EAX, [EBP].TBitmap.fPixelsPerByteMask
55919 AND EDX, EAX
55920 SUB EAX, EDX
55921 MOV EDX, [EBP].TBitmap.fDIBHeader
55922 MOVZX EDX, [EDX].TBitmapInfoHeader.biBitCount
55923 MUL EDX // EAX = Shf
55925 XCHG ECX, EAX // ECX = Shf, EAX = Pos
55926 MOV EDX, [EBP].TBitmap.fPixelMask
55927 SHL EDX, CL
55928 NOT EDX
55929 AND byte ptr [EAX], DL
55931 POP EDX // <- Pixel
55932 SHL EDX, CL
55933 OR byte ptr [EAX], DL
55934 end;
55935 {$ELSE ASM_VERSION} //Pascal
55936 procedure _SetDIBPixelsPalIdx( Bmp: PBitmap; X, Y: Integer; Value: TColor );
55937 var Pixel: Byte;
55938 Pos: PByte;
55939 Shf: Integer;
55940 begin
55941 Pixel := Bmp.DIBPalNearestEntry( Value );
55942 Pos := PByte( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta
55943 + X div (Bmp.fPixelsPerByteMask + 1) );
55944 Shf := (Bmp.fPixelsPerByteMask - (X and Bmp.fPixelsPerByteMask))
55945 * Bmp.fDIBHeader.bmiHeader.biBitCount;
55946 Pos^ := Pos^ and not (Bmp.fPixelMask shl Shf) or (Pixel shl Shf);
55947 end;
55948 {$ENDIF ASM_VERSION}
55949 //[END _SetDIBPixelsPalIdx]
55951 //[PROCEDURE _SetDIBPixels16bit]
55952 {$IFDEF ASM_VERSION}
55953 procedure _SetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
55955 ADD EDX, EDX
55956 ADD EDX, [EAX].TBitmap.fScanLine0
55957 PUSH EDX // -> X*2 + Bmp.fScanLine0
55958 PUSH [EAX].TBitmap.fPixelMask
55959 MOV EAX, [EAX].TBitmap.fScanLineDelta
55960 IMUL ECX
55961 PUSH EAX // -> Y* Bmp.fScanLineDelta
55962 MOV EAX, Value
55963 CALL Color2RGB
55964 POP EBP // <- Y* Bmp.fScanLineDelta
55965 POP EDX
55966 XOR ECX, ECX
55967 SUB DL, 16
55968 JZ @@16bit
55970 MOV CH, AL
55971 SHR CH, 1
55972 SHR EAX, 6
55973 MOV EDX, EAX
55974 AND DX, $3E0
55975 SHR EAX, 13
55976 JMP @@1516
55978 @@16bit:
55979 {$IFDEF PARANOIA}
55980 DB $24, $F8
55981 {$ELSE}
55982 AND AL, $F8
55983 {$ENDIF}
55984 MOV CH, AL
55985 SHR EAX, 5
55986 MOV EDX, EAX
55987 AND DX, $7E0
55988 SHR EAX, 14
55990 @@1516:
55991 MOV AH, CH
55992 AND AX, $FC1F
55993 OR AX, DX
55995 POP EDX
55996 MOV [EBP+EDX], AX
55997 end;
55998 {$ELSE ASM_VERSION} //Pascal
55999 procedure _SetDIBPixels16bit( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56000 var RGB16: Word;
56001 Pos: PWord;
56002 begin
56003 Value := Color2RGB( Value );
56004 if Bmp.fPixelMask = 15 then
56005 RGB16 := (Value shr 19) and $001F or (Value shr 6) and $03E0
56006 or (Value shl 7) and $7C00
56007 else
56008 RGB16 := (Value shr 19) and $001F or (Value shr 5) and $07E0
56009 or (Value shl 8) and $F800;
56010 Pos := PWord( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta + X * 2 );
56011 Pos^ := RGB16;
56012 end;
56013 {$ENDIF ASM_VERSION}
56014 //[END _SetDIBPixels16bit]
56016 //[PROCEDURE _SetDIBPixelsTrueColor]
56017 {$IFDEF ASM_VERSION}
56018 procedure _SetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56020 PUSH [EAX].TBitmap.fScanLineDelta
56021 PUSH [EAX].TBitmap.fScanLine0
56022 MOV EAX, [EAX].TBitmap.fBytesPerPixel
56023 MUL EDX
56024 POP EDX
56025 ADD EDX, EAX
56026 POP EAX
56027 PUSH EDX
56028 IMUL ECX
56029 POP EDX
56030 ADD EDX, EAX
56031 PUSH EDX
56032 MOV EAX, Value
56033 CALL Color2RGBQuad
56034 POP EDX
56035 AND dword ptr [EDX], $FF000000
56036 OR [EDX], EAX
56037 end;
56038 {$ELSE ASM_VERSION} //Pascal
56039 procedure _SetDIBPixelsTrueColor( Bmp: PBitmap; X, Y: Integer; Value: TColor );
56040 var RGB: TRGBQuad;
56041 Pos: PDWord;
56042 begin
56043 //Value := Color2RGB( Value );
56044 RGB := Color2RGBQuad( Value );
56045 Pos := PDWORD( Integer(Bmp.fScanLine0) + Y * Bmp.fScanLineDelta
56046 + X * Bmp.fBytesPerPixel );
56047 Pos^ := Pos^ and $FF000000 or DWORD(RGB);
56048 end;
56049 {$ENDIF ASM_VERSION}
56050 //[END _SetDIBPixelsTrueColor]
56052 {$IFDEF ASM_VERSION}
56053 //[procedure TBitmap.SetDIBPixels]
56054 procedure TBitmap.SetDIBPixels(X, Y: Integer; const Value: TColor);
56056 CMP word ptr [EAX].fSetDIBPixels+2, 0
56057 JNZ @@assigned
56058 PUSHAD
56059 MOV EBX, EAX
56060 XOR EDX, EDX
56061 CMP [EBX].fHandleType, DL // bmDIB = 0
56062 JNE @@ddb
56063 CALL GetScanLine
56064 MOV [EBX].fScanLine0, EAX
56065 XOR EDX, EDX
56066 INC EDX
56067 MOV EAX, EBX
56068 CALL GetScanLine
56069 SUB EAX, [EBX].fScanLine0
56070 MOV [EBX].fScanLineDelta, EAX
56071 MOV EAX, EBX
56072 CALL GetPixelFormat
56073 MOVZX ECX, AL
56074 MOV DX, $0F01
56075 MOV EAX, offset[_SetDIBPixelsPalIdx]
56076 MOV byte ptr [EBX].fBytesPerPixel, 4
56077 LOOP @@if4bit
56078 MOV EAX, offset[_SetDIBPixels1bit]
56079 @@if4bit:
56080 LOOP @@if8bit
56081 @@if8bit:
56082 LOOP @@if15bit
56083 DEC DL
56084 MOV DH, $FF
56085 @@if15bit:
56086 LOOP @@if16bit
56087 DEC DH
56088 INC ECX
56089 @@if16bit:
56090 LOOP @@if24bit
56091 INC DH
56092 MOV EAX, offset[_SetDIBPixels16bit]
56093 @@if24bit:
56094 LOOP @@if32bit
56095 DEC EDX
56096 DEC [EBX].fBytesPerPixel
56097 INC ECX
56098 @@if32bit:
56099 LOOP @@ifend
56100 INC EDX
56101 MOV EAX, offset[_SetDIBPixelsTrueColor]
56102 @@ifend:
56103 MOV byte ptr [EBX].fPixelMask, DH
56104 MOV byte ptr [EBX].fPixelsPerByteMask, DL
56105 MOV [EBX].fSetDIBPixels, EAX
56106 TEST EAX, EAX
56107 @@ddb:
56108 POPAD
56109 JNZ @@assigned
56110 PUSH Value
56111 CALL SetPixels
56112 JMP @@exit
56113 @@assigned:
56114 PUSH Value
56115 CALL [EAX].fSetDIBPixels
56116 @@exit:
56117 end;
56118 {$ELSE ASM_VERSION} //Pascal
56119 procedure TBitmap.SetDIBPixels(X, Y: Integer; const Value: TColor);
56120 begin
56121 if not Assigned( fSetDIBPixels ) then
56122 begin
56123 if fHandleType = bmDIB then
56124 begin
56125 fScanLine0 := ScanLine[ 0 ];
56126 fScanLineDelta := Integer(ScanLine[ 1 ]) - Integer(fScanLine0);
56127 case PixelFormat of
56128 pf1bit:
56129 begin
56130 //fPixelMask := $01;
56131 //fPixelsPerByteMask := 7;
56132 fSetDIBPixels := _SetDIBPixels1bit;
56133 end;
56134 pf4bit:
56135 begin
56136 fPixelMask := $0F;
56137 fPixelsPerByteMask := 1;
56138 fSetDIBPixels := _SetDIBPixelsPalIdx;
56139 end;
56140 pf8bit:
56141 begin
56142 fPixelMask := $FF;
56143 fPixelsPerByteMask := 0;
56144 fSetDIBPixels := _SetDIBPixelsPalIdx;
56145 end;
56146 pf15bit:
56147 begin
56148 fPixelMask := 15;
56149 fSetDIBPixels := _SetDIBPixels16bit;
56150 end;
56151 pf16bit:
56152 begin
56153 fPixelMask := 16;
56154 fSetDIBPixels := _SetDIBPixels16bit;
56155 end;
56156 pf24bit:
56157 begin
56158 fPixelsPerByteMask := 0;
56159 fBytesPerPixel := 3;
56160 fSetDIBPixels := _SetDIBPixelsTrueColor;
56161 end;
56162 pf32bit:
56163 begin
56164 fPixelsPerByteMask := 1;
56165 fBytesPerPixel := 4;
56166 fSetDIBPixels := _SetDIBPixelsTrueColor;
56167 end;
56168 else;
56169 end;
56170 end;
56171 if not Assigned( fSetDIBPixels ) then
56172 begin
56173 Pixels[ X, Y ] := Value;
56174 Exit;
56175 end;
56176 end;
56177 fSetDIBPixels( @Self, X, Y, Value );
56178 end;
56179 {$ENDIF ASM_VERSION}
56181 {$IFDEF ASM_VERSION}
56182 //[procedure TBitmap.FlipVertical]
56183 procedure TBitmap.FlipVertical;
56185 PUSH EBX
56186 MOV EBX, EAX
56187 MOV ECX, [EBX].fHandle
56188 JECXZ @@noHandle
56190 CALL StartDC
56191 PUSH SrcCopy
56192 MOV EDX, [EBX].fHeight
56193 PUSH EDX
56194 MOV ECX, [EBX].fWidth
56195 PUSH ECX
56196 PUSH 0
56197 PUSH 0
56198 PUSH EAX
56199 NEG EDX
56200 PUSH EDX
56201 PUSH ECX
56202 NEG EDX
56203 DEC EDX
56204 PUSH EDX
56205 PUSH 0
56206 PUSH EAX
56207 CALL StretchBlt
56208 CALL FinishDC
56209 POP EBX
56212 @@noHandle:
56213 MOV ECX, [EBX].fDIBBits
56214 JECXZ @@exit
56216 PUSHAD //----------------------------------------\
56217 XOR EBP, EBP // Y = 0
56218 //+++++++++++++++++++++++++++ provide fScanLineSize
56219 MOV EAX, EBX
56220 MOV EDX, EBP
56221 CALL GetScanLine //
56222 SUB ESP, [EBX].fScanLineSize
56224 @@loo: LEA EAX, [EBP*2]
56225 CMP EAX, [EBX].fHeight
56226 JG @@finloo
56228 MOV EAX, EBX
56229 MOV EDX, EBP
56230 CALL GetScanLine
56231 MOV ESI, EAX // ESI = ScanLine[ Y ]
56232 MOV EDX, ESP
56233 MOV ECX, [EBX].fScanLineSize
56234 PUSH ECX
56235 CALL System.Move
56237 MOV EAX, EBX
56238 MOV EDX, [EBX].fHeight
56239 SUB EDX, EBP
56240 DEC EDX
56241 CALL GetScanLine
56242 MOV EDI, EAX
56243 MOV EDX, ESI
56244 POP ECX
56245 PUSH ECX
56246 CALL System.Move
56248 POP ECX
56249 MOV EAX, ESP
56250 MOV EDX, EDI
56251 CALL System.Move
56253 INC EBP
56254 JMP @@loo
56256 @@finloo:
56257 ADD ESP, [EBX].fScanLineSize
56258 POPAD
56259 @@exit:
56260 POP EBX
56261 end;
56262 {$ELSE ASM_VERSION} //Pascal
56263 procedure TBitmap.FlipVertical;
56264 var DC: HDC;
56265 Save: THandle;
56266 TmpScan: PByte;
56267 Y: Integer;
56268 begin
56269 if fHandle <> 0 then
56270 begin
56271 fDetachCanvas( @Self );
56272 DC := CreateCompatibleDC( 0 );
56273 Save := SelectObject( DC, fHandle );
56274 StretchBlt( DC, 0, fHeight - 1, fWidth, -fHeight, DC, 0, 0, fWidth, fHeight, SRCCOPY );
56275 SelectObject( DC, Save );
56276 DeleteDC( DC );
56278 else
56279 if fDIBBits <> nil then
56280 begin
56281 GetMem( TmpScan, ScanLineSize );
56282 for Y := 0 to fHeight div 2 do
56283 begin
56284 Move( ScanLine[ Y ]^, TmpScan^, fScanLineSize );
56285 Move( ScanLine[ fHeight - Y - 1 ]^, ScanLine[ Y ]^, fScanLineSize );
56286 Move( TmpScan^, ScanLine[ fHeight - Y - 1 ]^, fScanLineSize );
56287 end;
56288 end;
56289 end;
56290 {$ENDIF ASM_VERSION}
56292 {$IFDEF ASM_VERSION}
56293 //[procedure TBitmap.FlipHorizontal]
56294 procedure TBitmap.FlipHorizontal;
56296 PUSH EBX
56297 MOV EBX, EAX
56298 CALL GetHandle
56299 TEST EAX, EAX
56300 JZ @@exit
56302 CALL StartDC
56303 PUSH SrcCopy
56304 MOV EDX, [EBX].fHeight
56305 PUSH EDX
56306 MOV ECX, [EBX].fWidth
56307 PUSH ECX
56308 PUSH 0
56309 PUSH 0
56310 PUSH EAX
56311 PUSH EDX
56312 NEG ECX
56313 PUSH ECX
56314 PUSH 0
56315 NEG ECX
56316 DEC ECX
56317 PUSH ECX
56318 PUSH EAX
56319 CALL StretchBlt
56320 CALL FinishDC
56321 @@exit:
56322 POP EBX
56323 end;
56324 {$ELSE ASM_VERSION} //Pascal
56325 procedure TBitmap.FlipHorizontal;
56326 var DC: HDC;
56327 Save: THandle;
56328 begin
56329 if GetHandle <> 0 then
56330 begin
56331 fDetachCanvas( @Self );
56332 DC := CreateCompatibleDC( 0 );
56333 Save := SelectObject( DC, fHandle );
56334 StretchBlt( DC, fWidth - 1, 0, -fWidth, fHeight, DC, 0, 0, fWidth, fHeight, SRCCOPY );
56335 SelectObject( DC, Save );
56336 DeleteDC( DC );
56337 end;
56338 end;
56339 {$ENDIF ASM_VERSION}
56341 {$IFDEF ASM_VERSION}
56342 //[procedure TBitmap.CopyRect]
56343 procedure TBitmap.CopyRect(const DstRect: TRect; SrcBmp: PBitmap;
56344 const SrcRect: TRect);
56346 PUSHAD
56347 MOV EBX, EAX
56348 MOV ESI, ECX
56349 MOV EDI, EDX
56350 CALL GetHandle
56351 TEST EAX, EAX
56352 JZ @@exit
56353 MOV EAX, ESI
56354 CALL GetHandle
56355 TEST EAX, EAX
56356 JZ @@exit
56357 CALL StartDC
56358 XCHG EBX, ESI
56359 CMP EBX, ESI
56360 JNZ @@diff1
56361 PUSH EAX
56362 PUSH 0
56363 JMP @@nodiff1
56364 @@diff1:
56365 CALL StartDC
56366 @@nodiff1:
56367 PUSH SrcCopy // ->
56368 MOV EBP, [SrcRect]
56369 MOV EAX, [EBP].TRect.Bottom
56370 MOV EDX, [EBP].TRect.Top
56371 SUB EAX, EDX
56372 PUSH EAX // ->
56373 MOV EAX, [EBP].TRect.Right
56374 MOV ECX, [EBP].TRect.Left
56375 SUB EAX, ECX
56376 PUSH EAX // ->
56377 PUSH EDX // ->
56378 PUSH ECX // ->
56379 PUSH dword ptr [ESP+24] // -> DCsrc
56380 MOV EAX, [EDI].TRect.Bottom
56381 MOV EDX, [EDI].TRect.Top
56382 SUB EAX, EDX
56383 PUSH EAX // ->
56384 MOV EAX, [EDI].TRect.Right
56385 MOV ECX, [EDI].TRect.Left
56386 SUB EAX, ECX
56387 PUSH EAX // ->
56388 PUSH EDX // ->
56389 PUSH ECX // ->
56390 PUSH dword ptr [ESP+13*4] // -> DCdst
56391 CALL StretchBlt
56392 CMP EBX, ESI
56393 JNE @@diff2
56394 POP ECX
56395 POP ECX
56396 JMP @@nodiff2
56397 @@diff2:
56398 CALL FinishDC
56399 @@nodiff2:
56400 CALL FinishDC
56401 @@exit:
56402 POPAD
56403 end;
56404 {$ELSE ASM_VERSION} //Pascal
56405 procedure TBitmap.CopyRect(const DstRect: TRect; SrcBmp: PBitmap;
56406 const SrcRect: TRect);
56407 var DCsrc, DCdst: HDC;
56408 SaveSrc, SaveDst: THandle;
56409 begin
56410 if (GetHandle = 0) or (SrcBmp.GetHandle = 0) then Exit;
56411 fDetachCanvas( @Self );
56412 fDetachCanvas( SrcBmp );
56413 DCsrc := CreateCompatibleDC( 0 );
56414 SaveSrc := SelectObject( DCsrc, SrcBmp.fHandle );
56415 DCdst := DCsrc;
56416 SaveDst := 0;
56417 if SrcBmp <> @Self then
56418 begin
56419 DCdst := CreateCompatibleDC( 0 );
56420 SaveDst := SelectObject( DCdst, fHandle );
56421 end;
56422 StretchBlt( DCdst, DstRect.Left, DstRect.Top, DstRect.Right - DstRect.Left,
56423 DstRect.Bottom - DstRect.Top, DCsrc, SrcRect.Left, SrcRect.Top,
56424 SrcRect.Right - SrcRect.Left, SrcRect.Bottom - SrcRect.Top,
56425 SRCCOPY );
56426 if SrcBmp <> @Self then
56427 begin
56428 SelectObject( DCdst, SaveDst );
56429 DeleteDC( DCdst );
56430 end;
56431 SelectObject( DCsrc, SaveSrc );
56432 DeleteDC( DCsrc );
56433 end;
56434 {$ENDIF ASM_VERSION}
56437 //[function TBitmap.CopyToClipboard]
56438 function TBitmap.CopyToClipboard: Boolean;
56439 var DibMem: PChar;
56440 HdrSize: Integer;
56441 Gbl: HGlobal;
56442 begin
56443 Result := FALSE;
56444 if Applet = nil then Exit;
56445 if not OpenClipboard( Applet.GetWindowHandle ) then
56446 Exit;
56447 if EmptyClipboard then
56448 begin
56449 HandleType := bmDIB;
56450 HdrSize := sizeof( TBitmapInfoHeader );
56451 if fDIBHeader.bmiHeader.biBitCount <= 8 then
56452 Inc( HdrSize,
56453 (1 shl fDIBHeader.bmiHeader.biBitCount) * Sizeof( TRGBQuad ) );
56454 Gbl := GlobalAlloc( GMEM_MOVEABLE, HdrSize + fDIBSize );
56455 DibMem := GlobalLock( Gbl );
56456 if DibMem <> nil then
56457 begin
56458 Move( fDIBHeader^, DibMem^, HdrSize );
56459 Move( fDIBBits^, Pointer( Integer( DibMem ) + HdrSize )^, fDIBSize );
56460 if not GlobalUnlock( Gbl ) and (GetLastError = NO_ERROR) then
56461 begin
56462 Result := SetClipboardData( CF_DIB, Gbl ) <> 0;
56463 end;
56464 end;
56465 end;
56466 CloseClipboard;
56467 end;
56469 //[function TBitmap.PasteFromClipboard]
56470 function TBitmap.PasteFromClipboard: Boolean;
56471 var Gbl: HGlobal;
56472 //DIBPtr: PChar;
56473 Size {, HdrSize}: Integer;
56474 Mem: PChar;
56475 Strm: PStream;
56476 begin
56477 Result := FALSE;
56478 if Applet = nil then Exit;
56479 if not OpenClipboard( Applet.GetWindowHandle ) then Exit;
56481 if IsClipboardFormatAvailable( CF_DIB ) then
56482 begin
56483 Gbl := GetClipboardData( CF_DIB );
56484 if Gbl <> 0 then
56485 begin
56486 Size := GlobalSize( Gbl );
56487 Mem := GlobalLock( Gbl );
56489 if (Size > 0) and (Mem <> nil) then
56490 begin
56491 Strm := NewMemoryStream;
56492 Strm.Write( Mem^, Size );
56493 Strm.Position := 0;
56494 LoadFromStreamEx( Strm );
56495 Strm.Free;
56496 Result := not Empty;
56497 end;
56498 FINALLY
56499 GlobalUnlock( Gbl );
56500 END;
56501 end;
56502 end;
56503 FINALLY
56504 CloseClipboard;
56505 END;
56506 end;
56516 ///////////////////////////////////////////////////////////////////////
56519 // I C O N
56522 ///////////////////////////////////////////////////////////////////////
56524 { -- icon -- }
56526 //[function NewIcon]
56527 function NewIcon: PIcon;
56528 begin
56530 New( Result, Create );
56531 {+}{++}(*Result := TIcon.Create;*){--}
56532 Result.FSize := 32;
56533 end;
56535 { TIcon }
56537 //[PROCEDURE asmIconEmpty]
56538 {$IFDEF ASM_VERSION}
56539 procedure asmIconEmpty( Icon: PIcon );
56541 CMP [EAX].TIcon.fHandle, 0
56542 end;
56543 {$ENDIF ASM_VERSION}
56544 //[END asmIconEmpty]
56546 {$IFDEF ASM_VERSION}
56547 //[procedure TIcon.Clear]
56548 procedure TIcon.Clear;
56549 asm //cmd //opd
56550 XOR ECX, ECX
56551 XCHG ECX, [EAX].fHandle
56552 JECXZ @@1
56553 CMP [EAX].fShareIcon, 0
56554 JNZ @@1
56555 PUSH EAX
56556 PUSH ECX
56557 CALL DestroyIcon
56558 POP EAX
56559 @@1: MOV [EAX].fShareIcon, 0
56560 end;
56561 {$ELSE ASM_VERSION} //Pascal
56562 procedure TIcon.Clear;
56563 begin
56564 if fHandle <> 0 then
56565 begin
56566 if not FShareIcon then
56567 //DeleteObject( fHandle );
56568 DestroyIcon( fHandle );
56569 fHandle := 0;
56570 end;
56571 fShareIcon := False;
56572 end;
56573 {$ENDIF ASM_VERSION}
56575 {$IFDEF ASM_VERSION}
56576 //[function TIcon.Convert2Bitmap]
56577 function TIcon.Convert2Bitmap(TranColor: TColor): HBitmap;
56578 asm //cmd //opd
56579 PUSH EBX
56580 PUSH ESI
56581 PUSH EDI
56582 PUSH EBP
56583 MOV EBX, EAX
56584 MOV EBP, EDX
56585 XOR EDX, EDX
56586 CALL asmIconEmpty
56587 JZ @@ret_0
56588 PUSH 0
56589 CALL GetDC
56590 PUSH EAX //> DC0
56591 PUSH EAX
56592 CALL CreateCompatibleDC
56593 XCHG EDI, EAX
56594 MOV EDX, [EBX].fSize
56596 POP EAX
56597 PUSH EAX
56598 PUSH EDX //>Bottom
56599 PUSH EDX //>Right
56600 PUSH 0 //>Top
56601 PUSH 0 //>Left
56603 PUSH EDX
56604 PUSH EDX
56605 PUSH EAX
56606 CALL CreateCompatibleBitmap
56607 XCHG EBP, EAX
56609 CALL Color2RGB
56610 PUSH EAX
56612 PUSH EBP
56613 PUSH EDI
56614 CALL SelectObject
56615 XCHG ESI, EAX
56617 CALL CreateSolidBrush
56619 MOV EDX, ESP
56620 PUSH EAX
56621 PUSH EAX
56622 PUSH EDX
56623 PUSH EDI
56624 CALL Windows.FillRect
56625 CALL DeleteObject
56627 XCHG EAX, EBX
56628 MOV EDX, EDI
56629 XOR ECX, ECX
56630 PUSH ECX
56631 CALL Draw
56633 PUSH EDI
56634 PUSH ESI
56635 CALL FinishDC
56637 ADD ESP, 16
56638 PUSH 0
56639 CALL ReleaseDC
56640 MOV EDX, EBP
56642 @@ret_0:
56643 XCHG EAX, EDX
56644 POP EBP
56645 POP EDI
56646 POP ESI
56647 POP EBX
56648 end;
56649 {$ELSE ASM_VERSION} //Pascal
56650 function TIcon.Convert2Bitmap(TranColor: TColor): HBitmap;
56651 var DC0, DC2: HDC;
56652 Save: THandle;
56653 Br: HBrush;
56654 begin
56655 Result := 0;
56656 if Empty then Exit;
56657 DC0 := GetDC( 0 );
56658 DC2 := CreateCompatibleDC( DC0 );
56659 Result := CreateCompatibleBitmap( DC0, fSize, fSize );
56660 Save := SelectObject( DC2, Result );
56661 Br := CreateSolidBrush( Color2RGB( TranColor ) );
56662 FillRect( DC2, MakeRect( 0, 0, fSize, fSize ), Br );
56663 DeleteObject( Br );
56664 Draw( DC2, 0, 0 );
56665 SelectObject( DC2, Save );
56666 DeleteDC( DC2 );
56667 ReleaseDC( 0, DC0 );
56668 end;
56669 {$ENDIF ASM_VERSION}
56671 {$IFDEF ASM_VERSION}
56672 //[destructor TIcon.Destroy]
56673 destructor TIcon.Destroy;
56674 asm //cmd //opd
56675 PUSH EAX
56676 CALL Clear
56677 POP EAX
56678 CALL TObj.Destroy
56679 end;
56680 {$ELSE ASM_VERSION} //Pascal
56681 destructor TIcon.Destroy;
56682 begin
56683 Clear;
56684 inherited;
56685 end;
56686 {$ENDIF ASM_VERSION}
56688 {$IFDEF ASM_VERSION}
56689 //[procedure TIcon.Draw]
56690 procedure TIcon.Draw(DC: HDC; X, Y: Integer);
56691 asm //cmd //opd
56692 CALL asmIconEmpty
56693 JZ @@exit
56694 PUSH DI_NORMAL
56695 PUSH 0
56696 PUSH 0
56697 PUSH [EAX].fSize
56698 PUSH [EAX].fSize
56699 PUSH [EAX].fHandle
56700 PUSH Y
56701 PUSH ECX
56702 PUSH EDX
56703 CALL DrawIconEx
56704 @@exit:
56705 end;
56706 {$ELSE ASM_VERSION} //Pascal
56707 procedure TIcon.Draw(DC: HDC; X, Y: Integer);
56708 begin
56709 if Empty then Exit;
56710 DrawIconEx( DC, X, Y, fHandle, fSize, fSize, 0, 0, DI_NORMAL );
56711 end;
56712 {$ENDIF ASM_VERSION}
56714 {$IFDEF ASM_VERSION}
56715 //[procedure TIcon.StretchDraw]
56716 procedure TIcon.StretchDraw(DC: HDC; Dest: TRect);
56717 asm //cmd //opd
56718 CALL asmIconEmpty
56719 JZ @@exit
56720 PUSH DI_NORMAL
56721 PUSH 0
56722 PUSH 0
56723 PUSH ECX
56724 PUSH ECX
56725 PUSH [EAX].fHandle
56726 PUSH [ECX].TRect.Top
56727 PUSH [ECX].TRect.Left
56728 PUSH EDX
56729 MOV EAX, [ECX].TRect.Bottom
56730 SUB EAX, [ECX].TRect.Top
56731 MOV [ESP+20], EAX
56732 MOV EAX, [ECX].TRect.Right
56733 SUB EAX, [ECX].TRect.Left
56734 MOV [ESP+16], EAX
56735 CALL DrawIconEx
56736 @@exit:
56737 end;
56738 {$ELSE ASM_VERSION} //Pascal
56739 procedure TIcon.StretchDraw(DC: HDC; Dest: TRect);
56740 begin
56741 if Empty then Exit;
56742 DrawIconEx( DC, Dest.Left, Dest.Top, FHandle, Dest.Right - Dest.Left,
56743 Dest.Bottom - Dest.Top, 0, 0, DI_NORMAL );
56744 end;
56745 {$ENDIF ASM_VERSION}
56747 //[function TIcon.GetEmpty]
56748 function TIcon.GetEmpty: Boolean;
56749 begin
56750 Result := fHandle = 0;
56751 end;
56754 //[function TIcon.GetHotSpot]
56755 function TIcon.GetHotSpot: TPoint;
56756 var II : TIconInfo;
56757 begin
56758 Result := MakePoint( 0, 0 );
56759 if FHandle = 0 then Exit;
56760 GetIconInfo( FHandle, II );
56761 Result.x := II.xHotspot;
56762 Result.y := II.yHotspot;
56763 if II.hbmMask <> 0 then
56764 DeleteObject( II.hbmMask );
56765 if II.hbmColor <> 0 then
56766 DeleteObject( II.hbmColor );
56767 end;
56770 //[procedure TIcon.LoadFromFile]
56771 procedure TIcon.LoadFromFile(const FileName: String);
56772 var Strm : PStream;
56773 begin
56774 Strm := NewReadFileStream( Filename );
56775 LoadFromStream( Strm );
56776 Strm.Free;
56777 end;
56780 //[procedure TIcon.LoadFromStream]
56781 procedure TIcon.LoadFromStream(Strm: PStream);
56782 var DesiredSize : Integer;
56783 Pos : DWord;
56784 Mem : PStream;
56785 ImgBmp, MskBmp : PBitmap;
56786 TmpBmp: PBitmap;
56787 function ReadIcon : Boolean;
56788 var IH : TIconHeader;
56789 IDI, FoundIDI : TIconDirEntry;
56790 I, SumSz, FoundSz, D : Integer;
56791 II : TIconInfo;
56792 BIH : TBitmapInfoheader;
56793 begin
56794 Result := False;
56795 if Strm.Read( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;
56796 if (IH.idReserved <> 0) or ((IH.idType <> 1) and (IH.idType <> 2)) or
56797 (IH.idCount < 1) then Exit;
56798 SumSz := Sizeof( IH );
56799 FoundSz := 1000;
56800 for I := 1 to IH.idCount do
56801 begin
56802 if Strm.Read( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;
56803 if (IDI.bWidth <> IDI.bHeight) and
56804 (IDI.bWidth * 2 <> IDI.bHeight) or
56805 (IDI.bWidth = 0) {or
56806 (IDI.bReserved <> 0) or (IDI.wPlanes <> 0) or (IDI.wBitCount <> 0)} then
56807 Exit;
56808 Inc( SumSz, IDI.dwBytesInRes + Sizeof( IDI ) );
56809 D := IDI.bWidth - DesiredSize;
56810 if D < 0 then D := -D;
56811 if D < FoundSz then
56812 begin
56813 FoundSz := D;
56814 FoundIDI := IDI;
56815 end;
56816 end;
56817 if FoundSz = 1000 then Exit;
56818 Strm.Seek( Integer( Pos ) + FoundIDI.dwImageOffset, spBegin );
56819 fSize := FoundIDI.bWidth;
56821 if Strm.Read( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;
56822 if (BIH.biWidth <> fSize) or
56823 (BIH.biHeight <> fSize * 2) and
56824 (BIH.biHeight <> fSize) then Exit;
56825 BIH.biHeight := fSize;
56827 Mem := NewMemoryStream;
56828 Mem.Write( BIH, Sizeof( BIH ) );
56829 if (FoundIDI.bColorCount >= 2) or (FoundIDI.bReserved = 1) or
56830 (FoundIDI.bColorCount = 0) then
56831 begin
56832 I := 0;
56833 if BIH.biBitCount <= 8 then
56834 I := (1 shl BIH.biBitCount) * Sizeof( TRGBQuad );
56835 if I > 0 then
56836 if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;
56837 I := ((BIH.biBitCount * fSize + 31) div 32) * 4 * fSize;
56838 if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;
56839 ImgBmp := NewBitmap( fSize, fSize );
56840 Mem.Seek( 0, spBegin );
56841 ImgBmp.LoadFromStream( Mem );
56842 if ImgBmp.Empty then Exit;
56843 end;
56845 BIH.biBitCount := 1;
56846 Mem.Seek( 0, spBegin );
56847 Mem.Write( BIH, Sizeof( BIH ) );
56848 I := 0;
56849 Mem.Write( I, Sizeof( I ) );
56850 I := $FFFFFF;
56851 Mem.Write( I, Sizeof( I ) );
56852 I := ((fSize + 31) div 32) * 4 * fSize;
56853 if Stream2Stream( Mem, Strm, I ) <> DWORD(I) then Exit;
56855 MskBmp := NewBitmap( fSize, fSize );
56856 Mem.Seek( 0, spBegin );
56857 MskBmp.LoadFromStream( Mem );
56858 if MskBmp.Empty then Exit;
56860 II.fIcon := True;
56861 II.xHotspot := 0;
56862 II.yHotspot := 0;
56863 II.hbmMask := MskBmp.Handle;
56864 II.hbmColor := 0;
56865 if ImgBmp <> nil then
56866 begin
56867 II.hbmColor := ImgBmp.Handle;
56868 {TmpBmp := NewBitmap( ImgBmp.Width, ImgBmp.Height );
56869 TmpBmp.HandleType := bmDIB;
56870 ImgBmp.Draw( TmpBmp.Canvas.Handle, 0, 0 );
56871 II.hbmColor := TmpBmp.Handle;}
56872 end;
56873 fHandle := CreateIconIndirect( II );
56874 //fShareIcon := False;
56875 Strm.Seek( Integer( Pos ) + SumSz, spBegin );
56876 Result := fHandle <> 0;
56877 end;
56878 begin
56879 DesiredSize := fSize;
56880 if DesiredSize = 0 then
56881 DesiredSize := GetSystemMetrics( SM_CXICON );
56882 Clear;
56883 Pos := Strm.Position;
56885 Mem := nil;
56886 ImgBmp := nil;
56887 MskBmp := nil;
56888 TmpBmp := nil;
56890 if not ReadIcon then
56891 begin
56892 Clear;
56893 Strm.Seek( Pos, spBegin );
56894 end;
56896 Mem.Free;
56897 ImgBmp.Free;
56898 MskBmp.Free;
56899 TmpBmp.Free;
56900 end;
56902 {$IFDEF ASM_VERSION}
56903 //[procedure TIcon.SaveToFile]
56904 procedure TIcon.SaveToFile(const FileName: String);
56905 asm //cmd //opd
56906 PUSH EAX
56907 MOV EAX, ESP
56908 MOV ECX, EDX
56909 XOR EDX, EDX
56910 CALL SaveIcons2File
56911 POP EAX
56912 end;
56913 {$ELSE ASM_VERSION} //Pascal
56914 procedure TIcon.SaveToFile(const FileName: String);
56915 begin
56916 SaveIcons2File( [ @Self ], FileName );
56917 end;
56918 {$ENDIF ASM_VERSION}
56920 {$IFDEF ASM_VERSION}
56921 //[procedure TIcon.SaveToStream]
56922 procedure TIcon.SaveToStream(Strm: PStream);
56923 asm //cmd //opd
56924 PUSH EAX
56925 MOV EAX, ESP
56926 MOV ECX, EDX
56927 XOR EDX, EDX
56928 CALL SaveIcons2Stream
56929 POP EAX
56930 end;
56931 {$ELSE ASM_VERSION} //Pascal
56932 procedure TIcon.SaveToStream(Strm: PStream);
56933 begin
56934 SaveIcons2Stream( [ @Self ], Strm );
56935 end;
56936 {$ENDIF ASM_VERSION}
56938 {$IFDEF ASM_noVERSION}
56939 //[procedure TIcon.SetHandle]
56940 procedure TIcon.SetHandle(const Value: HIcon);
56941 const szII = sizeof( TIconInfo );
56942 szBIH = sizeof(TBitmapInfoHeader);
56943 asm //cmd //opd
56944 CMP EDX, [EAX].fHandle
56945 JE @@exit
56946 PUSHAD
56947 PUSH EDX
56948 MOV EBX, EAX
56949 CALL Clear
56950 POP ECX
56951 MOV [EBX].fHandle, ECX
56952 JECXZ @@fin
56953 ADD ESP, -szBIH
56954 PUSH ESP
56955 PUSH ECX
56956 CALL GetIconInfo
56957 MOV ESI, [ESP].TIconInfo.hbmMask
56958 MOV EDI, [ESP].TIconInfo.hbmColor
56959 PUSH ESP
56960 PUSH szBIH
56961 PUSH ESI
56962 CALL GetObject
56963 POP EAX
56964 POP [EBX].fSize
56965 ADD ESP, szBIH-8
56966 TEST ESI, ESI
56967 JZ @@1
56968 PUSH ESI
56969 CALL DeleteObject
56970 @@1: TEST EDI, EDI
56971 JZ @@fin
56972 PUSH EDI
56973 CALL DeleteObject
56974 @@fin: POPAD
56975 @@exit:
56976 end;
56977 {$ELSE ASM_VERSION} //Pascal
56978 procedure TIcon.SetHandle(const Value: HIcon);
56979 var II : TIconInfo;
56980 B: TagBitmap;
56981 begin
56982 if FHandle = Value then Exit;
56983 Clear;
56984 FHandle := Value;
56985 if Value <> 0 then
56986 begin
56987 GetIconInfo( FHandle, II );
56988 GetObject( II.hbmMask, Sizeof( B ), @B );
56989 fSize := B.bmWidth;
56990 if II.hbmMask <> 0 then
56991 DeleteObject( II.hbmMask );
56992 if II.hbmColor <> 0 then
56993 DeleteObject( II.hbmColor );
56994 end;
56995 end;
56996 {$ENDIF ASM_VERSION}
56999 //[procedure TIcon.SetSize]
57000 procedure TIcon.SetSize(const Value: Integer);
57001 begin
57002 if FSize = Value then Exit;
57003 Clear;
57004 FSize := Value;
57005 end;
57007 const PossibleColorBits : array[1..7] of Byte = ( 1, 4, 8, 16, 24, 32, 0 );
57008 //[FUNCTION ColorBits]
57009 {$IFDEF ASM_VERSION}
57010 function ColorBits( ColorsCount : Integer ) : Integer;
57011 asm //cmd //opd
57012 PUSH EBX
57013 MOV EDX, offset[PossibleColorBits]
57014 @@loop: MOVZX ECX, byte ptr [EDX]
57015 JECXZ @@e_loop
57016 INC EDX
57017 XOR EBX, EBX
57018 INC EBX
57019 SHL EBX, CL
57020 CMP EBX, EAX
57021 JL @@loop
57022 @@e_loop:
57023 XCHG EAX, ECX
57024 POP EBX
57025 end;
57026 {$ELSE ASM_VERSION} //Pascal
57027 function ColorBits( ColorsCount : Integer ) : Integer;
57028 var I : Integer;
57029 begin
57030 for I := 1 to 6 do
57031 begin
57032 Result := PossibleColorBits[ I ];
57033 if (1 shl Result) >= ColorsCount then break;
57034 end;
57035 end;
57036 {$ENDIF ASM_VERSION}
57037 //[END ColorBits]
57039 //[function SaveIcons2StreamEx]
57040 function SaveIcons2StreamEx( const BmpHandles: array of HBitmap; Strm: PStream ): Boolean;
57041 var I, Off : Integer;
57042 IDI : TIconDirEntry;
57043 BIH : TBitmapInfoHeader;
57044 B: TagBitmap;
57045 function RGBArraySize : Integer;
57046 begin
57047 Result := 0;
57048 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
57049 Result := (IDI.bColorCount + (IDI.bReserved shl 8)) * Sizeof( TRGBQuad );
57050 end;
57051 function ColorDataSize( W, H: Integer ) : Integer;
57052 var N: Integer;
57053 begin
57054 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
57055 N := (ColorBits( IDI.bColorCount + (IDI.bReserved shl 8) ) )
57056 else
57057 begin
57058 N := IDI.wBitCount;
57059 end;
57060 Result := ((N * W + 31) div 32) * 4
57061 * H;
57062 end;
57063 function MaskDataSize( W, H: Integer ) : Integer;
57064 begin
57065 Result := ((W + 31) div 32) * 4 * H;
57066 end;
57067 var BColor, BMask: HBitmap;
57068 W, H: Integer;
57069 ImgBmp, MskBmp: PBitmap;
57070 IH : TIconHeader;
57071 Colors : PList;
57072 begin
57073 Assert( (High(BmpHandles) >= 0) and (High(BmpHandles) and 1 <> 0),
57074 'Incorrect parameters count in call to SaveIcons2StreamEx' );
57075 Result := False;
57076 IH.idReserved := 0;
57077 IH.idType := 1;
57078 IH.idCount := (High( BmpHandles )+1) div 2;
57079 if Strm.Write( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;
57080 Off := Sizeof( IH ) + IH.idCount * Sizeof( IDI );
57081 Colors := NewList;
57082 ImgBmp := NewBitmap( 0, 0 );
57083 MskBmp := NewBitmap( 0, 0 );
57086 for I := 0 to High( BmpHandles ) div 2 do
57087 begin
57088 BColor := BmpHandles[ I * 2 ];
57089 BMask := BmpHandles[ I * 2 + 1 ];
57090 if (BColor = 0) and (BMask = 0) then break;
57091 Assert( BMask <> 0, 'Mask bitmap not provided for saving icons in SaveIcons2StreamEx' );
57092 GetObject( BMask, Sizeof( B ), @ B );
57093 W := B.bmWidth;
57094 H := B.bmHeight;
57095 if BColor <> 0 then
57096 begin
57097 GetObject( BColor, Sizeof( B ), @B );
57098 Assert( (B.bmWidth = W) and (B.bmHeight = H),
57099 'Mask bitmap size must much color bitmap size in SaveIcons2StreamEx' );
57100 end;
57101 FillChar( IDI, Sizeof( IDI ), 0 );
57103 IDI.bWidth := W;
57104 IDI.bHeight := H;
57105 if BColor = 0 then
57106 IDI.bColorCount := 2
57107 else
57108 begin
57109 ImgBmp.Handle := CopyImage( BColor, IMAGE_BITMAP, W, H,
57110 LR_CREATEDIBSECTION );
57111 FillChar( BIH, Sizeof( BIH ), 0 );
57112 BIH.biSize := Sizeof( BIH );
57113 GetObject( ImgBmp.Handle, Sizeof( B ), @B );
57114 //if ImgBmp.HandleType = bmDDB then
57115 begin
57116 if (B.bmPlanes = 1) and (B.bmBitsPixel >= 15) then
57117 begin
57118 //ImgBmp.PixelFormat := pf24bit;
57119 IDI.bColorCount := 0;
57120 IDI.bReserved := 0;
57121 IDI.wBitCount := B.bmBitsPixel;
57123 else
57124 if B.bmPlanes * (1 shl B.bmBitsPixel) < 16 then
57125 begin
57126 ImgBmp.PixelFormat := pf1bit;
57127 IDI.bColorCount := 2;
57129 else
57130 if B.bmPlanes * (1 shl B.bmBitsPixel) < 256 then
57131 begin
57132 ImgBmp.PixelFormat := pf4bit;
57133 IDI.bColorCount := 16;
57135 else
57136 begin
57137 ImgBmp.PixelFormat := pf8bit;
57138 IDI.bColorCount := 0;
57139 IDI.bReserved := 1;
57140 end;
57141 //GetObject( ImgBmp.Handle, Sizeof( BIH ), @BIH );
57142 end;
57143 //IDI.bColorCount := (1 shl BIH.biBitCount) * BIH.biPlanes;
57144 end;
57145 Colors.Add( Pointer(IDI.bColorCount + (IDI.bReserved shl 8)) );
57146 IDI.dwBytesInRes := Sizeof( BIH ) + RGBArraySize +
57147 ColorDataSize( W, H ) + MaskDataSize( W, H );
57148 IDI.dwImageOffset := Off;
57149 if Strm.Write( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;
57150 Inc( Off, IDI.dwBytesInRes );
57151 end;
57152 for I := 0 to High( BmpHandles ) div 2 do
57153 begin
57154 BColor := BmpHandles[ I * 2 ];
57155 BMask := BmpHandles[ I * 2 + 1 ];
57156 if (BColor = 0) and (BMask = 0) then break;
57157 GetObject( BMask, Sizeof( B ), @ B );
57158 W := B.bmWidth;
57159 H := B.bmHeight;
57161 FillChar( BIH, Sizeof( BIH ), 0 );
57162 BIH.biSize := Sizeof( BIH );
57163 BIH.biWidth := W;
57164 BIH.biHeight := H;
57165 if BColor <> 0 then
57166 BIH.biHeight := W * 2;
57167 BIH.biPlanes := 1;
57168 PWord( @ IDI.bColorCount )^ := DWord( Colors.Items[ I ] );
57169 if IDI.wBitCount = 0 then
57170 IDI.wBitCount := ColorBits( PWord( @ IDI.bColorCount )^ );
57171 BIH.biBitCount := IDI.wBitCount;
57172 BIH.biSizeImage := Sizeof( BIH ) + ColorDataSize( W, H ) + MaskDataSize( W, H );
57173 if Strm.Write( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;
57174 if BColor <> 0 then
57175 begin
57177 ImgBmp.Handle := CopyImage( BColor, IMAGE_BITMAP, W, H, 0 );
57178 case BIH.biBitCount of
57179 1 : ImgBmp.PixelFormat := pf1bit;
57180 4 : ImgBmp.PixelFormat := pf4bit;
57181 8 : ImgBmp.PixelFormat := pf8bit;
57182 16: ImgBmp.PixelFormat := pf16bit;
57183 24: ImgBmp.PixelFormat := pf24bit;
57184 32: ImgBmp.PixelFormat := pf32bit;
57185 end;
57187 else
57188 begin
57189 ImgBmp.Handle := CopyImage( BMask, IMAGE_BITMAP, W, H, 0 );
57190 ImgBmp.PixelFormat := pf1bit;
57191 end;
57192 if ImgBmp.FDIBBits <> nil then
57193 begin
57194 if Strm.Write( Pointer(Integer(ImgBmp.FDIBHeader) + Sizeof(TBitmapInfoHeader))^,
57195 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) ) <>
57196 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) then Exit;
57197 if Strm.Write( ImgBmp.FDIBBits^, ColorDataSize( W, H ) ) <>
57198 DWord( ColorDataSize( W, H ) ) then Exit;
57199 end;
57200 MskBmp.Handle := CopyImage( BMask, IMAGE_BITMAP, W, H, 0 );
57202 MskBmp.PixelFormat := pf1bit;
57203 if Strm.Write( MskBmp.FDIBBits^, MaskDataSize( W, H ) ) <>
57204 DWord( MaskDataSize( W, H ) ) then Exit;
57205 end;
57207 FINALLY
57208 Colors.Free;
57209 ImgBmp.Free;
57210 MskBmp.Free;
57211 END;
57212 Result := True;
57213 end;
57215 {$IFDEF FPC}
57216 {$DEFINE _D3orFPC}
57217 {$ENDIF}
57218 {$IFDEF _D2orD3}
57219 {$DEFINE _D3orFPC}
57220 {$ENDIF}
57221 //[procedure SaveIcons2Stream]
57222 procedure SaveIcons2Stream( const Icons : array of PIcon; Strm : PStream );
57223 var I, J, Pos : Integer;
57224 {$IFDEF _D3orFPC}
57225 Bitmaps: array[ 0..63 ] of HBitmap;
57226 {$ELSE DELPHI}
57227 Bitmaps: array of HBitmap;
57228 {$ENDIF FPC/DELPHI}
57229 II: TIconInfo;
57230 Bmp: HBitmap;
57231 begin
57232 for I := 0 to High( Icons ) do
57233 begin
57234 if Icons[ I ].Handle = 0 then Exit;
57235 for J := I + 1 to High( Icons ) do
57236 if Icons[ I ].Size = Icons[ J ].Size then Exit;
57237 end;
57238 Pos := Strm.Position;
57240 {$IFDEF _D3orFPC}
57241 for I := 0 to High( Bitmaps ) do
57242 Bitmaps[ I ] := 0;
57243 {$ELSE DELPHI}
57244 SetLength( Bitmaps, Length( Icons ) * 2 );
57245 {$ENDIF FPC/DELPHI}
57246 for I := 0 to High( Icons ) do
57247 begin
57248 GetIconInfo( Icons[ I ].Handle, II );
57249 Bitmaps[ I * 2 ] := II.hbmColor;
57250 Bitmaps[ I * 2 + 1 ] := II.hbmMask;
57251 end;
57253 if not SaveIcons2StreamEx( Bitmaps, Strm ) then
57254 Strm.Seek( Pos, spBegin );
57256 for I := 0 to High( Bitmaps ) do
57257 begin
57258 Bmp := Bitmaps[ I ];
57259 if Bmp <> 0 then
57260 DeleteObject( Bmp );
57261 end;
57262 end;
57264 var I, J, Pos : Integer;
57265 IH : TIconHeader;
57266 Colors : PList;
57267 ImgBmp,
57268 MskBmp : PBitmap;
57269 function WriteIcons : Boolean;
57270 var I, Off : Integer;
57271 IDI : TIconDirEntry;
57272 BIH : TBitmapInfoHeader;
57273 II : TIconInfo;
57274 B: TagBitmap;
57275 function RGBArraySize : Integer;
57276 begin
57277 Result := 0;
57278 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
57279 Result := (IDI.bColorCount + (IDI.bReserved shl 8)) * Sizeof( TRGBQuad );
57280 end;
57281 function ColorDataSize : Integer;
57282 var N: Integer;
57283 begin
57284 //Result := 0;
57285 if (IDI.bColorCount >= 2) or (IDI.bReserved = 1) then
57286 N := (ColorBits( IDI.bColorCount + (IDI.bReserved shl 8) ) )
57287 else
57288 N := IDI.wBitCount;
57289 Result := ((N * Icons[ I ].Size + 31) div 32) * 4
57290 * Icons[ I ].Size;
57291 end;
57292 function MaskDataSize : Integer;
57293 begin
57294 Result := ((Icons[ I ].Size + 31) div 32) * 4
57295 * Icons[ I ].Size;
57296 end;
57297 begin
57298 Result := False;
57299 if Strm.Write( IH, Sizeof( IH ) ) <> Sizeof( IH ) then Exit;
57300 Off := Sizeof( IH ) + IH.idCount * Sizeof( IDI );
57301 for I := Low( Icons ) to High( Icons ) do
57302 begin
57303 FillChar( IDI, Sizeof( IDI ), 0 );
57304 IDI.bWidth := Icons[ I ].Size;
57305 IDI.bHeight := Icons[ I ].Size;
57306 GetIconInfo( Icons[ I ].Handle, II );
57307 if II.hbmColor = 0 then
57308 IDI.bColorCount := 2
57309 else
57310 begin
57311 {ImgBmp.Handle := CopyImage( II.hbmColor, IMAGE_BITMAP, Icons[ I ].Size,
57312 Icons[ I ].Size, LR_CREATEDIBSECTION );}
57313 ImgBmp.Handle := II.hbmColor;
57314 II.hbmColor := 0;
57315 FillChar( BIH, Sizeof( BIH ), 0 );
57316 BIH.biSize := Sizeof( BIH );
57317 GetObject( ImgBmp.Handle, Sizeof( B ), @B );
57318 //if ImgBmp.HandleType = bmDDB then
57319 begin
57320 if (B.bmPlanes = 1) and (B.bmBitsPixel >= 15) then
57321 begin
57322 //ImgBmp.PixelFormat := pf24bit;
57323 IDI.bColorCount := 0;
57324 IDI.bReserved := 0;
57325 IDI.wBitCount := B.bmBitsPixel;
57327 else
57328 if B.bmPlanes * (1 shl B.bmBitsPixel) < 16 then
57329 begin
57330 ImgBmp.PixelFormat := pf1bit;
57331 IDI.bColorCount := 2;
57333 else
57334 if B.bmPlanes * (1 shl B.bmBitsPixel) < 256 then
57335 begin
57336 ImgBmp.PixelFormat := pf4bit;
57337 IDI.bColorCount := 16;
57339 else
57340 begin
57341 ImgBmp.PixelFormat := pf8bit;
57342 IDI.bColorCount := 0;
57343 IDI.bReserved := 1;
57344 end;
57345 //GetObject( ImgBmp.Handle, Sizeof( BIH ), @BIH );
57346 end;
57347 //IDI.bColorCount := (1 shl BIH.biBitCount) * BIH.biPlanes;
57348 //--//DeleteObject( II.hbmColor );
57349 end;
57350 if II.hbmMask <> 0 then
57351 DeleteObject( II.hbmMask );
57352 Colors.Add( Pointer(IDI.bColorCount + (IDI.bReserved shl 8)) );
57353 IDI.dwBytesInRes := Sizeof( BIH ) + RGBArraySize +
57354 ColorDataSize + MaskDataSize;
57355 IDI.dwImageOffset := Off;
57356 if Strm.Write( IDI, Sizeof( IDI ) ) <> Sizeof( IDI ) then Exit;
57357 Inc( Off, IDI.dwBytesInRes );
57358 end;
57359 for I := Low( Icons ) to High( Icons ) do
57360 begin
57361 FillChar( BIH, Sizeof( BIH ), 0 );
57362 BIH.biSize := Sizeof( BIH );
57363 BIH.biWidth := Icons[ I ].Size;
57364 BIH.biHeight := Icons[ I ].Size;
57365 //GetObject( Icons[ I ].Handle, Sizeof( II ), @II );
57366 GetIconInfo( Icons[ I ].Handle, II );
57367 if II.hbmColor <> 0 then
57368 BIH.biHeight := Icons[ I ].Size * 2;
57369 BIH.biPlanes := 1;
57370 PWord( @ IDI.bColorCount )^ := DWord( Colors.Items[ I - Low( Icons ) ] );
57371 if IDI.wBitCount = 0 then
57372 IDI.wBitCount := ColorBits( PWord( @ IDI.bColorCount )^ );
57373 BIH.biBitCount := IDI.wBitCount;
57374 BIH.biSizeImage := Sizeof( BIH ) + ColorDataSize + MaskDataSize;
57375 if Strm.Write( BIH, Sizeof( BIH ) ) <> Sizeof( BIH ) then Exit;
57376 if II.hbmColor <> 0 then
57377 begin
57379 ImgBmp.Handle := {CopyImage( II.hbmColor, IMAGE_BITMAP, Icons[ I ].Size,
57380 Icons[ I ].Size, 0 );}
57381 II.hbmColor;
57382 II.hbmColor := 0;
57383 case BIH.biBitCount of
57384 1 : ImgBmp.PixelFormat := pf1bit;
57385 4 : ImgBmp.PixelFormat := pf4bit;
57386 8 : ImgBmp.PixelFormat := pf8bit;
57387 16: ImgBmp.PixelFormat := pf16bit;
57388 24: ImgBmp.PixelFormat := pf24bit;
57389 32: ImgBmp.PixelFormat := pf32bit;
57390 end;
57392 else
57393 begin
57394 ImgBmp.Handle := CopyImage( II.hbmMask, IMAGE_BITMAP, Icons[ I ].Size,
57395 Icons[ I ].Size, 0 );
57396 ImgBmp.PixelFormat := pf1bit;
57397 end;
57398 if ImgBmp.FDIBBits <> nil then
57399 begin
57400 if Strm.Write( Pointer(Integer(ImgBmp.FDIBHeader) + Sizeof(TBitmapInfoHeader))^,
57401 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) ) <>
57402 PWord( @ IDI.bColorCount )^ * Sizeof( TRGBQuad ) then Exit;
57403 if Strm.Write( ImgBmp.FDIBBits^, ColorDataSize ) <>
57404 DWord( ColorDataSize ) then Exit;
57405 end;
57406 MskBmp.Handle := CopyImage( II.hbmMask, IMAGE_BITMAP, Icons[ I ].Size,
57407 Icons[ I ].Size, 0 {LR_COPYRETURNORG} );
57408 //***
57409 if II.hbmMask <> 0 then
57410 DeleteObject( II.hbmMask );
57411 if II.hbmColor <> 0 then
57412 DeleteObject( II.hbmColor );
57413 //***
57415 MskBmp.PixelFormat := pf1bit;
57416 if Strm.Write( MskBmp.FDIBBits^, MaskDataSize ) <>
57417 DWord( MaskDataSize ) then Exit;
57418 end;
57419 Result := True;
57420 end;
57421 begin
57422 for I := Low( Icons ) to High( Icons ) do
57423 begin
57424 if Icons[ I ].Handle = 0 then Exit;
57425 for J := I + 1 to High( Icons ) do
57426 if Icons[ I ].Size = Icons[ J ].Size then Exit;
57427 end;
57428 IH.idReserved := 0;
57429 IH.idType := 1;
57430 IH.idCount := High( Icons ) - Low( Icons ) + 1;
57431 Pos := Strm.Position;
57432 Colors := NewList;
57433 ImgBmp := NewBitmap( 0, 0 );
57434 MskBmp := NewBitmap( 0, 0 );
57436 if not WriteIcons then
57437 Strm.Seek( Pos, spBegin );
57439 ImgBmp.Free;
57440 MskBmp.Free;
57441 Colors.Free;
57442 end;
57445 //[procedure SaveIcons2File]
57446 procedure SaveIcons2File( const Icons : array of PIcon; const FileName : String );
57447 var Strm: PStream;
57448 begin
57449 Strm := NewWriteFileStream( FileName );
57450 SaveIcons2Stream( Icons, Strm );
57451 Strm.Free;
57452 end;
57454 //[procedure TIcon.LoadFromExecutable]
57455 procedure TIcon.LoadFromExecutable(const FileName: String; IconIdx: Integer);
57456 var I: Integer;
57457 begin
57458 Clear;
57459 I := ExtractIcon( hInstance, PChar( FileName ), IconIdx );
57460 if I > 1 then
57461 Handle := I;
57462 end;
57464 //[function GetFileIconCount]
57465 function GetFileIconCount( const FileName: String ): Integer;
57466 begin
57467 Result := ExtractIcon( hInstance, PChar( FileName ), DWORD(-1) );
57468 end;
57470 //[procedure TIcon.LoadFromResourceID]
57471 procedure TIcon.LoadFromResourceID(Inst, ResID, DesiredSize: Integer);
57472 begin
57473 LoadFromResourceName( Inst, MAKEINTRESOURCE( ResID ), DesiredSize );
57474 end;
57476 //[procedure TIcon.LoadFromResourceName]
57477 procedure TIcon.LoadFromResourceName(Inst: Integer; ResName: PChar; DesiredSize: Integer);
57478 begin
57479 Handle := LoadImage( Inst, ResName, IMAGE_ICON, DesiredSize, DesiredSize,
57480 $8000 {LR_SHARED} );
57481 {if Handle = 0 then
57482 Handle := LoadIcon( Inst, ResName )
57483 else}
57484 if fHandle <> 0 then FShareIcon := True;
57485 end;
57487 //[function LoadImgIcon]
57488 function LoadImgIcon( RsrcName: PChar; Size: Integer ): HIcon;
57489 begin
57490 Result := LoadImage( hInstance, RsrcName, IMAGE_ICON, Size, Size, $8000 {LR_SHARED} );
57491 end;
57506 //[procedure AlignChildrenProc]
57507 procedure AlignChildrenProc( Sender: PObj );
57508 type
57509 TAligns = set of TControlAlign;
57510 var P: PControl;
57511 CR: TRect;
57512 procedure DoAlign( Allowed: TAligns );
57513 var I: Integer;
57514 C: PControl;
57515 R, R1: TRect;
57516 W, H: Integer;
57517 ChgPos, ChgSiz: Boolean;
57518 begin
57519 for I := 0 to P.fChildren.fCount - 1 do
57520 begin
57521 C := P.fChildren.fItems[ I ];
57522 if not C.ToBeVisible then continue;
57523 // important: not fVisible, and even not Visible, but ToBeVisible!
57524 if C.fNotUseAlign then continue;
57525 if C.FAlign in Allowed then
57526 begin
57527 R := C.BoundsRect;
57528 R1 := R;
57529 W := R.Right - R.Left;
57530 H := R.Bottom - R.Top;
57531 case C.FAlign of
57532 caTop:
57533 begin
57534 OffsetRect( R, 0, -R.Top + CR.Top + P.Margin );
57535 Inc( CR.Top, H + P.Margin );
57536 R.Left := CR.Left + P.Margin;
57537 R.Right := CR.Right - P.Margin;
57538 end;
57539 caBottom:
57540 begin
57541 OffsetRect( R, 0, -R.Bottom + CR.Bottom - P.Margin );
57542 Dec( CR.Bottom, H + P.Margin );
57543 R.Left := CR.Left + P.Margin;
57544 R.Right := CR.Right - P.Margin;
57545 end;
57546 caLeft:
57547 begin
57548 OffsetRect( R, -R.Left + CR.Left + P.Margin, 0 );
57549 Inc( CR.Left, W + P.Margin );
57550 R.Top := CR.Top + P.Margin;
57551 R.Bottom := CR.Bottom - P.Margin;
57552 end;
57553 caRight:
57554 begin
57555 OffsetRect( R, -R.Right + CR.Right - P.Margin, 0 );
57556 Dec( CR.Right, W + P.Margin );
57557 R.Top := CR.Top + P.Margin;
57558 R.Bottom := CR.Bottom - P.Margin;
57559 end;
57560 caClient:
57561 begin
57562 R := CR;
57563 InflateRect( R, -P.Margin, -P.Margin );
57564 end;
57565 end;
57566 if R.Right < R.Left then R.Right := R.Left;
57567 if R.Bottom < R.Top then R.Bottom := R.Top;
57568 ChgPos := (R.Left <> R1.Left) or (R.Top <> R1.Top);
57569 ChgSiz := (R.Right - R.Left <> W) or (R.Bottom - R.Top <> H);
57570 if ChgPos or ChgSiz then
57571 begin
57572 //if not C.Windowed then C.Invalidate;
57573 C.BoundsRect := R;
57574 if ChgSiz then
57575 AlignChildrenProc( C );
57576 //if not C.Windowed then C.Invalidate;
57577 end;
57578 end;
57579 end;
57580 end;
57581 begin
57582 P := Pointer( Sender );
57583 if P = nil then Exit; // Called for form - ignore.
57584 CR := P.ClientRect;
57585 DoAlign( [ caTop, caBottom ] );
57586 DoAlign( [ caLeft, caRight ] );
57587 DoAlign( [ caClient ] );
57588 end;
57591 //[procedure TControl.Set_Align]
57592 procedure TControl.Set_Align(const Value: TControlAlign);
57593 begin
57594 Global_Align := AlignChildrenProc;
57595 if fNotUseAlign then Exit;
57596 if FAlign = Value then Exit;
57597 FAlign := Value;
57598 //Global_Align( Parent );
57599 AlignChildrenProc( Parent );
57600 end;
57603 //[function TControl.SetAlign]
57604 function TControl.SetAlign(AAlign: TControlAlign): PControl;
57605 begin
57606 Set_Align( AAlign );
57607 Result := @Self;
57608 end;
57611 //[function WndProcPreventResizeFlicks]
57612 function WndProcPreventResizeFlicks( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
57613 type TRectsArray = array[0..2] of TRect;
57614 PRectsArray = ^TRectsArray;
57615 TChange = ( ChgL, ChgT, ChgR, ChgB );
57616 TChanges = Set of TChange;
57617 var Rects : PRectsArray;
57618 Changes : Set of TChange;
57619 Resizing : Boolean;
57620 X, Y, DX, DY : Integer;
57621 EntireRect, Src, Dst : TRect;
57623 function GetClientAfter : TRect;
57624 var R : TRect;
57625 begin
57626 R := Rects[ 2 ];
57627 OffsetRect( R, Rects[ 0 ].Left - Rects[ 1 ].Left,
57628 Rects[ 0 ].Top - Rects[ 1 ].Top );
57629 if Rects[ 0 ].Right - Rects[ 0 ].Left <> Rects[ 1 ].Right - Rects[ 1 ].Left then
57630 R.Right := R.Left + (R.Right - R.Left)
57631 + (Rects[ 0 ].Right - Rects[ 0 ].Left)
57632 - (Rects[ 1 ].Right - Rects[ 1 ].Left);
57633 if Rects[ 0 ].Bottom - Rects[ 0 ].Top <> Rects[ 1 ].Bottom - Rects[ 1 ].Top then
57634 R.Bottom := R.Top + (R.Bottom - R.Top)
57635 + (Rects[ 0 ].Bottom - Rects[ 0 ].Top)
57636 - (Rects[ 1 ].Bottom - Rects[ 1 ].Top);
57637 Result := R;
57638 end;
57640 procedure DoResize( F : PControl; Changes : TChanges );
57641 var ClientAfter : TRect;
57643 procedure CollectClipRgn( V : PControl; Changes : TChanges );
57644 var C : PControl;
57645 I : Integer;
57646 begin
57647 for I := 0 to V.FChildren.FCount - 1 do
57648 begin
57649 C := V.FChildren.FItems[ I ];
57650 if not C.Visible then Continue;
57652 if C.fNotUseAlign then
57653 begin
57654 C.Update;
57655 end;
57656 end;
57657 end; // of CollectClipRgn
57660 begin // DoResize
57661 ClientAfter := GetClientAfter;
57662 //ClipRgn := CreateRectRgn( ClientAfter.Left, ClientAfter.Top,
57663 // ClientAfter.Right, ClientAfter.Bottom );
57664 CollectClipRgn( F, Changes );
57665 //ScrollWithoutClipRgn;
57666 //DeleteObject( ClipRgn );
57667 end; // of DoResize
57669 var PR: PRect;
57670 R: TRect;
57671 begin // Procedure WndProcResizeFlicks
57672 Result := False;
57673 case Msg.message of
57674 WM_NCCALCSIZE:
57675 if Msg.wParam <> 0 then
57676 begin
57677 Rects := Pointer( Msg.lParam );
57678 Changes := [];
57679 if Rects[ 0 ].Left <> Rects[ 1 ].Left then
57680 Changes := Changes + [ ChgL ];
57681 if Rects[ 0 ].Top <> Rects[ 1 ].Top then
57682 Changes := Changes + [ ChgT ];
57683 if Rects[ 0 ].Right <> Rects[ 1 ].Right then
57684 Changes := Changes + [ ChgR ];
57685 if Rects[ 0 ].Bottom <> Rects[ 1 ].Bottom then
57686 Changes := Changes + [ ChgB ];
57687 Resizing := Changes * [ ChgL, ChgT ] <> [ ];
57688 if Resizing and not Sender.fNotUseAlign then
57689 begin
57690 EntireRect := GetClientAfter;
57691 OffsetRect( EntireRect, -EntireRect.Left, -EntireRect.Top );
57692 if EntireRect.Right - EntireRect.Left < Rects[ 2 ].Right - Rects[ 2 ].Left then
57693 EntireRect.Right := Rects[ 2 ].Right - Rects[ 2 ].Left;
57694 if EntireRect.Bottom - EntireRect.Top < Rects[ 2 ].Bottom - Rects[ 2 ].Top then
57695 EntireRect.Bottom := Rects[ 2 ].Bottom - Rects[ 2 ].Top;
57696 X := Min( Rects[ 0 ].Left, Rects[ 1 ].Left ) + Rects[ 2 ].Left - Rects[ 1 ].Left;
57697 Y := Min( Rects[ 0 ].Top, Rects[ 1 ].Top ) + Rects[ 2 ].Top - Rects[ 2 ].Top;
57698 OffsetRect( EntireRect, X, Y );
57699 DX := 0; DY := 0;
57700 if ChgL in Changes then
57701 DX := Rects[ 0 ].Left - Rects[ 1 ].Left;
57702 if ChgR in Changes then
57703 DX := Rects[ 0 ].Right - Rects[ 1 ].Right;
57704 if ChgT in Changes then
57705 DY := Rects[ 0 ].Top - Rects[ 1 ].Top;
57706 if ChgB in Changes then
57707 DY := Rects[ 0 ].Bottom - Rects[ 1 ].Bottom;
57708 DoResize( Sender, Changes );
57709 if (Changes = [ChgL]) {and (Rects[0].Left <> Rects[1].Left)} then
57710 begin
57711 Rslt := WVR_VALIDRECTS;
57712 Src := Rects[ 2 ];
57713 Dst := GetClientAfter;
57714 Src.Right := Src.Left - DX;
57715 Dst.Right := Dst.Left - DX;
57716 Rects[ 1 ] := Src;
57717 Rects[ 2 ] := Dst;
57719 else
57720 if (Changes = [ChgR]) {and (Rects[0].Right > Rects[1].Right)} then
57721 begin
57722 Rslt := WVR_VALIDRECTS;
57723 Src := Rects[ 2 ];
57724 Dst := GetClientAfter;
57725 Src.Left := Src.Right - DX;
57726 Dst.Left := Dst.Right - DX;
57727 Rects[ 1 ] := Src;
57728 Rects[ 2 ] := Dst;
57730 else
57731 if (Changes = [ChgT]) {and (Rects[0].Top <> Rects[1].Top)} then
57732 begin
57733 Rslt := WVR_VALIDRECTS;
57734 Src := Rects[ 2 ];
57735 Dst := GetClientAfter;
57736 Src.Bottom := Src.Top - DY;
57737 Dst.Bottom := Dst.Top - DY;
57738 Rects[ 1 ] := Src;
57739 Rects[ 2 ] := Dst;
57741 else
57742 if Changes = [ChgL,ChgT] then
57743 begin
57744 Rslt := WVR_VALIDRECTS;
57745 Src := Rects[ 2 ];
57746 Dst := GetClientAfter;
57747 Src.Left := Src.Right - DX;
57748 Dst.Left := Dst.Right - DX;
57749 Src.Bottom := Src.Top - DY;
57750 Dst.Bottom := Dst.Top - DY;
57751 Rects[ 1 ] := Src;
57752 Rects[ 2 ] := Dst;
57753 end;
57754 PostMessage( Sender.fHandle, CM_UPDATE, 0, 0 );
57756 {else
57757 if Sender.fNotUseAlign then
57758 begin
57759 end};
57760 end;
57761 CM_UPDATE:
57762 begin
57763 if Sender.fNotUpdate then
57764 begin
57765 Sender.fNotUpdate := False;
57766 Sender.Invalidate;
57767 end;
57768 Sender.Update;
57769 end;
57770 WM_SIZING:
57771 begin
57772 if (Msg.wParam = WMSZ_TOPLEFT) or (Msg.wParam = WMSZ_BOTTOMLEFT) or (Msg.wParam = WMSZ_TOPRIGHT) then
57773 begin
57774 PR := Pointer( Msg.lParam );
57775 GetWindowRect( Sender.fHandle, R );
57776 PostMessage( Sender.fHandle, CM_SIZEPOS, LoWord( PR.Left) or (PR.Top shl 16),
57777 LoWord( PR.Right - PR.Left ) or ( (PR.Bottom - PR.Top) shl 16) );
57778 if Msg.wParam = WMSZ_TOPLEFT then
57779 if Abs( R.Top - PR.Top ) < Abs( R.Left - PR.Left ) then
57780 PR.Top := R.Top
57781 else
57782 PR.Left := R.Left
57783 else
57784 if Msg.wParam = WMSZ_BOTTOMLEFT then
57785 if Abs( R.Bottom - PR.Bottom ) < Abs( R.Left - PR.Left ) then
57786 PR.Bottom := R.Bottom
57787 else
57788 PR.Left := R.Left
57789 else // WMSZ_TOPRIGHT
57790 if Abs( R.Top - PR.Top ) < Abs( R.Right - PR.Right ) then
57791 PR.Top := R.Top
57792 else
57793 PR.Right := R.Right;
57794 Sender.fNotUpdate := True;
57795 Rslt := 1;
57796 Result := TRUE;
57797 end;
57798 end;
57799 CM_SIZEPOS:
57800 begin
57801 Sender.fNotUpdate := False;
57802 SetWindowPos( Sender.fHandle, 0, SmallInt( LoWord( Msg.wParam ) ),
57803 SmallInt( HiWord( Msg.wParam ) ), SmallInt( LoWord( Msg.lParam ) ),
57804 SmallInt( HiWord( Msg.lParam ) ), SWP_NOZORDER or SWP_NOACTIVATE );
57805 end;
57806 WM_PAINT:
57807 begin
57808 if Sender.fNotUpdate then
57809 begin
57810 Rslt := 0;
57811 Result := True;
57812 end;
57813 end;
57814 WM_ERASEBKGND:
57815 begin
57816 if Sender.fNotUpdate then
57817 begin
57818 Rslt := 1;
57819 Result := True;
57820 end;
57821 end;
57822 end;
57823 end;
57826 //[function TControl.PreventResizeFlicks]
57827 function TControl.PreventResizeFlicks: PControl;
57828 begin
57829 fWndProcResizeFlicks := WndProcPreventResizeFlicks;
57830 Result := @Self;
57831 end;
57834 //[procedure TControl.Update]
57835 procedure TControl.Update;
57836 var I: Integer;
57837 C: PControl;
57838 begin
57839 if fUpdateCount > 0 then
57840 Exit;
57841 if fNotUpdate then Exit;
57842 if fHandle = 0 then Exit;
57843 UpdateWindow( fHandle );
57844 for I := 0 to fChildren.fCount - 1 do
57845 begin
57846 C := fChildren.fItems[ I ];
57847 C.Update;
57848 end;
57849 end;
57851 //[FUNCTION WndProcUpdate]
57852 {$IFDEF ASM_VERSION}
57853 function WndProcUpdate( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
57854 asm //cmd //opd
57855 PUSH EBX
57856 XCHG EBX, EAX
57857 MOV EAX, [EBX].TControl.fUpdateCount
57858 TEST EAX, EAX
57859 JZ @@exit
57861 XOR EAX, EAX
57862 MOV EDX, [EDX].TMsg.message
57863 CMP DX, WM_PAINT
57864 JNE @@chk_erasebkgnd
57866 MOV [ECX], EAX
57867 PUSH EAX
57868 PUSH [EBX].TControl.fHandle
57869 CALL ValidateRect
57870 JMP @@rslt_1
57871 @@chk_erasebkgnd:
57872 CMP DX, WM_ERASEBKGND
57873 JNE @@exit
57874 INC EAX
57875 MOV [ECX], EAX
57876 @@rslt_1:
57877 MOV AL, 1
57878 @@exit:
57879 POP EBX
57880 end;
57881 {$ELSE ASM_VERSION} //Pascal
57882 function WndProcUpdate( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
57883 begin
57884 if Sender.fUpdateCount > 0 then
57885 begin
57886 case Msg.message of
57887 WM_PAINT:
57888 begin
57889 ValidateRect( Sender.Handle, nil );
57890 Rslt := 0;
57891 end;
57892 WM_ERASEBKGND: Rslt := 1;
57893 else begin
57894 Result := FALSE;
57895 Exit;
57896 end;
57897 end;
57898 Result := TRUE;
57900 else Result := FALSE;
57901 end;
57902 {$ENDIF ASM_VERSION}
57903 //[END WndProcUpdate]
57905 //[procedure TControl.BeginUpdate]
57906 procedure TControl.BeginUpdate;
57907 begin
57908 Inc( fUpdateCount );
57909 AttachProc( @WndProcUpdate );
57910 end;
57912 //[procedure TControl.EndUpdate]
57913 procedure TControl.EndUpdate;
57914 begin
57915 Dec( fUpdateCount );
57916 if fUpdateCount <= 0 then
57917 begin
57918 Invalidate;
57919 //Update;
57920 end;
57921 end;
57924 //[function TControl.GetSelection]
57925 function TControl.GetSelection: String;
57926 var L: Integer;
57927 begin
57928 if fCommandActions.aGetSelection <> 0 then
57929 begin
57930 L := SelLength;
57931 SetString( Result, nil, L + 1 );
57932 Perform( fCommandActions.aGetSelection, 0, Integer( @Result[ 1 ] ) );
57934 else
57935 Result := Copy( Text, SelStart + 1, SelLength );
57936 end;
57939 //[procedure TControl.SetSelection]
57940 procedure TControl.SetSelection(const Value: String);
57941 begin
57942 ReplaceSelection( Value, True );
57943 end;
57946 //[procedure TControl.ReplaceSelection]
57947 procedure TControl.ReplaceSelection(const Value: String; aCanUndo: Boolean);
57948 begin
57949 if fCommandActions.aReplaceSel <> 0 then
57950 begin
57951 Perform( fCommandActions.aReplaceSel, Integer( aCanUndo ), Integer( Pchar( Value ) ) );
57952 end;
57953 end;
57955 //[procedure TControl.DeleteLines]
57956 procedure TControl.DeleteLines(FromLine, ToLine: Integer);
57957 var I1, I2: Integer;
57958 SStart, SLength: Integer;
57959 begin
57960 if FromLine > ToLine then Exit;
57961 Assert( FromLine >= 0, 'Incorrect line index' );
57962 I1 := Item2Pos( FromLine );
57963 I2 := Item2Pos( ToLine+1 );
57964 SStart := SelStart;
57965 SLength := SelLength;
57966 SelStart := I1;
57967 SelLength := I2 - I1;
57968 ReplaceSelection( '', TRUE );
57969 if SStart >= I2 then
57970 begin
57971 SStart := SStart - (I2 - I1);
57973 else
57974 if SStart >= I1 then
57975 begin
57976 SLength := SLength - (I2 - SStart);
57977 SStart := I1;
57979 else
57980 if SStart + SLength >= I2 then
57981 begin
57982 SLength := SLength - (I2 - I1);
57984 else
57985 if SStart + SLength >= I1 then
57986 begin
57987 SLength := I1 - SLength;
57988 end;
57989 SelStart := SStart;
57990 SelLength := Max( 0, SLength );
57991 end;
57994 //[procedure TControl.SetTabOrder]
57995 procedure TControl.SetTabOrder(const Value: Integer);
57996 var CL: PList;
57997 I : Integer;
57998 C: PControl;
57999 begin
58000 if Value = fTabOrder then Exit;
58001 CL := CollectTabControls( ParentForm );
58002 for I := 0 to CL.fCount - 1 do
58003 begin
58004 C := CL.fItems[ I ];
58005 if C.fTabOrder >= Value then
58006 Inc( C.fTabOrder );
58007 end;
58008 fTabOrder := Value;
58009 CL.Free;
58010 end;
58013 //[function TControl.GetFocused]
58014 function TControl.GetFocused: Boolean;
58015 begin
58016 if fIsControl then
58017 Result := ParentForm.fCurrentControl = @Self
58018 else
58019 Result := GetForegroundWindow = fHandle;
58020 end;
58023 //[procedure TControl.SetFocused]
58024 procedure TControl.SetFocused(const Value: Boolean);
58025 var PF: PControl;
58026 begin
58027 if not Value or not fTabStop then Exit;
58028 if fIsControl then
58029 begin
58030 PF := ParentForm;
58031 if Assigned( PF.fCurrentControl ) and (PF.fCurrentControl <> @ Self) then
58032 if Assigned( PF.fCurrentControl.fLeave ) then
58033 PF.fCurrentControl.fLeave( PF.fCurrentControl )
58034 else
58035 //ParentForm.fCurrentControl.Perform( WM_KILLFOCUS, 0, 0 );
58036 Windows.SetFocus( 0 );
58037 PF.fCurrentControl := @Self;
58038 if Assigned( fSetFocus ) then
58039 fSetFocus
58040 else
58041 SetFocus( GetWindowHandle );
58043 else
58044 begin
58045 SetForegroundWindow( GetWindowHandle );
58046 //SetFocus( fHandle );
58047 end;
58048 end;
58050 type
58051 PCharFormat = ^TCharFormat;
58058 //////////////////////////////////////////////////////////////////////
58061 // R I C H E D I T
58064 //////////////////////////////////////////////////////////////////////
58066 { -- rich edit -- }
58069 //[function TControl.REGetFont]
58070 function TControl.REGetFont: PGraphicTool;
58071 var CF: PCharFormat;
58072 FS: TFontStyle;
58073 begin
58074 CF := @fRECharFormatRec;
58075 FillChar( CF^, 82 {sizeof( TCharFormat2 )}, 0 );
58076 CF.cbSize := sizeof( RichEdit.TCharFormat ) + fCharFmtDeltaSz;
58077 if fTmpFont = nil then
58078 fTmpFont := NewFont;
58079 Result := fTmpFont;
58080 Result.OnChange := nil;
58081 Perform( EM_GETCHARFORMAT, 1, Integer( CF ) );
58082 Result.FontHeight := CF.yHeight;
58083 FS := [ ];
58084 if LongBool(CF.dwEffects and CFE_BOLD) then
58085 FS := [ fsBold ];
58086 if LongBool(CF.dwEffects and CFE_ITALIC) then
58087 FS := FS + [ fsItalic ];
58088 if LongBool(CF.dwEffects and CFE_STRIKEOUT) then
58089 FS := FS + [ fsStrikeOut ];
58090 if LongBool(CF.dwEffects and CFE_UNDERLINE) then
58091 FS := FS + [ fsUnderline ];
58092 Result.FontStyle := FS;
58093 if not LongBool(CF.dwEffects and CFE_AUTOCOLOR) then
58094 Result.Color := CF.crTextColor;
58095 Result.FontPitch := TFontPitch( CF.bPitchAndFamily and 3 );
58096 Result.FontCharset := CF.bCharSet;
58097 Result.FontName := CF.szFaceName;
58098 Result.OnChange := RESetFont;
58099 end;
58101 const RichAreas: array[ TRichFmtArea ] of Integer = ( SCF_SELECTION,
58102 SCF_WORD, 4 {SCF_ALL} );
58105 //[procedure TControl.RESetFontEx]
58106 procedure TControl.RESetFontEx(const Index: Integer);
58107 var CF: PCharFormat;
58108 FS: TFontStyle;
58109 begin
58110 CF := @fRECharFormatRec;
58111 FillChar( CF^, {82} sizeof( TCharFormat2 ), 0 );
58112 CF.cbSize := 60 { sizeof( TCharFormat ) } + fCharFmtDeltaSz;
58113 CF.dwMask := CFM_BOLD or CFM_COLOR or CFM_FACE or CFM_ITALIC
58114 or CFM_SIZE or CFM_STRIKEOUT or CFM_UNDERLINE;
58115 CF.yHeight := fTmpFont.FontHeight;
58116 FS := fTmpFont.FontStyle;
58117 if fsBold in FS then CF.dwEffects := CFE_BOLD;
58118 if fsItalic in FS then CF.dwEffects := CF.dwEffects or CFE_ITALIC;
58119 if fsStrikeOut in FS then CF.dwEffects := CF.dwEffects or CFE_STRIKEOUT;
58120 if fsUnderline in FS then CF.dwEffects := CF.dwEffects or CFE_UNDERLINE;
58121 CF.crTextColor := Color2RGB(fTmpFont.Color);
58122 CF.bCharSet := fTmpFont.FontCharset;
58123 CF.bPitchAndFamily := Ord( fTmpFont.FontPitch );
58124 StrLCopy( CF.szFaceName, PChar( fTmpFont.FontName ), 31 );
58125 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( CF ) );
58126 end;
58129 //[procedure TControl.RESetFont]
58130 procedure TControl.RESetFont(Value: PGraphicTool);
58131 var H: Integer;
58132 begin
58133 if Value <> fTmpFont then
58134 REGetFont;
58135 H := fTmpFont.fData.Font.Height;
58136 fTmpFont := fTmpFont.Assign( Value );
58137 if fTmpFont.fData.Font.Height = 0 then
58138 fTmpFont.fData.Font.Height := H;
58139 RESetFontEx( Integer( CFM_BOLD or CFM_COLOR or CFM_FACE or CFM_ITALIC
58140 or CFM_SIZE or CFM_STRIKEOUT or CFM_UNDERLINE ) );
58141 end;
58144 //[function TControl.REGetFontMask]
58145 function TControl.REGetFontMask( const Index: Integer ): Boolean;
58146 begin
58147 REGetFont;
58148 Result := LongBool( fRECharFormatRec.dwMask and Index );
58149 end;
58152 //[function TControl.REGetFontEffects]
58153 function TControl.REGetFontEffects(const Index: Integer): Boolean;
58154 begin
58155 REGetFont;
58156 Result := LongBool( fRECharFormatRec.dwEffects and Index );
58157 end;
58160 //[procedure TControl.RESetFontEffect]
58161 procedure TControl.RESetFontEffect(const Index: Integer;
58162 const Value: Boolean);
58163 var CF: PCharFormat;
58164 begin
58165 ReGetFont;
58166 CF := @fRECharFormatRec;
58167 CF.dwEffects := $FFFFFFFF and Index;
58168 if not Value then CF.dwEffects := 0;
58169 CF.dwMask := Index;
58170 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( CF ) );
58171 end;
58174 //[function TControl.REGetFontAttr]
58175 function TControl.REGetFontAttr(const Index: Integer): Integer;
58176 var CF: PDWORD;
58177 Mask: DWORD;
58178 begin
58179 REGetFont;
58180 CF := Pointer( Integer( @fRECharFormatRec ) + (HiWord(Index) and $7E) );
58181 Mask := $FFFFFFFF;
58182 if LongBool( HiWord(Index) and $1 ) then
58183 Mask := $FF;
58184 Result := CF^ and Mask;
58185 end;
58188 //[procedure TControl.RESetFontAttr]
58189 procedure TControl.RESetFontAttr(const Index, Value: Integer);
58190 {const
58191 CFE_MASK = CFE_AUTOCOLOR or CFE_BOLD or CFE_ITALIC or CFE_PROTECTED or CFE_STRIKEOUT or
58192 CFE_UNDERLINE or CFE_LINK or CFE_SUBSCRIPT or CFE_SUPERSCRIPT or}
58193 var CF: PDWORD;
58194 Mask: DWORD;
58195 begin
58196 REGetFont;
58197 CF := Pointer( Integer( @fRECharFormatRec ) + (HiWord(Index) and $7E) );
58198 Mask := 0;
58199 if LongBool( HiWord(Index) and $1 ) then
58200 Mask := $FFFFFF00;
58201 CF^ := CF^ and Mask or DWORD(Value);
58202 fRECharFormatRec.dwMask := Index and $FF81FFFF;
58203 if LongBool( fRECharFormatRec.dwMask and (CFM_COLOR or CFM_BACKCOLOR) ) then
58204 fRECharFormatRec.dwEffects := fRECharFormatRec.dwEffects and
58205 not (CFE_AUTOCOLOR or CFE_AUTOBACKCOLOR);
58206 {fRECharFormatRec.dwEffects := fRECharFormatRec.dwEffects and CFE_MASK;}
58207 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @fRECharFormatRec ) );
58208 end;
58210 //[procedure TControl.RESetFontAttr1]
58211 procedure TControl.RESetFontAttr1(const Index, Value: Integer);
58212 begin
58213 RESetFontAttr( Index, Color2RGB( Value ) );
58214 end;
58217 //[function TControl.REGetFontSizeValid]
58218 function TControl.REGetFontSizeValid: Boolean;
58219 begin
58220 Result := REGetFontMask( Integer( CFM_SIZE ) );
58221 end;
58224 //[function TControl.REGetFontName]
58225 function TControl.REGetFontName: String;
58226 begin
58227 ReGetFont;
58228 Result := fRECharFormatRec.szFaceName;
58229 end;
58232 //[procedure TControl.RESetFontName]
58233 procedure TControl.RESetFontName(const Value: String);
58234 begin
58235 ReGetFont;
58236 StrLCopy( fRECharFormatRec.szFaceName, PChar( Value ), Sizeof( fRECharFormatRec.szFaceName ) - 1 );
58237 fRECharFormatRec.dwMask := CFM_FACE;
58238 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @fRECharFormatRec ) );
58239 end;
58242 //[procedure TControl.SelectAll]
58243 procedure TControl.SelectAll;
58244 begin
58245 SelStart := 0;
58246 SelLength := -1; // this can be not working for some controls... //*//*
58247 end;
58250 //[function TControl.REGetCharformat]
58251 function TControl.REGetCharformat: TCharFormat;
58252 begin
58253 REGetFont;
58254 Result := fRECharFormatRec;
58255 end;
58258 //[procedure TControl.RESetCharFormat]
58259 procedure TControl.RESetCharFormat(const Value: TCharFormat);
58260 begin
58261 Perform( EM_SETCHARFORMAT, RichAreas[ fRECharArea ], Integer( @Value ) );
58262 end;
58265 //[function REOut2Stream]
58266 function REOut2Stream( Sender: PControl; Buf: PByte; Sz: DWORD; pSz: PInteger )
58267 :DWORD; stdcall;
58268 begin
58269 if Sz + Sender.fREStream.Position > Sender.fREStream.Size then
58270 Sender.fREStream.Size := Sender.fREStream.Size + DWORD( {Min(} Sz {, 8192 )} );
58271 pSz^ := Sender.fREStream.Write( Buf^, Sz );
58272 if Assigned( Sender.fOnProgress ) then
58273 Sender.fOnProgress( Sender );
58274 Result := 0;
58275 end;
58277 const TextTypes: array[ TRETextFormat ] of WORD = ( SF_RTF, SF_TEXT,
58278 SF_RTF or SFF_PLAINRTF, SF_RTFNOOBJS, SF_RTFNOOBJS or SFF_PLAINRTF,
58279 SF_TEXTIZED );
58282 //[function TControl.RE_SaveToStream]
58283 function TControl.RE_SaveToStream(Stream: PStream; Format: TRETextFormat;
58284 SelectionOnly: Boolean): Boolean;
58285 var ES: TEditStream;
58286 SelFlag: Integer;
58287 begin
58288 fREStream := Stream;
58289 ES.dwCookie := Integer( @Self );
58290 ES.dwError := 0;
58291 ES.pfnCallback := @REOut2Stream;
58292 SelFlag := 0;
58293 if SelectionOnly then
58294 SelFlag := SFF_SELECTION;
58295 Perform( EM_STREAMOUT, TextTypes[ Format ] or SelFlag, Integer( @ES ) );
58296 fREStream := nil;
58297 fREError := ES.dwError;
58298 Result := fREError = 0;
58299 end;
58301 //[procedure RE_AddText]
58302 procedure RE_AddText( Self_: PControl; const S: String );
58303 begin
58304 Self_.SelStart := Self_.TextSize;
58305 Self_.RE_Text[ reText, True ] := S;
58306 end;
58309 //[function TControl.REReadText]
58310 function TControl.REReadText(Format: TRETextFormat;
58311 SelectionOnly: Boolean): String;
58312 var B0: Integer;
58313 MS: PStream;
58314 begin
58315 fCommandActions.aAddText := RE_AddText;
58316 MS := NewMemoryStream;
58317 RE_SaveToStream( MS, Format, SelectionOnly );
58318 B0 := 0;
58319 MS.Write( B0, 1 );
58320 Result := PChar( MS.fMemory );
58321 MS.Free;
58322 end;
58325 //[function REInFromStream]
58326 function REInFromStream( Sender: PControl; Buf: PByte; Sz: DWORD; pSz: PInteger )
58327 :DWORD; stdcall;
58328 begin
58329 {$IFDEF _D3} if Sender.fREStrLoadLen >= 0 then {$ENDIF}
58330 if Sz > Sender.fREStrLoadLen then
58331 Sz := Sender.fREStrLoadLen;
58332 pSz^ := Sender.fREStream.Read( Buf^, Sz );
58333 Dec( Sender.fREStrLoadLen, pSz^ );
58334 if Assigned( Sender.fOnProgress ) then
58335 Sender.fOnProgress( Sender );
58336 Result := 0;
58337 end;
58340 //[function TControl.RE_LoadFromStream]
58341 function TControl.RE_LoadFromStream(Stream: PStream; Length: Integer;
58342 Format: TRETextFormat; SelectionOnly: Boolean): Boolean;
58343 var ES: TEditStream;
58344 SelFlag: Integer;
58345 begin
58346 fREStream := Stream;
58347 fREStrLoadLen := DWORD( Length );
58348 ES.dwCookie := Integer( @Self );
58349 ES.dwError := 0;
58350 ES.pfnCallback := @REInFromStream;
58351 SelFlag := 0;
58352 if SelectionOnly then
58353 SelFlag := SFF_SELECTION;
58354 Perform( EM_STREAMIN, TextTypes[ Format ] or SelFlag, Integer( @ES ) );
58355 fREStream := nil;
58356 fREError := ES.dwError;
58357 Result := fREError = 0;
58358 end;
58361 //[procedure TControl.REWriteText]
58362 procedure TControl.REWriteText(Format: TRETextFormat;
58363 SelectionOnly: Boolean; const Value: String);
58364 var MS: PStream;
58365 begin
58366 fCommandActions.aAddText := RE_AddText;
58367 MS := NewMemoryStream;
58368 MS.fMemory := PChar( Value );
58369 MS.fData.fSize := Length( Value );
58370 MS.fData.fCapacity := MS.fData.fSize;
58371 RE_LoadFromStream( MS, MS.fData.fSize, Format, SelectionOnly );
58372 MS.fMemory := nil;
58373 MS.Free;
58374 end;
58377 //[function TControl.RE_LoadFromFile]
58378 function TControl.RE_LoadFromFile(const Filename: String;
58379 Format: TRETextFormat; SelectionOnly: Boolean): Boolean;
58380 var Strm: PStream;
58381 begin
58382 Strm := NewReadFileStream( Filename );
58383 Result := RE_LoadFromStream( Strm, -1, Format, SelectionOnly );
58384 Strm.Free;
58385 end;
58388 //[function TControl.RE_SaveToFile]
58389 function TControl.RE_SaveToFile(const Filename: String;
58390 Format: TRETextFormat; SelectionOnly: Boolean): Boolean;
58391 var Strm: PStream;
58392 begin
58393 Strm := NewWriteFileStream( Filename );
58394 Result := RE_SaveToStream( Strm, Format, SelectionOnly );
58395 Strm.Free;
58396 end;
58399 //[function TControl.REGetParaFmt]
58400 function TControl.REGetParaFmt: TParaFormat;
58401 begin
58402 FillChar( Result, sizeof( TParaFormat2 ), 0 );
58403 Result.cbSize := sizeof( RichEdit.TParaFormat ) + fParaFmtDeltaSz;
58404 Perform( EM_GETPARAFORMAT, 0, Integer( @Result ) );
58405 end;
58408 //[procedure TControl.RESetParaFmt]
58409 procedure TControl.RESetParaFmt(const Value: TParaFormat);
58410 begin
58411 //Value.cbSize := szTParaFmtRec;
58412 Perform( EM_SETPARAFORMAT, 0, Integer( @Value ) );
58413 end;
58416 //[function TControl.REGetNumbering]
58417 function TControl.REGetNumbering: Boolean;
58418 begin
58419 Result := LongBool( ReGetParaAttr( 9 shl 16 ) );
58420 end;
58423 //[function TControl.REGetParaAttr]
58424 function TControl.REGetParaAttr( const Index: Integer ): Integer;
58425 var pDw : PDWORD;
58426 begin
58427 fREParaFmtRec := REGetParaFmt;
58428 pDw := Pointer( Integer( @fREParaFmtRec ) + ( HiWord( Index ) and $7E ) );
58429 Result := pDw^;
58430 if LongBool( HiWord( Index ) and 1 ) then
58431 Result := Result and $FFFF;
58432 end;
58435 //[function TControl.REGetParaAttrValid]
58436 function TControl.REGetParaAttrValid( const Index: Integer ): Boolean;
58437 begin
58438 Result := LongBool( ReGetParaAttr( 4 shl 16 ) and Index );
58439 end;
58442 //[function TControl.REGetTabCount]
58443 function TControl.REGetTabCount: Integer;
58444 begin
58445 Result := ReGetParaAttr( 27 shl 16 );
58446 end;
58449 //[function TControl.REGetTabs]
58450 function TControl.REGetTabs(Idx: Integer): Integer;
58451 begin
58452 Result := ReGetParaAttr( (28 + 4 * Idx) shl 16 );
58453 end;
58456 //[function TControl.REGetTextAlign]
58457 function TControl.REGetTextAlign: TRichTextAlign;
58458 begin
58459 Result := TRichTextAlign( ReGetParaAttr( 25 shl 16 ) - 1 );
58460 end;
58463 //[procedure TControl.RESetNumbering]
58464 procedure TControl.RESetNumbering(const Value: Boolean);
58465 begin
58466 RESetParaAttr( (9 shl 16) or PFM_NUMBERING, Integer( Value ) );
58467 end;
58470 //[procedure TControl.RESetParaAttr]
58471 procedure TControl.RESetParaAttr(const Index, Value: Integer);
58472 var pDw: PDWORD;
58473 Mask: Integer;
58474 begin
58475 REGetParaAttr( 0 );
58476 pDw := Pointer( Integer( @fREParaFmtRec ) + ( HiWord( Index ) and $7E ) );
58477 Mask := 0;
58478 if LongBool( HiWord( Index ) and 1 ) then
58479 Mask := Integer( $FFFF0000 );
58480 pDw^ := pDw^ and Mask or DWORD(Value);
58481 //////////////////////////////////////////////////////////////////////////////
58482 fREParaFmtRec.dwMask := Index and $8000FFFF;
58483 //////////////////////////////////////////////////////////////////////////////
58484 //fREParaFmtRec.dwMask := DWORD( Index ) or $8000FFFF; //
58485 //////////////////////////////////////////////////////////////////////////////
58486 RESetParaFmt( fREParaFmtRec );
58487 end;
58490 //[procedure TControl.RESetTabCount]
58491 procedure TControl.RESetTabCount(const Value: Integer);
58492 begin
58493 REGetParaAttr( 0 );
58494 RESetParaAttr( (27 shl 16) or PFM_TABSTOPS, Value );
58495 end;
58498 //[procedure TControl.RESetTabs]
58499 procedure TControl.RESetTabs(Idx: Integer; const Value: Integer);
58500 begin
58501 REGetParaAttr( 0 );
58502 RESetParaAttr( (28 + 4 * Idx) or PFM_TABSTOPS, Value );
58503 end;
58506 //[procedure TControl.RESetTextAlign]
58507 procedure TControl.RESetTextAlign(const Value: TRichTextAlign);
58508 begin
58509 RESetParaAttr( (25 shl 16) or PFM_ALIGNMENT, Ord( Value ) + 1 );
58510 end;
58513 //[function TControl.REGetStartIndentValid]
58514 function TControl.REGetStartIndentValid: Boolean;
58515 begin
58516 Result := REGetParaAttrValid( Integer( PFM_STARTINDENT ) );
58517 end;
58520 //[procedure TControl.RE_HideSelection]
58521 procedure TControl.RE_HideSelection(aHide: Boolean);
58522 begin
58523 Perform( EM_HIDESELECTION, Integer( aHide ), 1 );
58524 end;
58527 //[function TControl.RE_SearchText]
58528 function TControl.RE_SearchText(const Value: String; MatchCase,
58529 WholeWord, ScanForward: Boolean; SearchFrom, SearchTo: Integer): Integer;
58530 var Flags: Integer;
58531 FT: TFindText;
58532 begin
58533 Flags := Integer( ScanForward );
58534 if WholeWord then Flags := Flags or FT_WHOLEWORD;
58535 if MatchCase then Flags := Flags or FT_MATCHCASE;
58536 FT.chrg.cpMin := SearchFrom;
58537 FT.chrg.cpMax := SearchTo;
58538 FT.lpstrText := PChar( Value );
58539 Result := Perform( EM_FINDTEXT, Flags, Integer( @FT ) );
58540 end;
58543 //[function TControl.CanUndo]
58544 function TControl.CanUndo: Boolean;
58545 begin
58546 Result := LongBool( Perform( EM_CANUNDO, 0, 0 ) );
58547 end;
58550 //[procedure TControl.EmptyUndoBuffer]
58551 procedure TControl.EmptyUndoBuffer;
58552 begin
58553 Perform( EM_EMPTYUNDOBUFFER, 0, 0 );
58554 end;
58557 //[function TControl.Undo]
58558 function TControl.Undo: Boolean;
58559 begin
58560 Result := LongBool( Perform( EM_UNDO, 0, 0 ) );
58561 end;
58564 //[function TControl.RE_Redo]
58565 function TControl.RE_Redo: Boolean;
58566 begin
58567 Result := LongBool( Perform( EM_REDO, 0, 0 ) );
58568 end;
58571 //[function TControl.REGetAutoURLDetect]
58572 function TControl.REGetAutoURLDetect: Boolean;
58573 begin
58574 Result := LongBool( Perform( EM_GETAUTOURLDETECT, 0, 0 ) );
58575 end;
58578 //[procedure TControl.RESetAutoURLDetect]
58579 procedure TControl.RESetAutoURLDetect(const Value: Boolean);
58580 begin
58581 AttachProc( WndProc_RE_LinkNotify );
58582 Perform( EM_AUTOURLDETECT, Integer( Value ), 0 );
58583 end;
58586 //[function TControl.GetMaxTextSize]
58587 function TControl.GetMaxTextSize: DWORD;
58588 begin
58589 Result := Perform( EM_GETLIMITTEXT, 0, 0 );
58590 end;
58593 //[procedure TControl.SetMaxTextSize]
58594 procedure TControl.SetMaxTextSize(const Value: DWORD);
58595 var V1, V2: Integer;
58596 begin
58597 if fCommandActions.aSetLimit <> 0 then
58598 begin
58599 V1 := 0; V2 := Value;
58600 if fCommandActions.aSetLimit = EM_SETLIMITTEXT then
58601 begin
58602 V1 := Value; V2 := 0;
58603 end;
58604 Perform( fCommandActions.aSetLimit, V1, V2 );
58605 end;
58606 end;
58609 //[function WndProc_REFmt]
58610 function WndProc_REFmt( _Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
58611 var Mask: Integer;
58612 Shft, Flg: Boolean;
58613 Delta: Integer;
58614 TA: TRichTextAlign;
58615 ChgTA: Boolean;
58616 US: TRichUnderline;
58617 NS: TRichNumbering;
58618 NB: TRichNumBrackets;
58619 Side: TBorderEdge;
58620 Param: DWORD;
58621 begin
58622 Result := False;
58623 if Msg.message = WM_CHAR then
58624 if _Self_.FSupressTab then
58625 begin
58626 _Self_.FSupressTab := FALSE;
58627 if Msg.wParam = 9 then
58628 begin
58629 Result := TRUE;
58630 Exit;
58631 end;
58632 end;
58634 if Msg.message = WM_KEYDOWN then
58635 if GetKeyState( VK_CONTROL ) < 0 then
58636 begin
58637 Shft := GetKeyState( VK_SHIFT ) < 0;
58638 Rslt := 0;
58639 Result := True;
58640 Mask := 0;
58641 ChgTA := False; TA := raLeft;
58642 Param := Msg.wParam;
58643 //Msg.wParam := 0;
58644 case Param of
58645 Integer('Z'):
58646 begin
58647 if Shft then
58648 begin
58649 _Self_.RE_Redo;
58650 Exit;
58651 end;
58652 Result := False;
58653 end;
58655 Integer('L'): begin ChgTA := True; TA := raLeft; end;
58656 Integer('R'): begin ChgTA := True; TA := raRight; end;
58657 Integer('E'): begin ChgTA := True; TA := raCenter; end;
58658 Integer('J'): begin ChgTA := True; TA := raJustify; end;
58659 Integer('N'): begin
58660 if Shft then
58661 begin
58662 NS := _Self_.RE_NumStyle;
58663 NB := _Self_.RE_NumBrackets;
58664 if NS = rnBullets then
58665 begin
58666 _Self_.RE_NumStyle := rnNone;
58667 Exit;
58668 end;
58669 if NS = rnNone then
58670 begin
58671 _Self_.RE_NumStyle := rnBullets;
58672 //NB := rnbPlain;
58673 Exit;
58675 else
58676 if Ord( NB ) = 0 then
58677 NB := High(NB) else
58678 NB := Pred(NB);
58679 _Self_.RE_NumBrackets := NB;
58681 else
58682 begin
58683 NS := _Self_.RE_NumStyle;
58684 if Ord( NS ) = 0 then
58685 begin
58686 NS := rnURoman; //rnULetter; //High( NS );
58687 { because rnLRoman, rnURoman, rnNoNumber are not shown
58688 in RichEdit. }
58689 _Self_.RE_NumBrackets := rnbPeriod;
58690 end else
58691 NS := Pred(NS);
58692 _Self_.RE_NumStyle := NS;
58693 if NS in [ rnLRoman, rnURoman, rnArabic ] then
58694 _Self_.RE_NumStart := 1;
58695 end;
58696 Exit;
58697 end;
58698 Integer('W'): begin
58699 Delta := _Self_.RE_BorderWidth[ beLeft ] + 4;
58700 if Shft then Delta := -1;
58701 for Side := Low(Side) to High(Side) do
58702 begin
58703 if Delta < 0 then
58704 _Self_.RE_BorderStyle[ Side ] := _Self_.RE_BorderStyle[ Side ] + 1
58705 else
58706 begin
58707 _Self_.RE_BorderWidth[ Side ] := Delta;
58708 _Self_.RE_BorderSpace[ Side ] := Delta;
58709 end;
58710 end;
58711 Exit;
58712 end;
58713 (* TABLES STUFF -- to try, uncomment it and press CTRL+T in RichEdit.
58714 (and uncomment declaration for Tmp above).
58716 Not finished, and seems no way to figure it out - even RichEdit20.dll
58717 (i.e. Rich Edit v3.0) can not display tables properly formatted. :(((
58719 Integer('T'): begin
58720 if _Self_.RE_Table then
58721 begin
58722 //MsgOK( 'table' );
58723 end;
58724 Tmp := _Self_.REReadText( reRTF, True );
58725 if StrIsStartingFrom( PChar(Tmp), '{\rtf' )
58726 and (CopyTail( Tmp, 3 ) = '}'#$D#$A) then
58727 begin
58728 //Tmp := Copy( Tmp, 1, Length(Tmp) - 3 );
58729 _Self_.RE_Text[ reRTF, True ] := '{\rtf1' + //Copy( Tmp, 1, 6 ) +
58730 '\trowd' +
58731 //'\lytcalctblwd' +
58732 //'\oldlinewrap' +
58733 //'\alntblind' +
58734 //'\trgaph108' +
58735 '\trleft-108' +
58736 {'\trbrdrt\brdrs\brdrw10' +
58737 '\trbrdrl\brdrs\brdrw10' +
58738 '\trbrdrb\brdrs\brdrw10' +
58739 '\trbrdrr\brdrs\brdrw10' +
58740 '\trbrdrh\brdrs\brdrw10' +
58741 '\trbrdrv\brdrs\brdrw10' +}
58742 //'\clvertalt' +
58743 {'\clbrdrt\brdrs\brdrw10' +
58744 '\clbrdrl\brdrs\brdrw10' +
58745 '\clbrdrb\brdrs\brdrw10' +
58746 '\clbrdrr\brdrs\brdrw10' +}
58747 //'\cltxlrtb' +
58748 '\cellx1414' +
58749 //'\pard' +
58750 //'\plain' +
58751 //'\widctlpar' +
58752 '\trautofit1' +
58753 '\intbl' +
58754 //'\adjustright' +
58755 //'\fs20\lang1049' +
58756 //'\cgrid' +
58757 '\trrh0' +
58758 '{\clFitText{{\box\brdrs\brdrw20\brsp20}'+
58759 '\par}\cell\row}' +
58760 //'\pard\widctlpar' +
58761 //'\intbl'+
58762 //'\adjustright'+
58763 //'{\row}' +
58764 '\pard\widctlpar' +
58765 '}'#$D#$A;
58766 _Self_.Perform( WM_KEYDOWN, VK_UP, 0 );
58767 _Self_.Perform( WM_KEYUP, VK_UP, 0 );
58768 end;
58769 Exit;
58770 end;
58772 Integer('B'): Mask := CFM_BOLD;
58773 Integer('I'):
58774 begin
58775 Mask := CFM_ITALIC;
58776 _Self_.FSupressTab := TRUE;
58777 end;
58778 Integer('U'):
58779 begin
58780 if Shft then
58781 begin
58782 US := _Self_.RE_FmtUnderlineStyle;
58783 if Ord(US) = 0 then US := High(TRichUnderLine)
58784 else US := Pred( US );
58785 _Self_.RE_FmtUnderlineStyle := US;
58786 Exit;
58787 end;
58788 Mask := CFM_UNDERLINE;
58789 end;
58790 Integer('O'): Mask := CFM_STRIKEOUT;
58791 VK_SUBTRACT, VK_ADD: Mask := Integer( CFM_SIZE );
58792 else
58793 begin
58794 Result := False;
58795 Msg.wParam := Param;
58796 end;
58797 end;
58798 if not Result then Exit;
58800 if ChgTA then
58801 begin
58802 if Shft then Result := False
58803 else _Self_.RE_TextAlign := TA;
58804 Exit;
58805 end;
58807 _Self_.REGetFont;
58808 if Mask > 0 then
58809 begin
58810 if Shft then Result := False
58811 else begin
58812 Flg := _Self_.REGetFontEffects( Mask );
58813 if not Flg then
58814 _Self_.fRECharFormatRec.dwEffects := _Self_.fRECharFormatRec.dwEffects and not Mask;
58815 _Self_.fRECharFormatRec.dwEffects := _Self_.fRECharFormatRec.dwEffects xor DWORD(Mask);
58816 end;
58818 else
58819 begin
58820 if Msg.wParam = VK_SUBTRACT then
58821 Delta := -1
58822 else
58823 Delta := 1;
58824 if Shft then
58825 Mask := CFM_OFFSET;
58826 if Shft then
58827 Inc( _Self_.fRECharFormatRec.yOffset, Delta * _Self_.fRECharFormatRec.yHeight div 3 )
58828 else
58829 Inc( _Self_.fRECharFormatRec.yHeight, Delta * _Self_.fRECharFormatRec.yHeight div 8 );
58830 Flg := LongBool( _Self_.fRECharFormatRec.dwMask and Mask );
58831 if not Flg then
58832 _Self_.fRECharFormatRec.yOffset := 0;
58833 end;
58834 _Self_.fRECharFormatRec.dwMask := Mask;
58835 _Self_.Perform( EM_SETCHARFORMAT, SCF_SELECTION { RichAreas[ _Self_.fRECharArea ] }, Integer( @_Self_.fRECharFormatRec ) );
58836 end;
58837 end;
58840 //[function TControl.RE_FmtStandard]
58841 function TControl.RE_FmtStandard: PControl;
58842 begin
58843 AttachProc( WndProc_REFmt );
58844 Result := @Self;
58845 end;
58847 //[FUNCTION EnumDynHandlers]
58848 {$IFDEF ASM_VERSION}
58849 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
58850 asm //cmd //opd
58851 CMP [EAX].TControl.fRefCount, 0
58852 JL @@fin_false
58853 PUSHAD
58854 MOV EBX, EAX
58855 MOV EBP, ECX
58856 MOV ECX, [EBX].TControl.fDynHandlers
58857 JECXZ @@ret_false
58858 MOV ESI, ECX
58859 MOV ECX, [ESI].TList.fCount
58860 JECXZ @@ret_false
58861 MOV EDI, ECX
58862 SHR EDI, 1
58863 CALL TControl.RefInc
58864 @@loo: DEC EDI
58865 JS @@e_loo
58866 PUSH EDX
58867 PUSH EBX
58868 {$IFNDEF ENUM_DYN_HANDLERS_AFTER_RUN}
58869 XOR EAX, EAX
58870 CMP [AppletTerminated], AL
58871 JZ @@do_call
58872 MOV ECX, [ESI].TList.fItems
58873 MOV ECX, [ECX+EDI*8+4]
58874 JECXZ @@skip_call
58875 {$ENDIF}
58876 @@do_call:
58877 MOV EAX, [ESI].TList.fItems
58878 MOV EAX, [EAX+EDI*8]
58879 XCHG EAX, EBX
58880 MOV ECX, EBP
58881 CALL EBX
58882 @@skip_call:
58883 POP EBX
58884 POP EDX
58885 TEST AL, AL
58886 JZ @@loo
58887 @@ret_true:
58888 MOV EAX, EBX
58889 CALL TControl.RefDec
58890 POPAD
58891 MOV AL, 1
58893 @@e_loo:
58894 XOR EAX, EAX
58895 INC EAX
58896 CMP [EBX].TControl.fRefCount, EAX
58897 JE @@ret_true
58898 MOV EAX, EBX
58899 CALL TControl.RefDec
58900 @@ret_false:
58901 POPAD
58902 @@fin_false:
58903 XOR EAX, EAX
58904 end;
58905 {$ELSE ASM_VERSION} //Pascal
58906 function EnumDynHandlers( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
58907 var I: Integer;
58908 Proc: TWindowFunc;
58909 begin
58910 Result := False;
58911 if Self_.fRefCount < 0 then Exit;
58912 if (Self_.fDynHandlers = nil) or (Self_.fDynHandlers.fCount = 0) then Exit;
58913 Self_.RefInc; // Prevent destroying Self_
58914 for I := Self_.fDynHandlers.fCount div 2 - 1 downto 0 do
58915 begin
58916 Proc := Self_.fDynHandlers.fItems[ I * 2 ];
58917 {$IFNDEF ENUM_DYN_HANDLERS_AFTER_RUN}
58918 if not AppletTerminated or (Self_.fDynHandlers.fItems[ I * 2 + 1 ] <> nil) then
58919 {$ENDIF}
58920 if Proc( Self_, Msg, Rslt ) then
58921 begin
58922 Result := True;
58923 break;
58924 end;
58925 end;
58926 {$IFDEF DEBUG_ENDSESSION}
58927 if EndSession_Initiated then
58928 begin
58929 LogFileOutput( GetStartDir + 'es_debug.txt',
58930 'ENUM_DYN_HANDLERS: Self_:' + Int2Hex( DWORD( Self_ ), 8 ) );
58931 LogFileOutput( GetStartDir + 'es_debug.txt',
58932 'ENUM_DYN_HANDLERS: Self_.fRefCount:' + Int2Str( Self_.fRefCount ) );
58933 end;
58934 {$ENDIF}
58935 if LongBool(Self_.fRefCount and 1) then
58936 Result := True; // If Self_ will be destroyed now, stop further processing
58937 Self_.RefDec; // Destroy Self_, if Free was called for it while processing attached procedures
58938 end;
58939 {$ENDIF ASM_VERSION}
58940 //[END EnumDynHandlers]
58942 {$IFDEF ASM_VERSION}
58943 //[procedure TControl.AttachProcEx]
58944 procedure TControl.AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );
58945 asm //cmd //opd
58946 PUSH EBX
58947 PUSH EDI
58948 PUSH ECX
58949 XCHG EBX, EAX
58950 MOV EDI, EDX
58951 MOV [EBX].fOnDynHandlers, offset[EnumDynHandlers]
58952 MOV ECX, [EBX].TControl.fDynHandlers
58953 INC ECX
58954 LOOP @@1
58955 CALL NewList
58956 XCHG ECX, EAX
58957 MOV [EBX].TControl.fDynHandlers, ECX
58958 @@1:
58959 PUSH ECX
58960 MOV EAX, EBX
58961 MOV EDX, EDI
58962 CALL TControl.IsProcAttached
58963 TEST AL, AL
58964 POP EBX
58965 JNZ @@exit
58966 MOV EAX, EBX
58967 MOV EDX, EDI
58968 CALL TList.Add
58969 XCHG EAX, EBX
58970 POP EDX
58971 PUSH EDX
58972 CALL TList.Add
58973 @@exit:
58974 POP ECX
58975 POP EDI
58976 POP EBX
58977 end;
58978 {$ELSE ASM_VERSION} //Pascal
58979 procedure TControl.AttachProcEx( Proc: TWindowFunc; ExecuteAfterAppletTerminated: Boolean );
58980 begin
58981 if fDynHandlers = nil then
58982 fDynHandlers := NewList;
58983 if not IsProcAttached( Proc ) then
58984 begin
58985 fDynHandlers.Add( @Proc );
58986 fDynHandlers.Add( Pointer( Integer( ExecuteAfterAppletTerminated ) ) );
58987 end;
58988 fOnDynHandlers := EnumDynHandlers;
58989 end;
58990 {$ENDIF ASM_VERSION}
58992 //[procedure TControl.AttachProc]
58993 procedure TControl.AttachProc(Proc: TWindowFunc);
58994 begin
58995 AttachProcEx( Proc, FALSE );
58996 end;
58999 //[procedure TControl.DetachProc]
59000 procedure TControl.DetachProc(Proc: TWindowFunc);
59001 var I: Integer;
59002 begin
59003 if fDynHandlers = nil then Exit;
59004 I := fDynHandlers.IndexOf( @Proc );
59005 if I >=0 then
59006 begin
59007 fDynHandlers.Delete( I );
59008 fDynHandlers.Delete( I );
59009 end;
59010 end;
59012 {$IFDEF ASM_VERSION}
59013 //[function TControl.IsProcAttached]
59014 function TControl.IsProcAttached(Proc: TWindowFunc): Boolean;
59015 asm //cmd //opd
59016 MOV ECX, [EAX].TControl.fDynHandlers
59017 JECXZ @@exit
59018 XCHG EAX, ECX
59019 CALL TList.IndexOf
59020 TEST EAX, EAX
59021 SETGE CL
59022 @@exit: XCHG EAX, ECX
59023 end;
59024 {$ELSE ASM_VERSION} //Pascal
59025 function TControl.IsProcAttached(Proc: TWindowFunc): Boolean;
59026 var I: Integer;
59027 begin
59028 Result := False;
59029 if fDynHandlers = nil then Exit;
59030 I := fDynHandlers.IndexOf( @Proc );
59031 Result := I >=0;
59032 end;
59033 {$ENDIF ASM_VERSION}
59035 //[function WndProcAutoPopupMenu]
59036 function WndProcAutoPopupMenu( Control: PControl; var Msg: TMsg; var MsgRslt: Integer ): Boolean;
59037 var R: TRect;
59038 M: Word;
59039 I: Integer;
59040 P: TPoint;
59041 begin
59042 if (Msg.message = WM_CONTEXTMENU) and
59043 (Control.fAutoPopupMenu <> nil) then
59044 begin
59045 {$IFDEF USE_MENU_CURCTL}
59046 PMenu( Control.fAutoPopupMenu ).fCurCtl := Control;
59047 {$ENDIF USE_MENU_CURCTL}
59048 P.X := SmallInt( LoWord( Msg.lParam ) );
59049 P.Y := SmallInt( HiWord( Msg.lParam ) );
59050 if (Msg.lParam = -1) then
59051 begin
59052 I := Control.CurIndex;
59053 M := Control.fCommandActions.aItem2XY;
59054 if (I >= 0) and (M <> 0) then
59055 begin
59056 CASE M OF
59057 EM_POSFROMCHAR:
59058 begin
59059 I := Control.SelStart + Control.SelLength;
59060 // Edit or Rich Edit 2:
59061 I := Control.Perform( M, I, 1 );
59062 P.X := SmallInt( LoWord( I ) );
59063 P.Y := SmallInt( HiWord( I ) );
59064 end;
59065 LB_GETITEMRECT, LVM_GETITEMRECT, TCM_GETITEMRECT:
59066 begin
59067 R.Left := LVIR_BOUNDS;
59068 Control.Perform( M, I, Integer( @ R ) );
59069 P.X := R.Left;
59070 P.Y := R.Bottom;
59071 end;
59072 TVM_GETITEMRECT:
59073 begin
59074 I := Control.TVSelected;
59075 R.Left := I;
59076 Control.Perform( M, 1, Integer( @ R ) );
59077 P.X := R.Left;
59078 P.Y := R.Bottom;
59079 end;
59080 END;
59081 R := Control.ClientRect;
59082 if P.X < R.Left then P.X := R.Left;
59083 if P.X > R.Right then P.X := R.Right;
59084 if P.Y < R.Top then P.Y := R.Top;
59085 if P.Y > R.Bottom then P.Y := R.Bottom;
59086 end;
59087 P := Control.Client2Screen( P );
59088 end;
59089 PMenu( Control.fAutoPopupMenu ).Popup( P.X, P.Y );
59090 Result := TRUE;
59092 else
59093 Result := FALSE;
59094 end;
59096 //[procedure TControl.SetAutoPopupMenu]
59097 procedure TControl.SetAutoPopupMenu(PopupMenu: PObj);
59098 { new version - by Alexander Pravdin. Allows to attach a submenu (e.g. of the
59099 main menu) as a popup menu to a control, to avoid duplicating menu object,
59100 if it is the same already as desired. }
59101 var pm: PMenu;
59102 begin
59103 if PopupMenu <> nil then
59104 {$IFDEF USE_MENU_CURCTL}
59105 begin
59106 pm := PMenu( PopupMenu );
59107 if ( pm.FParent <> nil ) then
59108 begin
59109 while pm.FControl = nil do
59110 pm := pm.FParent;
59111 PMenu( PopupMenu ).FControl := pm.FControl;
59113 else
59114 begin
59115 PMenu( PopupMenu ).FControl := @Self;
59116 end;
59117 AttachProc(WndProcAutoPopupMenu);
59118 AttachProc(WndProcMenu)
59120 else begin
59121 DetachProc(WndProcAutoPopupMenu);
59122 DetachProc(WndProcMenu);
59123 end;
59124 {$ELSE}
59125 begin
59126 pm := PMenu( PopupMenu );
59127 while pm.FControl = nil do pm := pm.Parent;
59128 PMenu( PopupMenu ).FControl := pm.FControl;
59129 end;
59130 {$ENDIF}
59131 fAutoPopupMenu := PopupMenu;
59132 {$IFNDEF USE_MENU_CURCTL}
59133 AttachProc( WndProcAutoPopupMenu );
59134 {$ENDIF}
59135 end;
59137 //[function SearchAnsiMnemonics]
59138 function SearchAnsiMnemonics( const S: String ): String;
59139 var I: Integer;
59140 Sh: ShortInt;
59141 begin
59142 Result := S;
59143 for I := 1 to Length( Result ) do
59144 begin
59145 Sh := VkKeyScanEx( Result[ I ], MnemonicsLocale );
59146 if Sh <> -1 then
59147 Result[ I ] := Char( Sh );
59148 end;
59149 end;
59151 //[procedure SupportAnsiMnemonics]
59152 procedure SupportAnsiMnemonics( LocaleID: Integer );
59153 begin
59154 MnemonicsLocale := LocaleID;
59155 SearchMnemonics := SearchAnsiMnemonics;
59156 end;
59158 //[function WndProcMnemonics]
59159 function WndProcMnemonics( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59160 var Form: PControl;
59162 function HandleMnenonic( Prnt: PControl ): Boolean;
59163 var C: PControl;
59164 XY: Integer;
59165 procedure DoPressMnemonic;
59166 begin
59167 if Msg.message = WM_SYSKEYDOWN then
59168 begin
59169 Form.FPressedMnemonic := Msg.wParam;
59170 C.Perform( WM_LBUTTONDOWN, MK_LBUTTON, XY );
59172 else
59173 begin
59174 Form.FPressedMnemonic := 0;
59175 C.Perform( WM_LBUTTONUP, MK_LBUTTON, XY );
59176 end;
59177 end;
59178 var I, J: Integer;
59179 R: TRect;
59180 begin
59181 for I := 0 to Prnt.ChildCount-1 do
59182 begin
59183 C := Prnt.Children[ I ];
59184 if C.IsButton then
59185 if C.Enabled then
59186 begin
59187 if C.fCommandActions.aGetCount = TB_BUTTONCOUNT then
59188 for J := 0 to C.Count-1 do
59189 begin
59190 if C.TBButtonEnabled[ J ] then
59191 if pos( '&' + Char( Msg.wParam ), SearchMnemonics( C.TBButtonText[ J ] ) ) > 0 then
59192 begin
59193 C.fCurIndex := J;
59194 C.fCurItem := C.TBIndex2Item( J );
59195 R := C.TBButtonRect[ J ];
59196 XY := R.Left or (R.Top shl 16);
59197 DoPressMnemonic;
59198 Result := TRUE;
59199 Exit;
59200 end;
59201 end;
59202 if pos( '&' + Char( Msg.wParam ), SearchMnemonics( C.Caption ) ) > 0 then
59203 begin
59204 XY := 0;
59205 DoPressMnemonic;
59206 Result := TRUE;
59207 Exit;
59208 end;
59209 end;
59210 if HandleMnenonic( C ) then
59211 begin
59212 Result := TRUE;
59213 Exit;
59214 end;
59215 end;
59216 Result := FALSE;
59217 end;
59219 {$IFDEF NEW_MENU_ACCELL}
59220 function FindByCtlRef(C: PControl; Accell: TMenuAccelerator): Boolean;
59222 function FindInMenu(M: PMenu): PMenu;
59224 I: Integer;
59225 SM: PMenu;
59226 begin
59227 for I := 0 to M.FItems.Count - 1 do begin
59228 Result := M.FItems.Items[I];
59229 if (Cardinal(Result.Accelerator) = Cardinal(Accell)) and Result.Enabled then
59230 Exit;
59231 end;
59232 Result := nil;
59233 for I := 0 to M.FItems.Count - 1 do begin
59234 SM := PMenu(M.FItems.Items[I]);
59235 if (SM.FItems.Count > 0) then
59236 Result := FindInMenu(SM);
59237 if (Result <> nil) then
59238 Break;
59239 end;
59240 end;
59242 function FindInMenu2(M: PMenu): Boolean;
59244 MI: PMenu;
59245 begin
59246 if (M <> nil) then begin
59247 MI := FindInMenu(M);
59248 if (MI <> nil) then begin
59249 //M.FControl.Perform(WM_COMMAND, MI.FId, 0);
59250 C.Perform(WM_COMMAND, MI.FId, 0); // fixed
59251 Result := True;
59252 Exit;
59253 end;
59254 end;
59255 Result := False;
59256 end;
59259 Parent: PControl;
59260 begin
59261 Result := False;
59262 if not FindInMenu2(PMenu(C.fAutoPopupMenu)) then
59263 if not FindInMenu2(PMenu(C.fMenuObj)) then begin
59264 Parent := C.Parent;
59265 if (Parent <> nil) then
59266 Result := FindByCtlRef(Parent, Accell);
59267 end;
59268 end;
59271 Ac: TMenuAccelerator;
59272 {$ENDIF}
59273 begin
59274 Result := FALSE;
59275 if (Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST) then
59276 begin
59277 {$IFDEF NEW_MENU_ACCELL}
59278 Ac := MakeAccelerator(FVIRTKEY or GetShiftState, Msg.wParam);
59279 Result := FindByCtlRef(Sender, Ac);
59280 {$ELSE}
59281 if Sender.fAccelTable <> 0 then
59282 Result := LongBool( TranslateAccelerator( Sender.fHandle, Sender.fAccelTable, Msg ) );
59283 if not Result then
59284 begin
59285 if Sender.fCurrentControl <> nil then
59286 if Sender.fCurrentControl.fAccelTable <> 0 then
59287 Result := LongBool( TranslateAccelerator( Sender.fCurrentControl.fHandle,
59288 Sender.fCurrentControl.fAccelTable, Msg ) );
59289 end;
59290 if not Result then
59291 begin
59292 Form := Sender.ParentForm;
59293 if Form <> nil then
59294 if Form.fAccelTable <> 0 then
59295 Result := LongBool( TranslateAccelerator( Form.fHandle,
59296 Form.fAccelTable, Msg ) );
59297 end;
59298 {$ENDIF}
59299 end;
59300 if Result then Exit;
59301 if (Msg.message = WM_SYSKEYUP) or
59302 (Msg.message = WM_SYSKEYDOWN) and (GetKeyState( VK_MENU ) < 0) then
59303 begin
59304 Rslt := 0;
59305 Form := Sender.ParentForm;
59306 if Form <> nil then
59307 begin
59308 { ----------------------- }
59309 //Form.Caption := Form.Caption + '<';
59310 if Char( Msg.wParam ) in [ 'A'..'Z', '0'..'9' ] then
59311 begin
59312 if HandleMnenonic( Form ) then
59313 begin
59314 Result := TRUE;
59315 Exit;
59317 else
59318 begin
59319 { ---------------------- }
59320 //Form.Caption := Form.Caption + '?';
59321 end;
59322 end;
59323 end;
59325 else
59326 if Msg.message = WM_KEYUP then
59327 begin
59328 Rslt := 0;
59329 Form := Sender.ParentForm;
59330 if Form <> nil then
59331 begin
59332 { ------------------------ }
59333 //Form.Caption := Form.Caption + '>';
59334 if Msg.wParam = VK_MENU then
59335 begin
59336 if Form.FPressedMnemonic <> 0 then
59337 Form.FPressedMnemonic := Form.FPressedMnemonic or $80000000;
59339 else
59340 if Char( Msg.wParam ) in [ 'A'..'Z', '0'..'9' ] then
59341 begin
59342 if HandleMnenonic( Form ) then
59343 begin
59344 Result := TRUE;
59345 Exit;
59347 else
59348 begin
59349 { --------------------- }
59350 //Form.Caption := form.Caption + '-';
59351 end;
59352 end;
59353 end;
59354 end;
59355 Result := FALSE;
59356 end;
59358 //[function TControl.SupportMnemonics]
59359 function TControl.SupportMnemonics: PControl;
59360 begin
59361 fGlobalProcKeybd := WndProcMnemonics;
59362 Result := @Self;
59363 end;
59366 //[API RevokeDragDrop]
59367 function RevokeDragDrop(wnd: HWnd): HResult; stdcall;
59368 external 'ole32.dll' name 'RevokeDragDrop';
59371 //[function TControl.RE_NoOLEDragDrop]
59372 function TControl.RE_NoOLEDragDrop: PControl;
59373 begin
59374 RevokeDragDrop( Handle );
59375 Result := @Self;
59376 end;
59379 //[function WndProcOnResize]
59380 function WndProcOnResize( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59381 begin
59382 if Msg.message = WM_SIZE then
59383 begin
59384 if Assigned( Self_.fOnResize ) then
59385 Self_.fOnResize( Self_ );
59386 end;
59387 Result := False;
59388 end;
59391 //[procedure TControl.SetOnResize]
59392 procedure TControl.SetOnResize(const Value: TOnEvent);
59393 begin
59394 FOnResize := Value;
59395 AttachProc( WndProcOnResize );
59396 end;
59398 //[function WndProcMove]
59399 function WndProcMove( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59400 begin
59401 if Msg.message = WM_MOVE then
59402 begin
59403 if Assigned( Self_.FOnMove ) then
59404 Self_.FOnMove( Self_ );
59405 end;
59406 Result := False;
59407 end;
59409 //[procedure TControl.SetOnMove]
59410 procedure TControl.SetOnMove(const Value: TOnEvent);
59411 begin
59412 FOnMove := Value;
59413 AttachProc( WndProcMove );
59414 end;
59416 //[function WndProc_REBottomless]
59417 function WndProc_REBottomless( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59418 begin
59419 if Msg.message = WM_SIZE then
59420 Self_.Perform( EM_REQUESTRESIZE, 0, 0 );
59421 Result := False;
59422 end;
59425 //[function TControl.RE_Bottomless]
59426 function TControl.RE_Bottomless: PControl;
59427 begin
59428 AttachProc( WndProc_REBottomless );
59429 Result := @Self;
59430 end;
59433 //[procedure TControl.RE_Append]
59434 procedure TControl.RE_Append(const S: String; ACanUndo: Boolean);
59435 begin
59436 SelStart := TextSize;
59437 if S <> '' then
59438 begin
59439 ReplaceSelection( S, ACanUndo );
59440 SelStart := TextSize;
59441 end;
59442 end;
59445 //[procedure TControl.RE_InsertRTF]
59446 procedure TControl.RE_InsertRTF(const S: String);
59447 var MS: PStream;
59448 begin
59449 MS := NewMemoryStream;
59450 MS.Size := Length( S ) + 1;
59451 Move( S[ 1 ], MS.Memory^, Length( S ) + 1 );
59452 RE_LoadFromStream( MS, Length( S ), reRTF, TRUE );
59453 MS.Free;
59454 end;
59457 //[procedure TControl.DoSelChange]
59458 procedure TControl.DoSelChange;
59459 begin
59460 if Assigned( fOnSelChange ) then fOnSelChange( @Self )
59461 else
59462 if Assigned( fOnChange ) then fOnChange( @Self );
59463 end;
59466 //[function TControl.REGetUnderlineEx]
59467 function TControl.REGetUnderlineEx: TRichUnderline;
59468 begin
59469 Result := TRichUnderline( REGetFontAttr( (81 shl 16) or CFM_UNDERLINETYPE ) - 1 );
59470 end;
59473 //[procedure TControl.RESetUnderlineEx]
59474 procedure TControl.RESetUnderlineEx(const Value: TRichUnderline);
59475 begin
59476 RESetFontAttr( (81 shl 16) or CFM_UNDERLINETYPE, Ord( Value ) + 1 );
59477 RESetFontEffect( CFM_UNDERLINE, True );
59478 end;
59481 //[function TControl.GetTextSize]
59482 function TControl.GetTextSize: Integer;
59483 begin
59484 Result := 0;
59485 if fHandle <> 0 then
59486 Result := GetWindowTextLength( fHandle );
59487 end;
59490 //[function TControl.REGetTextSize]
59491 function TControl.REGetTextSize(Units: TRichTextSize): Integer;
59492 const TextLengthFlags: array[ TRichTextSizes ] of Integer =
59493 ( not GTL_UseCRLF, not GTL_Precise, GTL_Close, GTL_NUMBytes );
59494 var GTL: TGetTextLengthEx;
59495 begin
59496 GTL.flags := MakeFlags( @Units, TextLengthFlags );
59497 if not(rtsBytes in Units) then
59498 GTL.flags := GTL.flags or GTL_NUMCHARS;
59499 GTL.codepage := CP_ACP;
59500 Result := Perform( EM_GETTEXTLENGTHEX, Integer( @GTL ), 0 );
59501 end;
59503 //[function TControl.RE_TextSizePrecise]
59504 function TControl.RE_TextSizePrecise: Integer;
59505 var gtlex : TGetTextLengthEx;
59506 begin
59507 gtlex.flags := GTL_PRECISE;
59508 gtlex.codepage := CP_ACP;
59509 Result := Perform(EM_GETTEXTLENGTHEX,WPARAM(@gtlex), 0 );
59510 end;
59513 //[function TControl.REGetNumStyle]
59514 function TControl.REGetNumStyle: TRichNumbering;
59515 begin
59516 Result := TRichNumbering( ReGetParaAttr( 9 shl 16 ) );
59517 end;
59520 //[procedure TControl.RESetNumStyle]
59521 procedure TControl.RESetNumStyle(const Value: TRichNumbering);
59522 begin
59523 RESetParaAttr( (9 shl 16) or PFM_NUMBERING, Ord( Value ) );
59524 end;
59527 //[function TControl.REGetNumBrackets]
59528 function TControl.REGetNumBrackets: TRichNumBrackets;
59529 begin
59530 REGetParaAttr( 0 );
59531 Result := TRichNumBrackets( (fREParaFmtRec.wNumberingStyle shr 8) {and 3} );
59532 end;
59535 //[procedure TControl.RESetNumBrackets]
59536 procedure TControl.RESetNumBrackets(const Value: TRichNumBrackets);
59537 begin
59538 REGetParaAttr( 0 );
59539 fREParaFmtRec.wNumberingStyle := fREParaFmtRec.wNumberingStyle and $F8FF
59540 or Word( Ord( Value ) shl 8 );
59541 fREParaFmtRec.dwMask := PFM_NUMBERINGSTYLE;
59542 RE_ParaFmt := fREParaFmtRec;
59543 end;
59546 //[function TControl.REGetNumTab]
59547 function TControl.REGetNumTab: Integer;
59548 begin
59549 REGetParaAttr( 0 );
59550 Result := fREParaFmtRec.wNumberingTab;
59551 end;
59554 //[procedure TControl.RESetNumTab]
59555 procedure TControl.RESetNumTab(const Value: Integer);
59556 begin
59557 REGetParaAttr( 0 );
59558 fREParaFmtRec.wNumberingTab := Value;
59559 fREParaFmtRec.dwMask := PFM_NUMBERINGTAB;
59560 RE_ParaFmt := fREParaFmtRec;
59561 end;
59564 //[function TControl.REGetNumStart]
59565 function TControl.REGetNumStart: Integer;
59566 begin
59567 REGetParaAttr( 0 );
59568 Result := fREParaFmtRec.wNumberingStart;
59569 end;
59572 //[procedure TControl.RESetNumStart]
59573 procedure TControl.RESetNumStart(const Value: Integer);
59574 begin
59575 REGetParaAttr( 0 );
59576 fREParaFmtRec.wNumberingStart := Value;
59577 fREParaFmtRec.dwMask := PFM_NUMBERINGSTART;
59578 RE_ParaFmt := fREParaFmtRec;
59579 end;
59582 //[function TControl.REGetSpacing]
59583 function TControl.REGetSpacing( const Index: Integer ): Integer;
59584 begin
59585 REGetParaAttr( 0 );
59586 Result := PInteger( Integer(@fREParaFmtRec.dySpaceBefore) + (Index and $F) )^;
59587 end;
59590 //[procedure TControl.RESetSpacing]
59591 procedure TControl.RESetSpacing(const Index, Value: Integer);
59592 begin
59593 REGetParaAttr( 0 );
59594 PInteger( Integer(@fREParaFmtRec.dySpaceBefore) + (Index and $F) )^ := Value;
59595 fREParaFmtRec.dwMask := Index and not $F;
59596 RE_ParaFmt := fREParaFmtRec;
59597 end;
59600 //[function TControl.REGetSpacingRule]
59601 function TControl.REGetSpacingRule: Integer;
59602 begin
59603 REGetParaAttr( 0 );
59604 Result := fREParaFmtRec.bLineSpacingRule;
59605 end;
59608 //[procedure TControl.RESetSpacingRule]
59609 procedure TControl.RESetSpacingRule(const Value: Integer);
59610 begin
59611 REGetParaAttr( 0 );
59612 fREParaFmtRec.bLineSpacingRule := Value;
59613 fREParaFmtRec.dwMask := PFM_LINESPACING;
59614 RE_ParaFmt := fREParaFmtRec;
59615 end;
59618 //[function TControl.REGetLevel]
59619 function TControl.REGetLevel: Integer;
59620 begin
59621 REGetParaAttr( 0 );
59622 Result := fREParaFmtRec.bCRC;
59623 end;
59626 //[function TControl.REGetBorder]
59627 function TControl.REGetBorder(Side: TBorderEdge; const Index: Integer): Integer;
59628 begin
59629 REGetParaAttr( 0 );
59630 Result := PWORD( Integer(@fREParaFmtRec.wBorderSpace) + Index )^ shr (Ord(Side) * 4);
59631 end;
59634 //[procedure TControl.RESetBorder]
59635 procedure TControl.RESetBorder(Side: TBorderEdge; const Index: Integer;
59636 const Value: Integer);
59637 var Mask: Word;
59638 pW : PWord;
59639 begin
59640 REGetParaAttr( 0 );
59641 pw := PWORD( Integer(@fREParaFmtRec.wBorderSpace) + Index );
59642 Mask := $F shl (Ord(Side) * 4);
59643 pw^ := pw^ and not Mask or (Value shl (4 * Ord(Side)) );
59644 fREParaFmtRec.dwMask := PFM_BORDER;
59645 RE_ParaFmt := fREParaFmtRec;
59646 end;
59649 //[function TControl.REGetParaEffect]
59650 function TControl.REGetParaEffect(const Index: Integer): Boolean;
59651 begin
59652 Result := LongBool( HiWord( REGetParaAttr( 8 shl 16 ) ) and Index );
59653 end;
59656 //[procedure TControl.RESetParaEffect]
59657 procedure TControl.RESetParaEffect(const Index: Integer;
59658 const Value: Boolean);
59659 var Idx: Integer;
59660 begin
59661 REGetParaAttr( 0 );
59662 fREParaFmtRec.wReserved := Index;
59663 Idx := Index;
59664 //if Idx >= $4000 then Idx := $4000;
59665 fREParaFmtRec.dwMask := Idx shl 16;
59666 RE_ParaFmt := fREParaFmtRec;
59667 end;
59670 //[function WndProc_REMonitorIns]
59671 function WndProc_REMonitorIns( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59672 begin
59673 Result := False;
59674 if (Msg.message = WM_KEYDOWN) and (Msg.wParam = VK_INSERT) and
59675 ((GetKeyState(VK_CONTROL) or GetKeyState(VK_SHIFT) or GetKeyState(VK_MENU)) >= 0) then
59676 begin
59677 if not Self_.fReOvrDisable then
59678 Self_.fREOvr := not Self_.fREOvr
59679 else
59680 Result := True;
59681 if assigned( Self_.fOnREInsModeChg ) then
59682 Self_.fOnREInsModeChg( Self_ );
59683 end;
59684 end;
59687 //[function TControl.REGetOverwite]
59688 function TControl.REGetOverwite: Boolean;
59689 begin
59690 AttachProc( WndProc_REMonitorIns );
59691 Result := fREOvr;
59692 end;
59695 //[procedure TControl.RESetOverwrite]
59696 procedure TControl.RESetOverwrite(const Value: Boolean);
59697 begin
59698 if fREOvr = Value then Exit;
59699 Perform( WM_KEYDOWN, VK_INSERT, 0 );
59700 Perform( WM_KEYUP, VK_INSERT, 0 );
59701 end;
59704 //[procedure TControl.RESetOvrDisable]
59705 procedure TControl.RESetOvrDisable(const Value: Boolean);
59706 begin
59707 REGetOverwite;
59708 fReOvrDisable := Value;
59709 end;
59712 //[function WndProc_RichEdTransp_ParentPaint]
59713 function WndProc_RichEdTransp_ParentPaint( Self_:PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59714 var I: Integer;
59715 C: PControl;
59716 begin
59717 if (Msg.message = WM_PAINT) and (Msg.wParam = 0) then
59718 begin
59719 for I := 0 to Self_.fChildren.fCount - 1 do
59720 begin
59721 C := Self_.fChildren.fItems[ I ];
59722 if C.fIsCommonControl then
59723 begin
59724 Inc( C.fUpdCount );
59725 PostMessage( C.fHandle, CM_NCUPDATE, C.fUpdCount, WM_PAINT );
59726 InvalidateRect( C.fHandle, nil, False );
59727 end;
59728 end;
59729 end;
59730 Result := False;
59731 end;
59734 //[function WndProc_RichEdTransp_Update]
59735 function WndProc_RichEdTransp_Update( Self_:PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59736 var Rgn, Rgn1: HRgn;
59737 R, CR: TRect;
59738 Pt: TPoint;
59739 VW, HH, VH, HW: Integer;
59740 begin
59741 case Msg.message of
59742 WM_CHAR, WM_KILLFOCUS, WM_SETFOCUS:
59743 begin
59744 PostMessage( Self_.fHandle, CM_INVALIDATE, 0, 0 );
59745 end;
59746 WM_PAINT:
59747 if Msg.wParam = 0 then
59748 begin
59749 Inc( Self_.fUpdCount );
59750 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
59751 end;
59752 WM_SIZE:
59753 begin
59754 Inc( Self_.fUpdCount );
59755 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
59756 PostMessage( Self_.fHandle, CM_INVALIDATE, 0, 0 );
59757 end;
59758 WM_ERASEBKGND:
59759 if Msg.wParam = 0 then
59760 begin
59761 Inc( Self_.fUpdCount );
59762 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
59763 end;
59764 WM_HSCROLL, WM_VSCROLL:
59765 begin
59766 Self_.fREScrolling := LoWord( Msg.wParam ) <> SB_ENDSCROLL;
59767 Inc( Self_.fUpdCount );
59768 PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
59769 if Self_.fREScrolling then
59770 Self_.Invalidate;
59771 end;
59772 CM_INVALIDATE:
59773 begin
59774 //Self_.Update;
59775 Self_.Parent.Invalidate;
59776 Self_.Invalidate;
59777 //Inc( Self_.fUpdCount );
59778 //PostMessage( Self_.fHandle, CM_NCUPDATE, Self_.fUpdCount, Msg.message );
59779 end;
59780 CM_NCUPDATE:
59781 if Msg.wParam = Self_.fUpdCount then
59782 begin
59783 //if Msg.lParam = WM_PAINT then
59784 // UpdateWindow( Self_.fHandle );
59785 GetWindowRect( Self_.fHandle, R );
59786 Windows.GetClientRect( Self_.fHandle, CR );
59787 Pt.x := 0; Pt.y := 0;
59788 Pt := Self_.Client2Screen( Pt );
59789 OffsetRect( CR, Pt.x, Pt.y );
59790 Rgn := CreateRectRgn( R.Left, R.Top, R.Right, R.Bottom );
59791 if Self_.fREScrolling then
59792 begin
59793 VW := GetSystemMetrics( SM_CXVSCROLL );
59794 HH := GetSystemMetrics( SM_CYHSCROLL );
59795 VH := GetSystemMetrics( SM_CYVSCROLL );
59796 HW := GetSystemMetrics( SM_CXHSCROLL );
59797 if CR.Right + VW <= R.Right then
59798 begin
59799 Rgn1 := CreateRectRgn( CR.Right, CR.Top + VH, CR.Right + VW, CR.Bottom - VH );
59800 CombineRgn( Rgn, Rgn, Rgn1, RGN_DIFF );
59801 DeleteObject( Rgn1 );
59802 end;
59803 if CR.Bottom + HH <= R.Bottom then
59804 begin
59805 Rgn1 := CreateRectRgn( CR.Left + HW, CR.Bottom, CR.Right - HW, CR.Bottom + HH );
59806 CombineRgn( Rgn, Rgn, Rgn1, RGN_DIFF );
59807 DeleteObject( Rgn1 );
59808 end;
59809 end;
59810 Self_.Perform( WM_NCPAINT, Rgn, 0 );
59811 DeleteObject( Rgn ); // Unremarked By M.Gerasimov
59812 end;
59813 end;
59814 Result := False;
59815 end;
59818 //[function TControl.REGetTransparent]
59819 function TControl.REGetTransparent: Boolean;
59820 begin
59821 Result := Longbool(ExStyle and WS_EX_TRANSPARENT);
59822 end;
59825 //[procedure TControl.RESetTransparent]
59826 procedure TControl.RESetTransparent(const Value: Boolean);
59827 begin
59828 ExStyle := ExStyle or WS_EX_TRANSPARENT;
59829 fParent.AttachProc( WndProc_RichEdTransp_ParentPaint );
59830 AttachProc( WndProc_RichEdTransp_Update );
59831 fTransparent := Value;
59832 end;
59835 //[procedure TControl.RESetOnURL]
59836 procedure TControl.RESetOnURL(const Index: Integer; const Value: TOnEvent);
59837 begin
59838 if Index = 0 then
59839 fOnREOverURL := Value
59840 else
59841 fOnREURLClick := Value;
59842 RE_AutoURLDetect := assigned(fOnREOverURL) or assigned(fOnREURLClick);
59843 end;
59845 {$IFDEF F_P}
59846 //[function TControl.REGetOnURL]
59847 function TControl.REGetOnURL(const Index: Integer): TOnEvent;
59848 begin
59849 CASE Index OF
59850 0: Result := fOnREOverURL;
59851 else Result := fOnREURLClick;
59852 END;
59853 end;
59854 {$ENDIF F_P}
59857 //[function TControl.REGetLangOptions]
59858 function TControl.REGetLangOptions(const Index: Integer): Boolean;
59859 begin
59860 Result := LongBool( Perform( EM_GETLANGOPTIONS, 0, 0 ) and Index);
59861 end;
59864 //[procedure TControl.RESetLangOptions]
59865 procedure TControl.RESetLangOptions(const Index: Integer;
59866 const Value: Boolean);
59867 var Mask: Integer;
59868 begin
59869 Mask := -1;
59870 if not Value then Inc( Mask );
59871 Perform( EM_SETLANGOPTIONS, 0, Perform( EM_GETLANGOPTIONS, 0, 0 ) and
59872 not Index or (Mask and Index) );
59873 end;
59875 //[API _TrackMouseEvent]
59876 function _TrackMouseEvent(lpEventTrack: PTrackMouseEvent): BOOL;
59877 external cctrl name '_TrackMouseEvent';
59879 //[function DoTrackMouseEvent]
59880 function DoTrackMouseEvent(lpEventTrack: PTrackMouseEvent): BOOL;
59881 var FunTrack: function(lpEventTrack: PTrackMouseEvent): BOOL; stdcall;
59882 ComCtlModule: THandle;
59883 begin
59884 Result := FALSE;
59885 ComCtlModule := GetModuleHandle( cctrl );
59886 if ComCtlModule = 0 then Exit;
59887 FunTrack := GetProcAddress( ComCtlModule, '_TrackMouseEvent' );
59888 if not Assigned( FunTrack ) then Exit;
59889 Result := FunTrack( lpEventTrack );
59890 end;
59893 //[function WndProcMouseEnterLeave]
59894 function WndProcMouseEnterLeave( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
59895 var P: TPoint;
59896 MouseWasInControl: Boolean;
59897 Yes: Boolean;
59898 Track: TTrackMouseEvent;
59899 begin
59900 case Msg.message of
59901 WM_MOUSEFIRST..WM_MOUSELAST:
59902 begin
59903 MouseWasInControl := Self_.MouseInControl;
59904 if Assigned( Self_.fOnTestMouseOver ) then
59905 Yes := Self_.fOnTestMouseOver( Self_ )
59906 else
59907 begin
59908 GetCursorPos( P );
59909 P := Self_.Screen2Client( P );
59910 Yes := PointInRect( P, Self_.ClientRect );
59911 end;
59912 if MouseWasInControl <> Yes then
59913 begin
59914 //???Self_.InvalidateErase( FALSE );
59915 if Yes then
59916 begin
59917 Self_.fMouseInControl := TRUE;
59918 if Assigned( Self_.fOnMouseEnter ) then
59919 Self_.fOnMouseEnter( Self_ );
59920 Track.cbSize := Sizeof( Track );
59921 Track.dwFlags := TME_LEAVE;
59922 Track.hwndTrack := Self_.Handle;
59923 //Track.dwHoverTime := 0;
59924 DoTrackMouseEvent( @ Track );
59925 //???Self_.InvalidateErase( FALSE );
59927 else
59928 begin
59929 Self_.fMouseInControl := FALSE;
59930 Track.cbSize := Sizeof( Track );
59931 Track.dwFlags := TME_LEAVE or TME_CANCEL;
59932 Track.hwndTrack := Self_.Handle;
59933 //Track.dwHoverTime := 0;
59934 DoTrackMouseEvent( @ Track );
59935 if Assigned( Self_.fOnMouseLeave ) then
59936 Self_.fOnMouseLeave( Self_ );
59937 //???Self_.InvalidateErase( FALSE );
59938 end;
59939 end;
59940 end;
59941 WM_MOUSELEAVE:
59942 begin
59943 if Self_.fMouseInControl then
59944 begin
59945 Self_.fMouseInControl := FALSE;
59946 {$IFDEF GRAPHCTL_HOTTRACK}
59947 if Assigned( Self_.fMouseLeaveProc ) then
59948 Self_.fMouseLeaveProc( Self_ );
59949 {$ENDIF}
59950 if Assigned( Self_.fOnMouseLeave ) then
59951 Self_.fOnMouseLeave( Self_ );
59952 //???Self_.InvalidateErase( FALSE );
59953 end;
59954 end;
59955 end;
59956 Result := False;
59957 end;
59959 //[procedure ProvideMouseEnterLeave]
59960 procedure ProvideMouseEnterLeave( Self_: PControl );
59961 begin
59962 InitCommonControls;
59963 Self_.AttachProc( WndProcMouseEnterLeave );
59964 //???Self_.InvalidateErase( FALSE );
59965 end;
59967 //[procedure TControl.SetFlat]
59968 procedure TControl.SetFlat(const Value: Boolean);
59969 begin
59970 //if fFlat = Value then Exit;
59971 fFlat := Value;
59972 fMouseInControl := FALSE;
59973 ProvideMouseEnterLeave( @Self );
59974 Invalidate;
59975 end;
59977 //[procedure TControl.SetOnMouseEnter]
59978 procedure TControl.SetOnMouseEnter(const Value: TOnEvent);
59979 begin
59980 fOnMouseEnter := Value;
59981 ProvideMouseEnterLeave( @Self );
59982 end;
59984 //[procedure TControl.SetOnMouseLeave]
59985 procedure TControl.SetOnMouseLeave(const Value: TOnEvent);
59986 begin
59987 fOnMouseLeave := Value;
59988 ProvideMouseEnterLeave( @Self );
59989 end;
59991 //[procedure TControl.SetOnTestMouseOver]
59992 procedure TControl.SetOnTestMouseOver(const Value: TOnTestMouseOver);
59993 begin
59994 fOnTestMouseOver := Value;
59995 ProvideMouseEnterLeave( @Self );
59996 end;
59998 //[function WndProcEdTransparent]
59999 function WndProcEdTransparent( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60000 begin
60001 if (Msg.message = WM_KEYDOWN) or
60002 (Msg.message = WM_MOUSEMOVE) and (GetKeyState( VK_LBUTTON ) < 0) or
60003 (Msg.message = WM_LBUTTONUP) or (Msg.message = WM_LBUTTONDOWN) then
60004 Self_.Invalidate;
60005 Result := False; // continue handling of a message anyway
60006 end;
60008 //[procedure TControl.EdSetTransparent]
60009 procedure TControl.EdSetTransparent(const Value: Boolean);
60010 begin
60011 Transparent := Value;
60012 AttachProc( WndProcEdTransparent );
60013 end;
60015 //[function WndProcSpeedButton]
60016 function WndProcSpeedButton( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
60017 begin
60018 Result := False;
60019 if Msg.message = WM_SETFOCUS then
60020 begin
60021 Result := TRUE;
60022 Rslt := 0;
60023 end;
60024 end;
60026 //[function TControl.LikeSpeedButton]
60027 function TControl.LikeSpeedButton: PControl;
60028 var Form: PControl;
60029 begin
60030 AttachProc( WndProcSpeedButton );
60031 fTabstop := False;
60032 Style := Style and not WS_TABSTOP;
60033 Form := ParentForm;
60034 if Form <> nil then
60035 if Form.fCurrentControl = @Self then
60036 begin
60037 Form.GotoControl( VK_TAB );
60038 if Form.fCurrentControl = @Self then
60039 Form.fCurrentControl := nil;
60040 end;
60041 Result := @Self;
60042 end;
60044 { -- Unicode -- }
60045 //[function TControl.SetUnicode]
60046 function TControl.SetUnicode(Unicode: Boolean): PControl;
60047 begin
60048 Perform( CCM_SETUNICODEFORMAT, Integer( Unicode ), 0 );
60049 Result := @ Self;
60050 end;
60052 { -- TabControl -- }
60054 //[function TControl.GetPages]
60055 function TControl.GetPages(Idx: Integer): PControl;
60056 var Item: TTCItem;
60057 begin
60058 Item.mask := TCIF_PARAM;
60059 if Perform( TCM_GETITEM, Idx, Integer( @Item ) ) = 0 then
60060 Result := nil
60061 else
60062 Result := Pointer( Item.lParam );
60063 end;
60065 //[function TControl.TCGetItemText]
60066 function TControl.TCGetItemText(Idx: Integer): String;
60067 var TI: TTCItem;
60068 Buffer: array[ 0..1023 ] of Char;
60069 begin
60070 TI.mask := TCIF_TEXT;
60071 TI.pszText := @Buffer[ 0 ];
60072 TI.cchTextMax := sizeof( Buffer );
60073 Buffer[ 0 ] := #0;
60074 Perform( TCM_GETITEM, Idx, Integer( @TI ) );
60075 Result := Buffer;
60076 end;
60078 //[procedure TControl.TCSetItemText]
60079 procedure TControl.TCSetItemText(Idx: Integer; const Value: String);
60080 var TI: TTCItem;
60081 begin
60082 TI.mask := TCIF_TEXT;
60083 TI.pszText := PChar( Value );
60084 Perform( TCM_SETITEM, Idx, Integer( @TI ) );
60085 end;
60087 //[function TControl.TCGetItemImgIDx]
60088 function TControl.TCGetItemImgIDx(Idx: Integer): Integer;
60089 var TI: TTCItem;
60090 begin
60091 TI.mask := TCIF_IMAGE;
60092 if Perform( TCM_GETITEM, Idx, Integer( @TI ) ) = 0 then
60093 Result := -1
60094 else
60095 Result := TI.iImage;
60096 end;
60098 //[procedure TControl.TCSetItemImgIdx]
60099 procedure TControl.TCSetItemImgIdx(Idx: Integer; const Value: Integer);
60100 var TI: TTCItem;
60101 begin
60102 TI.mask := TCIF_IMAGE;
60103 TI.iImage := Value;
60104 Perform( TCM_SETITEM, Idx, Integer( @TI ) );
60105 end;
60107 //[function TControl.TCGetItemRect]
60108 function TControl.TCGetItemRect(Idx: Integer): TRect;
60109 begin
60110 if Perform( TCM_GETITEMRECT, Idx, Integer( @Result ) ) = 0 then
60111 begin
60112 Result.Left := 0;
60113 Result.Right := 0;
60114 Result.Top := 0;
60115 Result.Bottom := 0;
60116 end;
60117 end;
60119 //[procedure TControl.TC_SetPadding]
60120 procedure TControl.TC_SetPadding(cx, cy: Integer);
60121 begin
60122 Perform( TCM_SETPADDING, 0, cx or (cy shl 16) );
60123 end;
60125 //[function TControl.TC_TabAtPos]
60126 function TControl.TC_TabAtPos(x, y: Integer): Integer;
60127 type TTCHittestInfo = packed record
60128 Pt: TPoint;
60129 Fl: DWORD;
60130 end;
60131 var HTI: TTCHitTestInfo;
60132 begin
60133 HTI.Pt.x := x;
60134 HTI.Pt.y := y;
60135 Result := Perform( TCM_HITTEST, 0, Integer( @HTI ) );
60136 end;
60138 //[function TControl.TC_DisplayRect]
60139 function TControl.TC_DisplayRect: TRect;
60140 begin
60141 Windows.GetClientRect( fHandle, Result );
60142 Perform( TCM_ADJUSTRECT, 0, Integer( @Result ) );
60143 end;
60145 //[function TControl.TC_IndexOf]
60146 function TControl.TC_IndexOf(const S: String): Integer;
60147 begin
60148 Result := TC_SearchFor( S, -1, FALSE );
60149 end;
60151 //[function TControl.TC_SearchFor]
60152 function TControl.TC_SearchFor(const S: String; StartAfter: Integer;
60153 Partial: Boolean): Integer;
60154 var I: Integer;
60155 begin
60156 Result := -1;
60157 for I := StartAfter+1 to Count-1 do
60158 begin
60159 if Partial and ( Copy( TC_Items[ I ], 1, Length( S ) ) = S ) or
60160 ( TC_Items[ I ] = S ) then
60161 begin
60162 Result := I;
60163 break;
60164 end;
60165 end;
60166 end;
60168 //[function TControl.TC_Insert]
60169 function TControl.TC_Insert(Idx: Integer; const TabText: String;
60170 TabImgIdx: Integer): PControl;
60171 var TI: TTCItem;
60172 begin
60173 Result := NewPanel( @Self, esNone );
60174 Result.FAlign := caClient;
60175 Result.fNotUseAlign := True;
60176 Result.fVisibleWoParent := TRUE;
60177 Result.Visible := Count = 0;
60178 TI.mask := TCIF_TEXT or TCIF_IMAGE or TCIF_PARAM;
60179 TI.iImage := TabImgIdx;
60180 TI.pszText := PChar( TabText );
60181 TI.lParam := Integer( Result );
60182 Perform( TCM_INSERTITEM, Idx, Integer( @TI ) );
60183 Result.BoundsRect := TC_DisplayRect;
60184 end;
60186 //[procedure TControl.TC_Delete]
60187 procedure TControl.TC_Delete(Idx: Integer);
60188 var Page: PControl;
60189 begin
60190 Page := TC_Pages[ Idx ];
60191 if Page = nil then Exit;
60192 Perform( TCM_DELETEITEM, Idx, 0 );
60193 Page.Free;
60194 end;
60196 { -- TreeView -- }
60198 //[function TControl.TVGetItemIdx]
60199 function TControl.TVGetItemIdx(const Index: Integer): THandle;
60200 begin
60201 Result := Perform( TVM_GETNEXTITEM, Index, 0 );
60202 end;
60204 //[procedure TControl.TVSetItemIdx]
60205 procedure TControl.TVSetItemIdx(const Index: Integer;
60206 const Value: THandle);
60207 begin
60208 Perform( TVM_SELECTITEM, Index, Value );
60209 end;
60211 //[function TControl.TVGetItemNext]
60212 function TControl.TVGetItemNext(Item: THandle; const Index: Integer): THandle;
60213 begin
60214 Result := Perform( TVM_GETNEXTITEM, Index, Item );
60215 end;
60217 //[function TControl.TVGetItemRect]
60218 function TControl.TVGetItemRect(Item: THandle; TextOnly: Boolean): TRect;
60219 begin
60220 Result.Left := Item;
60221 if Perform( TVM_GETITEMRECT, Integer( TextOnly ), Integer( @Result ) ) = 0 then
60222 begin
60223 Result.Left := 0;
60224 Result.Right := 0;
60225 Result.Top := 0;
60226 Result.Bottom := 0;
60227 end;
60228 end;
60230 //[function TControl.TVGetItemVisible]
60231 function TControl.TVGetItemVisible(Item: THandle): Boolean;
60232 var R: TRect;
60233 begin
60234 R := TVItemRect[ Item, False ];
60235 Result := R.Bottom > R.Top;
60236 end;
60238 //[procedure TControl.TVSetItemVisible]
60239 procedure TControl.TVSetItemVisible(Item: THandle; const Value: Boolean);
60240 begin
60241 if Value then
60242 Perform( TVM_ENSUREVISIBLE, 0, Item );
60243 end;
60245 //[function TControl.TVGetItemStateFlg]
60246 function TControl.TVGetItemStateFlg(Item: THandle; const Index: Integer): Boolean;
60247 var TVI: TTVItem;
60248 begin
60249 TVI.mask := TVIF_HANDLE or TVIF_STATE;
60250 TVI.hItem := Item;
60251 TVI.stateMask := Index;
60252 Result := False;
60253 if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then
60254 Result := (TVI.state and Index) <> 0;
60255 end;
60257 //[procedure TControl.TVSetItemStateFlg]
60258 procedure TControl.TVSetItemStateFlg(Item: THandle; const Index: Integer;
60259 const Value: Boolean);
60260 var TVI: TTVItem;
60261 begin
60262 TVI.mask := TVIF_HANDLE or TVIF_STATE;
60263 TVI.hItem := Item;
60264 TVI.stateMask := Index;
60265 TVI.state := $FFFFFFFF and Index;
60266 if not Value then
60267 TVI.state := 0;
60268 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
60269 end;
60271 //[function TControl.TVGetItemImage]
60272 function TControl.TVGetItemImage(Item: THandle; const Index: Integer): Integer;
60273 var TVI: TTVItem;
60274 begin
60275 TVI.mask := TVIF_HANDLE or Loword( Index );
60276 TVI.hItem := Item;
60277 if Hiword( Index ) <> 0 then
60278 begin
60279 TVI.mask := TVIF_STATE or TVIF_HANDLE;
60280 TVI.stateMask := Loword( Index );
60281 end;
60282 Result := -1;
60283 if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then
60284 begin
60285 if Hiword( Index ) <> 0 then
60286 Result := (TVI.state shr Hiword( Index )) and $F
60287 else
60288 if Loword( Index ) = TVIF_IMAGE then
60289 Result := TVI.iImage
60290 else
60291 Result := TVI.iSelectedImage;
60292 end;
60293 end;
60295 //[procedure TControl.TVSetItemImage]
60296 procedure TControl.TVSetItemImage(Item: THandle; const Index: Integer;
60297 const Value: Integer);
60298 var TVI: TTVItem;
60299 begin
60300 TVI.mask := TVIF_HANDLE or Loword( Index );
60301 TVI.hItem := Item;
60302 TVI.iImage := Value;
60303 TVI.iSelectedImage := Value;
60304 if Hiword( Index ) <> 0 then
60305 begin
60306 TVI.mask := TVIF_STATE or TVIF_HANDLE;
60307 TVI.stateMask := Loword( Index );
60308 TVI.state := Value shl Hiword( Index );
60309 end;
60310 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
60311 end;
60313 //[function TControl.TVGetItemText]
60314 function TControl.TVGetItemText(Item: THandle): String;
60315 var TVI: TTVItem;
60316 Buffer: array[ 0..4095 ] of Char;
60317 begin
60318 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
60319 TVI.hItem := Item;
60320 TVI.pszText := @Buffer[ 0 ];
60321 Buffer[ 0 ] := #0;
60322 TVI.cchTextMax := Sizeof( Buffer );
60323 Perform( TVM_GETITEM, 0, Integer( @TVI ) );
60324 Result := Buffer;
60325 end;
60327 //[procedure TControl.TVSetItemText]
60328 procedure TControl.TVSetItemText(Item: THandle; const Value: String);
60329 var TVI: TTVItem;
60330 begin
60331 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
60332 TVI.hItem := Item;
60333 TVI.pszText := PChar( Value );
60334 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
60335 end;
60337 {$IFNDEF _FPC}
60338 {$IFNDEF _D2}
60339 //[function TControl.TVGetItemTextW]
60340 function TControl.TVGetItemTextW(Item: THandle): WideString;
60341 var TVI: TTVItemW;
60342 Buffer: array[ 0..4095 ] of WideChar;
60343 begin
60344 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
60345 TVI.hItem := Item;
60346 TVI.pszText := @Buffer[ 0 ];
60347 Buffer[ 0 ] := #0;
60348 TVI.cchTextMax := High( Buffer ) + 1;
60349 Perform( TVM_GETITEMW, 0, Integer( @TVI ) );
60350 Result := Buffer;
60351 end;
60353 //[procedure TControl.TVSetItemTextW]
60354 procedure TControl.TVSetItemTextW(Item: THandle; const Value: WideString);
60355 var TVI: TTVItemW;
60356 begin
60357 TVI.mask := TVIF_HANDLE or TVIF_TEXT;
60358 TVI.hItem := Item;
60359 TVI.pszText := PWideChar( Value );
60360 Perform( TVM_SETITEMW, 0, Integer( @TVI ) );
60361 end;
60362 {$ENDIF _D2}
60363 {$ENDIF _FPC}
60365 //[function TControl.TVItemPath]
60366 function TControl.TVItemPath(Item: THandle; Delimiter: Char): String;
60367 begin
60368 if Item = 0 then
60369 Item := TVSelected;
60370 Result := '';
60371 while Item <> 0 do
60372 begin
60373 if Result <> '' then
60374 Result := Delimiter + Result;
60375 Result := TVItemText[ Item ] + Result;
60376 Item := TVItemParent[ Item ];
60377 end;
60378 end;
60380 {$IFNDEF _FPC}
60381 {$IFNDEF _D2}
60382 //[function TControl.TVItemPathW]
60383 function TControl.TVItemPathW(Item: THandle;
60384 Delimiter: WideChar): WideString;
60385 begin
60386 if Item = 0 then
60387 Item := TVSelected;
60388 Result := '';
60389 while Item <> 0 do
60390 begin
60391 if Result <> '' then
60392 Result := {$IFDEF _D3} '' + {$ENDIF} Delimiter + Result;
60393 Result := TVItemTextW[ Item ] + Result;
60394 Item := TVItemParent[ Item ];
60395 end;
60396 end;
60397 {$ENDIF _D2}
60398 {$ENDIF _FPC}
60400 //[function TControl.TV_GetItemHasChildren]
60401 function TControl.TV_GetItemHasChildren(Item: THandle): Boolean;
60402 var TVI: TTVItem;
60403 begin
60404 TVI.mask := TVIF_HANDLE or TVIF_CHILDREN;
60405 TVI.hItem := Item;
60406 Perform( TVM_GETITEM, 0, Integer( @TVI ) );
60407 Result := TVI.cChildren = 1;
60408 end;
60410 //[procedure TControl.TV_GetItemChildCount]
60411 function TControl.TV_GetItemChildCount(Item: THandle): Integer;
60412 var Node: THandle;
60413 begin
60414 Result := 0;
60415 Node := TVItemChild[ Item ];
60416 while Node <> 0 do
60417 begin
60418 Inc( Result );
60419 Node := TVItemNext[ Node ];
60420 end;
60421 end;
60423 //[procedure TControl.TV_SetItemHasChildren]
60424 procedure TControl.TV_SetItemHasChildren(Item: THandle;
60425 const Value: Boolean);
60426 var TVI: TTVItem;
60427 begin
60428 TVI.mask := TVIF_HANDLE or TVIF_CHILDREN;
60429 TVI.hItem := Item;
60430 TVI.cChildren := 1 and Integer( Value );
60431 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
60432 end;
60434 //[function TControl.TVItemAtPos]
60435 function TControl.TVItemAtPos(x, y: Integer; var Where: DWORD): THandle;
60436 var HTI: TTVHitTestInfo;
60437 begin
60438 HTI.pt.x := x;
60439 HTI.pt.y := y;
60440 Result := Perform( TVM_HITTEST, 0, Integer( @HTI ) );
60441 Where := HTI.fl;
60442 end;
60444 type
60445 TTVInsertStruct = packed Record
60446 hParent: THandle;
60447 hAfter : THandle;
60448 item: TTVItem;
60449 end;
60450 TTVInsertStructEx = packed Record
60451 hParent: THandle;
60452 hAfter : THandle;
60453 item: TTVItemEx;
60454 end;
60456 //[function TControl.TVInsert]
60457 function TControl.TVInsert(nParent, nAfter: THandle;
60458 const Txt: String): THandle;
60459 var TVIns: TTVInsertStruct;
60460 begin
60461 TVIns.hParent := nParent;
60462 TVIns.hAfter := nAfter;
60463 TVIns.item.mask := TVIF_TEXT;
60464 TVIns.item.pszText := PChar( Txt );
60465 Result := Perform( TVM_INSERTITEM, 0, Integer( @TVIns ) );
60466 Invalidate;
60467 end;
60469 {$IFNDEF _FPC}
60470 {$IFNDEF _D2}
60471 type
60472 TTVInsertStructW = packed Record
60473 hParent: THandle;
60474 hAfter : THandle;
60475 item: TTVItemW;
60476 end;
60477 TTVInsertStructExW = packed Record
60478 hParent: THandle;
60479 hAfter : THandle;
60480 item: TTVItemExW;
60481 end;
60483 //[function TControl.TVInsertW]
60484 function TControl.TVInsertW(nParent, nAfter: THandle;
60485 const Txt: WideString): THandle;
60486 var TVIns: TTVInsertStructW;
60487 begin
60488 TVIns.hParent := nParent;
60489 TVIns.hAfter := nAfter;
60490 TVIns.item.mask := TVIF_TEXT;
60491 if Txt = '' then TVIns.item.pszText := nil
60492 else TVIns.item.pszText := PWideChar( @ Txt[ 1 ] );
60493 Result := Perform( TVM_INSERTITEMW, 0, Integer( @ TVIns ) );
60494 Invalidate;
60495 end;
60496 {$ENDIF _D2}
60497 {$ENDIF _FPC}
60499 //[procedure TControl.TVExpand]
60500 procedure TControl.TVExpand(Item: THandle; Flags: DWORD);
60501 begin
60502 Perform( TVM_EXPAND, Flags, Item );
60503 end;
60505 //[procedure TControl.TVSort]
60506 procedure TControl.TVSort( N: THandle );
60507 var a: Cardinal;
60508 b: Boolean;
60509 begin
60510 b := N = 0;
60511 if b then
60512 begin
60513 N := TVRoot;
60514 end;
60515 while N <> 0 do
60516 begin
60517 a := TVItemChild[N];
60518 if a > 0 then
60519 TVSort(a);
60520 Perform(TVM_SORTCHILDREN, 0, N);
60521 N := TVItemNext[N];
60522 end;
60523 if b then //moved by Tr"]f
60524 Perform(TVM_SORTCHILDREN, 0, 0); //+ by YS
60525 end;
60527 //[procedure TControl.TVDelete]
60528 procedure TControl.TVDelete(Item: THandle);
60529 begin
60530 Perform( TVM_DELETEITEM, 0, Item );
60531 Invalidate;
60532 end;
60534 //[function TControl.TVGetItemData]
60535 function TControl.TVGetItemData(Item: THandle): Pointer;
60536 var TVI: TTVItem;
60537 begin
60538 TVI.mask := TVIF_HANDLE or TVIF_PARAM;
60539 TVI.hItem := Item;
60540 Result := nil;
60541 if Perform( TVM_GETITEM, 0, Integer( @TVI ) ) <> 0 then
60542 Result := Pointer( TVI.lParam );
60543 end;
60545 //[procedure TControl.TVSetItemData]
60546 procedure TControl.TVSetItemData(Item: THandle; const Value: Pointer);
60547 var TVI: TTVItem;
60548 begin
60549 TVI.mask := TVIF_HANDLE or TVIF_PARAM;
60550 TVI.hItem := Item;
60551 TVI.lParam := Integer( Value );
60552 Perform( TVM_SETITEM, 0, Integer( @TVI ) );
60553 end;
60555 //[procedure TControl.TVEditItem]
60556 procedure TControl.TVEditItem(Item: THandle);
60557 begin
60558 Perform( TVM_EDITLABEL, 0, Item );
60559 end;
60561 //[procedure TControl.TVStopEdit]
60562 procedure TControl.TVStopEdit(Cancel: Boolean);
60563 begin
60564 Perform( TVM_ENDEDITLABELNOW, Integer( Cancel ), 0 );
60565 end;
60567 //[function WndProcTVRightClickSelect]
60568 function WndProcTVRightClickSelect( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;
60569 var I: Integer;
60570 Where: DWORD;
60571 begin
60572 if Msg.message = WM_RBUTTONDOWN then
60573 begin
60574 I := Sender.TVItemAtPos( SmallInt( Msg.lParam and $FFFF ),
60575 SmallInt( Msg.lParam shr 16 ), Where );
60576 if I <> 0 then
60577 Sender.TVSelected := I;
60578 end;
60579 Result := FALSE;
60580 end;
60582 //[procedure TControl.SetTVRightClickSelect]
60583 procedure TControl.SetTVRightClickSelect(const Value: Boolean);
60584 begin
60585 fTVRightClickSelect := Value;
60586 if Value then
60587 AttachProc( @WndProcTVRightClickSelect );
60588 end;
60590 //[procedure TControl.SetOnTVDelete]
60591 procedure TControl.SetOnTVDelete( const Value: TOnTVDelete );
60592 begin
60593 fOnTVDelete := Value;
60594 if fParent <> nil then
60595 begin
60596 fParent.Add2AutoFreeEx( Clear );
60597 fParent.DetachProc( WndProcNotify );
60598 fParent.AttachProcEx( WndProcNotify, TRUE );
60599 end;
60600 AttachProcEx( ProcTVDeleteItem, TRUE );
60601 end;
60603 //[function Clipboard2Text]
60604 function Clipboard2Text: String;
60605 var gbl: THandle;
60606 str: PChar;
60607 begin
60608 Result := '';
60609 if OpenClipboard( 0 ) then
60610 begin
60611 if IsClipboardFormatAvailable( CF_TEXT ) then
60612 begin
60613 gbl := GetClipboardData( CF_TEXT );
60614 if gbl <> 0 then
60615 begin
60616 str := GlobalLock( gbl );
60617 if str <> nil then
60618 begin
60619 Result := str;
60620 GlobalUnlock( gbl );
60621 end;
60622 end;
60623 end;
60624 CloseClipboard;
60625 end;
60626 end;
60629 {$IFNDEF _D2}
60630 //[function Clipboard2WText]
60631 function Clipboard2WText: WideString;
60632 var gbl: THandle;
60633 str: PWideChar;
60634 begin
60635 Result := '';
60636 if OpenClipboard( 0 ) then
60637 begin
60638 if IsClipboardFormatAvailable( CF_UNICODETEXT ) then
60639 begin
60640 gbl := GetClipboardData( CF_UNICODETEXT );
60641 if gbl <> 0 then
60642 begin
60643 str := GlobalLock( gbl );
60644 if str <> nil then
60645 begin
60646 Result := str;
60647 GlobalUnlock( gbl );
60648 end;
60649 end;
60650 end;
60651 CloseClipboard;
60652 end;
60653 end;
60654 {$ENDIF}
60657 //[function Text2Clipboard]
60658 function Text2Clipboard( const S: String ): Boolean;
60659 var gbl: THandle;
60660 str: PChar;
60661 begin
60662 Result := False;
60663 if not OpenClipboard( 0 ) then Exit;
60664 EmptyClipboard;
60665 if S <> '' then
60666 begin
60667 gbl := GlobalAlloc( GMEM_DDESHARE, Length( S ) + 1 );
60668 if gbl <> 0 then
60669 begin
60670 str := GlobalLock( gbl );
60671 Move( S[ 1 ], str^, Length( S ) + 1 );
60672 GlobalUnlock( gbl );
60673 Result := SetClipboardData( CF_TEXT, gbl ) <> 0;
60674 end;
60676 else
60677 Result := True;
60678 CloseClipboard;
60679 end;
60682 {$IFNDEF _D2}
60683 //[function WText2Clipboard]
60684 function WText2Clipboard( const WS: WideString ): Boolean;
60685 var gbl: THandle;
60686 str: PChar;
60687 begin
60688 Result := False;
60689 if not OpenClipboard( 0 ) then Exit;
60690 EmptyClipboard;
60691 if WS <> '' then
60692 begin
60693 gbl := GlobalAlloc( GMEM_DDESHARE, (Length( WS ) + 1) * 2 );
60694 if gbl <> 0 then
60695 begin
60696 str := GlobalLock( gbl );
60697 Move( WS[ 1 ], str^, (Length( WS ) + 1) * 2 );
60698 GlobalUnlock( gbl );
60699 Result := SetClipboardData( CF_UNICODETEXT, gbl ) <> 0;
60700 end;
60702 else
60703 Result := True;
60704 CloseClipboard;
60705 end;
60706 {$ENDIF}
60709 //[function TControl.Size]
60710 function TControl.Size(W, H: Integer): PControl;
60711 var C, P: PControl;
60712 dW, dH: Integer;
60713 begin
60714 C := @Self;
60715 while True do
60716 begin
60717 dW := 0; dH := 0;
60718 P := C.FParent;
60719 if C.ToBeVisible {or C.fCreateHidden {or (P <> nil) and (P.fVisible)} then
60720 begin
60721 if C.fAlign in [caLeft, caRight, caClient] then
60722 begin
60723 if H > 0 then
60724 begin
60725 dH := H - C.Height; H := 0;
60726 end;
60727 end;
60728 if C.fAlign in [caTop, caBottom, caClient] then
60729 begin
60730 if W > 0 then
60731 begin
60732 dW := W - C.Width; W := 0;
60733 end;
60734 end;
60735 end;
60736 if (W > 0) or (H > 0) then
60737 begin
60738 C.SetSize( W, H );
60739 if (P <> nil) // {Ralf Junker}
60740 and not P.IsApplet then
60741 C.ResizeParent;
60742 end;
60743 if (dW = 0) and (dH = 0) then break;
60744 C := P; //C.FParent;
60745 if C = nil then break;
60746 //if not C.fIsControl then break;
60747 if C.IsApplet then break;
60748 W := C.Width + dW;
60749 H := C.Height + dH;
60750 end;
60751 Result := @Self;
60752 end;
60754 //[procedure AutoSzProc]
60755 procedure AutoSzProc( Self_: PControl );
60756 var DeltaX, DeltaY: Integer;
60757 SZ: TSize; PT: TPoint;
60758 Txt: String;
60759 Chg: Boolean;
60760 R: TRect;
60761 Flags: DWORD;
60762 {+ecm}
60763 OldFont: HFONT;
60764 CtlHavingFont: PControl;
60765 {/+ecm}
60766 begin
60767 Txt := Self_.fCaption;
60768 SZ.cx := 0;
60769 SZ.cy := 0;
60770 if Txt <> '' then
60771 begin
60772 if Assigned( Self_.fFont ) then
60773 if Self_.fFont.fData.Font.Italic then
60774 Txt := Txt + ' ';
60775 Self_.GetWindowHandle; // this line must be here.
60776 //-- otherwise, when handle is not yet allocated,
60777 // it is requested in TCanvas.GetHandle, and in result
60778 // of unpredictable recursion some memory can be currupted.
60779 Self_.Canvas.TextArea( Txt, SZ, PT );
60780 if Self_.fWordWrap and (Self_.fAlign <> caClient) then
60781 begin
60782 R := Self_.ClientRect;
60783 Flags := DT_CALCRECT or DT_EXPANDTABS or DT_WORDBREAK;
60784 CASE Self_.fTextAlign OF
60785 taCenter: Flags := Flags or DT_CENTER;
60786 taRight : Flags := Flags or DT_RIGHT;
60787 END;
60788 {-ecm}
60789 // CASE Self_.fVerticalAlign OF
60790 // vaCenter: Flags := Flags or DT_VCENTER;
60791 // vaBottom: Flags := Flags or DT_BOTTOM;
60792 // END;
60793 {/-ecm}
60794 {+ecm}
60795 CtlHavingFont := Self_;
60796 while (CtlHavingFont <> nil) and not Assigned( CtlHavingFont.FFont ) do
60797 CtlHavingFont := CtlHavingFont.Parent;
60798 OldFont := 0;
60799 if Assigned( CtlHavingFont ) then
60800 OldFont := SelectObject( Self_.Canvas.Handle, CtlHavingFont.Font.Handle );
60801 {/+ecm}
60802 // DrawText return the height of the text !
60803 SZ.cy := DrawText( Self_.fCanvas.Handle, PChar( Txt ), Length( Txt ), R, Flags );
60804 {+ecm}
60805 if Assigned( CtlHavingFont ) then
60806 SelectObject(Self_.Canvas.fHandle,OldFont);
60807 {/+ecm}
60808 SZ.cx := R.Right - R.Left;
60809 //SZ.cy := R.Bottom - R.Top;
60810 end;
60811 end;
60812 Chg := FALSE;
60813 if Self_.FAlign in [ caNone, caLeft, caRight ] then
60814 begin
60815 DeltaX := Self_.fCommandActions.aAutoSzX;
60816 if Self_.Width <> SZ.cx + DeltaX then
60817 begin
60818 Self_.Width := SZ.cx + DeltaX;
60819 Chg := TRUE;
60820 end;
60821 end;
60822 if Self_.FAlign in [ caNone, caTop, caBottom ] then
60823 begin
60824 DeltaY := Self_.fCommandActions.aAutoSzY;
60825 if Self_.Height <> SZ.cy + DeltaY then
60826 begin
60827 Self_.Height := SZ.cy + DeltaY;
60828 Chg := TRUE;
60829 end;
60830 end;
60831 if Chg then
60832 begin
60833 if Self_.fParent <> nil then
60834 Global_Align( Self_.fParent );
60835 Global_Align( Self_ );
60836 end;
60837 end;
60839 //[function TControl.AutoSize]
60840 function TControl.AutoSize(AutoSzOn: Boolean): PControl;
60841 begin
60842 if AutoSzOn then
60843 begin
60844 fAutoSize := AutoSzProc;
60845 fAutoSize( @Self );
60847 else
60848 fAutoSize := nil;
60849 Result := @Self;
60850 end;
60852 //[function TControl.IsAutoSize]
60853 function TControl.IsAutoSize: Boolean;
60854 begin
60855 Result := Assigned( fAutoSize );
60856 end;
60859 //[function TControl.GetToBeVisible]
60860 function TControl.GetToBeVisible: Boolean;
60861 begin
60862 Result := fVisible or fCreateHidden or fVisibleWoParent;
60863 if fIsControl then
60864 if Parent <> nil then
60865 begin
60866 if fVisibleWoParent then
60867 Result := fVisible
60868 else
60869 begin
60870 Parent.Visible; // needed to provide correct fVisible for a form!
60871 Result := Result and Parent.ToBeVisible;
60872 end;
60873 end;
60874 end;
60876 { -- TTree -- }
60878 {$IFDEF USE_CONSTRUCTORS}
60879 //[function NewTree]
60880 function NewTree( AParent: PTree; const AName: String ): PTree;
60881 begin
60882 New( Result, CreateTree( AParent, AName ) );
60883 end;
60884 //[END NewTree]
60885 {$ELSE not_USE_CONSTRUCTORS}
60886 //[function NewTree]
60887 function NewTree( AParent: PTree; const AName: String ): PTree;
60888 begin
60890 New( Result, Create );
60891 {+}{++}(*Result := PTree.Create;*){--}
60892 if AParent <> nil then
60893 AParent.Add( Result );
60894 Result.fParent := AParent;
60895 Result.fNodeName := AName;
60896 end;
60897 //[END NewTree]
60898 {$ENDIF USE_CONSTRUCTORS}
60900 { TTree }
60902 //[procedure TTree.Add]
60903 procedure TTree.Add(Node: PTree);
60904 var Previous: PTree;
60905 begin
60906 Node.Unlink;
60907 if fChildren = nil then
60908 fChildren := NewList;
60909 Previous := nil;
60910 if fChildren.fCount > 0 then
60911 Previous := fChildren.fItems[ fChildren.fCount - 1 ];
60912 if Previous <> nil then
60913 begin
60914 Previous.fNext := Node;
60915 Node.fPrev := Previous;
60916 end;
60917 fChildren.Add( Node );
60918 Node.fParent := @Self;
60919 end;
60921 //[procedure TTree.Clear]
60922 procedure TTree.Clear;
60923 var I: Integer;
60924 begin
60925 if fChildren = nil then Exit;
60926 for I := fChildren.fCount - 1 downto 0 do
60927 PTree( fChildren.fItems[ I ] ).Free;
60928 end;
60930 {$IFDEF USE_CONSTRUCTORS}
60931 //[constructor TTree.CreateTree]
60932 constructor TTree.CreateTree(AParent: PTree; const AName: String);
60933 begin
60934 inherited Create;
60935 if AParent <> nil then
60936 AParent.Add( @Self );
60937 fParent := AParent;
60938 fName := AName;
60939 end;
60940 {$ENDIF}
60942 //[destructor TTree.Destroy]
60943 destructor TTree.Destroy;
60944 begin
60945 Unlink;
60946 Clear;
60947 fNodeName := '';
60948 inherited;
60949 end;
60951 //[function TTree.GetCount]
60952 function TTree.GetCount: Integer;
60953 begin
60954 Result := 0;
60955 if fChildren = nil then Exit;
60956 Result := fChildren.fCount;
60957 end;
60959 //[function TTree.GetIndexAmongSiblings]
60960 function TTree.GetIndexAmongSiblings: Integer;
60961 begin
60962 Result := -1;
60963 if fParent = nil then Exit;
60964 Result := fParent.fChildren.IndexOf( @Self );
60965 end;
60967 //[function TTree.GetItems]
60968 function TTree.GetItems(Idx: Integer): PTree;
60969 begin
60970 Result := nil;
60971 if fChildren = nil then Exit;
60972 Result := fChildren.Items[ Idx ];
60973 end;
60975 //[function TTree.GetLevel]
60976 function TTree.GetLevel: Integer;
60977 var Node: PTree;
60978 begin
60979 Result := 0;
60980 Node := fParent;
60981 while Node <> nil do
60982 begin
60983 Inc( Result );
60984 Node := Node.fParent;
60985 end;
60986 end;
60988 //[function TTree.GetRoot]
60989 function TTree.GetRoot: PTree;
60990 begin
60991 Result := @Self;
60992 while Result.fParent <> nil do
60993 Result := Result.fParent;
60994 end;
60996 //[function TTree.GetTotal]
60997 function TTree.GetTotal: Integer;
60998 var I: Integer;
60999 begin
61000 Result := Count;
61001 if Result <> 0 then
61002 begin
61003 for I := 0 to Count - 1 do
61004 Result := Result + Items[ I ].Total;
61005 end;
61006 end;
61008 //[procedure TTree.Init]
61009 procedure TTree.Init;
61010 begin
61011 if FParent <> nil then
61012 FParent.Add( @Self );
61013 end;
61015 //[procedure TTree.Insert]
61016 procedure TTree.Insert(Before, Node: PTree);
61017 var Previous: PTree;
61018 begin
61019 Node.Unlink;
61020 if fChildren = nil then
61021 fChildren := NewList;
61022 Previous := nil;
61023 if Before <> nil then
61024 Previous := Before.fPrev;
61025 if Previous <> nil then
61026 begin
61027 Previous.fNext := Node;
61028 Node.fPrev := Previous;
61029 end;
61030 if Before <> nil then
61031 begin
61032 Node.fNext := Before;
61033 Before.fPrev := Node;
61034 fChildren.Insert( fChildren.IndexOf( Before ), Node );
61036 else
61037 fChildren.Add( Node );
61038 Node.fParent := @Self;
61039 end;
61041 //[function CompareTreeNodes]
61042 function CompareTreeNodes( const Data: Pointer; const e1, e2: DWORD ): Integer;
61043 var List: PList;
61044 begin
61045 List := Data;
61046 Result := AnsiCompareStr( PTree( List.fItems[ e1 ] ).fNodeName,
61047 PTree( List.fItems[ e2 ] ).fNodeName );
61048 end;
61050 //[procedure SwapTreeNodes]
61051 procedure SwapTreeNodes( const Data: Pointer; const e1, e2: DWORD );
61052 var List: PList;
61053 begin
61054 List := Data;
61055 List.Swap( e1, e2 );
61056 end;
61058 //[procedure TTree.SwapNodes]
61059 procedure TTree.SwapNodes( i1, i2: Integer );
61060 begin
61061 fChildren.Swap( i1, i2 );
61062 end;
61064 //[procedure TTree.SortByName]
61065 procedure TTree.SortByName;
61066 begin
61067 if Count <= 1 then Exit;
61068 SortData( fChildren, fChildren.fCount, CompareTreeNodes, SwapTreeNodes );
61069 end;
61071 //[procedure TTree.Unlink]
61072 procedure TTree.Unlink;
61073 var I: Integer;
61074 begin
61075 if fPrev <> nil then
61076 fPrev.fNext := fNext;
61077 if fNext <> nil then
61078 fNext.fPrev := fPrev;
61079 if (fParent <> nil) then
61080 begin
61081 I := fParent.fChildren.IndexOf( @Self );
61082 fParent.fChildren.Delete( I );
61083 if fParent.fChildren.fCount = 0 then
61084 begin
61085 fParent.fChildren.Free;
61086 fParent.fChildren := nil;
61087 end;
61088 end;
61089 fPrev := nil;
61090 fNext := nil;
61091 fParent := nil;
61092 end;
61094 //[function TTree.IsParentOfNode]
61095 function TTree.IsParentOfNode(Node: PTree): Boolean;
61096 begin
61097 Result := TRUE;
61098 while Node <> nil do
61099 begin
61100 if Node = @ Self then Exit;
61101 Node := Node.Parent;
61102 end;
61103 Result := FALSE;
61104 end;
61106 //[function TTree.IndexOf]
61107 function TTree.IndexOf(Node: PTree): Integer;
61108 begin
61109 Result := -1;
61110 if not IsParentOfNode( Node ) then Exit;
61111 while Node <> @ Self do
61112 begin
61113 Inc( Result );
61114 while Node.PrevSibling <> nil do
61115 begin
61116 Node := Node.PrevSibling;
61117 Inc( Result, 1 + Node.Total );
61118 end;
61119 Node := Node.Parent;
61120 end;
61121 end;
61124 //[procedure TControl.ProcessPendingMessages]
61125 procedure TControl.ProcessPendingMessages;
61126 var Msg: TMsg;
61127 begin
61128 if LOWORD( GetQueueStatus( QS_ALLINPUT ) ) <> 0 then
61129 if PeekMessage( Msg, 0, 0, 0, PM_NOREMOVE {or PM_NOYIELD} )
61130 or PeekMessage( Msg, HWnd(-1), 0, 0, PM_NOREMOVE {or PM_NOYIELD} )
61131 then
61132 Applet.ProcessMessages;
61133 end;
61135 //[procedure TControl.ProcessPaintMessages]
61136 procedure TControl.ProcessPaintMessages;
61137 var Msg: TMsg;
61138 begin
61139 while PeekMessage( Msg, Handle, 15, 15, PM_NOREMOVE ) do
61140 //while GetQueueStatus( QS_PAINT ) <> 0 do
61141 Applet.ProcessMessage;
61142 end;
61152 ///////////////////////////////////////////////////////////////////////
61155 // W I N D O W S
61158 ///////////////////////////////////////////////////////////////////////
61162 { -- Set of window-related utility functions. -- }
61163 type
61164 PGUIThreadInfo = ^TGUIThreadInfo;
61165 tagGUITHREADINFO = packed record
61166 cbSize: DWORD;
61167 flags: DWORD;
61168 hwndActive: HWND;
61169 hwndFocus: HWND;
61170 hwndCapture: HWND;
61171 hwndMenuOwner: HWND;
61172 hwndMoveSize: HWND;
61173 hwndCaret: HWND;
61174 rcCaret: TRect;
61175 end;
61176 TGUIThreadInfo = tagGUITHREADINFO;
61178 const
61179 GUI_CARETBLINKING = $00000001;
61180 GUI_INMOVESIZE = $00000002;
61181 GUI_INMENUMODE = $00000004;
61182 GUI_SYSTEMMENUMODE = $00000008;
61183 GUI_POPUPMENUMODE = $00000010;
61185 {function GetGUIThreadInfo (idThread: DWORD; var pgui: TGUIThreadinfo): BOOL; stdcall;
61186 external user32 name 'GetGUIThreadInfo';}
61188 type TGUIThreadInfo_Proc = function( ThreadID: THandle; var GTI: TGUIThreadInfo )
61189 : Boolean; stdcall;
61191 var Proc_GetGUIThreadInfo: TGuiThreadInfo_Proc;
61193 //[function GetWindowChild]
61194 function GetWindowChild( Wnd: HWnd; Kind: TWindowChildKind ): HWnd;
61195 var GTI: TGuiThreadInfo;
61196 ThreadID: THandle;
61197 Module: THandle;
61198 begin
61199 if not Assigned( Proc_GetGUIThreadInfo ) then
61200 begin
61201 Module := GetModuleHandle( 'User32' );
61202 Proc_GetGUIThreadInfo := GetProcAddress( Module, 'GetGUIThreadInfoA' );
61203 if not Assigned( Proc_GetGUIThreadInfo ) then
61204 Proc_GetGUIThreadInfo := Pointer( -1 );
61205 end;
61206 Result := Wnd;
61207 if Integer( @Proc_GetGUIThreadInfo ) = -1 then
61208 Exit;
61209 Result := 0;
61210 if Wnd = 0 then
61211 ThreadID := GetCurrentThreadID
61212 else
61213 ThreadID := GetWindowThreadProcessID( Wnd, nil );
61214 if ThreadID = 0 then Exit;
61215 GTI.cbSize := Sizeof( GTI );
61216 if Proc_GetGUIThreadInfo( ThreadId, GTI ) then
61217 begin
61218 case Kind of
61219 wcActive: Result := GTI.hwndActive;
61220 wcFocus: Result := GTI.hwndFocus;
61221 wcCapture: Result := GTI.hwndCapture;
61222 wcMenuOwner: Result := GTI.hwndMenuOwner;
61223 wcMoveSize: Result := GTI.hwndMoveSize;
61224 wcCaret: Result := GTI.hwndCaret;
61225 end;
61226 end;
61227 end;
61229 //[function GetFocusedChild]
61230 function GetFocusedChild( Wnd: HWnd ): HWnd;
61231 var Tr1, Tr2: THandle;
61232 begin
61233 Result := 0;
61234 Tr1 := GetCurrentThreadId;
61235 Tr2 := GetWindowThreadProcessId( Wnd, nil );
61236 if Tr1 = Tr2 then
61237 Result := GetFocus
61238 else
61239 if AttachThreadInput( Tr2, Tr1, True ) then
61240 begin
61241 Result := GetFocus;
61242 AttachThreadInput( Tr2, Tr1, False );
61243 end;
61244 end;
61246 //[function WaitFocusedWndChild]
61247 function WaitFocusedWndChild( Wnd: HWnd ): HWnd;
61248 var T1, T2: Integer;
61249 W: HWnd;
61250 begin
61251 Sleep( 50 );
61252 T1 := GetTickCount;
61253 while True do
61254 begin
61255 W := GetTopWindow( Wnd );
61256 if W = 0 then W := Wnd;
61257 W := GetFocusedChild( W );
61258 if W <> 0 then
61259 begin
61260 Wnd := W;
61261 break;
61262 end;
61263 T2 := GetTickCount;
61264 if Abs( T1 - T2 ) > 100 then break;
61265 end;
61266 Result := Wnd;
61267 end;
61269 //[function Stroke2Window]
61270 function Stroke2Window( Wnd: HWnd; const S: String ): Boolean;
61271 var P: PChar;
61272 begin
61273 Result := False;
61274 //Wnd := GetTopWindow( Wnd );
61275 Wnd := WaitFocusedWndChild( Wnd );
61276 if Wnd = 0 then Exit;
61277 P := PChar( S );
61278 while P^ <> #0 do
61279 begin
61280 PostMessage( Wnd, WM_CHAR, Integer( P^ ), 1 );
61281 Inc( P );
61282 end;
61283 Result := True;
61284 end;
61286 //[function Stroke2WindowEx]
61287 function Stroke2WindowEx( Wnd: HWnd; const S: String; Wait: Boolean ): Boolean;
61288 var P: PChar;
61289 EndChar: Char;
61290 MsgDn, MsgUp, SCA: Integer;
61292 function Compare( Pattern: PChar ): Boolean;
61293 var Pos: PChar;
61294 C1, C2: Char;
61295 begin
61296 Pos := P;
61297 while Pattern^ <> #0 do
61298 begin
61299 C1 := Pattern^;
61300 C2 := Pos^;
61301 if C1 in [ 'a'..'z' ] then
61302 C1 := Char( Ord( C1 ) - $20 );
61303 if C2 in [ 'a'..'z' ] then
61304 C2 := Char( Ord( C2 ) - $20 );
61305 if C1 <> C2 then
61306 begin
61307 Result := False;
61308 Exit;
61309 end;
61310 Inc( Pos );
61311 Inc( Pattern );
61312 end;
61313 while Pos^ = ' ' do Inc( Pos );
61314 P := Pos;
61315 Result := True;
61316 end;
61318 procedure Send( Msg, KeyCode: Integer );
61319 var lParam: Integer;
61320 begin
61321 Wnd := WaitFocusedWndChild( Wnd );
61322 if Wnd = 0 then Exit;
61323 lParam := 1;
61324 if longBool( SCA and 4 ) then
61325 lParam := $20000001;
61326 if Msg = MsgUp then
61327 lParam := lParam or Integer($D0000000);
61328 PostMessage( Wnd, Msg, KeyCode, lParam );
61329 Applet.ProcessMessages;
61330 if Wait then
61331 Sleep( 50 );
61332 end;
61334 function CompareSend( Pattern: PChar; Value2Send: Integer ): Boolean;
61335 begin
61336 if Compare( Pattern ) then
61337 begin
61338 Send( MsgDn, Value2Send );
61339 Send( MsgUp, Value2Send );
61340 Result := True;
61342 else
61343 Result := False;
61344 end;
61346 function ParseKeys( EndChar: Char ): PChar;
61347 var FN: Integer;
61348 begin
61349 SCA := 0;
61350 while not (P^ in [ #0, EndChar ]) do
61351 begin
61352 if Compare( 'Shift' ) then SCA := SCA or 1
61353 else
61354 if Compare( 'Ctrl' ) then SCA := SCA or 2
61355 else
61356 if Compare( 'Alt' ) then SCA := SCA or 4
61357 else
61358 break;
61359 end;
61360 MsgDn := WM_KEYDOWN;
61361 MsgUp := WM_KEYUP;
61362 if LongBool( SCA and 4 ) then
61363 begin
61364 MsgDn := WM_SYSKEYDOWN;
61365 MsgUp := WM_SYSKEYUP;
61366 keybd_event( VK_MENU, 0, 0, 0 );
61367 Send( WM_SYSKEYDOWN, VK_MENU );
61368 end;
61369 if LongBool( SCA and 2 ) then
61370 begin
61371 keybd_event( VK_CONTROL, 0, 0, 0 );
61372 Send( WM_KEYDOWN, VK_CONTROL );
61373 end;
61374 if Longbool( SCA and 1 ) then
61375 begin
61376 keybd_event( VK_SHIFT, 0, 0, 0 );
61377 Send( WM_KEYDOWN, VK_SHIFT );
61378 end;
61379 while not (P^ in [ #0, EndChar ]) do
61380 begin
61381 if (P^ = 'F') and (P[ 1 ] in [ '1'..'9' ]) then
61382 begin
61383 Inc( P );
61384 FN := Ord( P^ ) - Ord( '0' );
61385 if (FN = 1) and (P[ 1 ] in [ '0'..'2' ]) then
61386 begin
61387 Inc( P );
61388 FN := 10 + Ord( P^ ) - Ord( '0' );
61389 end;
61390 repeat Inc( P ) until P^ <> ' ';
61391 FN := FN + $6F;
61392 Send( MsgDn, FN );
61393 Send( MsgUp, FN );
61395 else
61396 if Compare( 'Numpad' ) then
61397 begin
61398 if P^ in [ '0'..'9' ] then
61399 begin
61400 FN := Ord( P^ ) - Ord( '0' ) + $60;
61401 repeat Inc( P^ ) until P^ <> ' ';
61402 Send( MsgDn, FN );
61403 Send( MsgUp, FN );
61404 end;
61406 else
61407 if not (CompareSend( 'Add', $6B ) or
61408 CompareSend( 'Gray+', $6B ) or
61409 CompareSend( 'Apps', $5D ) or
61410 CompareSend( 'BackSpace', $08 ) or
61411 CompareSend( 'BkSp', $08 ) or
61412 CompareSend( 'BS', $08 ) or
61413 CompareSend( 'Break', $13 ) or
61414 CompareSend( 'CapsLock', $14 ) or
61415 CompareSend( 'Clear', $0C ) or
61416 CompareSend( 'Decimal', $6E ) or
61417 CompareSend( 'Del', $2E ) or
61418 CompareSend( 'Delete', $2E ) or
61419 CompareSend( 'Divide', $6F ) or
61420 CompareSend( 'Gray/', $6F ) or
61421 CompareSend( 'Down', $28 ) or
61422 CompareSend( 'End', $23 ) or
61423 CompareSend( 'Enter', $0D ) or
61424 CompareSend( 'Return', $0D ) or
61425 CompareSend( 'CR', $0D ) or
61426 CompareSend( 'Esc', $1B ) or
61427 CompareSend( 'Escape', $1B ) or
61428 CompareSend( 'Help', $2F ) or
61429 CompareSend( 'Home', $24 ) or
61430 CompareSend( 'Ins', $2D ) or
61431 CompareSend( 'Insert', $2D ) or
61432 CompareSend( 'Left', $25 ) or
61433 CompareSend( 'LWin', $5B ) or
61434 CompareSend( 'Multiply', $6A ) or
61435 CompareSend( 'Gray*', $6A ) or
61436 CompareSend( 'NumLock', $90 ) or
61437 CompareSend( 'PgDn', $22 ) or
61438 CompareSend( 'PgUp', $21 ) or
61439 CompareSend( 'PrintScrn', $2C ) or
61440 CompareSend( 'Right', $27 ) or
61441 CompareSend( 'RWin', $5C ) or
61442 CompareSend( 'Separator', $6C ) or
61443 CompareSend( 'ScrollLock', $91 ) or
61444 CompareSend( 'Subtract', $6D ) or
61445 CompareSend( 'Tab', $09 ) or
61446 CompareSend( 'Gray-', $6D ) or
61447 CompareSend( 'Up', $26 )) then break;
61448 end;
61449 while not (P^ in [ #0, EndChar ]) do
61450 begin
61451 if P^ in [ 'A'..'Z', '0'..'9' ] then
61452 begin
61453 Send( MsgDn, Integer( P^ ) );
61454 Send( MsgUp, Integer( P^ ) );
61456 else
61457 if P^ in [ #1..#255 ] then
61458 Stroke2Window( Wnd, '' + P^ );
61459 repeat Inc( P ) until (P^ <> ' ');
61460 end;
61461 if P^ = EndChar then
61462 Inc( P );
61463 if Longbool( SCA and 1 ) then
61464 begin
61465 Send( WM_KEYUP, VK_SHIFT );
61466 keybd_event( VK_SHIFT, 0, KEYEVENTF_KEYUP, 0 );
61467 end;
61468 if LongBool( SCA and 2 ) then
61469 begin
61470 Send( WM_KEYUP, VK_CONTROL );
61471 keybd_event( VK_CONTROL, 0, KEYEVENTF_KEYUP, 0 );
61472 end;
61473 if LongBool( SCA and 4 ) then
61474 begin
61475 Send( WM_SYSKEYUP, VK_MENU );
61476 keybd_event( VK_MENU, 0, KEYEVENTF_KEYUP, 0 );
61477 end;
61478 Result := P;
61479 end;
61481 begin
61482 Result := False;
61483 Wnd := GetTopWindow( Wnd );
61484 Wnd := GetFocusedChild( Wnd );
61485 if Wnd = 0 then Exit;
61486 P := PChar( S );
61487 while P^ <> #0 do
61488 begin
61489 if not (P^ in [ '[', '{' ]) then
61490 begin
61491 Stroke2Window( Wnd, '' + P^ );
61492 Inc( P );
61494 else
61495 begin
61496 if P^ = '[' then
61497 EndChar := ']'
61498 else
61499 EndChar := '}';
61500 Inc( P );
61501 P := ParseKeys( EndChar );
61502 end;
61503 end;
61504 Result := True;
61505 end;
61507 type
61508 PHWnd = ^HWnd;
61510 TFindWndRec = packed Record
61511 ThreadID : DWord;
61512 WndFound : HWnd;
61513 end;
61514 PFindWndRec = ^TFindWndRec;
61516 //[function EnumWindowsProc]
61517 function EnumWindowsProc( Wnd : HWnd; Find : PFindWndRec ) : Boolean;
61518 stdcall;
61519 var Id : DWord;
61520 begin
61521 Result := True;
61522 Id := GetWindowThreadProcessId( Wnd, @Id );
61523 if Id = Find.ThreadID then
61524 begin
61525 Find.WndFound := Wnd;
61526 Result := False;
61527 end;
61528 end;
61530 //[function FindWindowByThreadID]
61531 function FindWindowByThreadID( ThreadID : DWORD ) : HWnd;
61532 var Find : TFindWndRec;
61533 begin
61534 Find.ThreadID := ThreadID;
61535 Find.WndFound := 0;
61536 EnumWindows( @EnumWindowsProc, Integer( @Find ) );
61537 Result := Find.WndFound;
61538 end;
61540 //[function GetDesktopRect]
61541 function GetDesktopRect : TRect;
61542 var W1, W2 : HWnd;
61543 begin
61544 Result := MakeRect( 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) );
61545 W2 := findwindow(nil,'Program Manager');
61546 W1 := findwindowex(W2,0,'SHELLDLL_DefView',nil);
61547 if W1 = 0 then Exit;
61548 GetWindowRect( W1, Result );
61549 end;
61551 //[function GetWorkArea]
61552 function GetWorkArea: TRect;
61553 begin
61554 SystemParametersInfo( SPI_GETWORKAREA, 0, @ Result, 0 );
61555 end;
61557 //[function ExecuteWait]
61558 function ExecuteWait( const AppPath, CmdLine, DfltDirectory: String;
61559 Show: DWORD; TimeOut: DWORD; ProcID: PDWORD ): Boolean;
61560 var Flags: DWORD;
61561 Startup: TStartupInfo;
61562 ProcInf: TProcessInformation;
61563 DfltDir: PChar;
61564 App: String;
61565 begin
61566 Result := FALSE;
61567 Flags := CREATE_NEW_CONSOLE;
61568 if Show = SW_HIDE then
61569 Flags := Flags or {$IFDEF F_P}$08000000{$ELSE}CREATE_NO_WINDOW{$ENDIF};
61570 FillChar( Startup, SizeOf( Startup ), 0 );
61571 Startup.cb := Sizeof( Startup );
61572 Startup.wShowWindow := Show;
61573 Startup.dwFlags := STARTF_USESHOWWINDOW;
61574 if ProcID <> nil then
61575 ProcID^ := 0;
61576 DfltDir := nil;
61577 if DfltDirectory <> '' then
61578 DfltDir := PChar( DfltDirectory );
61579 if ProcID <> nil then
61580 ProcID^ := 0;
61581 App := AppPath;
61582 if (pos( ' ', App ) > 0) and (pos( '"', App ) <= 0) then
61583 App := '"' + App + '"';
61584 if (App <> '') and (CmdLine <> '') then
61585 App := App + ' ';
61586 if CreateProcess( nil, PChar( App + CmdLine ), nil,
61587 nil, FALSE, Flags, nil, DfltDir, Startup,
61588 ProcInf ) then
61589 begin
61590 if WaitForSingleObject( ProcInf.hProcess, TimeOut ) = WAIT_OBJECT_0 then
61591 begin
61592 CloseHandle( ProcInf.hProcess );
61593 Result := TRUE;
61595 else
61596 begin
61597 if ProcID <> nil then
61598 ProcID^ := ProcInf.hProcess;
61599 end;
61600 CloseHandle( ProcInf.hThread );
61601 end;
61602 end;
61604 //[function ExecuteIORedirect]
61605 function ExecuteIORedirect( const AppPath, CmdLine, DfltDirectory: String;
61606 Show: DWORD; ProcID: PDWORD; InPipe, OutPipeWr, OutPipeRd: PHandle ): Boolean;
61607 var Flags: DWORD;
61608 Startup: TStartupInfo;
61609 ProcInf: TProcessInformation;
61610 DfltDir: PChar;
61611 SecurityAttributes: TSecurityAttributes;
61612 SaveStdOut, SaveStdIn: THandle;
61613 ChildStdOutRd, ChildStdOutWr: THandle;
61614 ChildStdInRd, ChildStdInWr: THandle;
61615 ChildStdOutRdDup: THandle;
61616 ChildStdInWrDup: THandle;
61618 procedure Do_CloseHandle( var Handle: THandle );
61619 begin
61620 if Handle <> 0 then
61621 begin
61622 CloseHandle( Handle );
61623 Handle := 0;
61624 end;
61625 end;
61627 procedure Close_Handles;
61628 begin
61629 Do_CloseHandle( ChildStdOutRd );
61630 Do_CloseHandle( ChildStdOutWr );
61631 Do_CloseHandle( ChildStdInRd );
61632 Do_CloseHandle( ChildStdInWr );
61633 end;
61635 function RedirectInputOutput: Boolean;
61636 begin
61637 Result := FALSE;
61638 if (OutPipeRd <> nil) or (OutPipeWr <> nil) then
61639 begin
61640 // redirect output
61641 SaveStdOut := GetStdHandle(STD_OUTPUT_HANDLE);
61642 if not CreatePipe( ChildStdOutRd, ChildStdOutWr, @ SecurityAttributes, 0 ) then
61643 Exit;
61644 if not SetStdHandle( STD_OUTPUT_HANDLE, ChildStdOutWr ) then
61645 Exit;
61646 if not DuplicateHandle( GetCurrentProcess, ChildStdOutRd,
61647 GetCurrentProcess, @ ChildStdOutRdDup, 0, FALSE,
61648 2 {DUPLICATE_SAME_ACCESS} ) then
61649 Exit;
61650 Do_CloseHandle( ChildStdOutRd );
61651 if OutPipeRd <> nil then
61652 OutPipeRd^ := ChildStdOutRdDup;
61653 if OutPipeWr <> nil then
61654 OutPipeWr^ := ChildStdOutWr;
61655 end;
61656 if InPipe <> nil then
61657 begin
61658 // redirect input
61659 SaveStdIn := GetStdHandle(STD_INPUT_HANDLE);
61660 if not CreatePipe( ChildStdInRd, ChildStdInWr, @ SecurityAttributes, 0 ) then
61661 Exit;
61662 if not SetStdHandle( STD_INPUT_HANDLE, ChildStdInRd ) then
61663 Exit;
61664 if not DuplicateHandle( GetCurrentProcess, ChildStdInWr,
61665 GetCurrentProcess, @ ChildStdInWrDup, 0, FALSE,
61666 2 {DUPLICATE_SAME_ACCESS} ) then
61667 Exit;
61668 Do_CloseHandle( ChildStdInWr );
61669 if InPipe <> nil then
61670 InPipe^ := ChildStdInWrDup;
61671 Do_CloseHandle( ChildStdInRd );
61672 end;
61673 Result := TRUE;
61674 end;
61676 procedure Restore_Saved_StdInOut;
61677 begin
61678 SetStdHandle( STD_OUTPUT_HANDLE, SaveStdOut );
61679 SetStdHandle( STD_INPUT_HANDLE, SaveStdIn );
61680 end;
61682 begin
61683 Result := FALSE;
61684 Flags := 0;
61685 if Show = SW_HIDE then
61686 Flags := Flags or {$IFDEF F_P}$08000000{$ELSE}CREATE_NO_WINDOW{$ENDIF};
61687 FillChar( Startup, SizeOf( Startup ), 0 );
61688 Startup.cb := Sizeof( Startup );
61689 if ProcID <> nil then
61690 ProcID^ := 0;
61691 DfltDir := nil;
61692 SecurityAttributes.nLength := Sizeof( SecurityAttributes );
61693 SecurityAttributes.lpSecurityDescriptor := nil;
61694 SecurityAttributes.bInheritHandle := TRUE;
61695 SaveStdOut := 0;
61696 SaveStdIn := 0;
61697 ChildStdOutRd := 0;
61698 ChildStdOutWr := 0;
61699 ChildStdInRd := 0;
61700 ChildStdInWr := 0;
61701 if not RedirectInputOutput then
61702 begin
61703 Close_Handles;
61704 Exit;
61705 end;;
61706 if DfltDirectory <> '' then
61707 DfltDir := PChar( DfltDirectory );
61708 if CreateProcess( nil, PChar( '"' + AppPath + '" ' + CmdLine ),
61709 nil, nil, TRUE, Flags, nil, DfltDir, Startup,
61710 ProcInf ) then
61711 begin
61712 if ProcID <> nil then
61713 ProcID^ := ProcInf.hProcess
61714 else
61715 CloseHandle( ProcInf.hProcess );
61716 CloseHandle( ProcInf.hThread );
61717 Restore_Saved_StdInOut;
61718 Result := TRUE;
61720 else
61721 begin
61722 Restore_Saved_StdInOut;
61723 Close_Handles;
61724 Exit;
61725 end;
61726 end;
61728 //[function ExecuteConsoleAppIORedirect]
61729 function ExecuteConsoleAppIORedirect( const AppPath, CmdLine, DfltDirectory: String;
61730 Show: DWORD; const InStr: String; var OutStr: String; WaitTimeout: DWORD ): Boolean;
61731 var PipeIn, PipeOutRd, PipeOutWr: THandle;
61732 ProcID: DWORD;
61733 BytesCount: DWORD;
61734 Buffer: array[ 0..4096 ] of Char;
61735 BufStr: String;
61736 PPipeIn: PHandle;
61737 begin
61738 Result := FALSE;
61739 PPipeIn := @ PipeIn;
61740 if InStr = '' then
61741 PPipeIn := nil;
61742 PipeOutRd := 0;
61743 PipeOutWr := 0;
61744 if not ExecuteIORedirect( AppPath, CmdLine, DfltDirectory, Show, @ ProcID,
61745 PPipeIn, @ PipeOutWr, @ PipeOutRd ) then Exit;
61746 if PPipeIn <> nil then
61747 begin
61748 if InStr <> '' then
61749 WriteFile( PipeIn, InStr[ 1 ], Length( InStr ), BytesCount, nil );
61750 CloseHandle( PipeIn );
61751 end;
61752 OutStr := '';
61753 if WaitForSingleObject( ProcID, WaitTimeOut ) = WAIT_OBJECT_0 then
61754 begin
61755 CloseHandle( ProcID );
61756 CloseHandle( PipeOutWr );
61757 while ReadFile( PipeOutRd, Buffer, Sizeof( Buffer ), BytesCount, nil ) do
61758 begin
61759 SetLength( BufStr, BytesCount );
61760 Move( Buffer[ 0 ], BufStr[ 1 ], BytesCount );
61761 OutStr := OutStr + BufStr;
61762 end;
61764 else
61765 CloseHandle( PipeOutWr );
61766 CloseHandle( PipeOutRd );
61767 Result := TRUE;
61768 end;
61770 {$IFDEF _D2}
61771 //[API OpenProcessToken]
61772 function OpenProcessToken(ProcessHandle: THandle; DesiredAccess: DWORD;
61773 var TokenHandle: THandle): BOOL; stdcall;
61774 external advapi32 name 'OpenProcessToken';
61775 {$ENDIF}
61777 //[function WindowsShutdown]
61778 function WindowsShutdown( const Machine : String; Force, Reboot : Boolean ) : Boolean;
61780 hToken: THandle;
61781 tkp, tkp_prev: TTokenPrivileges;
61782 dwRetLen :DWORD;
61783 Flags: Integer;
61784 begin
61785 Result := False;
61786 if Integer( GetVersion ) < 0 then // Windows95/98/Me
61787 begin
61788 if Machine <> '' then Exit;
61789 Flags := EWX_SHUTDOWN;
61790 if Reboot then
61791 Flags := Flags or EWX_REBOOT;
61792 if Force then
61793 Flags := Flags or EWX_FORCE;
61794 Result := ExitWindowsEx( Flags, 0 );
61795 Exit;
61796 end;
61798 OpenProcessToken(GetCurrentProcess(),
61799 TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY,
61800 hToken);
61802 if not LookupPrivilegeValue(PChar(Machine), 'SeShutdownPrivilege',
61803 tkp.Privileges[0].Luid) then Exit;
61804 tkp_prev:=tkp;
61805 tkp.PrivilegeCount:=1;
61806 tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
61807 AdjustTokenPrivileges(hToken, FALSE, tkp, sizeof(tkp), tkp_prev,
61808 dwRetLen);
61810 if not LookupPrivilegeValue(PChar(Machine),
61811 'SeRemoteShutdownPrivilege',
61812 tkp.Privileges[0].Luid)
61813 then
61814 Exit;
61816 tkp.PrivilegeCount:=1;
61817 tkp.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
61818 AdjustTokenPrivileges(hToken, FALSE, tkp, sizeof(tkp), tkp_prev,
61819 dwRetLen);
61821 Result := InitiateSystemShutdown(PChar(Machine),nil, 0, Force, Reboot);
61822 end;
61824 var SaveWinVer: Byte = $FF;
61826 //[function WinVer]
61827 function WinVer : TWindowsVersion;
61828 {* Returns Windows version. }
61829 var OVI: TOsVersionInfo;
61830 begin
61831 if SaveWinVer <> $FF then Result := TWindowsVersion( SaveWinVer )
61832 else
61833 begin
61834 OVI.dwOSVersionInfoSize := Sizeof( OVI );
61835 GetVersionEx( OVI );
61836 with OVI do
61837 if dwPlatformId = VER_PLATFORM_WIN32_NT then
61838 begin
61839 Result := wvNT;
61840 if dwMajorVersion >= 6 then
61841 Result := wvLongHorn
61842 else begin
61843 if dwMajorVersion >= 5 then
61844 if dwMinorVersion >=1 then
61845 Result := wvXP
61846 else
61847 Result := wvY2K;
61848 end;
61850 else
61851 if dwPlatformId = VER_PLATFORM_WIN32_WINDOWS then
61852 begin
61853 Result := wv95;
61854 if (dwMajorVersion > 4) or (dwMajorVersion = 4)
61855 and (dwMinorVersion >= 10) then
61856 Result := wv98;
61858 else
61859 Result := wv31; // Windows 3.1 (WIN32s)
61860 SaveWinVer := Ord( Result );
61861 end;
61862 end;
61864 //[function IsWinVer]
61865 function IsWinVer( Ver : TWindowsVersions ) : Boolean;
61866 {* Returns True if Windows version is in given range of values. }
61867 begin
61868 Result := WinVer in Ver;
61869 end;
61871 //[procedure TControl.SetAlphaBlend]
61872 procedure TControl.SetAlphaBlend(const Value: Integer);
61873 const
61874 LWA_COLORKEY=$00000001;
61875 LWA_ALPHA=$00000002;
61876 ULW_COLORKEY=$00000001;
61877 ULW_ALPHA=$00000002;
61878 ULW_OPAQUE=$00000004;
61879 WS_EX_LAYERED=$00080000;
61880 type
61881 TSetLayeredWindowAttributes=
61882 function( hwnd: Integer; crKey: TColor; bAlpha: Byte; dwFlags: DWORD )
61883 : Boolean; stdcall;
61885 SetLayeredWindowAttributes: TSetLayeredWindowAttributes;
61886 User32: THandle;
61887 dw: DWORD;
61888 begin
61889 if Value = fAlphaBlend then Exit;
61890 fAlphaBlend := Value;
61891 User32 := GetModuleHandle( 'User32' );
61892 SetLayeredWindowAttributes := GetProcAddress( User32,
61893 'SetLayeredWindowAttributes' );
61894 if Assigned( SetLayeredWindowAttributes ) then
61895 begin
61896 dw := GetWindowLong( GetWindowHandle, GWL_EXSTYLE );
61897 if Byte( Value ) < 255 then
61898 begin
61899 SetWindowLong( fHandle, GWL_EXSTYLE, dw or WS_EX_LAYERED );
61900 SetLayeredWindowAttributes( fHandle, 0, Value and $FF, LWA_ALPHA);
61902 else
61903 SetWindowLong( fHandle, GWL_EXSTYLE, dw and not WS_EX_LAYERED );
61904 end;
61905 end;
61907 //[function TControl.SetPosition]
61908 function TControl.SetPosition( X, Y: Integer ): PControl;
61909 begin
61910 Left := X;
61911 Top := Y;
61912 Result := @Self;
61913 end;
61915 //[function NewColorDialog]
61916 function NewColorDialog( FullOpen: TColorCustomOption ): PColorDialog;
61917 var I: Integer;
61918 begin
61920 New( Result, Create );
61921 {+}{++}(*Result := PColorDialog.Create;*){--}
61922 Result.ColorCustomOption := FullOpen;
61923 for I := 1 to 16 do
61924 Result.CustomColors[ I ] := clWhite;
61925 end;
61926 //[END NewColorDialog]
61928 { TColorDialog }
61930 //[function TColorDialog.Execute]
61931 function TColorDialog.Execute: Boolean;
61932 var CD: TChooseColor;
61933 begin
61934 CD.lStructSize := Sizeof( CD );
61935 CD.hWndOwner := OwnerWindow;
61936 //CD.hInstance := 0;
61937 CD.rgbResult := Color2RGB( Color );
61938 CD.lpCustColors := @CustomColors[ 1 ];
61939 CD.Flags := CC_RGBINIT;
61940 case ColorCustomOption of
61941 ccoFullOpen: CD.Flags := CD.Flags or CC_FULLOPEN;
61942 ccoPreventFullOpen: CD.Flags := CD.Flags or CC_PREVENTFULLOPEN;
61943 end;
61944 Result := ChooseColor( CD );
61945 if Result then
61946 Color := CD.rgbResult;
61947 end;
61949 //[procedure TControl.SetMaxProgress]
61950 procedure TControl.SetMaxProgress(const Index, Value: Integer);
61951 begin
61952 // ignore index, and set Value via PBM_SETRANGE32: ()
61953 Perform( PBM_SETRANGE32, 0, Value );
61954 end;
61956 //[procedure TControl.SetDroppedWidth]
61957 procedure TControl.SetDroppedWidth(const Value: Integer);
61958 begin
61959 FDroppedWidth := Value;
61960 Perform( CB_SETDROPPEDWIDTH, Value, 0 );
61961 end;
61963 //[function TControl.LVGetItemState]
61964 function TControl.LVGetItemState(Idx: Integer): TListViewItemState;
61965 type
61966 PListViewItemState = ^TListViewItemState;
61967 var I: Byte;
61968 begin
61969 I := Perform( LVM_GETITEMSTATE, Idx,
61970 LVIS_CUT or LVIS_DROPHILITED or LVIS_FOCUSED or LVIS_SELECTED );
61971 Result := PListViewItemState( @ I )^;
61972 end;
61974 //[procedure TControl.LVSetItemState]
61975 procedure TControl.LVSetItemState(Idx: Integer; const Value: TListViewItemState);
61976 var Data: TLVItem;
61977 begin
61978 Data.stateMask := LVIS_FOCUSED or LVIS_SELECTED or LVIS_CUT or LVIS_DROPHILITED;
61979 Data.state := PByte( @ Value )^;
61980 Perform( LVM_SETITEMSTATE, Idx, Integer( @Data ) );
61981 end;
61983 //[procedure TControl.LVSelectAll]
61984 procedure TControl.LVSelectAll;
61985 begin
61986 LVSetItemState( -1, [ lvisSelect ] );
61987 end;
61989 //[function TControl.LVItemInsert]
61990 function TControl.LVItemInsert(Idx: Integer; const aText: String): Integer;
61991 var LVI: TLVItem;
61992 begin
61993 LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;
61994 LVI.iItem := Idx;
61995 LVI.iSubItem := 0;
61996 LVI.pszText := PChar( aText );
61997 Result := Perform( LVM_INSERTITEM, 0, Integer( @LVI ) );
61998 end;
62000 {$IFNDEF _FPC}
62001 {$IFNDEF _D2}
62002 //[function TControl.LVItemInsertW]
62003 function TControl.LVItemInsertW(Idx: Integer;
62004 const aText: WideString): Integer;
62005 var LVI: TLVItemW;
62006 begin
62007 LVI.mask := LVIF_TEXT or LVIF_DI_SETITEM;
62008 LVI.iItem := Idx;
62009 LVI.iSubItem := 0;
62010 LVI.pszText := PWideChar( aText );
62011 Result := Perform( LVM_INSERTITEMW, 0, Integer( @LVI ) );
62012 end;
62013 {$ENDIF _D2}
62014 {$ENDIF _FPC}
62016 //[function TControl.LVItemAdd]
62017 function TControl.LVItemAdd(const aText: String): Integer;
62018 begin
62019 Result := LVItemInsert( Count, aText );
62020 end;
62022 {$IFNDEF _FPC}
62023 {$IFNDEF _D2}
62024 //[function TControl.LVItemAddW]
62025 function TControl.LVItemAddW(const aText: WideString): Integer;
62026 begin
62027 Result := LVItemInsertW( Count, aText );
62028 end;
62029 {$ENDIF _D2}
62030 {$ENDIF _FPC}
62032 //[function TControl.LVGetSttImgIdx]
62033 function TControl.LVGetSttImgIdx(Idx: Integer): Integer;
62034 begin
62035 Result := Perform( LVM_GETITEMSTATE, Idx, LVIS_STATEIMAGEMASK ) shr 12;
62036 end;
62038 //[procedure TControl.LVSetSttImgIdx]
62039 procedure TControl.LVSetSttImgIdx(Idx: Integer; const Value: Integer);
62040 var LVI: TLVItem;
62041 begin
62042 LVI.stateMask := LVIS_STATEIMAGEMASK;
62043 LVI.state := Value shl 12;
62044 Perform( LVM_SETITEMSTATE, Idx, Integer( @LVI ) );
62045 end;
62047 //[function TControl.LVGetOvlImgIdx]
62048 function TControl.LVGetOvlImgIdx(Idx: Integer): Integer;
62049 begin
62050 Result := Perform( LVM_GETITEMSTATE, Idx, LVIS_OVERLAYMASK ) shr 8;
62051 end;
62053 //[procedure TControl.LVSetOvlImgIdx]
62054 procedure TControl.LVSetOvlImgIdx(Idx: Integer; const Value: Integer);
62055 var LVI: TLVItem;
62056 begin
62057 LVI.stateMask := LVIS_OVERLAYMASK;
62058 LVI.state := Value shl 8;
62059 Perform( LVM_SETITEMSTATE, Idx, Integer( @LVI ) );
62060 end;
62062 //[function TControl.LVGetItemData]
62063 function TControl.LVGetItemData(Idx: Integer): DWORD;
62064 var LVI: TLVItem;
62065 begin
62066 LVI.mask := LVIF_PARAM;
62067 LVI.iItem := Idx;
62068 LVI.iSubItem := 0;
62069 Perform( LVM_GETITEM, 0, Integer( @LVI ) );
62070 Result := LVI.lParam;
62071 end;
62073 //[procedure TControl.LVSetItemData]
62074 procedure TControl.LVSetItemData(Idx: Integer; const Value: DWORD);
62075 var LVI: TLVItem;
62076 begin
62077 LVI.mask := LVIF_PARAM;
62078 LVI.iItem := Idx;
62079 LVI.iSubItem := 0;
62080 LVI.lParam := Value;
62081 Perform( LVM_SETITEM, 0, Integer( @LVI ) );
62082 end;
62084 //[function TControl.LVGetItemIndent]
62085 function TControl.LVGetItemIndent(Idx: Integer): Integer;
62086 var LI: TLVItem;
62087 begin
62088 LI.mask := LVIF_INDENT;
62089 LI.iItem := Idx;
62090 LI.iSubItem := 0;
62091 Perform( LVM_GETITEM, 0, Integer( @LI ) );
62092 Result := LI.iIndent;
62093 end;
62095 //[procedure TControl.LVSetItemIndent]
62096 procedure TControl.LVSetItemIndent(Idx: Integer; const Value: Integer);
62097 var LI: TLVItem;
62098 begin
62099 LI.mask := LVIF_INDENT or LVIF_DI_SETITEM;
62100 LI.iItem := Idx;
62101 LI.iSubItem := 0;
62102 LI.iIndent := Value;
62103 Perform( LVM_SETITEM, 0, Integer( @LI ) );
62104 end;
62106 type
62107 TNMLISTVIEW = packed Record
62108 hdr: TNMHDR;
62109 iItem: Integer;
62110 iSubItem: Integer;
62111 uNewState: Integer;
62112 uOldState: Integer;
62113 uChanged: Integer;
62114 ptAction: Integer;
62115 lParam: DWORD;
62116 end;
62117 PNMLISTVIEW = ^TNMLISTVIEW;
62119 //[function WndProc_LVDeleteItem]
62120 function WndProc_LVDeleteItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
62121 : Boolean;
62122 var Hdr: PNMHDR;
62123 LV: PNMListView;
62124 begin
62125 Result := FALSE;
62126 if Msg.message = WM_NOTIFY then
62127 begin
62128 Hdr := Pointer(Msg.lParam);
62129 if Hdr.hwndFrom = Sender.Handle then
62130 begin
62131 LV := Pointer( Hdr );
62132 if Hdr.code = LVN_DELETEITEM then
62133 begin
62134 if Assigned( Sender.OnDeleteLVItem ) then
62135 Sender.OnDeleteLVItem( Sender, LV.iItem );
62136 Result := TRUE;
62138 else
62139 if Hdr.code = LVN_DELETEALLITEMS then
62140 begin
62141 if Assigned( Sender.OnDeleteAllLVItems ) then
62142 begin
62143 Sender.OnDeleteAllLVItems( Sender );
62144 Rslt := 0;
62145 if Assigned( Sender.OnDeleteLVItem ) then
62146 Rslt := 1;
62147 end;
62148 Result := TRUE;
62149 end;
62150 end;
62151 end;
62152 end;
62154 //[procedure TControl.SetOnDeleteAllLVItems]
62155 procedure TControl.SetOnDeleteAllLVItems(const Value: TOnEvent);
62156 begin
62157 fOnDeleteAllLVItems := Value;
62158 AttachProc( @WndProc_LVDeleteItem );
62159 end;
62161 //[procedure TControl.SetOnDeleteLVItem]
62162 procedure TControl.SetOnDeleteLVItem(const Value: TOnDeleteLVItem);
62163 begin
62164 fOnDeleteLVItem := Value;
62165 AttachProc( @WndProc_LVDeleteItem );
62166 end;
62168 //[function WndProc_LVData]
62169 function WndProc_LVData( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
62170 : Boolean;
62171 var Hdr: PNMHDR;
62172 DI: PLVDispInfo;
62173 Store: Boolean;
62174 Txt: String;
62175 LV: PControl;
62176 {$IFDEF UNICODE_CTRLS}
62177 TxtW: WideString;
62178 {$ENDIF UNICODE_CTRLS}
62179 begin
62180 Result := FALSE;
62181 if Msg.message = WM_NOTIFY then
62182 begin
62183 Hdr := Pointer(Msg.lParam);
62184 if Hdr.hwndFrom = Sender.Handle then
62185 begin
62186 if (Hdr.code = LVN_GETDISPINFO)
62187 {$IFDEF UNICODE_CTRLS}
62188 or (Hdr.code = LVN_GETDISPINFOW)
62189 {$ENDIF UNICODE_CTRLS}
62190 then
62191 begin
62192 DI := Pointer( Hdr );
62193 LV := Sender;
62194 if LV <> nil then
62195 begin
62196 Txt := '';
62197 DI.item.iImage := -1;
62198 DI.item.state := 0;
62199 Store := FALSE;
62200 if (Assigned( LV.OnLVData )
62201 {$IFDEF UNICODE_CTRLS}
62202 or Assigned( LV.OnLVDataW )
62203 {$ENDIF UNICODE_CTRLS}
62205 and (DI.item.iItem >= 0) then
62206 begin
62207 {$IFDEF UNICODE_CTRLS}
62208 TxtW := '';
62209 if Assigned( LV.ONLVDataW ) then
62210 LV.OnLVDataW( LV, DI.item.iItem, DI.item.iSubItem, TxtW,
62211 DI.item.iImage, DWORD( DI.item.state ), Store )
62212 else
62213 {$ENDIF UNICODE_CTRLS}
62214 LV.OnLVData( LV, DI.item.iItem, DI.item.iSubItem, Txt,
62215 DI.item.iImage, DWORD( DI.item.state ), Store );
62216 {$IFNDEF UNICODE_CTRLS}
62217 if (LV.fCaption = nil) or (Integer( StrLen( LV.fCaption ) ) <=
62218 Length( Txt ) ) then
62219 {$ENDIF UNICODE_CTRLS}
62220 begin
62221 if LV.fCaption <> nil then
62222 FreeMem( LV.fCaption );
62223 {$IFDEF UNICODE_CTRLS}
62224 GetMem( LV.fCaption, (Length( Txt ) + Length( TxtW ) + 1)
62225 * Sizeof( WideChar ) );
62226 {$ELSE NOT_UNICODE_CTRLS}
62227 GetMem( LV.fCaption, Length( Txt ) + 1 );
62228 {$ENDIF NOT_UNICODE_CTRLS}
62229 end;
62230 {$IFDEF UNICODE_CTRLS}
62231 PWord( @ LV.fCaption[ 0 ] )^ := 0;
62232 {$ELSE}
62233 LV.fCaption[ 0 ] := #0;
62234 {$ENDIF}
62235 if Txt {$IFDEF UNICODE_CTRLS} + TxtW {$ENDIF UNICODE_CTRLS}
62236 <> '' then
62237 begin
62238 {$IFDEF UNICODE_CTRLS}
62239 if Hdr.code = LVN_GETDISPINFOW then
62240 begin
62241 if Txt <> '' then
62242 TxtW := Txt;
62243 Move( TxtW[ 1 ], LV.fCaption[ 0 ], (Length( TxtW ) + 1) * Sizeof( WideChar ) );
62244 end else
62245 {$ENDIF UNICODE_CTRLS}
62246 StrCopy( LV.fCaption, @Txt[ 1 ] );
62247 end;
62248 DI.item.pszText := LV.fCaption;
62249 if Store then
62250 DI.item.mask := DI.item.mask or LVIF_DI_SETITEM;
62251 end;
62252 Result := TRUE;
62253 end;
62254 end;
62255 end;
62256 end;
62257 end;
62259 //[procedure TControl.SetOnLVData]
62260 procedure TControl.SetOnLVData(const Value: TOnLVData);
62261 begin
62262 fOnLVData := Value;
62263 AttachProc( @WndProc_LVData );
62264 Perform( LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK or LVIS_STATEIMAGEMASK, 0 );
62265 end;
62267 //[procedure TControl.SetOnLVDataW]
62268 {$IFNDEF _FPC}
62269 {$IFNDEF _D2}
62270 procedure TControl.SetOnLVDataW(const Value: TOnLVDataW);
62271 begin
62272 fOnLVDataW := Value;
62273 AttachProc( @WndProc_LVData );
62274 Perform( LVM_SETCALLBACKMASK, LVIS_OVERLAYMASK or LVIS_STATEIMAGEMASK, 0 );
62275 end;
62276 {$ENDIF _D2}
62277 {$ENDIF _FPC}
62279 //[function WndProc_LVCustomDraw]
62280 function WndProc_LVCustomDraw( Sender: PControl; var Msg: TMsg;
62281 var Rslt: Integer ): Boolean;
62282 var NMCustDraw: PNMLVCustomDraw;
62283 NMHdr: PNMHdr;
62284 ItemIdx, SubItemIdx: Integer;
62285 S: TListViewItemState;
62286 ItemState: TDrawState;
62287 begin
62288 Result := FALSE;
62289 if Msg.message = WM_NOTIFY then
62290 begin
62291 NMHdr := Pointer( Msg.lParam );
62292 if (NMHdr.code = NM_CUSTOMDRAW) and Assigned( Sender.fOnLVCustomDraw ) then
62293 begin
62294 NMCustDraw := Pointer( Msg.lParam );
62295 ItemIdx := -1;
62296 SubItemIdx := -1;
62297 if LongBool( NMCustDraw.nmcd.dwDrawStage and CDDS_ITEM ) then
62298 ItemIdx := NMCustDraw.nmcd.dwItemSpec;
62299 if LongBool( NMCustDraw.nmcd.dwDrawStage and CDDS_SUBITEM ) then
62300 SubItemIdx := NMCustDraw.iSubItem;
62301 ItemState := [ ];
62302 if ItemIdx >= 0 then
62303 begin
62304 S := Sender.LVItemState[ ItemIdx ];
62305 if lvisFocus in S then
62306 ItemState := ItemState + [ odsFocused ];
62307 if lvisSelect in S then
62308 ItemState := ItemState + [ odsSelected ];
62309 if lvisBlend in S then
62310 ItemState := ItemState + [ odsGrayed ];
62311 if lvisHighlight in S then
62312 ItemState := ItemState + [ odsMarked ];
62313 end;
62315 Sender.Canvas;
62317 Rslt := Sender.FOnLVCustomDraw( Sender, {Sender.Canvas.Handle} NMCustDraw.nmcd.hdc,
62318 NMCustDraw.nmcd.dwDrawStage, ItemIdx, SubItemIdx, NMCustDraw.nmcd.rc,
62319 ItemState, TColor( NMCustDraw.clrText ), TColor( NMCustDraw.clrTextBk ) );
62321 Result := TRUE;
62322 end;
62323 end;
62324 end;
62326 //[procedure TControl.SetOnLVCustomDraw]
62327 procedure TControl.SetOnLVCustomDraw(const Value: TOnLVCustomDraw);
62328 begin
62329 fOnLVCustomDraw := Value;
62330 AttachProc( @WndProc_LVCustomDraw );
62331 end;
62333 //[function CompareLVItems]
62334 function CompareLVItems( Idx1, Idx2: Integer; ListView: PControl ): Integer; stdcall;
62335 begin
62336 if Assigned( ListView.fOnCompareLVItems ) then
62337 Result := ListView.fOnCompareLVItems( ListView, Idx1, Idx2 )
62338 else
62339 Result := 0;
62340 end;
62342 //[procedure TControl.LVSort]
62343 procedure TControl.LVSort;
62344 begin
62345 Perform( LVM_SORTITEMSEX, Integer(@Self), Integer(@CompareLVItems) );
62346 end;
62348 //[function CompareLVItemsData]
62349 function CompareLVItemsData( D1, D2: DWORD; ListView: PControl ): Integer; stdcall;
62350 begin
62351 if Assigned( ListView.fOnCompareLVItems ) then
62352 Result := ListView.fOnCompareLVItems( ListView, D1, D2 )
62353 else
62354 Result := 0;
62355 end;
62357 //[procedure TControl.LVSortData]
62358 procedure TControl.LVSortData;
62359 begin
62360 Perform( LVM_SORTITEMS, Integer( @Self ), Integer( @CompareLVItemsData ) );
62361 end;
62363 //[function WndProc_LVColumnClick]
62364 function WndProc_LVColumnClick( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
62365 : Boolean;
62366 var Hdr: PNMHDR;
62367 LV: PNMListView;
62368 begin
62369 Result := FALSE;
62370 if Msg.message = WM_NOTIFY then
62371 begin
62372 Hdr := Pointer(Msg.lParam);
62373 if Hdr.hwndFrom = Sender.Handle then
62374 begin
62375 LV := Pointer( Hdr );
62376 if Hdr.code = LVN_COLUMNCLICK then
62377 begin
62378 if Assigned( Sender.OnColumnClick ) then
62379 Sender.OnColumnClick( Sender, LV.iSubItem );
62380 Result := TRUE;
62381 end;
62382 end;
62383 end;
62384 end;
62386 //[procedure TControl.SetOnColumnClick]
62387 procedure TControl.SetOnColumnClick(const Value: TOnLVColumnClick);
62388 begin
62389 fOnColumnClick := Value;
62390 AttachProc( @WndProc_LVColumnClick );
62391 end;
62393 //[function WndProc_LVStateChange]
62394 function WndProc_LVStateChange( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;
62395 var NMOD: PNMLVODStateChange;
62396 NMLV: PNMLISTVIEW;
62397 begin
62398 if Msg.message = WM_NOTIFY then
62399 begin
62400 NMOD := Pointer( Msg.lParam );
62401 NMLV := Pointer( Msg.lParam );
62402 if NMOD.hdr.code = LVN_ODSTATECHANGED then
62403 begin
62404 if Assigned( Sender.OnLVStateChange ) then
62405 Sender.OnLVStateChange( Sender, NMOD.iFrom, NMOD.iTo,
62406 NMOD.uOldState, NMOD.uNewState );
62408 else
62409 if NMLV.hdr.code = LVN_ITEMCHANGED then
62410 begin
62411 if Assigned( Sender.OnLVStateChange ) then
62412 Sender.OnLVStateChange( Sender, NMLV.iItem, NMLV.iItem,
62413 NMLV.uOldState, NMLV.uNewState );
62414 end;
62415 end;
62416 Result := FALSE;
62417 end;
62419 //[procedure TControl.SetOnLVStateChange]
62420 procedure TControl.SetOnLVStateChange(const Value: TOnLVStateChange);
62421 begin
62422 FOnLVStateChange := Value;
62423 AttachProc( WndProc_LVStateChange );
62424 end;
62426 //[function WndProc_LVDelete]
62427 function WndProc_LVDelete( Sender: PControl; var Msg: TMsg; var R: Integer ): Boolean;
62428 var NMLV: PNMLISTVIEW;
62429 begin
62430 if Msg.message = WM_NOTIFY then
62431 begin
62432 NMLV := Pointer( Msg.lParam );
62433 if NMLV.hdr.code = LVN_DELETEITEM then
62434 begin
62435 if Assigned( Sender.OnLVDelete ) then
62436 Sender.OnLVDelete( Sender, NMLV.iItem );
62437 end;
62438 end;
62439 Result := FALSE;
62440 end;
62442 //[procedure TControl.SetOnLVDelete]
62443 procedure TControl.SetOnLVDelete(const Value: TOnLVDelete);
62444 begin
62445 FOnLVDelete := Value;
62446 Add2AutoFreeEx( Clear );
62447 AttachProcEx( WndProc_LVDelete, TRUE );
62448 if fParent <> nil then
62449 begin
62450 fParent.DetachProc( WndProcNotify );
62451 fParent.AttachProcEx( WndProcNotify, TRUE );
62452 end;
62453 end;
62455 //[function CompareLVColumns]
62456 function CompareLVColumns( Idx1, Idx2: Integer; Sender: PControl ): Integer; stdcall;
62457 var S1, S2: String;
62458 begin
62459 //--- changed by Mike Gerasimov:
62460 S1 := Sender.LVItems[ Idx1, Sender.fColumn ];
62461 S2 := Sender.LVItems[ Idx2, Sender.fColumn ];
62462 If lvoSortAscending in Sender.fLVOptions Then
62463 Result := AnsiCompareStrNoCase( S1, S2 )
62464 Else
62465 If lvoSortDescending in Sender.fLVOptions Then
62466 Result := AnsiCompareStrNoCase( S2, S1 )
62467 Else
62468 Result:=0;
62469 end;
62471 //[procedure TControl.LVSortColumn]
62472 procedure TControl.LVSortColumn(Idx: Integer);
62473 begin
62474 fColumn := Idx;
62475 Perform( LVM_SORTITEMSEX, Integer(@Self), Integer(@CompareLVColumns) );
62476 end;
62478 //[function TControl.LVIndexOf]
62479 function TControl.LVIndexOf(const S: String): Integer;
62480 begin
62481 Result := LVSearchFor( S, -1, FALSE );
62482 end;
62484 //[function TControl.LVIndexOfW]
62485 {$IFNDEF _FPC}
62486 {$IFNDEF _D2}
62487 function TControl.LVIndexOfW(const S: WideString): Integer;
62488 begin
62489 Result := LVSearchForW( S, -1, FALSE );
62490 end;
62491 {$ENDIF _D2}
62492 {$ENDIF _FPC}
62494 //[function TControl.LVSearchFor]
62495 function TControl.LVSearchFor(const S: String; StartAfter: Integer;
62496 Partial: Boolean): Integer;
62497 var f: TLVFindInfo;
62498 begin
62499 f.lParam := 0;
62500 f.flags := LVFI_STRING;
62501 if Partial then
62502 f.flags := LVFI_STRING or LVFI_PARTIAL;
62503 f.psz := @s[1];
62504 result := Perform(LVM_FINDITEM,StartAfter,integer(@f));
62505 end;
62507 {$IFNDEF _FPC}
62508 {$IFNDEF _D2}
62509 //[function TControl.LVSearchForW]
62510 function TControl.LVSearchForW(const S: WideString; StartAfter: Integer;
62511 Partial: Boolean): Integer;
62512 var f: TLVFindInfoW;
62513 begin
62514 f.lParam := 0;
62515 f.flags := LVFI_STRING;
62516 if Partial then
62517 f.flags := LVFI_STRING or LVFI_PARTIAL;
62518 f.psz := @s[1];
62519 result := Perform(LVM_FINDITEMW,StartAfter,integer(@f));
62520 end;
62521 {$ENDIF _D2}
62522 {$ENDIF _FPC}
62524 function WndProcLVMeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
62526 pMI: PMeasureItemStruct;
62527 P: PControl;
62528 H: Integer;
62529 wId: DWORD;
62530 i: Integer;
62531 begin
62532 Result := FALSE;
62533 if Msg.message = WM_MEASUREITEM then begin
62534 pMI := Pointer(Msg.lParam);
62535 with pMI^ do begin
62536 for i:=0 to Sender.ChildCount-1 do begin
62537 P := Sender.Children[i];
62538 if P <> nil then begin
62539 wId := GetWindowLong(P.Handle,GWL_ID);
62540 if CtlID = wId then begin
62541 H := P.Perform(WM_MEASUREITEM,0,0);
62542 if H > 0 then begin
62543 itemHeight := H;
62544 Rslt:=1;
62545 Result := TRUE;
62546 end;
62547 break;
62548 end;
62549 end;
62550 end;
62551 end;
62552 end;
62553 end;
62555 function WndProcLVMeasureItem2( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
62556 begin
62557 Result := FALSE;
62558 if (Msg.message = WM_MEASUREITEM) and (Msg.wParam = 0) then begin
62559 Rslt := Sender.fLVItemHeight;
62560 Result := TRUE;
62561 end;
62563 end;
62565 function TControl.SetLVItemHeight(Value: Integer): PControl;
62566 begin
62567 Set_LVItemHeight( Value );
62568 Result := @ Self;
62569 end;
62571 procedure TControl.Set_LVItemHeight(Value: Integer);
62572 begin
62573 if fLVItemHeight <> Value then begin
62574 if fLVItemHeight = 0 then begin
62575 Parent.AttachProc(WndProcLVMeasureItem);
62576 AttachProc(WndProcLVMeasureItem2);
62577 end;
62578 fLVItemHeight := Value;
62579 end;
62580 end;
62582 //[function TControl.IndexOf]
62583 function TControl.IndexOf(const S: String): Integer;
62584 begin
62585 Result := SearchFor( S, -1, FALSE );
62586 end;
62588 //[function TControl.SearchFor]
62589 function TControl.SearchFor(const S: String; StartAfter: Integer;
62590 Partial: Boolean): Integer;
62591 var Cmd: Integer;
62592 I: Integer;
62593 begin
62594 Cmd := fCommandActions.aFindItem;
62595 if Partial then
62596 Cmd := fCommandActions.aFindPartial;
62597 if Cmd <> 0 then
62598 Result := Perform( Cmd, StartAfter, Integer( PChar( S ) ) )
62599 else
62600 begin
62601 Result := -1;
62602 for I := StartAfter+1 to Count-1 do
62603 begin
62604 if Partial and ( Copy( Items[ I ], 1, Length( S ) ) = S ) or
62605 ( Items[ I ] = S ) then
62606 begin
62607 Result := I;
62608 break;
62609 end;
62610 end;
62611 end;
62612 end;
62614 //[function TControl.DefaultBtnProc]
62615 function TControl.DefaultBtnProc(var Msg: TMsg;
62616 var Rslt: Integer): Boolean;
62617 var Btn: PControl;
62618 F: PControl;
62619 //Msg1: TMsg;
62620 begin
62621 if Assigned( fOldOnMessage ) then
62622 begin
62623 Result := fOldOnMessage( Msg, Rslt );
62624 if Result then Exit;
62625 end;
62626 Result := FALSE;
62627 if AppletTerminated then Exit;
62628 F := Applet;
62629 if not F.fIsForm then
62630 begin
62631 F := F.fCurrentControl;
62632 if F = nil then Exit;
62633 end;
62634 Btn := nil;
62635 if ((Msg.message = WM_KEYDOWN) or (Msg.message = WM_KEYUP)) and
62636 ((Msg.wParam = VK_RETURN) or (Msg.wParam = VK_ESCAPE)) then
62637 begin
62638 if (Msg.wParam = VK_RETURN) and
62639 (F.fDefaultBtnCtl <> nil) and
62640 F.fDefaultBtnCtl.ToBeVisible and
62641 F.fDefaultBtnCtl.Enabled and
62642 ((F.fCurrentControl=nil) or (not F.fCurrentControl.fCancelBtn and
62643 not F.fCurrentControl.fIgnoreDefault)
62644 or (F.fCurrentControl = F.fDefaultBtnCtl)
62645 ) then
62646 Btn := F.fDefaultBtnCtl
62647 else
62648 if (Msg.wParam = VK_ESCAPE) and
62649 (F.fCancelBtnCtl <> nil) and
62650 F.fCancelBtnCtl.ToBeVisible and
62651 F.fCancelBtnCtl.Enabled then
62652 Btn := F.fCancelBtnCtl
62653 else
62654 if (Msg.wParam = VK_RETURN) and
62655 (F.fAllBtnReturnClick or fAllBtnReturnClick) and
62656 (F.ActiveControl <> nil) and
62657 (F.ActiveControl.IsButton) and
62658 (F.ActiveControl.Count = 0) then
62659 Btn := F.ActiveControl;
62660 if Btn <> nil then
62661 begin
62662 if Msg.message = WM_KEYDOWN then
62663 Btn.Focused := TRUE;
62664 Btn.Perform( Msg.message, DWORD( ' ' ), Msg.lParam );
62665 Msg.wParam := 0;
62666 Result := TRUE;
62667 Rslt := 0;
62668 Exit;
62670 end;
62671 Result := FALSE;
62672 end;
62674 //[procedure TControl.SetDefaultBtn]
62675 procedure TControl.SetDefaultBtn(const Index: Integer;
62676 const Value: Boolean);
62677 var F, C: PControl;
62678 begin
62679 if Index = 13 then
62680 begin
62681 fDefaultBtn := Value;
62682 fCancelBtn := FALSE;
62684 else
62685 if Index = 27 then
62686 begin
62687 fCancelBtn := Value;
62688 fDefaultBtn := FALSE;
62689 end;
62690 if Applet = nil then Exit;
62691 F := ParentForm;
62692 if F <> nil then
62693 begin
62694 if Value then
62695 begin
62696 if @ Applet.fOnMessage <> @ TControl.DefaultBtnProc then
62697 Applet.fOldOnMessage := Applet.fOnMessage; // fixed by YS
62698 Applet.fOnMessage := Applet.DefaultBtnProc;
62700 else
62701 begin
62702 Applet.fOnMessage := Applet.fOldOnMessage;
62703 Applet.fOldOnMessage := nil;
62704 end;
62705 C := nil;
62706 if Value then C := @ Self;
62707 if Index = 13 then
62708 begin
62709 F.fDefaultBtnCtl := C;
62710 if Value then
62711 Style := Style or BS_DEFPUSHBUTTON
62712 else
62713 Style := Style and not BS_DEFPUSHBUTTON;
62715 else
62716 if Index = 27 then
62717 F.fCancelBtnCtl := C;
62718 end;
62719 end;
62721 {$IFDEF F_P}
62722 //[function TControl.GetDefaultBtn]
62723 function TControl.GetDefaultBtn(const Index: Integer): Boolean;
62724 begin
62725 CASE Index OF
62726 13: Result := fDefaultBtn;
62727 27: Result := fCancelBtn;
62728 END;
62729 end;
62730 {$ENDIF F_P}
62732 //[function TControl.AllBtnReturnClick]
62733 function TControl.AllBtnReturnClick: PControl;
62734 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
62735 begin
62736 // nothing: already implemented in WndProcBtnReturnClick
62737 Result := @ Self;
62738 end;
62739 {$ELSE}
62740 var F: PControl;
62741 begin
62742 SetDefaultBtn( 0, TRUE );
62743 F := ParentForm;
62744 if F <> nil then
62745 F.fAllBtnReturnClick := TRUE;
62746 Result := @ Self;
62747 end;
62748 {$ENDIF}
62750 //[function WndProc_CNDrawItem]
62751 function WndProc_CNDrawItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
62752 : Boolean;
62753 type PDrawAction = ^TDrawAction;
62754 PDrawState = ^TDrawState;
62755 var DI: PDrawItemStruct;
62756 begin
62757 Result := FALSE;
62758 if Msg.message = CN_DRAWITEM then
62759 begin
62760 DI := Pointer( Msg.lParam );
62761 if Assigned( Sender.OnDrawItem ) then
62762 begin
62763 if Sender.OnDrawItem( Sender, DI.hDC, DI.rcItem, DI.itemID,
62764 PDrawAction( @ DI.itemAction )^,
62765 PDrawState( @ DI.itemState )^ )
62766 then Rslt := 1
62767 else Rslt := 0;
62768 Result := TRUE;
62770 else Rslt := 0;
62771 end;
62772 end;
62774 //[procedure TControl.SetOnDrawItem]
62775 procedure TControl.SetOnDrawItem(const Value: TOnDrawItem);
62776 begin
62777 fOnDrawItem := Value;
62778 if Parent <> nil then
62779 Parent.AttachProc( @WndProc_DrawItem );
62780 AttachProc( @WndProc_CNDrawItem );
62781 end;
62783 //[function WndProc_MeasureItem]
62784 function WndProc_MeasureItem( Sender: PControl; var Msg: TMsg; var Rslt: Integer )
62785 : Boolean;
62786 var MI: PMeasureItemStruct;
62787 Control: PControl;
62788 I: Integer;
62789 begin
62790 Result := FALSE;
62791 if Msg.message = WM_MEASUREITEM then
62792 begin
62793 MI := Pointer( Msg.lParam );
62794 for I := 0 to Sender.ChildCount - 1 do
62795 begin
62796 Control := Sender.Children[ I ];
62797 if Control.Menu = MI.CtlID then
62798 begin
62799 if Assigned( Control.OnMeasureItem ) then
62800 begin
62801 MI.itemHeight := Control.OnMeasureItem( Control, MI.itemID );
62802 if MI.itemHeight > 0 then
62803 begin
62804 Rslt := 1;
62805 Result := TRUE;
62806 end;
62807 end;
62808 break;
62809 end;
62810 end;
62811 end;
62812 end;
62814 //[procedure TControl.SetOnMeasureItem]
62815 procedure TControl.SetOnMeasureItem(const Value: TOnMeasureItem);
62816 begin
62817 fOnMeasureItem := Value;
62818 if Parent <> nil then
62819 Parent.AttachProc( @WndProc_MeasureItem );
62820 end;
62822 //[function TControl.GetItemData]
62823 function TControl.GetItemData(Idx: Integer): DWORD;
62824 begin
62825 Result := 0;
62826 if fCommandActions.aGetItemData <> 0 then
62827 Result := Perform( fCommandActions.aGetItemData, Idx, 0 );
62828 end;
62830 //[procedure TControl.SetItemData]
62831 procedure TControl.SetItemData(Idx: Integer; const Value: DWORD);
62832 begin
62833 if fCommandActions.aSetItemData <> 0 then
62834 Perform( fCommandActions.aSetItemData, Idx, Value );
62835 end;
62837 //[function TControl.GetLVCurItem]
62838 function TControl.GetLVCurItem: Integer;
62839 begin
62840 Result := Perform( LVM_GETNEXTITEM, -1, LVNI_SELECTED );
62841 end;
62843 //[procedure TControl.SetLVCurItem]
62844 procedure TControl.SetLVCurItem(const Value: Integer);
62845 begin
62846 if (lvoMultiselect in LVOptions) or (Value <> LVCurItem ) then
62847 LVItemState[ -1 ] := [ ];
62848 if Value >= 0 then
62849 LVItemState[ Value ] := [ lvisSelect, lvisFocus ];
62850 end;
62852 //[function TControl.LVNextItem]
62853 function TControl.LVNextItem(IdxPrev: Integer; Attrs: DWORD): Integer;
62854 begin
62855 Result := Perform( LVM_GETNEXTITEM, IdxPrev, Attrs );
62856 end;
62858 //[function TControl.LVNextSelected]
62859 function TControl.LVNextSelected(IdxPrev: Integer): Integer;
62860 begin
62861 Result := Perform( LVM_GETNEXTITEM, IdxPrev, LVNI_SELECTED );
62862 end;
62864 //[function TControl.GetLVFocusItem]
62865 function TControl.GetLVFocusItem: Integer;
62866 begin
62867 Result := Perform( LVM_GETNEXTITEM, -1, LVNI_FOCUSED );
62868 end;
62870 //[procedure TControl.Close]
62871 procedure TControl.Close;
62872 begin
62873 PostMessage( Handle, WM_CLOSE, 0, 0 );
62874 end;
62876 //[function WndProcMinimize]
62877 function WndProcMinimize( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
62878 var Wnd: PControl;
62879 begin
62880 Result := FALSE;
62881 if (Msg.message = WM_SYSCOMMAND) and ((Msg.wParam and $FFF0) = SC_MINIMIZE)then
62882 begin
62883 if Applet <> nil then
62884 begin
62885 Wnd := Applet.FMinimizeWnd;
62886 if Wnd <> nil then
62887 SetWindowPos( Applet.Handle, 0, Wnd.Left, Wnd.Top, Wnd.Width, 0,
62888 SWP_NOZORDER or SWP_NOREDRAW);
62889 end;
62890 end;
62891 end;
62893 //[procedure TControl.MinimizeNormalAnimated]
62894 procedure TControl.MinimizeNormalAnimated;
62895 var App: PControl;
62896 begin
62897 App := Applet;
62898 if App = nil then
62899 App := @Self;
62900 App.FMinimizeWnd := @Self;
62901 App.AttachProc( @WndProcMinimize );
62902 end;
62904 //[function WndProcDropFiles]
62905 function WndProcDropFiles( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
62906 var hDrop: THandle;
62907 Pt: TPoint;
62908 FList: String;
62909 I, N: Integer;
62910 Buf: array[ 0..MAX_PATH ] of Char;
62911 begin
62912 if Msg.message = WM_DROPFILES then
62913 if Assigned( Sender.FOnDropFiles ) then
62914 begin
62915 hDrop := Msg.wParam;
62916 DragQueryPoint( hDrop, Pt );
62917 N := DragQueryFile( hDrop, $FFFFffff, nil, 0 );
62918 FList := '';
62919 for I := 0 to N-1 do
62920 begin
62921 if FList <> '' then
62922 FList := FList + #13;
62923 DragQueryFile( hDrop, I, Buf, Sizeof( Buf ) );
62924 FList := FList + Buf;
62925 end;
62926 DragFinish( hDrop );
62927 Sender.FOnDropFiles( Sender, FList, Pt );
62928 Rslt := 0;
62929 Result := TRUE;
62930 Exit;
62931 end;
62932 Result := FALSE;
62933 end;
62935 //[procedure TControl.SetOnDropFiles]
62936 procedure TControl.SetOnDropFiles(const Value: TOnDropFiles);
62937 begin
62938 FOnDropFiles := Value;
62939 AttachProc( @WndProcDropFiles );
62940 DragAcceptFiles( GetWindowHandle, Assigned( Value ) );
62941 end;
62943 //[function WndProcShowHide]
62944 function WndProcShowHide( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
62945 var IsVisible: Boolean;
62946 begin
62947 if Msg.message = WM_SHOWWINDOW then
62948 if Msg.hwnd = Sender.Handle then
62949 begin
62950 IsVisible := IsWindowVisible( Sender.Handle );
62951 if LongBool( Msg.wParam ) then
62952 begin
62953 Sender.fVisible := TRUE;
62954 if not IsVisible then
62955 if Assigned( Sender.FOnShow ) then
62956 Sender.FOnShow( Sender );
62958 else
62959 begin
62960 Sender.fVisible := FALSE;
62961 if IsVisible then
62962 if Assigned( Sender.FOnHide ) then
62963 Sender.FOnHide( Sender );
62964 end;
62965 end;
62966 Result := FALSE;
62967 end;
62969 //[procedure TControl.SetOnHide]
62970 procedure TControl.SetOnHide(const Value: TOnEvent);
62971 begin
62972 FOnHide := Value;
62973 AttachProc( WndProcShowHide );
62974 end;
62976 //[procedure TControl.SetOnShow]
62977 procedure TControl.SetOnShow(const Value: TOnEvent);
62978 begin
62979 FOnShow := Value;
62980 AttachProc( WndProcShowHide );
62981 end;
62983 //[function TControl.BringToFront]
62984 function TControl.BringToFront: PControl;
62985 begin
62986 SetWindowPos( GetWindowHandle, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or
62987 SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_SHOWWINDOW );
62988 Result := @Self;
62989 end;
62991 //[function TControl.SendToBack]
62992 function TControl.SendToBack: PControl;
62993 begin
62994 SetWindowPos( GetWindowHandle, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOSIZE or SWP_NOMOVE or
62995 SWP_NOACTIVATE or SWP_NOOWNERZORDER );
62996 Result := @Self;
62997 end;
62999 //[procedure TControl.DragStart]
63000 procedure TControl.DragStart;
63001 begin
63002 PostMessage( GetWindowHandle, WM_SYSCOMMAND, $F012, 0 );
63003 end;
63005 //[function WndProcDragWindow]
63006 function WndProcDragWindow( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63007 var P: TPoint;
63008 begin
63009 if Msg.message = WM_MOUSEMOVE then
63010 begin
63011 if Sender.FDragging then
63012 begin
63013 GetCursorPos( P );
63014 P.x := P.x - Sender.fMouseStartPos.x + Sender.fDragStartPos.x;
63015 P.y := P.y - Sender.fMouseStartPos.y + Sender.fDragStartPos.y;
63016 Sender.Position := P;
63017 end;
63018 end;
63019 Result := FALSE;
63020 end;
63022 //[procedure TControl.DragStartEx]
63023 procedure TControl.DragStartEx;
63024 var StartBounds: TRect;
63025 begin
63026 GetCursorPos( fMouseStartPos );
63027 StartBounds := BoundsRect;
63028 fDragStartPos.x := StartBounds.Left;
63029 fDragStartPos.y := StartBounds.Top;
63030 SetCapture( GetWindowHandle );
63031 fDragging := TRUE;
63032 AttachProc( WndProcDragWindow );
63033 end;
63035 //[procedure TControl.DragStopEx]
63036 procedure TControl.DragStopEx;
63037 begin
63038 if FDragging then
63039 begin
63040 ReleaseCapture;
63041 FDragging := FALSE;
63042 end;
63043 end;
63045 //[function CallDragCallBack]
63046 function CallDragCallBack( Sender: PControl; var Stop: Boolean ): Boolean;
63047 var P: TPoint;
63048 Shape, ShapeWas: Integer;
63049 begin
63050 GetCursorPos( P );
63051 Shape := LoadCursor( 0, IDC_HAND );
63052 ShapeWas := Shape;
63053 Result := Sender.fDragCallback( Sender, P.x, P.y, Shape, Stop );
63054 if not Stop then
63055 begin
63056 if not Result then
63057 if Shape = ShapeWas then
63058 Shape := LoadCursor( 0, IDC_NO );
63059 ScreenCursor := Shape;
63061 else
63062 begin
63063 ScreenCursor := 0;
63064 Shape := Sender.fCursor;
63065 end;
63066 Windows.SetCursor( Shape );
63067 end;
63069 //[function WndProcDrag]
63070 function WndProcDrag( Sender: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
63071 var Stop: Boolean;
63072 begin
63073 if Sender.fDragging then
63074 begin
63075 Stop := FALSE;
63076 case Msg.message of
63077 WM_MOUSEMOVE:
63078 CallDragCallBack( Sender, Stop );
63079 WM_LBUTTONUP, WM_RBUTTONUP:
63080 begin
63081 Stop := TRUE;
63082 CallDragCallBack( Sender, Stop );
63083 end;
63084 else
63085 begin
63086 Result := FALSE;
63087 Exit;
63088 end;
63089 end;
63090 if Stop then
63091 begin
63092 ReleaseCapture;
63093 Sender.fDragging := FALSE;
63095 else
63096 begin
63097 Result := TRUE;
63098 exit;
63099 end;
63100 end;
63101 Result := FALSE;
63102 end;
63104 //[procedure TControl.DragItem]
63105 procedure TControl.DragItem(OnDrag: TOnDrag);
63106 begin
63107 fDragCallback := OnDrag;
63108 fDragging := TRUE;
63109 SetCapture( GetWindowHandle );
63110 AttachProc( WndProcDrag );
63111 end;
63114 {$IFDEF USE_CONSTRUCTORS} //****************************************************//
63116 //[constructor TControl.CreateWindowed]
63117 constructor TControl.CreateWindowed(AParent: PControl; AClassName: PChar; //
63118 ACtl3D: Boolean); //
63119 begin //
63120 CreateParented( AParent ); //
63121 fOnDynHandlers := WndProcDummy; //
63122 fWndProcKeybd := WndProcDummy; //
63123 fWndProcResizeFlicks := WndProcDummy; //
63124 fCommandActions.aClear := ClearText; //
63125 fWindowed := True; //
63126 fControlClassName := AClassName; //
63128 fControlClick := DummyObjProc; //
63130 fColor := clBtnFace; //
63131 fTextColor := clWindowText; //
63132 fMargin := 2; //
63133 fCtl3D := True; //
63134 fCtl3Dchild := True; //
63135 if AParent <> nil then //
63136 begin //
63137 fWndProcResizeFlicks := AParent.fWndProcResizeFlicks; //
63138 fGotoControl := AParent.fGotoControl; //
63139 fDoubleBuffered := AParent.fDoubleBuffered; //
63140 fTransparent := AParent.fTransparent; //
63141 fCtl3Dchild := AParent.fCtl3Dchild; //
63142 if AParent.fCtl3Dchild then //
63143 fCtl3D := ACtl3D //
63144 else //
63145 fCtl3D := False; //
63146 fMargin := AParent.fMargin; //
63147 with fBoundsRect do //
63148 begin //
63149 Left := AParent.fMargin + AParent.fClientLeft; //
63150 Top := AParent.fMargin + AParent.fClientTop; //
63151 Right := Left + 64; //
63152 Bottom := Top + 64; //
63153 end; //
63154 fTextColor := AParent.fTextColor; //
63155 fFont := fFont.Assign( AParent.fFont ); //
63156 if fFont <> nil then //
63157 begin //
63158 fFont.fOnChange := FontChanged; //
63159 FontChanged( fFont ); //
63160 end; //
63161 fColor := AParent.fColor; //
63162 fBrush := fBrush.Assign( AParent.fBrush ); //
63163 if fBrush <> nil then //
63164 begin //
63165 fBrush.fOnChange := BrushChanged; //
63166 BrushChanged( fBrush ); //
63167 end; //
63168 end; //
63169 end; //
63171 //[constructor TControl.CreateApplet]
63172 constructor TControl.CreateApplet(const ACaption: String); //
63173 begin //
63174 AppButtonUsed := True; //
63175 CreateWindowed( nil, 'App', TRUE ); //
63176 FIsApplet := TRUE; //
63177 fStyle := WS_VISIBLE or WS_SYSMENU or WS_POPUP or WS_MINIMIZEBOX //
63178 or WS_CAPTION; //
63179 fExStyle := WS_EX_APPWINDOW; //
63180 FCreateWndExt := CreateAppButton; //
63181 AttachProc( WndProcApp ); //
63182 Caption := ACaption; //
63183 end; //
63185 //[constructor TControl.CreateForm]
63186 constructor TControl.CreateForm(AParent: PControl; const ACaption: String); //
63187 begin //
63188 CreateWindowed( AParent, 'Form', TRUE ); //
63189 AttachProc( WndProcForm ); //
63190 AttachProc( WndProcDoEraseBkgnd ); //
63191 Caption := ACaption; //
63192 end; //
63194 //[constructor TControl.CreateControl]
63195 constructor TControl.CreateControl(AParent: PControl; AClassName: PChar; //
63196 AStyle: DWORD; ACtl3D: Boolean; Actions: PCommandActions); //
63197 var Form: PControl; //
63198 begin //
63199 CreateWindowed( AParent, AClassName, ACtl3D ); //
63200 if Actions <> nil then //
63201 fCommandActions := Actions^; //
63202 fIsControl := True; //
63203 fStyle := AStyle or WS_CLIPSIBLINGS or WS_CLIPCHILDREN; //
63204 fVisible := (Style and WS_VISIBLE) <> 0; //
63205 fTabstop := (Style and WS_TABSTOP) <> 0; //
63206 if (AParent <> nil) then //
63207 begin //
63208 Inc( AParent.ParentForm.fTabOrder ); //
63209 fTabOrder := AParent.ParentForm.fTabOrder; //
63210 end; //
63211 fLookTabKeys := [ tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn ]; //
63212 if fCtl3D then //
63213 begin //
63214 fStyle := fStyle and not WS_BORDER; //
63215 fExStyle := fExStyle or WS_EX_CLIENTEDGE; //
63216 end; //
63217 if (Style and WS_TABSTOP) <> 0 then //
63218 begin //
63219 Form := ParentForm; //
63220 if Form <> nil then //
63221 if Form.FCurrentControl = nil then //
63222 Form.FCurrentControl := @Self; //
63223 end; //
63224 //fCreateParamsExt := CreateParams2; //
63225 fMenu := CtlIdCount; //
63226 Inc( CtlIdCount ); //
63227 AttachProc( WndProcCtrl ); //
63228 end; //
63230 //[constructor TControl.CreateButton]
63231 constructor TControl.CreateButton(AParent: PControl; //
63232 const ACaption: String); //
63233 begin //
63234 CreateControl( AParent, 'BUTTON', //
63235 WS_VISIBLE or WS_CHILD or //
63236 BS_PUSHLIKE or WS_TABSTOP, False, @ButtonActions ); //
63237 with fBoundsRect do //
63238 Bottom := Top + 22; //
63239 fTextAlign := taCenter; //
63240 Caption := ACaption; //
63241 end; //
63243 //[constructor TControl.CreateBitBtn]
63244 constructor TControl.CreateBitBtn(AParent: PControl; //
63245 const ACaption: String; AOptions: TBitBtnOptions; ALayout: TGlyphLayout; //
63246 AGlyphBitmap: HBitmap; AGlyphCount: Integer); //
63247 var //
63248 B: TBitmapInfo; //
63249 W, H: Integer; //
63250 begin //
63251 CreateControl( AParent, 'BUTTON', WS_VISIBLE or WS_CHILD or //
63252 WS_TABSTOP or BS_OWNERDRAW, False, @ButtonActions ); //
63253 fBitBtnOptions := AOptions; //
63254 fGlyphLayout := ALayout; //
63255 fGlyphBitmap := AGlyphBitmap; //
63256 with fBoundsRect do //
63257 begin //
63258 Bottom := Top + 22; //
63259 W := 0; H := 0; //
63260 if AGlyphBitmap <> 0 then //
63261 begin //
63262 if bboImageList in AOptions then //
63263 ImageList_GetIconSize( AGlyphBitmap, W, H ) //
63264 else //
63265 begin //
63266 if GetObject( AGlyphBitmap, Sizeof(B), @B ) > 0 then //
63267 begin //
63268 W := B.bmiHeader.biWidth; //
63269 H := B.bmiHeader.biHeight; //
63270 if AGlyphCount = 0 then //
63271 AGlyphCount := W div H; //
63272 if AGlyphCount > 1 then //
63273 W := W div AGlyphCount; //
63274 end; //
63275 end; //
63276 if W > 0 then //
63277 if ACaption = '' then //
63278 Right := Left + W //
63279 else //
63280 Right := Right + W; //
63281 if H > 0 then //
63282 Bottom := Top + H; //
63283 if not ( bboNoBorder in AOptions ) then //
63284 begin //
63285 if W > 0 then //
63286 Inc( Right, 2 ); //
63287 if H > 0 then //
63288 Inc( Bottom, 2 ); //
63289 end; //
63290 end; //
63291 fGlyphWidth := W; //
63292 fGlyphHeight := H; //
63293 end; //
63294 fGlyphCount := AGlyphCount; //
63295 if AParent <> nil then //
63296 AParent.AttachProc( WndProc_DrawItem ); //
63297 AttachProc( WndProcBitBtn ); //
63298 fTextAlign := taCenter; //
63299 Caption := ACaption; //
63300 end; //
63302 //[constructor TControl.CreateLabel]
63303 constructor TControl.CreateLabel(AParent: PControl; //
63304 const ACaption: String); //
63305 begin //
63306 CreateControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or //
63307 SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY, //
63308 False, @LabelActions ); //
63309 fIsStaticControl := 1; //
63310 fSizeRedraw := True; //
63311 fBoundsRect.Bottom := fBoundsRect.Top + 22; //
63312 Caption := ACaption; //
63313 end; //
63315 //[constructor TControl.CreateWordWrapLabel]
63316 constructor TControl.CreateWordWrapLabel(AParent: PControl; //
63317 const ACaption: String); //
63318 begin //
63319 CreateLabel( AParent, ACaption ); //
63320 fBoundsRect.Bottom := fBoundsRect.Top + 44; //
63321 fStyle := fStyle and not SS_LEFTNOWORDWRAP; //
63322 end; //
63324 //[constructor TControl.CreateLabelEffect]
63325 constructor TControl.CreateLabelEffect(AParent: PControl; ACaption: String; //
63326 AShadowDeep: Integer); //
63327 begin //
63328 CreateLabel( AParent, ACaption ); //
63329 fIsStaticControl := 0; //
63330 AttachProc( WndProcLabelEffect ); //
63331 fTextAlign := taCenter; //
63332 fTextColor := clBtnShadow; //
63333 fShadowDeep := AShadowDeep; //
63334 fIgnoreWndCaption := True; //
63335 with fBoundsRect do //
63336 begin //
63337 Bottom := Top + 40; //
63338 end; //
63339 end; //
63341 //[constructor TControl.CreatePaintBox]
63342 constructor TControl.CreatePaintBox(AParent: PControl); //
63343 begin //
63344 CreateLabel( AParent, '' ); //
63345 with fBoundsRect do //
63346 begin //
63347 Right := Left + 40; //
63348 Bottom := Top + 40; //
63349 end; //
63350 end; //
63352 {$IFDEF ASM_VERSION} //
63353 //[constructor TControl.CreateGradientPanel]
63354 constructor TControl.CreateGradientPanel(AParent: PControl; AColor1, //
63355 AColor2: TColor); //
63356 asm //cmd //opd //
63357 XOR EDX, EDX //
63358 PUSH EDX //
63359 CALL CreateLabel //
63360 MOV ECX, AColor1 //
63361 MOV [EAX].fColor1, ECX //
63362 MOV ECX, AColor2 //
63363 MOV [EAX].fColor2, ECX //
63364 MOV EDX, [EAX].fBoundsRect.Left //
63365 ADD EDX, 40 //
63366 MOV [EAX].fBoundsRect.Right, EDX //
63367 MOV EDX, [EAX].fBoundsRect.Top //
63368 ADD EDX, 40 //
63369 MOV [EAX].fBoundsRect.Bottom, EDX //
63370 PUSH EAX //
63371 MOV EDX, offset[ WndProcGradient ] //
63372 CALL AttachProc //
63373 POP EAX //
63374 end; //
63375 {$ELSE ASM_VERSION} //Pascal //
63376 constructor TControl.CreateGradientPanel(AParent: PControl; AColor1, //
63377 AColor2: TColor); //
63378 begin //
63379 CreateLabel( AParent, '' ); //
63380 AttachProc( WndProcGradient ); //
63381 fColor2 := AColor2; //
63382 fColor1 := AColor1; //
63383 with fBoundsRect do //
63384 begin //
63385 Right := Left + 40; //
63386 Bottom := Top + 40; //
63387 end; //
63388 end; //
63389 {$ENDIF ASM_VERSION} //
63391 //[constructor TControl.CreateGradientPanelEx]
63392 constructor TControl.CreateGradientPanelEx(AParent: PControl; AColor1, //
63393 AColor2: TColor; AStyle: TGradientStyle; ALayout: TGradientLayout); //
63394 begin //
63395 CreateLabel( AParent, '' ); //
63396 AttachProc( WndProcGradientEx ); //
63397 fColor2 := AColor2; //
63398 fColor1 := AColor1; //
63399 fGradientStyle := AStyle; //
63400 fGradientLayout := ALayout; //
63401 with fBoundsRect do //
63402 begin //
63403 Right := Left + 40; //
63404 Bottom := Top + 40; //
63405 end; //
63406 end; //
63408 //[constructor TControl.CreateGroupbox]
63409 constructor TControl.CreateGroupbox(AParent: PControl; //
63410 const ACaption: String); //
63411 begin //
63412 CreateButton( AParent, ACaption ); //
63413 with fBoundsRect do //
63414 begin //
63415 Right := Left + 100; //
63416 Bottom := Top + 100; //
63417 end; //
63418 fStyle := WS_VISIBLE or WS_CHILD or BS_GROUPBOX or WS_TABSTOP; //
63419 fClientTop := 22; //
63420 fClientLeft := 2; //
63421 fClientBottom := 2; //
63422 fClientRight := 2; //
63423 fTabstop := False; //
63424 end; //
63426 //[constructor TControl.CreateCheckbox]
63427 constructor TControl.CreateCheckbox(AParent: PControl; //
63428 const ACaption: String); //
63429 begin //
63430 CreateButton( AParent, ACaption ); //
63431 with fBoundsRect do //
63432 begin //
63433 Right := Left + 72; //
63434 end; //
63435 fStyle := WS_VISIBLE or WS_CHILD or //
63436 BS_AUTOCHECKBOX or WS_TABSTOP; //
63437 end; //
63439 //[constructor TControl.CreateRadiobox]
63440 constructor TControl.CreateRadiobox(AParent: PControl; //
63441 const ACaption: String); //
63442 begin //
63443 CreateCheckbox( AParent, ACaption ); //
63444 fStyle := WS_VISIBLE or WS_CHILD or //
63445 BS_RADIOBUTTON or WS_TABSTOP or WS_GROUP; //
63446 fControlClick := ClickRadio; //
63447 if AParent <> nil then //
63448 begin //
63449 AParent.fRadioLast := fMenu; //
63450 if AParent.fRadio1st = 0 then //
63451 begin //
63452 AParent.fRadio1st := fMenu; //
63453 SetRadioChecked; //
63454 end; //
63455 end; //
63456 end; //
63458 //[constructor TControl.CreateEditbox]
63459 constructor TControl.CreateEditbox(AParent: PControl; //
63460 AOptions: TEditOptions); //
63461 var Flags: Integer; //
63462 begin //
63463 Flags := MakeFlags( @AOptions, EditFlags ); //
63464 if not(eoMultiline in AOptions) then //
63465 Flags := Flags and not(WS_HSCROLL or WS_VSCROLL); //
63466 CreateControl( AParent, 'EDIT', WS_VISIBLE or WS_CHILD or WS_TABSTOP //
63467 or WS_BORDER or Flags, True, @EditActions ); //
63468 //YS fCursor := LoadCursor( 0, IDC_IBEAM ); // //YS
63469 with fBoundsRect do //
63470 begin //
63471 Right := Left + 100; //
63472 Bottom := Top + 22; //
63473 if eoMultiline in AOptions then //
63474 begin //
63475 Right := Right + 100; //
63476 Bottom := Top + 200; //
63477 end; //
63478 end; //
63479 fColor := clWindow; //
63480 fLookTabKeys := [ tkTab, tkUpDown, tkPageUpPageDn ]; //
63481 if eoMultiline in AOptions then //
63482 fLookTabKeys := [ tkTab ]; //
63483 if eoWantTab in AOptions then //
63484 fLookTabKeys := fLookTabKeys - [ tkTab ]; //
63485 end; //
63487 //[constructor TControl.CreatePanel]
63488 constructor TControl.CreatePanel(AParent: PControl; AStyle: TEdgeStyle); //
63489 const Edgestyles: array[ TEdgeStyle ] of DWORD = ( WS_DLGFRAME, SS_SUNKEN, 0 ); //
63490 begin //
63491 CreateControl( AParent, 'STATIC', WS_VISIBLE or WS_CHILD or //
63492 SS_LEFTNOWORDWRAP or SS_NOPREFIX or SS_NOTIFY, False, //
63493 @LabelActions ); //
63494 with fBoundsRect do //
63495 begin //
63496 Right := Left + 100; //
63497 Bottom := Top + 100; //
63498 end; //
63499 Style := Style or Edgestyles[ AStyle ]; //
63500 ExStyle := ExStyle or WS_EX_CONTROLPARENT; //
63501 end; //
63503 //[constructor TControl.CreateSplitter]
63504 constructor TControl.CreateSplitter(AParent: PControl; AMinSizePrev, //
63505 AMinSizeNext: Integer; EdgeStyle: TEdgeStyle); //
63506 var PrevCtrl: PControl; //
63507 Sz0: Integer; //
63508 begin //
63509 CreatePanel( AParent, EdgeStyle ); //
63510 fSplitMinSize1 := AMinSizePrev; //
63511 fSplitMinSize2 := AMinSizeNext; //
63512 Sz0 := 4; //
63513 with fBoundsRect do //
63514 begin //
63515 Right := Left + Sz0; //
63516 Bottom := Top + Sz0; //
63517 end; //
63518 if AParent <> nil then //
63519 begin //
63520 if AParent.fChildren.fCount > 1 then //
63521 begin //
63522 PrevCtrl := AParent.fChildren.fItems[ AParent.fChildren.fCount - 2 ]; //
63523 case PrevCtrl.FAlign of //
63524 caLeft, caRight: //
63525 begin //
63526 fCursor := LoadCursor( 0, IDC_SIZEWE ); //
63527 end; //
63528 caTop, caBottom: //
63529 begin //
63530 fCursor := LoadCursor( 0, IDC_SIZENS ); //
63531 end; //
63532 end; //
63533 Align := PrevCtrl.FAlign; //
63534 end; //
63535 end; //
63536 AttachProc( WndProcSplitter ); //
63537 end; //
63539 //[constructor TControl.CreateListbox]
63540 constructor TControl.CreateListbox(AParent: PControl; //
63541 AOptions: TListOptions); //
63542 var Flags: Integer; //
63543 begin //
63544 Flags := MakeFlags( @AOptions, ListFlags ); //
63545 CreateControl( AParent, 'LISTBOX', WS_VISIBLE or WS_CHILD or WS_TABSTOP //
63546 or WS_BORDER or WS_VSCROLL //
63547 or LBS_NOTIFY or Flags, True, @ListActions ); //
63548 with fBoundsRect do //
63549 begin //
63550 Right := Right + 100; //
63551 Bottom := Top + 200; //
63552 end; //
63553 fColor := clWindow; //
63554 fLookTabKeys := [ tkTab, tkLeftRight ]; //
63555 end; //
63557 //[constructor TControl.CreateCombobox]
63558 constructor TControl.CreateCombobox(AParent: PControl; //
63559 AOptions: TComboOptions); //
63560 var Flags: Integer; //
63561 begin //
63562 Flags := MakeFlags( @AOptions, ComboFlags ); //
63563 CreateControl( AParent, 'COMBOBOX', //
63564 WS_VISIBLE or WS_CHILD or WS_VSCROLL or //
63565 CBS_DROPDOWN or CBS_HASSTRINGS or WS_TABSTOP or Flags, //
63566 True, @ComboActions ); //
63567 fCreateWndExt := CreateComboboxWnd; //
63568 fDropDownProc := ComboboxDropDown; //
63569 fClsStyle := fClsStyle or CS_DBLCLKS; //
63570 with fBoundsRect do //
63571 begin //
63572 Right := Left + 100; //
63573 Bottom := Top + 22; //
63574 end; //
63575 fColor := clWindow; //
63576 fLookTabKeys := [ tkTab ]; //
63577 if coReadOnly in AOptions then //
63578 fLookTabKeys := [ tkTab, tkLeftRight ]; //
63579 end; //
63581 //[constructor TControl.CreateCommonControl]
63582 constructor TControl.CreateCommonControl(AParent: PControl; //
63583 AClassName: PChar; AStyle: DWORD; ACtl3D: Boolean; //
63584 Actions: PCommandActions); //
63585 begin //
63586 {*************} DoInitCommonControls( ICC_WIN95_CLASSES ); //
63587 CreateControl( AParent, AClassName, AStyle, ACtl3D, Actions ); //
63588 fIsCommonControl := True; //
63589 if AParent <> nil then //
63590 begin //
63591 AttachProc( WndProcParentResize ); //
63592 AParent.AttachProc( WndProcResize ); //
63593 AttachProc( WndProcCommonNotify ); //
63594 AParent.AttachProc( WndProcNotify ); //
63595 end; //
63596 end; //
63598 //[constructor TControl.CreateRichEdit1]
63599 constructor TControl.CreateRichEdit1(AParent: PControl; //
63600 AOptions: TEditOptions); //
63601 var Flags, I: Integer; //
63602 begin //
63603 if FRichEditModule = 0 then //
63604 begin //
63605 for I := 0 to 2 do //
63606 begin //
63607 FRichEditModule := LoadLibrary( RichEditLibnames[ I ] ); //
63608 if FRichEditModule > HINSTANCE_ERROR then break; //
63609 RichEditClass := 'RichEdit'; //
63610 end; //
63611 if FRichEditModule <= HINSTANCE_ERROR then //
63612 FRichEditModule := 0; //
63613 end; //
63614 Flags := MakeFlags( @AOptions, RichEditFlags ); //
63615 CreateCommonControl( AParent, RichEditClass, WS_VISIBLE or WS_CHILD //
63616 or WS_TABSTOP or WS_BORDER or ES_MULTILINE or Flags, //
63617 True, @RichEditActions ); //
63619 AttachProc( WndProcRichEditNotify ); //
63620 fDoubleBuffered := False; //
63621 fCannotDoubleBuf := True; //
63622 with fBoundsRect do //
63623 begin //
63624 Right := Right + 100; //
63625 Bottom := Top + 200; //
63626 end; //
63627 fColor := clWindow; //
63628 fLookTabKeys := [ tkTab ]; //
63629 if eoWantTab in AOptions then //
63630 fLookTabKeys := [ ]; //
63631 Perform( EM_SETEVENTMASK, 0, //
63632 ENM_CHANGE or ENM_SELCHANGE or ENM_REQUESTRESIZE or //
63633 ENM_PROTECTED or $04000000 {ENM_LINK} ); //
63634 Perform( EM_SETBKGNDCOLOR, 0, Color2RGB(fColor)); //
63635 end; //
63638 //[constructor TControl.CreateRichEdit]
63639 constructor TControl.CreateRichEdit(AParent: PControl; //
63640 AOptions: TEditOptions); //
63641 var OldRichEditClass, OldRichEditLib: PChar; //
63642 begin //
63643 if OleInit then //
63644 begin //
63645 OldRichEditClass := RichEditClass; //
63646 RichEditClass := 'RichEdit20A'; //
63647 OldRichEditLib := RichEditLib; //
63648 RichEditLib := 'RICHED20.DLL'; //
63649 CreateRichEdit1( AParent, AOptions ); //
63650 fCharFmtDeltaSz := 24; //
63651 // sizeof( TCharFormat2 ) - sizeof( RichEdit.TCharFormat ); //
63652 fParaFmtDeltaSz := sizeof( TParaFormat2 ) - sizeof( RichEdit.TParaFormat ); //
63653 RichEditClass := OldRichEditClass; //
63654 RichEditLib := OldRichEditLib; //
63655 end //
63656 else //
63657 CreateRichEdit1( AParent, AOptions ); //
63658 end; //
63660 //[constructor TControl.CreateProgressbar]
63661 constructor TControl.CreateProgressbar(AParent: PControl); //
63662 const ProgressBarFlags: array[ TProgressbarOption ] of Integer = //
63663 (PBS_VERTICAL, PBS_SMOOTH ); //
63664 begin //
63665 CreateCommonControl( AParent, PROGRESS_CLASS, //
63666 WS_CHILD or WS_VISIBLE, True, nil ); //
63667 with fBoundsRect do //
63668 begin //
63669 Right := Left + 300; //
63670 Bottom := Top + 20; //
63671 end; //
63672 fMenu := 0; //
63673 fTextColor := clHighlight; //
63674 end; //
63676 //[constructor TControl.CreateProgressbarEx]
63677 constructor TControl.CreateProgressbarEx(AParent: PControl; //
63678 AOptions: TProgressbarOptions); //
63679 const ProgressBarFlags: array[ TProgressbarOption ] of Integer = //
63680 (PBS_VERTICAL, PBS_SMOOTH ); //
63681 begin //
63682 CreateProgressbar( AParent ); //
63683 fStyle := fStyle or DWORD( MakeFlags( @AOptions, ProgressBarFlags ) ); //
63684 end; //
63686 //[constructor TControl.CreateListView]
63687 constructor TControl.CreateListView(AParent: PControl; //
63688 AStyle: TListViewStyle; AOptions: TListViewOptions; AImageListSmall, //
63689 AImageListNormal, AImageListState: PImageList); //
63690 begin //
63691 CreateCommonControl( AParent, WC_LISTVIEW, ListViewStyles[ AStyle ] or //
63692 LVS_SHAREIMAGELISTS or WS_CHILD or WS_VISIBLE or WS_TABSTOP, //
63693 True, @ListViewActions ); //
63694 fLVOptions := AOptions; //
63695 fLVStyle := AStyle; //
63696 fCreateWndExt := ApplyImageLists2ListView; //
63697 with fBoundsRect do //
63698 begin //
63699 Right := Left + 200; //
63700 Bottom := Top + 150; //
63701 end; //
63702 ImageListSmall := AImageListSmall; //
63703 ImageListNormal := AImageListNormal; //
63704 ImageListState := AImageListState; //
63705 fLVTextBkColor := clWindow; //
63706 fLookTabKeys := [ tkTab ]; //
63707 end; //
63709 //[constructor TControl.CreateTreeView]
63710 constructor TControl.CreateTreeView(AParent: PControl; //
63711 AOptions: TTreeViewOptions; AImgListNormal, AImgListState: PImageList); //
63712 var Flags: Integer; //
63713 begin //
63714 Flags := MakeFlags( @AOptions, TreeViewFlags ); //
63715 CreateCommonControl( AParent, WC_TREEVIEW, Flags or WS_VISIBLE or //
63716 WS_CHILD or WS_TABSTOP, True, @TreeViewActions ); //
63717 fCreateWndExt := ApplyImageLists2Control; //
63718 fColor := clWindow; //
63719 AttachProc( WndProcTreeView ); //
63720 with fBoundsRect do //
63721 begin //
63722 Right := Left + 150; //
63723 Bottom := Top + 200; //
63724 end; //
63725 ImageListNormal := AImgListNormal; //
63726 ImageListState := AImgListState; //
63727 fLookTabKeys := [ tkTab ]; //
63728 end; //
63730 //[constructor TControl.CreateTabControl]
63731 constructor TControl.CreateTabControl(AParent: PControl; ATabs: array of String;//
63732 AOptions: TTabControlOptions; //
63733 AImgList: PImageList; AImgList1stIdx: Integer); //
63734 var I, II : Integer; //
63735 Flags: Integer; //
63736 begin //
63737 Flags := MakeFlags( @AOptions, TabControlFlags ); //
63738 if tcoFocusTabs in AOptions then //
63739 Flags := Flags or (WS_TABSTOP or TCS_FOCUSONBUTTONDOWN); //
63740 CreateCommonControl( AParent, WC_TABCONTROL, //
63741 Flags or (WS_CHILD or WS_CLIPSIBLINGS or WS_CLIPCHILDREN or //
63742 WS_VISIBLE), True, @TabControlActions ); //
63743 if not( tcoBorder in AOptions ) then //
63744 fExStyle := fExStyle and not WS_EX_CLIENTEDGE; //
63745 AttachProc( WndProcTabControl ); //
63746 with fBoundsRect do //
63747 begin //
63748 Right := Left + 100; //
63749 Bottom := Top + 100; //
63750 end; //
63751 if AImgList <> nil then //
63752 Perform( TCM_SETIMAGELIST, 0, AImgList.Handle ); //
63753 II := AImgList1stIdx; //
63754 for I := 0 to High( ATabs ) do //
63755 begin //
63756 TC_Insert( I, ATabs[ I ], II ); //
63757 Inc( II ); //
63758 end; //
63759 fLookTabKeys := [ tkTab ]; //
63760 end; //
63762 //[constructor TControl.CreateToolbar]
63763 constructor TControl.CreateToolbar(AParent: PControl; //
63764 AAlign: TControlAlign; AOptions: TToolbarOptions; ABitmap: HBitmap; //
63765 AButtons: array of PChar; ABtnImgIdxArray: array of Integer); //
63766 var Flags: DWORD; //
63767 begin //
63768 if not( tboTextBottom in AOptions ) then //
63769 AOptions := AOptions + [ tboTextRight ]; //
63770 if tboTextRight in AOptions then //
63771 AOptions := AOptions - [ tboTextBottom ]; //
63772 Flags := MakeFlags( @AOptions, ToolbarOptions ); //
63773 CreateCommonControl( AParent, TOOLBARCLASSNAME, ToolbarAligns[ Align ] or //
63774 WS_CHILD or WS_VISIBLE {or WS_TABSTOP} //
63775 or TBSTYLE_TOOLTIPS or Flags, //
63776 (not (Align in [caNone])) and //
63777 not (tboNoDivider in AOptions), nil ); //
63778 fCommandActions.aClear := ClearToolbar; //
63779 fCommandActions.aGetCount := TB_BUTTONCOUNT; //
63780 with fBoundsRect do //
63781 begin //
63782 if AAlign in [ caNone ] then //
63783 begin //
63784 Bottom := Top + 26; //
63785 Right := Left + 1000; //
63786 end //
63787 else //
63788 begin //
63789 Left := 0; Right := 0; //
63790 Top := 0; Bottom := 0; //
63791 end; //
63792 end; //
63793 Perform(TB_SETEXTENDEDSTYLE, 0, Perform(TB_GETEXTENDEDSTYLE, 0, 0) or //
63794 TBSTYLE_EX_DRAWDDARROWS); //
63796 AttachProc( WndProcToolbarCtrl ); //
63797 Perform( TB_BUTTONSTRUCTSIZE, Sizeof( TTBButton ), 0 ); //
63798 Perform( TB_SETINDENT, fMargin, 0 ); //
63799 with fBoundsRect do //
63800 begin //
63801 if AAlign in [ caLeft, caRight ] then //
63802 Right := Left + 24 //
63803 else if not (AAlign in [caNone]) then //
63804 Bottom := Top + 22; //
63805 end; //
63806 if ABitmap <> 0 then //
63807 TBAddBitmap( ABitmap ); //
63808 TBAddButtons( AButtons, ABtnImgIdxArray ); //
63809 Perform( WM_SIZE, 0, 0 ); //
63810 end; //
63812 //[constructor TImageList.CreateImageList]
63813 constructor TImageList.CreateImageList(POwner: Pointer); //
63814 var AOwner: PControl; //
63815 begin //
63816 {*************} DoInitCommonControls( ICC_WIN95_CLASSES ); //
63817 Create; //
63818 FAllocBy := 1; //
63819 FMasked := True; //
63820 if POwner = nil then exit; //
63821 FBkColor := TColor( CLR_NONE );
63822 //ImageList_SetBkColor( FHandle, CLR_NONE );
63824 AOwner := POwner; //
63825 FControl := AOwner; //
63826 fNext := PImageList( AOwner.fImageList ); //
63827 if AOwner.fImageList <> nil then //
63828 PImageList( AOwner.fImageList ).fPrev := @Self; //
63829 AOwner.fImageList := @Self; //
63830 end; //
63832 //[constructor TThread.ThreadCreate]
63833 constructor TThread.ThreadCreate; //
63834 begin //
63835 IsMultiThread := True; //
63836 Create; //
63837 FSuspended := True; //
63838 FHandle := CreateThread( nil, // no security //
63839 0, // the same stack size //
63840 @ThreadFunc, // thread entry point //
63841 @Self, // parameter to pass to ThreadFunc //
63842 CREATE_SUSPENDED, // always SUSPENDED //
63843 FThreadID ); // receive thread ID //
63844 end; //
63846 //[constructor TThread.ThreadCreateEx]
63847 constructor TThread.ThreadCreateEx( const Proc: TOnThreadExecute ); //
63848 begin //
63849 ThreadCreate; //
63850 OnExecute := Proc; //
63851 Resume; //
63852 end; //
63854 {$ENDIF USE_CONSTRUCTORS} //****************************************************//
63857 //[procedure InvalidateExW]
63858 procedure InvalidateExW( Wnd: HWnd );
63859 begin
63860 InvalidateRect( Wnd, nil, TRUE );
63861 Wnd := GetWindow( Wnd, GW_CHILD );
63862 while Wnd <> 0 do
63863 begin
63864 InvalidateExW( Wnd );
63865 Wnd := GetWindow( Wnd, GW_HWNDNEXT );
63866 end;
63867 end;
63869 //[procedure TControl.InvalidateEx]
63870 procedure TControl.InvalidateEx;
63871 begin
63872 if fHandle = 0 then Exit;
63873 InvalidateExW( fHandle );
63874 end;
63876 //[procedure InvalidateNCW]
63877 procedure InvalidateNCW( Wnd: HWnd; Recursive: Boolean );
63878 begin
63879 SendMessage( Wnd, WM_NCPAINT, 1, 0 );
63880 if not Recursive then Exit;
63881 Wnd := GetWindow( Wnd, GW_CHILD );
63882 while Wnd <> 0 do
63883 begin
63884 InvalidateNCW( Wnd, Recursive );
63885 Wnd := GetWindow( Wnd, GW_HWNDNEXT );
63886 end;
63887 end;
63889 //[procedure TControl.InvalidateNC]
63890 procedure TControl.InvalidateNC(Recursive: Boolean);
63891 begin
63892 if fHandle = 0 then Exit;
63893 InvalidateNCW( fHandle, Recursive );
63894 end;
63896 //[procedure TControl.SetClientMargin]
63897 procedure TControl.SetClientMargin(const Index, Value: Integer);
63898 begin
63899 case Index of
63900 1: fClientTop := Value;
63901 2: fClientBottom := Value;
63902 3: fClientLeft := Value;
63903 4: fClientRight := Value;
63904 end;
63905 Global_Align( @Self );
63906 end;
63908 {$IFDEF F_P}
63909 //[function TControl.GetClientMargin]
63910 function TControl.GetClientMargin(const Index: Integer): Integer;
63911 begin
63912 CASE Index OF
63913 1: Result := fClientTop;
63914 2: Result := fClientBottom;
63915 3: Result := fClientLeft;
63916 4: Result := fClientRight;
63917 END;
63918 end;
63919 {$ENDIF F_P}
63921 {------------------------------------------------------------------------------}
63923 { G R A P H C O N T R O L S }
63925 {------------------------------------------------------------------------------}
63927 {$IFDEF GRAPHCTL_XPSTYLES}
63928 type TOpenThemeDataProc = function( Wnd: HWnd; pszClassList: PWideChar ): THandle;
63929 stdcall;
63930 TDrawThemeBackground = function( Theme: THandle; DC: HDC; iPartId: Integer;
63931 iStateId: Integer; Rect, ClipRect: PRect ): Integer;
63932 stdcall;
63933 TGetThemeBackgroundContentRect = function( Theme: THandle; DC: HDC;
63934 iPartId, iStateId: Integer; Rect, ContentRect: PRect ):
63935 Integer; stdcall;
63936 TDrawThemeText = function( Theme: THandle; DC: HDC; iPartId, iStateId: Integer;
63937 pszText: PWideChar; iCharCount: Integer;
63938 dwTextFlags, dwTextFlags2: DWORD; Rect: PRect ): Integer;
63939 stdcall;
63940 TCloseThemeData = function( Theme: THandle ): Integer; stdcall;
63941 var fOpenThemeDataProc: TOpenThemeDataProc;
63942 fDrawthemeBackground: TDrawThemeBackground;
63943 fGetThemeBackgroundcontentRect: TGetThemeBackgroundContentRect;
63944 fDrawThemeText: TDrawThemeText;
63945 fCloseThemeData: TCloseThemeData;
63946 uxtheme_lib: THandle;
63947 function OpenThemeDataProc: TOpenThemeDataProc;
63948 begin
63949 Result := nil;
63950 if Integer(uxtheme_lib) = -1 then Exit;
63951 if uxtheme_lib = 0 then
63952 uxtheme_lib := LoadLibrary( 'uxtheme.dll' );
63953 if uxtheme_lib = 0 then
63954 begin
63955 uxtheme_lib := DWORD( -1 );
63956 Exit;
63957 end;
63958 fOpenThemeDataProc := GetProcAddress( uxtheme_lib, 'OpenThemeData' );
63959 fDrawthemeBackground := GetProcAddress( uxtheme_lib, 'DrawThemeBackground' );
63960 fGetThemeBackgroundcontentRect := GetProcAddress( uxtheme_lib, 'GetThemeBackgroundContentRect' );
63961 fDrawThemeText := GetProcAddress( uxtheme_lib, 'DrawThemeText' );
63962 fCloseThemeData := GetProcAddress( uxtheme_lib, 'CloseThemeData' );
63963 if not Assigned( fOpenThemeDataProc ) or
63964 not Assigned( fDrawThemeBackground ) or
63965 not Assigned( fGetThemeBackgroundcontentRect ) or
63966 not Assigned( fDrawThemeText ) or
63967 not Assigned( fCloseThemeData ) then
63968 begin
63969 FreeLibrary( uxtheme_lib );
63970 uxtheme_lib := DWORD( -1 );
63971 fOpenThemeDataProc := nil;
63972 fDrawThemeBackground := nil;
63973 fGetThemeBackgroundcontentRect := nil;
63974 fDrawThemeText := nil;
63975 fCloseThemeData := nil;
63976 end;
63977 Result := fOpenThemeDataProc;
63978 end;
63980 procedure DrawFormattedTextXP( Theme: THandle; Ctl: PControl; DC: HDC;
63981 var R: TRect; CtlType, CtlStates, Flags1, Flags2: Integer );
63982 var OldFont: Integer;
63983 OldBrush: Integer;
63984 ParentHavingFont: PControl;
63985 begin
63986 ParentHavingFont := Ctl;
63987 while (ParentHavingFont <> nil) and not Assigned( ParentHavingFont.FFont )
63988 and not ParentHavingFont.IsForm do
63989 ParentHavingFont := ParentHavingFont.Parent;
63990 OldFont := 0;
63991 if Assigned( ParentHavingFont ) then
63992 OldFont := SelectObject( DC, ParentHavingFont.Font.Handle );
63993 OldBrush := SelectObject( DC, GetStockObject( NULL_BRUSH ) );
63994 fDrawThemeText( Theme, DC, CtlType, CtlStates, @ WideString( Ctl.fCaption )[ 1 ],
63995 Length( Ctl.fCaption ), Flags1, Flags2, @ R );
63996 SelectObject( DC, OldBrush );
63997 if Assigned( ParentHavingFont ) then
63998 SelectObject( DC, OldFont );
63999 end;
64000 {$ENDIF}
64003 procedure PaintGraphicChildren( Self_, Sender: PControl; DC: HDC );
64004 var i, sav: Integer;
64005 C: PControl;
64006 R: TRect;
64007 rgn: HRgn;
64008 begin
64009 for i := Self_.ChildCount-1 downto 0 do
64010 begin
64011 C := Self_.Children[ i ];
64012 if not C.Visible then continue;
64013 R := C.BoundsRect;
64014 if (C.Handle = 0) and not C.fWindowed and
64015 Assigned( C.fPaintProc ) then
64016 begin
64017 sav := SaveDC( DC );
64018 rgn := CreateRectRgnIndirect( R );
64019 ExtSelectClipRgn( DC, rgn, RGN_AND );
64020 DeleteObject( rgn );
64021 Free_And_Nil( C.fCanvas );
64023 C.fCanvas := Self_.Canvas;
64024 if Assigned( C.OnPrepaint ) then
64025 C.OnPrePaint( C, DC );
64027 if Assigned( C.OnPaint ) then
64028 C.OnPaint( C, DC )
64029 else
64030 C.fPaintProc( DC );
64032 if Assigned( C.OnPostPaint ) then
64033 C.OnPostPaint( C, DC );
64035 C.fCanvas := nil;
64037 Self_.Canvas.Brush.Assign( Self_.Brush );
64038 Self_.Canvas.Font.Assign( Self_.Font );
64040 RestoreDC( DC, sav );
64041 ExcludeClipRect( DC, R.Left, R.Top, R.Right, R.Bottom );
64042 end;
64043 end;
64044 if Self_.fIsGroupBox then
64045 begin
64046 Self_.fErasingBkgnd := TRUE;
64047 R := Self_.BoundsRect;
64048 OffsetRect( R, -R.Left, -R.Top );
64049 Self_.Canvas.FillRect( R );
64050 Self_.GroupBoxPaint( DC );
64051 Self_.fErasingBkgnd := FALSE;
64053 else
64054 if Assigned( Self_.fOnPaint2 ) then
64055 Self_.fOnPaint2( Self_, DC )
64056 else
64057 Self_.Canvas.FillRect( Self_.ClientRect );
64058 end;
64060 function WndProc_ParentOfGraphicCtl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
64061 var WasOnPaint: TOnPaint;
64062 i: Integer;
64063 C: PControl;
64064 Pt: TPoint;
64065 PF: PControl;
64066 begin
64067 Result := FALSE;
64068 if (Msg.message = WM_PAINT) or (Msg.message = WM_PRINT) then
64069 begin
64070 WasOnPaint := Self_.fOnPaint;
64071 Self_.fOnPaint2 := Self_.fOnPaint;
64072 Self_.fPaintMsg := Msg;
64073 TMethod( Self_.fOnPaint ) := MakeMethod( Self_, @ PaintGraphicChildren );
64074 Result := WndProcPaint( Self_, Msg, Rslt );
64075 Self_.fOnPaint := WasOnPaint;
64077 else
64078 if (Msg.message >= WM_MOUSEFIRST) and (Msg.message <= WM_MOUSELAST) then
64079 begin
64080 Pt.X := SmallInt( LoWord( Msg.lParam ) );
64081 Pt.Y := SmallInt( HiWord( Msg.lParam ) );
64082 for i := 0 to Self_.ChildCount-1 do
64083 begin
64084 if (i = 0) and (Self_.fPushedBtn <> nil) then
64085 C := Self_.fPushedBtn
64086 else
64087 C := Self_.Children[ i ];
64088 if (C = Self_.fPushedBtn) OR
64089 C.fVisible and C.fEnabled and PtInRect( C.BoundsRect, Pt ) then
64090 begin
64091 if not C.fWindowed and
64092 (C.fCursor <> 0) and (C.fCursor <> Self_.fCursor) and
64093 (ScreenCursor = 0) then
64094 begin
64095 if Self_.fSaveCursor = 0 then
64096 begin
64097 Self_.fSaveCursor := Self_.fCursor;
64098 if Self_.fCursor = 0 then
64099 Self_.fSaveCursor := LoadCursor( 0, IDC_ARROW );
64100 end;
64101 Self_.Cursor := C.fCursor;
64102 Windows.SetCursor( C.fCursor );
64103 end;
64104 {$IFDEF GRAPHCTL_HOTTRACK}
64105 if not C.fWindowed and (Applet.fHotCtl <> C) then
64106 begin
64107 if Applet.fHotCtl <> nil then
64108 begin
64109 Applet.fHotCtl.fHot := FALSE;
64110 if not Applet.fHotCtl.fWindowed then
64111 begin
64112 Applet.fHotCtl.Invalidate;
64113 if Assigned( Applet.fHotCtl.OnMouseLeave ) then
64114 Applet.fHotCtl.OnMouseLeave( Applet.fHotCtl );
64115 end;
64116 Applet.fHotCtl.RefDec;
64117 end;
64118 C.RefInc;
64119 Applet.fHotCtl := C;
64120 C.fHot := TRUE;
64121 C.Invalidate;
64122 Self_.fMouseLeaveProc := Self_.MouseLeaveFromParentOfGraphCtl;
64123 ProvideMouseEnterLeave( Self_ );
64124 if Assigned( C.OnMouseEnter ) then
64125 C.OnMouseEnter( C );
64126 end;
64127 {$ENDIF GRAPHCTL_HOTTRACK}
64128 if C.fWindowed then
64129 begin
64130 Msg.hwnd := C.fHandle;
64131 Pt := Self_.Client2Screen( Pt );
64132 Pt := C.Screen2Client( Pt );
64133 Msg.lParam := Pt.Y shl 16 or (Pt.X and $FFFF);
64134 end;
64135 Rslt := C.WndProc( Msg );
64136 if not C.fWindowed then
64137 if Assigned( C.fGraphCtlMouseEvent ) then
64138 C.fGraphCtlMouseEvent( Msg )
64139 else
64140 if (Msg.message = WM_LBUTTONDOWN) or
64141 (Msg.message = WM_RBUTTONDOWN) or
64142 (Msg.message = WM_MBUTTONDOWN) then
64143 C.DoClick;
64144 Result := TRUE;
64145 Exit;
64146 end;
64147 end;
64148 {$IFDEF GRAPHCTL_HOTTRACK}
64149 Self_.MouseLeaveFromParentOfGraphCtl( Self_ );
64150 {$ENDIF GRAPHCTL_HOTTRACK}
64151 if Self_.fIsGroupBox and (
64152 (Msg.message = WM_LBUTTONDOWN) or
64153 (Msg.message = WM_LBUTTONDBLCLK) or
64154 (Msg.message = WM_LBUTTONUP)
64155 ) then
64156 begin
64157 Self_.Invalidate;
64158 end;
64159 if Self_.fSaveCursor <> 0 then
64160 begin
64161 Self_.Cursor := Self_.fSaveCursor;
64162 Self_.fSaveCursor := 0;
64163 if ScreenCursor = 0 then
64164 Windows.SetCursor( Self_.fCursor );
64165 end;
64167 else
64168 if (Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST) then
64169 begin
64170 if Self_.IsControl then
64171 PF := Self_.ParentForm
64172 else
64173 PF := Self_;
64174 if (PF.fCurrentControl <> nil) and not PF.fCurrentControl.fWindowed then
64175 begin
64176 if Assigned( PF.fCurrentControl.fKeyboardProcess ) and
64177 PF.fCurrentControl.fKeyboardProcess( Msg, Rslt ) then
64178 else
64179 Rslt := PF.fCurrentControl.WndProc( Msg );
64180 Result := TRUE;
64182 else
64183 begin
64184 if Self_.fIsGroupBox and (Msg.wParam = WORD( ' ' )) and
64186 (Msg.message = WM_KEYDOWN) or
64187 (Msg.message = WM_SYSKEYDOWN) or
64188 (Msg.message = WM_KEYUP) or
64189 (Msg.message = WM_SYSKEYUP) or
64190 (Msg.message = WM_CHAR) or
64191 (Msg.message = WM_SYSCHAR)
64192 ) then
64193 begin
64194 Self_.Invalidate;
64195 end;
64196 end;
64198 else
64199 if Msg.message = CM_QUIT then
64200 begin
64201 C := Pointer( Msg.wParam );
64202 C.Free;
64204 else
64205 if Msg.message = CM_FOCUSGRAPHCTL then
64206 begin
64207 C := Pointer( Msg.wParam );
64208 PF := C.ParentForm;
64209 if (PF.fCurrentControl <> nil) and (PF.fCurrentControl <> C) then
64210 begin
64211 PF.fCurrentControl.fFocused := FALSE;
64212 PF.fCurrentControl.Invalidate;
64213 end;
64214 PF.fCurrentControl := C;
64215 C.Parent.fCurrentControl := C;
64216 C.Parent.fFocusHandle := C.Parent.fHandle;
64217 C.fFocused := TRUE;
64218 C.Invalidate;
64219 C.fLeave := C.LeaveGraphButton;
64220 C.RefDec;
64221 end;
64222 end;
64224 function WndProc_FormHavingGraphCtl( Self_: PControl; var Msg: TMsg; var Rslt: Integer ): Boolean;
64225 var Msg2: TMsg;
64226 begin
64227 Result := FALSE;
64228 if Msg.message = WM_ACTIVATE then
64229 begin
64230 if Self_.fCurrentControl <> nil then
64231 Self_.fCurrentControl.Invalidate;
64233 else
64234 if (Msg.message >= WM_KEYFIRST) and (Msg.message <= WM_KEYLAST) then
64235 begin
64236 if (Self_.fCurrentControl <> nil) and not Self_.fCurrentControl.fWindowed then
64237 begin
64238 if (Msg.message = WM_KEYDOWN) and ((Msg.wParam = 32) or (Msg.wParam = 13)) then
64239 begin
64240 if not PeekMessage( Msg2, Msg.hwnd, WM_CHAR, WM_CHAR, pm_noRemove ) or
64241 (Msg2.wParam <> Msg.wParam) then
64242 Msg.message := WM_CHAR;
64244 else
64245 if (Msg.message = WM_SYSKEYDOWN) and ((Msg.wParam = 32) or (Msg.wParam = 13)) then
64246 begin
64247 if not PeekMessage( Msg2, Msg.hwnd, WM_SYSCHAR, WM_SYSCHAR, pm_noRemove ) or
64248 (Msg2.wParam <> Msg.wParam) then
64249 Msg.message := WM_SYSCHAR;
64250 end;
64251 if Assigned( Self_.fCurrentControl.fKeyboardProcess ) and
64252 Self_.fCurrentControl.fKeyboardProcess( Msg, Rslt ) then
64253 else
64254 Rslt := Self_.fCurrentControl.WndProc( Msg );
64255 Result := TRUE;
64256 end;
64257 end;
64258 end;
64260 {$IFDEF GRAPHCTL_HOTTRACK}
64261 procedure TControl.MouseLeaveFromParentOfGraphCtl(Sender: PObj);
64262 var C: PControl;
64263 Pt: TPoint;
64264 begin
64265 if AppletTerminated then Exit;
64266 GetCursorPos( Pt );
64267 Pt := Screen2Client( Pt );
64268 if (Applet.fHotCtl <> nil) and (fChildren.IndexOf( Applet.fHotCtl ) >= 0) then
64269 begin
64270 C := Applet.fHotCtl;
64271 if PtInRect( C.BoundsRect, Pt ) then Exit;
64272 Applet.fHotCtl := nil;
64273 C.fHot := FALSE;
64274 if not C.fWindowed then
64275 C.Invalidate;
64276 if Assigned( C.OnMouseLeave ) then
64277 C.OnMouseLeave( C );
64278 C.RefDec;
64279 end;
64280 end;
64281 {$ENDIF GRAPHCTL_HOTTRACK}
64283 procedure NotifyGraphCtlAboutNewParent(Prnt, Chld: PControl);
64284 begin
64285 if (Chld <> nil) and (Prnt <> nil) then
64286 Prnt.AttachProc( WndProc_ParentOfGraphicCtl );
64287 end;
64289 function _NewGraphCtl( AParent: PControl; ATabStop: Boolean ): PControl;
64290 begin
64292 new( Result, Create );
64293 {+}{++}(*Result := PControl.CreateParented( AParent );*){--}
64294 Result.fWindowed := FALSE;
64295 Result.fVisible := TRUE;
64296 Result.fCreateVisible := TRUE;
64297 Result.fIsControl := TRUE;
64298 Result.fMenu := CtlIdCount;
64299 Inc( CtlIdCount );
64300 Result.fBitBtnOptions := [ bboFixed ]; // to return Checked = fChecked w/o window handle
64301 Result.fIgnoreWndCaption := TRUE;
64302 Result.fNotifyChild := @ NotifyGraphCtlAboutNewParent;
64303 Result.fSizeRedraw := TRUE;
64304 Result.fTabstop := ATabStop;
64305 if ATabStop then
64306 Result.fLookTabKeys := [ tkTab, tkLeftRight, tkUpDown, tkPageUpPageDn ];
64307 if AParent <> nil then
64308 begin
64309 Result.Parent := AParent;
64310 Result.Border := AParent.Border;
64311 AParent.AttachProc( WndProc_ParentOfGraphicCtl );
64312 if ATabStop then
64313 begin
64314 Inc( AParent.ParentForm.fTabOrder );
64315 Result.fTabOrder := AParent.ParentForm.fTabOrder;
64316 end;
64317 if AParent.IsControl then
64318 AParent.ParentForm.AttachProc( WndProc_FormHavingGraphCtl );
64319 if AParent.fIsGroupBox then
64320 begin
64321 AParent.Style := AParent.Style and
64322 not BS_GROUPBOX; // otherwise the groupbox is flickering A LOT!
64323 AParent.Parent.AttachProc( WndProc_ParentOfGraphicCtl );
64324 end;
64325 end;
64326 end;
64328 function NewGraphLabel( AParent: PControl; const ACaption: String ): PControl;
64329 begin
64330 {$IFDEF INPACKAGE}
64331 Result := NewLabel( AParent, ACaption );
64332 {$ELSE}
64333 Result := _NewGraphCtl( AParent, FALSE );
64334 Result.fCommandActions := LabelActions;
64335 Result.fPaintProc := Result.GraphicLabelPaint;
64336 Result.Caption := ACaption;
64337 {$ENDIF}
64338 end;
64340 function NewWordWrapGraphLabel( AParent: PControl; const ACaption: String ): PControl;
64341 begin
64342 {$IFDEF INPACKAGE}
64343 Result := NewWordWrapLabel( AParent, ACaption );
64344 {$ELSE}
64345 Result := NewGraphLabel( AParent, ACaption );
64346 Result.fWordWrap := TRUE;
64347 {$ENDIF}
64348 end;
64350 function NewGraphPaintBox( AParent: PControl ): PControl;
64351 begin
64352 {$IFDEF INPACKAGE}
64353 Result := NewPaintbox( AParent );
64354 {$ELSE}
64355 Result := NewGraphLabel( AParent, '' );
64356 {$ENDIF}
64357 end;
64359 procedure ClickGraphCheck(Sender: PObj);
64360 var Ctl: PControl;
64361 begin
64362 Ctl := Pointer( Sender );
64363 if not Ctl.Enabled then Exit;
64364 Ctl.Focused := TRUE;
64365 Ctl.fChecked := not Ctl.fChecked;
64366 Ctl.Invalidate;
64367 if Assigned( Ctl.OnClick ) then
64368 Ctl.OnClick( Ctl );
64369 end;
64371 function NewGraphCheckBox( AParent: PControl; const ACaption: String ): PControl;
64372 begin
64373 {$IFDEF INPACKAGE}
64374 Result := NewCheckbox( AParent, ACaption );
64375 {$ELSE}
64376 Result := NewGraphButton( AParent, ACaption );
64377 Result.TextAlign := taLeft;
64378 Result.fCommandActions.aAutoSzX := GetSystemMetrics( SM_CXMENUCHECK ) + 4;
64379 Result.fPaintProc := Result.GraphicCheckBoxPaint;
64380 Result.fGraphCtlMouseEvent := Result.GraphicCheckBoxMouse;
64381 Result.fControlClick := @ ClickGraphCheck;
64382 {$ENDIF}
64383 end;
64385 procedure ClickGraphRadio(Sender: PObj);
64386 var Ctl, C: PControl;
64387 i: Integer;
64388 begin
64389 Ctl := Pointer( Sender );
64390 if not Ctl.Enabled then Exit;
64391 Ctl.Focused := TRUE;
64392 Ctl.Checked := TRUE;
64393 if Ctl.Parent <> nil then
64394 for i := 0 to Ctl.Parent.ChildCount-1 do
64395 begin
64396 C := Ctl.Parent.Children[ i ];
64397 if (C <> Ctl) and (@ C.fControlClick = @ ClickGraphRadio) then
64398 C.Checked := FALSE;
64399 end;
64400 end;
64402 function NewGraphRadioBox( AParent: PControl; const ACaption: String ): PControl;
64403 begin
64404 {$IFDEF INPACKAGE}
64405 Result := NewRadiobox( AParent, ACaption );
64406 if (@ ClickGraphRadio) <> nil then;
64407 {$ELSE}
64408 Result := NewGraphButton( AParent, ACaption );
64409 Result.TextAlign := taLeft;
64410 Result.fCommandActions.aAutoSzX := GetSystemMetrics( SM_CXMENUCHECK ) + 4;
64411 Result.fPaintProc := Result.GraphicRadioBoxPaint;
64412 Result.fControlClick := @ ClickGraphRadio;
64413 if AParent <> nil then
64414 begin
64415 AParent.fRadioLast := Result.fMenu;
64416 if AParent.fRadio1st = 0 then
64417 begin
64418 AParent.fRadio1st := Result.fMenu;
64419 Result.SetRadioChecked;
64420 end;
64421 end;
64422 {$ENDIF}
64423 end;
64425 function NewGraphButton( AParent: PControl; const ACaption: String ): PControl;
64426 begin
64427 {$IFDEF INPACKAGE}
64428 Result := NewButton( AParent, ACaption );
64429 {$ELSE}
64430 Result := _NewGraphCtl( AParent, TRUE );
64431 Result.fCommandActions := ButtonActions;
64432 Result.fPaintProc := Result.GraphicButtonPaint;
64433 Result.Caption := ACaption;
64434 Result.TextAlign := taCenter;
64435 Result.VerticalAlign := vaCenter;
64436 Result.fGraphCtlMouseEvent := Result.GraphicButtonMouse;
64437 Result.fSetFocus := Result.GraphButtonSetFocus;
64438 Result.fKeyboardProcess := Result.GraphButtonKeyboardProcess;
64439 {$ENDIF}
64440 end;
64442 function NewGraphEditbox( AParent: PControl; Options: TEditOptions ): PControl;
64443 begin
64444 {$IFDEF INPACKAGE}
64445 Result := NewEditbox( AParent, Options );
64446 {$ELSE}
64447 Result := _NewGraphCtl( AParent, TRUE );
64448 Result.fCommandActions := EditActions;
64449 Result.fPaintProc := Result.GraphicEditPaint;
64450 Result.fEditOptions := Options;
64451 Result.VerticalAlign := vaCenter;
64452 Result.fColor := clWindow;
64453 Result.fGraphCtlMouseEvent := Result.GraphicEditMouse;
64454 Result.fSetFocus := Result.GraphEditBoxSetFocus;
64455 Result.fLookTabKeys := [ tkTab, tkUpDown, tkPageUpPageDn ];
64456 Result.fLeave := Result.LeaveGraphEdit;
64457 {$ENDIF}
64458 end;
64460 type TGrayTextData = packed record
64461 Ctl: PControl;
64462 W, H: Integer;
64463 Flags: DWORD;
64464 end;
64465 PGrayTextData = ^TGrayTextData;
64467 function DrawTextGrayed( DC: HDC; lData, wData, cX, cY: Integer ): BOOL; stdcall;
64468 var GDT: PGrayTextData;
64469 R: TRect;
64470 begin
64471 GDT := Pointer( lData );
64472 R := MakeRect( 0, 0, cX, cY );
64473 DrawFormattedText( GDT.Ctl, DC, R, GDT.Flags or $80000000 );
64474 Result := TRUE;
64475 end;
64477 procedure DrawFormattedText( Ctl: PControl; DC: HDC; var R: TRect; Flags: DWORD {EditCtl: Boolean} );
64478 var Fmt: DWORD;
64479 OldFont: Integer;
64480 OldBrush: Integer;
64481 ParentHavingFont: PControl;
64482 GTD: TGrayTextData;
64483 dX, dY: Integer;
64484 R1: TRect;
64485 begin
64486 Fmt := DT_EXPANDTABS or Flags and $7FFFFFFF;
64487 {if pos( #13, Ctl.fCaption ) <= 0 then
64488 Fmt := Fmt or DT_SINGLELINE //(commented since this prevents even using #13 chars);
64489 else}
64490 if Ctl.WordWrap then
64491 Fmt := Fmt or DT_WORDBREAK;
64492 if Flags and DT_EDITCONTROL <> 0 then
64493 Inc( R.Left, 4 );
64495 ParentHavingFont := Ctl;
64496 while (ParentHavingFont <> nil) and not Assigned( ParentHavingFont.FFont )
64497 and not ParentHavingFont.IsForm do
64498 ParentHavingFont := ParentHavingFont.Parent;
64499 OldFont := 0;
64500 if Assigned( ParentHavingFont ) then
64501 OldFont := SelectObject( DC, ParentHavingFont.Font.Handle );
64503 R1 := R;
64504 Windows.DrawText( DC, PChar( Ctl.Caption ), Length( Ctl.Caption ), R,
64505 Fmt or DT_CALCRECT );
64506 CASE Ctl.fTextAlign OF
64507 taCenter:
64508 dX := (R1.Right - R1.Left - (R.Right - R.Left)) div 2;
64509 taRight:
64510 dX := R1.Right - R.Right;
64511 else
64512 dX := 0;
64513 END;
64514 CASE Ctl.fVerticalAlign OF
64515 vaCenter:
64516 dY := (R1.Bottom - R1.Top - (R.Bottom - R.Top)) div 2;
64517 vaBottom:
64518 dY := R1.Bottom - R.Bottom;
64519 else
64520 dY := 0;
64521 END;
64522 OffsetRect( R, dX, dY );
64524 if Ctl.fEnabled or (Flags and $80000000 <> 0) then
64525 begin
64526 OldBrush := SelectObject( DC, GetStockObject( NULL_BRUSH ) );
64527 Windows.DrawText( DC, PChar( Ctl.Caption ), Length( Ctl.Caption ), R,
64528 Fmt );
64529 SelectObject( DC, OldBrush );
64531 else
64532 begin
64533 GTD.Ctl := Ctl;
64534 GTD.W := R.Right - R.Left;
64535 GTD.H := R.Bottom - R.Top;
64536 GTD.Flags := Flags;
64537 Windows.DrawState( DC, GetStockObject( NULL_BRUSH ), @ DrawTextGrayed,
64538 Integer( @ GTD ), Length( Ctl.fCaption ), R.Left, R.Top, R.Right - R.Left, R.Bottom - R.Top,
64539 DST_COMPLEX or DSS_DISABLED );
64540 end;
64541 if Assigned( ParentHavingFont ) then
64542 SelectObject( DC, OldFont );
64543 end;
64545 { TGraphicControl }
64547 procedure TControl.GraphicLabelPaint(DC: HDC);
64548 var R: TRect;
64549 begin
64550 R := ClientRect;
64551 if not Assigned( OnPrepaint ) then
64552 Canvas.FillRect( R );
64553 if Text <> '' then
64554 DrawFormattedText( @ Self, DC, R, 0 )
64555 end;
64557 procedure TControl.GraphicCheckBoxPaint(DC: HDC);
64558 var R, R1: TRect;
64559 Flag: DWORD;
64560 W, H: Integer;
64561 {$IFDEF GRAPHCTL_XPSTYLES}
64562 Theme: THandle;
64563 {$ENDIF}
64564 begin
64565 R := ClientRect;
64566 if not Assigned( OnPrepaint ) then
64567 Canvas.FillRect( R );
64569 {$IFDEF GRAPHCTL_XPSTYLES}
64570 OpenThemeDataProc;
64571 Theme := 0;
64572 if Assigned( fOpenThemeDataProc ) and not DoNotDrawGraphCtlsUsingXPStyles then
64573 Theme := fOpenThemeDataProc( 0, 'Button' );
64574 if Theme <> 0 then
64575 begin
64577 W := GetSystemMetrics( SM_CXMENUCHECK );
64578 H := GetSystemMetrics( SM_CYMENUCHECK );
64580 R1 := R;
64581 R1.Right := R1.Left + W;
64582 if fWordWrap then
64583 R1.Top := R1.Top + Border
64584 else
64585 R1.Top := R1.Top + (R1.Bottom - R1.Top - H) div 2;
64586 R1.Bottom := R1.Top + H;
64588 Flag := 1; {CBS_UNCHECKEDNORMAL}
64589 if not Enabled then
64590 Flag := 4 {CBS_UNCHECKEDDISABLED}
64591 else
64592 if fHot then
64593 Flag := 2; {CBS_UNCHECKEDHOT}
64594 if fChecked then
64595 Inc( Flag, 4 );
64596 fDrawThemeBackground( Theme, DC, 3 {BP_CHECKBOX}, Flag, @R1, @R );
64598 R.Left := R1.Left + W + Border;
64600 if fCaption <> '' then
64601 begin
64602 DrawFormattedText( @ Self, DC, R, DT_CALCRECT );
64603 if fWordWrap then
64604 begin
64605 DrawFormattedText( @ Self, DC, R, 0 );
64606 GraphCtlDrawFocusRect( DC, R );
64608 else
64609 begin
64610 GraphCtlDrawFocusRect( DC, R );
64611 DrawFormattedTextXP( Theme, @ Self, DC, R, 3 {BP_CHECKBOX}, Flag, 0, 0 );
64612 end;
64613 end;
64615 fCloseThemeData( Theme );
64617 else
64618 {$ENDIF}
64619 begin
64621 W := GetSystemMetrics( SM_CXMENUCHECK );
64622 H := GetSystemMetrics( SM_CYMENUCHECK );
64624 R1 := R;
64625 R1.Right := R1.Left + W;
64626 if fWordWrap then
64627 R1.Top := R1.Top + Border
64628 else
64629 R1.Top := R1.Top + (R1.Bottom - R1.Top - H) div 2;
64630 R1.Bottom := R1.Top + H;
64631 Flag := 0;
64632 if fChecked then
64633 Flag := DFCS_CHECKED;
64634 DrawFrameControl( DC, R1, DFC_BUTTON, DFCS_BUTTONCHECK or DFCS_TRANSPARENT or Flag );
64636 R.Left := R1.Left + W + Border;
64637 DrawFormattedText( @ Self, DC, R, 0 );
64638 GraphCtlDrawFocusRect( DC, R );
64639 end;
64640 end;
64642 procedure TControl.GraphicCheckBoxMouse(var Msg: TMsg);
64643 begin
64644 if (Msg.message = WM_LBUTTONDOWN) or (Msg.message = WM_LBUTTONDBLCLK) then
64645 ClickGraphCheck( @ Self );
64646 end;
64648 procedure TControl.GraphicRadioBoxPaint(DC: HDC);
64649 var R, R1: TRect;
64650 Flag: DWORD;
64651 W, H: Integer;
64652 {$IFDEF GRAPHCTL_XPSTYLES}
64653 Theme: THandle;
64654 {$ENDIF}
64655 begin
64656 R := ClientRect;
64657 if not Assigned( OnPrepaint ) then
64658 Canvas.FillRect( R );
64659 {$IFDEF GRAPHCTL_XPSTYLES}
64660 OpenThemeDataProc;
64661 Theme := 0;
64662 if Assigned( fOpenThemeDataProc ) and not DoNotDrawGraphCtlsUsingXPStyles then
64663 Theme := fOpenThemeDataProc( 0, 'button' );
64664 if Theme <> 0 then
64665 begin
64667 Flag := 1; {CBS_UNCHECKEDNORMAL}
64668 if not Enabled then
64669 Flag := 4 {CBS_UNCHECKEDDISABLED}
64670 else
64671 if fHot then
64672 Flag := 2; {CBS_UNCHECKEDHOT}
64673 if fChecked then
64674 Inc( Flag, 4 );
64676 W := GetSystemMetrics( SM_CXMENUCHECK );
64677 H := GetSystemMetrics( SM_CYMENUCHECK );
64679 R1 := R;
64680 R1.Right := R1.Left + W;
64681 if fWordWrap then
64682 R1.Top := R1.Top + Border
64683 else
64684 R1.Top := R1.Top + (R1.Bottom - R1.Top - H) div 2;
64685 R1.Bottom := R1.Top + H;
64687 fDrawThemeBackground( Theme, DC, 2 {BP_RADIOBOX}, Flag, @R1, @R );
64688 R.Left := R1.Left + W + Border;
64690 if fCaption <> '' then
64691 begin
64692 DrawFormattedText( @ Self, DC, R, DT_CALCRECT );
64693 if fWordWrap then
64694 begin
64695 DrawFormattedText( @ Self, DC, R, 0 );
64696 GraphCtlDrawFocusRect( DC, R );
64698 else
64699 begin
64700 GraphCtlDrawFocusRect( DC, R );
64701 DrawFormattedTextXP( Theme, @ Self, DC, R, 2 {BP_RADIOBOX}, Flag, 0, 0 );
64702 end;
64703 end;
64704 fCloseThemeData( Theme );
64706 else
64707 {$ENDIF}
64708 begin
64709 W := GetSystemMetrics( SM_CXMENUCHECK );
64710 H := GetSystemMetrics( SM_CYMENUCHECK );
64711 R1 := R;
64712 R1.Right := R1.Left + W;
64713 if fWordWrap then
64714 R1.Top := R1.Top + Border
64715 else
64716 R1.Top := R1.Top + (R1.Bottom - R1.Top - H) div 2;
64717 R1.Bottom := R1.Top + H;
64718 Flag := 0;
64719 if fChecked then
64720 Flag := DFCS_CHECKED;
64721 DrawFrameControl( DC, R1, DFC_BUTTON, DFCS_BUTTONRADIO or DFCS_TRANSPARENT
64722 or DFCS_ADJUSTRECT or Flag );
64723 R.Left := R1.Right + 2;
64724 DrawFormattedText( @ Self, DC, R, 0 );
64725 GraphCtlDrawFocusRect( DC, R );
64726 end;
64727 end;
64729 procedure TControl.GraphicButtonPaint(DC: HDC);
64730 var R: TRect;
64731 Flag: DWORD;
64732 {$IFDEF GRAPHCTL_XPSTYLES}
64733 Flag1: DWORD;
64734 Theme: THandle;
64735 {$ENDIF}
64736 II: TIconInfo;
64737 BI: TagBitmap;
64738 Y: Integer;
64739 R1: TRect;
64740 begin
64741 R := ClientRect;
64742 if not Assigned( OnPrepaint ) then
64743 Canvas.FillRect( R );
64744 {$IFDEF GRAPHCTL_XPSTYLES}
64745 OpenThemeDataProc;
64746 Theme := 0;
64747 if Assigned( fOpenThemeDataProc ) and not DoNotDrawGraphCtlsUsingXPStyles then
64748 Theme := fOpenThemeDataProc( 0, 'Button' );
64749 if Theme <> 0 then
64750 begin
64751 Flag := 1; {PBS_UNCHECKEDNORMAL}
64752 if not Enabled then
64753 Flag := 4 {PBS_UNCHECKEDDISABLED}
64754 else
64755 if fPushed then
64756 Flag := 3 {PBS_UNCHECKEDPRESSED}
64757 else
64758 if fHot then
64759 Flag := 2; {PBS_UNCHECKEDHOT}
64760 if fChecked then
64761 Inc( Flag, 4 );
64763 fDrawThemeBackground( Theme, DC, 1 {BP_PUSHBUTTON}, Flag, @R, @R );
64765 fGetThemeBackgroundContentRect( Theme, DC, 1 {BS_PUSHBUTTON}, Flag, @R, @R1 );
64766 GraphCtlDrawFocusRect( DC, R1 );
64768 if (fButtonIcon <> 0) and GetIconInfo( fButtonIcon, II ) then
64769 begin
64770 if GetObject( II.hbmColor, Sizeof( BI ), @ BI ) <> 0 then
64771 begin
64772 CASE fVerticalAlign OF
64773 vaTop:
64774 Y := R.Top + Border;
64775 vaBottom:
64776 Y := R.Bottom - Border - BI.bmHeight;
64777 else //vaCenter:
64778 Y := R.Top + (R.Bottom - R.Top - BI.bmHeight) div 2;
64779 END;
64780 DrawIcon( DC, R.Left + Border, Y, fButtonIcon );
64781 Inc( R1.Left, BI.bmWidth + Border * 2 );
64782 end;
64783 DeleteObject( II.hbmColor );
64784 if II.hbmMask <> 0 then
64785 DeleteObject( II.hbmMask );
64786 end;
64788 if fCaption <> '' then
64789 begin
64790 Flag1 := DT_SINGLELINE;
64791 if WordWrap then
64792 Flag1 := DT_WORDBREAK;
64793 DrawFormattedText( @ Self, DC, R1, DT_CALCRECT );
64794 {CASE fTextAlign OF
64795 taCenter: Flag1 := Flag1 or DT_CENTER;
64796 taRight: Flag1 := Flag1 or DT_RIGHT;
64797 //else Flag1 := Flag1 or DT_LEFT;
64798 END;
64799 CASE fVerticalAlign OF
64800 vaCenter: Flag1 := Flag1 or DT_VCENTER;
64801 vaBottom: Flag1 := Flag1 or DT_BOTTOM;
64802 //else Flag1 := Flag1 or DT_TOP;
64803 END;}
64804 DrawFormattedTextXP( Theme, @ Self, DC, R1, 1 {BP_PUSHBUTTON}, Flag,
64805 Flag1, 0 );
64806 end;
64807 fCloseThemeData( Theme );
64809 else
64810 {$ENDIF}
64811 begin
64812 Flag := 0;
64813 if fChecked then
64814 Flag := DFCS_CHECKED
64815 else
64816 if fPushed then
64817 Flag := DFCS_PUSHED;
64818 if fFlat then
64819 Flag := Flag or DFCS_FLAT;
64820 DrawFrameControl( DC, R, DFC_BUTTON, DFCS_BUTTONPUSH or DFCS_TRANSPARENT or
64821 DFCS_ADJUSTRECT or Flag );
64822 {$IFNDEF GRAPHCTL_XPSTYLES} R1 := R; {$ENDIF}
64824 if (fButtonIcon <> 0) and GetIconInfo( fButtonIcon, II ) then
64825 begin
64826 if GetObject( II.hbmColor, Sizeof( BI ), @ BI ) <> 0 then
64827 begin
64828 CASE fVerticalAlign OF
64829 vaTop:
64830 Y := R.Top + Border;
64831 vaBottom:
64832 Y := R.Bottom - Border - BI.bmHeight;
64833 else //vaCenter:
64834 Y := R.Top + (R.Bottom - R.Top - BI.bmHeight) div 2;
64835 END;
64836 DrawIcon( DC, R.Left + Border, Y, fButtonIcon );
64837 Inc( R1.Left, BI.bmWidth + Border * 2 );
64838 end;
64839 DeleteObject( II.hbmColor );
64840 if II.hbmMask <> 0 then
64841 DeleteObject( II.hbmMask );
64842 end;
64844 DrawFormattedText( @ Self, DC, R1, 0 );
64845 GraphCtlDrawFocusRect( DC, R );
64846 end;
64847 end;
64849 procedure TControl.GraphicButtonMouse(var Msg: TMsg);
64850 var Pt: TPoint;
64851 begin
64852 CASE Msg.message OF
64853 WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:
64854 begin
64855 GraphButtonSetFocus;
64856 RefInc;
64857 SetCapture( Parent.Handle );
64858 Parent.fPushedBtn := @ Self;
64859 fPushed := TRUE;
64860 Invalidate;
64861 end;
64862 WM_LBUTTONUP:
64863 begin
64864 ReleaseCapture;
64865 if fPushed then
64866 begin
64867 Pt.X := SmallInt( LoWord( Msg.lParam ) );
64868 Pt.Y := SmallInt( HiWord( Msg.lParam ) );
64869 if PtInRect( ClientRect, Pt ) then
64870 DoClick;
64871 fPushed := FALSE;
64872 Parent.fPushedBtn := nil;
64873 end;
64874 Invalidate;
64875 RefDec;
64876 end;
64877 END;
64878 end;
64880 procedure TControl.GraphButtonSetFocus;
64881 var PF: PControl;
64882 CC: PControl;
64883 W: HWnd;
64884 begin
64885 if not fTabStop then Exit;
64886 PF := ParentForm;
64887 if (PF.fCurrentControl <> nil) and (PF.fCurrentControl <> @ Self) and
64888 (PF.fCurrentControl <> Parent) then
64889 begin
64890 CC := PF.fCurrentControl;
64891 CC.RefInc;
64892 Parent.Focused := TRUE;
64893 if Assigned( CC.fLeave ) then
64894 CC.fLeave( PF.fCurrentControl )
64895 else
64896 Windows.SetFocus( 0 );
64897 CC.RefDec;
64899 else
64900 begin
64901 W := GetFocus;
64902 if (W <> Parent.fHandle) and (W <> 0) then
64903 begin
64904 Windows.SetFocus( 0 );
64905 Parent.Focused := TRUE;
64906 end;
64907 end;
64908 if Parent.fHandle <> 0 then
64909 begin
64910 fFocused := TRUE;
64911 Parent.Postmsg( CM_FOCUSGRAPHCTL, Integer( @ Self ), 0 );
64912 RefInc;
64913 end;
64914 end;
64916 procedure TControl.LeaveGraphButton( Sender: PObj );
64917 begin
64918 fFocused := FALSE;
64919 if Parent.fCurrentControl = @ Self then
64920 Parent.fCurrentControl := nil;
64921 if ParentForm.fCurrentControl = @ Self then
64922 ParentForm.fCurrentControl := nil;
64923 Invalidate;
64924 end;
64926 function TControl.GraphButtonKeyboardProcess(var Msg: TMsg;
64927 var Rslt: Integer): Boolean;
64928 var SpacePressed: Boolean;
64929 begin
64930 Result := FALSE;
64931 SpacePressed := Msg.wParam = Word( ' ' );
64932 {$IFDEF ALL_BUTTONS_RESPOND_TO_ENTER}
64933 SpacePressed := SpacePressed or (Msg.wParam = 13);
64934 {$ENDIF}
64935 if not SpacePressed then Exit;
64936 if (Msg.message = WM_KEYDOWN) or (Msg.message = WM_SYSKEYDOWN) then
64937 begin
64938 Parent.fPushedBtn := @ Self;
64939 fPushed := TRUE;
64940 Invalidate;
64941 Result := TRUE; /////
64943 else
64944 if (Msg.message = WM_KEYUP) or (Msg.message = WM_SYSKEYUP) then
64945 begin
64946 fPushed := FALSE;
64947 Parent.fPushedBtn := nil;
64948 Invalidate;
64949 Result := TRUE; /////
64951 else
64952 if (Msg.message = WM_CHAR) or (Msg.message = WM_SYSCHAR) then
64953 begin
64954 DoClick;
64955 Result := TRUE;
64956 end;
64957 end;
64959 procedure TControl.GraphicEditPaint(DC: HDC);
64960 var R: TRect;
64961 {$IFDEF GRAPHCTL_XPSTYLES}
64962 R1: TRect;
64963 Flag, Flag1: DWORD;
64964 Theme: THandle;
64965 {$ENDIF}
64966 begin
64967 R := ClientRect;
64968 {$IFDEF GRAPHCTL_XPSTYLES}
64969 OpenThemeDataProc;
64970 Theme := 0;
64971 if Assigned( fOpenThemeDataProc ) and not DoNotDrawGraphCtlsUsingXPStyles then
64972 Theme := fOpenThemeDataProc( 0, 'Edit' );
64973 if Theme <> 0 then
64974 begin
64975 Flag := 1; {ETS_NORMAL}
64976 if not Enabled then
64977 Flag := 4 {ETS_DISABLED}
64978 else
64979 if eoReadonly in fEditOptions then
64980 Flag := 6 {ETS_READONLY}
64981 else
64982 if fFocused then
64983 Flag := 5 {ETS_FOCUSED}
64984 else
64985 if fHot then
64986 Flag := 2; {ETS_HOT}
64988 fDrawThemeBackground( Theme, DC, 1 {EP_EDITTEXT}, Flag, @R, @R );
64990 Inc( R.Left, 2 );
64991 Dec( R.Right, 2 );
64992 fGetThemeBackgroundContentRect( Theme, DC, 1 {EP_EDITTEXT}, Flag, @R, @R1 );
64994 if fCaption <> '' then
64995 begin
64996 Flag1 := DT_SINGLELINE;
64997 if eoMultiline in fEditOptions then
64998 Flag1 := DT_WORDBREAK;
64999 CASE fTextAlign OF
65000 taCenter: Flag1 := Flag1 or DT_CENTER;
65001 taRight: Flag1 := Flag1 or DT_RIGHT;
65002 //else Flag1 := Flag1 or DT_LEFT;
65003 END;
65004 CASE fVerticalAlign OF
65005 vaCenter: Flag1 := Flag1 or DT_VCENTER;
65006 vaBottom: Flag1 := Flag1 or DT_BOTTOM;
65007 //else Flag1 := Flag1 or DT_TOP;
65008 END;
65009 DrawFormattedTextXP( Theme, @ Self, DC, R1, 1 {EP_EDITTEXT}, Flag,
65010 Flag1, 0 );
65011 end;
65012 fCloseThemeData( Theme );
65014 else
65015 {$ENDIF}
65016 begin
65017 if not Assigned( OnPrepaint ) then
65018 begin
65019 Canvas.Brush.Color := fColor;
65020 Canvas.FillRect( R );
65021 end;
65023 DrawEdge( DC, R, BDR_SUNKENINNER or BDR_SUNKENOUTER, BF_ADJUST or BF_RECT );
65025 DrawFormattedText( @ Self, DC, R, DT_EDITCONTROL );
65026 end;
65027 end;
65029 procedure TControl.GraphicEditMouse(var Msg: TMsg);
65030 var E: PControl;
65031 Pt: TPoint;
65032 begin
65033 CASE Msg.message OF
65034 WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:
65035 if not ( eoReadOnly in fEditOptions ) then
65036 begin
65037 E := EditGraphEdit;
65038 Pt.X := Smallint( LoWord( Msg.lParam ) ) - Left;
65039 Pt.Y := Smallint( HiWord( Msg.lParam ) ) - Top;
65040 PostMessage( E.Handle, Msg.message, Msg.wParam,
65041 Pt.Y shl 16 or Pt.X and $FFFF );
65042 end;
65043 END;
65044 end;
65046 function TControl.EditGraphEdit: PControl;
65047 var E: PControl;
65048 begin
65049 E := NewEditBox( Parent, fEditOptions )
65050 .SetPosition( Left, Top )
65051 .SetSize( Width, Height )
65052 .SetAlign( Align );
65053 E.fTabOrder := fTabOrder;
65054 E.Text := Text;
65055 E.OnChange := ChangeGraphEdit;
65056 E.Color := Color;
65057 E.fCursor := fCursor;
65058 E.CreateWindow;
65059 E.OnLeave := LeaveGraphEdit;
65060 E.fLeave := LeaveGraphEdit;
65061 E.Focused := TRUE;
65062 E.OnChar := OnChar;
65063 E.OnKeyDown := OnKeyDown;
65064 E.OnKeyUp := OnKeyUp;
65065 E.OnDestroy := DestroyGraphEdit;
65066 //E.Font.Assign( Font );
65067 Result := E;
65068 Visible := FALSE;
65069 fEditCtl := E;
65070 end;
65072 procedure TControl.LeaveGraphEdit(Sender: PObj);
65073 begin
65074 if PControl( Sender ).fWindowed and Assigned( fEditCtl ) then
65075 begin
65076 Text := PControl( Sender ).Text;
65077 fEditCtl := nil;
65078 Visible := TRUE;
65079 ParentForm.fCurrentControl := @ Self;
65080 Parent.fCurrentControl := @ Self;
65081 Parent.Postmsg( CM_QUIT, DWORD( Sender ), 0 );
65083 else
65084 if Assigned( fEditCtl ) then
65085 begin
65086 fEditCtl.fLeave( fEditCtl );
65087 end;
65088 end;
65090 procedure TControl.ChangeGraphEdit(Sender: PObj);
65091 begin
65092 Text := PControl( Sender ).Text;
65093 end;
65095 procedure TControl.GraphEditboxSetFocus;
65096 begin
65097 EditGraphEdit;
65098 end;
65100 procedure TControl.DestroyGraphEdit(Sender: PObj);
65101 begin
65102 fEditCtl := nil;
65103 end;
65105 procedure TControl.GraphCtlDrawFocusRect(DC: HDC; const R: TRect);
65106 var rgn: HRgn;
65107 begin
65108 if fFocused and (GetActiveWindow = ParentForm.Handle) then
65109 begin
65110 BeginPath( DC );
65111 Canvas.FrameRect( R );
65112 EndPath( DC );
65113 Canvas.FrameRect( R );
65114 DrawFocusRect( DC, R );
65115 rgn := PathToRegion( DC );
65116 ExtSelectClipRgn( DC, rgn, RGN_DIFF );
65117 DeleteObject( rgn );
65118 end;
65119 end;
65121 procedure TControl.GroupBoxPaint(DC: HDC);
65122 var bk_erased: Boolean;
65124 procedure DoEraseBkgnd;
65125 var R: TRect;
65126 begin
65127 bk_erased := TRUE;
65128 if Assigned( OnEraseBkgnd ) then
65129 OnEraseBkgnd( @ Self, DC )
65130 else
65131 begin
65132 R := BoundsRect;
65133 OffsetRect( R, -R.Left, -R.Top );
65134 SetBkMode( DC, OPAQUE );
65135 SetBkColor( DC, Color2RGB( fColor ) );
65136 SetBrushOrgEx( DC, 0, 0, nil );
65137 Windows.FillRect( DC, R, Global_GetCtlBrushHandle( @ Self ) );
65138 end;
65139 end;
65141 var R, R1, R0: TRect;
65142 rgn, rgn2, rgntxt, rgnsav, rgnsavall: HRgn;
65143 i: Integer;
65144 C: PControl;
65145 {$IFDEF GRAPHCTL_XPSTYLES}
65146 Theme: THandle;
65147 Flag: DWORD;
65148 {$ENDIF}
65149 begin
65150 if not fErasingBkgnd then
65151 Exit;
65152 R := ClientRect;
65153 Dec( R.Top, 14 { Self_.fClientTop div 2 } );
65154 Dec( R.Left, fClientLeft );
65155 Inc( R.Right, fClientRight );
65156 Inc( R.Bottom, fClientBottom );
65158 rgnsavall := CreateRectRgn( 0, 0, 0, 0 );
65159 GetClipRgn( DC, rgnsavall );
65163 for i := 0 to ChildCount-1 do
65164 begin
65165 C := Children[ i ];
65166 if not C.fWindowed and C.fVisible then
65167 begin
65168 rgn := CreateRectRgnIndirect( C.BoundsRect );
65169 ExtSelectClipRgn( DC, rgn, RGN_DIFF );
65170 DeleteObject( rgn );
65171 end;
65172 end;
65174 {$IFDEF GRAPHCTL_XPSTYLES}
65176 OpenThemeDataProc;
65177 Theme := 0;
65178 if Assigned( fOpenThemeDataProc ) and not DoNotDrawGraphCtlsUsingXPStyles then
65179 Theme := fOpenThemeDataProc( 0, 'Button' );
65180 if Theme <> 0 then
65181 begin
65182 DoEraseBkgnd;
65184 Flag := 1; {GBS_NORMAL}
65185 if not Enabled then
65186 Flag := 2; {GBS_DISABLED}
65187 R1 := R;
65189 rgnsav := 0;
65190 if fCaption <> '' then
65191 begin
65192 R1.Top := 0;
65193 Inc( R1.Left, 8 );
65194 Dec( R1.Right, 8 );
65195 BeginPath( DC );
65196 DrawFormattedTextXP( Theme, @ Self, DC, R1, 4 {BP_GROUPBOX}, Flag, 0, 0 );
65197 EndPath( DC );
65198 rgntxt := PathToRegion( DC );
65199 if rgntxt = 0 then
65200 begin
65201 R1.Right := R1.Left + Canvas.TextWidth( fCaption );
65202 R1.Bottom := R1.Top + Canvas.TextHeight( fCaption );
65203 rgntxt := CreateRectRgnIndirect( R1 );
65204 end;
65205 DrawFormattedTextXP( Theme, @ Self, DC, R1, 4 {BP_GROUPBOX}, Flag, 0, 0 );
65206 GetRgnBox( rgntxt, R0 );
65207 Dec( R0.Left, 3 );
65208 Inc( R0.Right, 3 );
65209 DeleteObject( rgntxt );
65210 rgn := CreateRectRgnIndirect( R0 );
65212 else
65213 begin
65214 rgn := 0;
65215 end;
65216 if rgn <> 0 then
65217 begin
65218 rgnsav := CreateRectRgn( 0, 0, 0, 0 );
65219 GetClipRgn( DC, rgnsav );
65220 ExtSelectClipRgn( DC, rgn, RGN_DIFF );
65221 DeleteObject( rgn );
65222 end;
65224 fDrawThemeBackground( Theme, DC, 4 {BP_GROUPBOX}, Flag, @R, @R );
65226 if rgnsav <> 0 then
65227 begin
65228 SelectClipRgn( DC, rgnsav );
65229 DeleteObject( rgnsav );
65230 end;
65232 fCloseThemeData( Theme );
65234 else
65235 {$ENDIF}
65236 begin
65237 bk_erased := FALSE;
65239 R1 := R;
65240 R1.Top := 0;
65241 R1.Bottom := ClientRect.Top;
65242 Inc( R1.Left, 16 );
65243 Dec( R1.Right, 16 );
65244 fVerticalAlign := vaCenter;
65245 BeginPath( DC );
65246 Canvas.TextOut( R1.Left, R1.Top, fCaption );
65247 EndPath( DC );
65248 Canvas.TextOut( R1.Left, R1.Top, fCaption );
65249 rgntxt := PathToRegion( DC );
65250 if rgntxt = 0 then // òàêîå - â ñëó÷àå øðèôòà ïî óìîë÷àíèþ!
65251 begin
65252 R1.Right := R1.Left + Canvas.TextWidth( fCaption );
65253 R1.Bottom := R1.Top + Canvas.TextHeight( fCaption );
65254 rgntxt := CreateRectRgnIndirect( R1 );
65255 end;
65257 GetRgnBox( rgntxt, R0 );
65258 rgn2 := CreateRectRgnIndirect( R0 );
65260 rgnsav := CreateRectRgn( 0, 0, 0, 0 );
65261 GetClipRgn( DC, rgnsav );
65262 ExtSelectClipRgn( DC, rgn2, RGN_DIFF );
65263 DeleteObject( rgn2 );
65265 BeginPath( DC );
65266 DrawEdge( DC, R, BDR_RAISEDINNER or BDR_SUNKENOUTER, BF_RECT );
65267 EndPath( DC );
65268 rgn := PathToRegion( DC );
65269 if rgn = 0 then DoEraseBkgnd;
65270 DrawEdge( DC, R, BDR_RAISEDINNER or BDR_SUNKENOUTER, BF_RECT );
65272 SelectClipRgn( DC, rgnsav );
65273 DeleteObject( rgnsav );
65275 if rgn <> 0 then
65276 begin
65277 ExtSelectClipRgn( DC, rgn, RGN_DIFF );
65278 DeleteObject( rgn );
65279 end;
65280 ExtSelectClipRgn( DC, rgntxt, RGN_DIFF );
65281 DeleteObject( rgntxt );
65283 if not bk_erased then DoEraseBkgnd;
65284 end;
65286 FINALLY
65287 SelectClipRgn( DC, rgnsavall );
65288 DeleteObject( rgnsavall );
65289 END;
65290 end;
65292 function TControl.MakeWordWrap: PControl;
65293 begin
65294 fWordWrap := TRUE;
65295 Style := fStyle and not SS_LEFTNOWORDWRAP;
65296 Result := @ Self;
65297 end;
65299 { -- }
65300 {$IFDEF USE_CUSTOMEXTENSIONS}
65301 {$I CUSTOM_CODE_EXTENSION.inc} // See comments in TControl
65302 {$ENDIF USE_CUSTOMEXTENSIONS}
65304 //[initialization]
65306 initialization
65307 //[finalization]
65308 finalization
65309 {$IFDEF UNLOAD_RICHEDITLIB}
65310 if FRichEditModule <> 0 then
65311 FreeLibrary( FRichEditModule );
65312 {$ENDIF UNLOAD_RICHEDITLIB}
65313 {$IFDEF USE_NAMES}
65314 NamedObjectsList.Free;
65315 {$ENDIF}
65317 //[END OF KOL.pas]
65318 end.