Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | daniel-mar | 1 | unit DXClass; |
2 | |||
3 | interface |
||
4 | |||
5 | {$INCLUDE DelphiXcfg.inc} |
||
6 | |||
7 | uses |
||
8 | Windows, Messages, SysUtils, Classes, Controls, Forms, MMSystem, DirectX; |
||
9 | |||
10 | type |
||
11 | |||
12 | { EDirectDrawError } |
||
13 | |||
14 | EDirectXError = class(Exception); |
||
15 | |||
16 | { TDirectX } |
||
17 | |||
18 | TDirectX = class(TPersistent) |
||
19 | private |
||
20 | procedure SetDXResult(Value: HRESULT); |
||
21 | protected |
||
22 | FDXResult: HRESULT; |
||
23 | procedure Check; virtual; |
||
24 | public |
||
25 | property DXResult: HRESULT read FDXResult write SetDXResult; |
||
26 | end; |
||
27 | |||
28 | { TDirectXDriver } |
||
29 | |||
30 | TDirectXDriver = class(TCollectionItem) |
||
31 | private |
||
32 | FGUID: PGUID; |
||
33 | FGUID2: TGUID; |
||
34 | FDescription: string; |
||
35 | FDriverName: string; |
||
36 | procedure SetGUID(Value: PGUID); |
||
37 | public |
||
38 | property GUID: PGUID read FGUID write SetGUID; |
||
39 | property Description: string read FDescription write FDescription; |
||
40 | property DriverName: string read FDriverName write FDriverName; |
||
41 | end; |
||
42 | |||
43 | { TDirectXDrivers } |
||
44 | |||
45 | TDirectXDrivers = class(TCollection) |
||
46 | private |
||
47 | function GetDriver(Index: Integer): TDirectXDriver; |
||
48 | public |
||
49 | constructor Create; |
||
50 | property Drivers[Index: Integer]: TDirectXDriver read GetDriver; default; |
||
51 | end; |
||
52 | |||
53 | { TDXForm } |
||
54 | |||
55 | TDXForm = class(TForm) |
||
56 | private |
||
57 | FStoreWindow: Boolean; |
||
58 | FWindowPlacement: TWindowPlacement; |
||
59 | procedure WMSYSCommand(var Msg: TWMSYSCommand); message WM_SYSCOMMAND; |
||
60 | protected |
||
61 | procedure CreateParams(var Params: TCreateParams); override; |
||
62 | public |
||
63 | constructor Create(AOnwer: TComponent); override; |
||
64 | destructor Destroy; override; |
||
65 | procedure RestoreWindow; |
||
66 | procedure StoreWindow; |
||
67 | end; |
||
68 | |||
69 | { TCustomDXTimer } |
||
70 | |||
71 | TDXTimerEvent = procedure(Sender: TObject; LagCount: Integer) of object; |
||
72 | |||
73 | TCustomDXTimer = class(TComponent) |
||
74 | private |
||
75 | FActiveOnly: Boolean; |
||
76 | FEnabled: Boolean; |
||
77 | FFrameRate: Integer; |
||
78 | FInitialized: Boolean; |
||
79 | FInterval: Cardinal; |
||
80 | FInterval2: Cardinal; |
||
81 | FNowFrameRate: Integer; |
||
82 | FOldTime: DWORD; |
||
83 | FOldTime2: DWORD; |
||
84 | FOnActivate: TNotifyEvent; |
||
85 | FOnDeactivate: TNotifyEvent; |
||
86 | FOnTimer: TDXTimerEvent; |
||
87 | procedure AppIdle(Sender: TObject; var Done: Boolean); |
||
88 | function AppProc(var Message: TMessage): Boolean; |
||
89 | procedure Finalize; |
||
90 | procedure Initialize; |
||
91 | procedure Resume; |
||
92 | procedure SetActiveOnly(Value: Boolean); |
||
93 | procedure SetEnabled(Value: Boolean); |
||
94 | procedure SetInterval(Value: Cardinal); |
||
95 | procedure Suspend; |
||
96 | protected |
||
97 | procedure DoActivate; virtual; |
||
98 | procedure DoDeactivate; virtual; |
||
99 | procedure DoTimer(LagCount: Integer); virtual; |
||
100 | procedure Loaded; override; |
||
101 | public |
||
102 | constructor Create(AOwner: TComponent); override; |
||
103 | destructor Destroy; override; |
||
104 | property ActiveOnly: Boolean read FActiveOnly write SetActiveOnly; |
||
105 | property Enabled: Boolean read FEnabled write SetEnabled; |
||
106 | property FrameRate: Integer read FFrameRate; |
||
107 | property Interval: Cardinal read FInterval write SetInterval; |
||
108 | property OnActivate: TNotifyEvent read FOnActivate write FOnActivate; |
||
109 | property OnDeactivate: TNotifyEvent read FOnDeactivate write FOnDeactivate; |
||
110 | property OnTimer: TDXTimerEvent read FOnTimer write FOnTimer; |
||
111 | end; |
||
112 | |||
113 | { TDXTimer } |
||
114 | |||
115 | TDXTimer = class(TCustomDXTimer) |
||
116 | published |
||
117 | property ActiveOnly; |
||
118 | property Enabled; |
||
119 | property Interval; |
||
120 | property OnActivate; |
||
121 | property OnDeactivate; |
||
122 | property OnTimer; |
||
123 | end; |
||
124 | |||
125 | { TControlSubClass } |
||
126 | |||
127 | TControlSubClassProc = procedure(var Message: TMessage; DefWindowProc: TWndMethod) of object; |
||
128 | |||
129 | TControlSubClass = class |
||
130 | private |
||
131 | FControl: TControl; |
||
132 | FDefWindowProc: TWndMethod; |
||
133 | FWindowProc: TControlSubClassProc; |
||
134 | procedure WndProc(var Message: TMessage); |
||
135 | public |
||
136 | constructor Create(Control: TControl; WindowProc: TControlSubClassProc); |
||
137 | destructor Destroy; override; |
||
138 | end; |
||
139 | |||
140 | { THashCollectionItem } |
||
141 | |||
142 | THashCollectionItem = class(TCollectionItem) |
||
143 | private |
||
144 | FHashCode: Integer; |
||
145 | FIndex: Integer; |
||
146 | FName: string; |
||
147 | FLeft: THashCollectionItem; |
||
148 | FRight: THashCollectionItem; |
||
149 | procedure SetName(const Value: string); |
||
150 | procedure AddHash; |
||
151 | procedure DeleteHash; |
||
152 | protected |
||
153 | function GetDisplayName: string; override; |
||
154 | procedure SetIndex(Value: Integer); override; |
||
155 | public |
||
156 | constructor Create(Collection: TCollection); override; |
||
157 | destructor Destroy; override; |
||
158 | procedure Assign(Source: TPersistent); override; |
||
159 | property Index: Integer read FIndex write SetIndex; |
||
160 | published |
||
161 | property Name: string read FName write SetName; |
||
162 | end; |
||
163 | |||
164 | { THashCollection } |
||
165 | |||
166 | THashCollection = class(TCollection) |
||
167 | private |
||
168 | FHash: array[0..255] of THashCollectionItem; |
||
169 | public |
||
170 | function IndexOf(const Name: string): Integer; |
||
171 | end; |
||
172 | |||
173 | function Max(Val1, Val2: Integer): Integer; |
||
174 | function Min(Val1, Val2: Integer): Integer; |
||
175 | |||
176 | function Cos256(i: Integer): Double; |
||
177 | function Sin256(i: Integer): Double; |
||
178 | |||
179 | function PointInRect(const Point: TPoint; const Rect: TRect): Boolean; |
||
180 | function RectInRect(const Rect1, Rect2: TRect): Boolean; |
||
181 | function OverlapRect(const Rect1, Rect2: TRect): Boolean; |
||
182 | |||
183 | function WideRect(ALeft, ATop, AWidth, AHeight: Integer): TRect; |
||
184 | procedure ReleaseCom(out Com); |
||
185 | function DXLoadLibrary(const FileName, FuncName: string): TFarProc; |
||
186 | |||
187 | implementation |
||
188 | |||
189 | uses DXConsts; |
||
190 | |||
191 | function Max(Val1, Val2: Integer): Integer; |
||
192 | begin |
||
193 | if Val1>=Val2 then Result := Val1 else Result := Val2; |
||
194 | end; |
||
195 | |||
196 | function Min(Val1, Val2: Integer): Integer; |
||
197 | begin |
||
198 | if Val1<=Val2 then Result := Val1 else Result := Val2; |
||
199 | end; |
||
200 | |||
201 | function PointInRect(const Point: TPoint; const Rect: TRect): Boolean; |
||
202 | begin |
||
203 | Result := (Point.X >= Rect.Left) and |
||
204 | (Point.X <= Rect.Right) and |
||
205 | (Point.Y >= Rect.Top) and |
||
206 | (Point.Y <= Rect.Bottom); |
||
207 | end; |
||
208 | |||
209 | function RectInRect(const Rect1, Rect2: TRect): Boolean; |
||
210 | begin |
||
211 | Result := (Rect1.Left >= Rect2.Left) and |
||
212 | (Rect1.Right <= Rect2.Right) and |
||
213 | (Rect1.Top >= Rect2.Top) and |
||
214 | (Rect1.Bottom <= Rect2.Bottom); |
||
215 | end; |
||
216 | |||
217 | function OverlapRect(const Rect1, Rect2: TRect): Boolean; |
||
218 | begin |
||
219 | Result := (Rect1.Left < Rect2.Right) and |
||
220 | (Rect1.Right > Rect2.Left) and |
||
221 | (Rect1.Top < Rect2.Bottom) and |
||
222 | (Rect1.Bottom > Rect2.Top); |
||
223 | end; |
||
224 | |||
225 | function WideRect(ALeft, ATop, AWidth, AHeight: Integer): TRect; |
||
226 | begin |
||
227 | with Result do |
||
228 | begin |
||
229 | Left := ALeft; |
||
230 | Top := ATop; |
||
231 | Right := ALeft+AWidth; |
||
232 | Bottom := ATop+AHeight; |
||
233 | end; |
||
234 | end; |
||
235 | |||
236 | var |
||
237 | CosinTable: array[0..255] of Double; |
||
238 | |||
239 | procedure InitCosinTable; |
||
240 | var |
||
241 | i: Integer; |
||
242 | begin |
||
243 | for i:=0 to 255 do |
||
244 | CosinTable[i] := Cos((i/256)*2*PI); |
||
245 | end; |
||
246 | |||
247 | function Cos256(i: Integer): Double; |
||
248 | begin |
||
249 | Result := CosinTable[i and 255]; |
||
250 | end; |
||
251 | |||
252 | function Sin256(i: Integer): Double; |
||
253 | begin |
||
254 | Result := CosinTable[(i+192) and 255]; |
||
255 | end; |
||
256 | |||
257 | procedure ReleaseCom(out Com); |
||
258 | begin |
||
259 | end; |
||
260 | |||
261 | var |
||
262 | LibList: TStringList; |
||
263 | |||
264 | function DXLoadLibrary(const FileName, FuncName: string): Pointer; |
||
265 | var |
||
266 | i: Integer; |
||
267 | h: THandle; |
||
268 | begin |
||
269 | if LibList=nil then |
||
270 | LibList := TStringList.Create; |
||
271 | |||
272 | i := LibList.IndexOf(AnsiLowerCase(FileName)); |
||
273 | if i=-1 then |
||
274 | begin |
||
275 | { DLL is loaded. } |
||
276 | h := LoadLibrary(PChar(FileName)); |
||
277 | if h=0 then |
||
278 | raise Exception.CreateFmt(SDLLNotLoaded, [FileName]); |
||
279 | LibList.AddObject(AnsiLowerCase(FileName), Pointer(h)); |
||
280 | end else |
||
281 | begin |
||
282 | { DLL has already been loaded. } |
||
283 | h := THandle(LibList.Objects[i]); |
||
284 | end; |
||
285 | |||
286 | Result := GetProcAddress(h, PChar(FuncName)); |
||
287 | if Result=nil then |
||
288 | raise Exception.CreateFmt(SDLLNotLoaded, [FileName]); |
||
289 | end; |
||
290 | |||
291 | procedure FreeLibList; |
||
292 | var |
||
293 | i: Integer; |
||
294 | begin |
||
295 | if LibList<>nil then |
||
296 | begin |
||
297 | for i:=0 to LibList.Count-1 do |
||
298 | FreeLibrary(THandle(LibList.Objects[i])); |
||
299 | LibList.Free; |
||
300 | end; |
||
301 | end; |
||
302 | |||
303 | { TDirectX } |
||
304 | |||
305 | procedure TDirectX.Check; |
||
306 | begin |
||
307 | end; |
||
308 | |||
309 | procedure TDirectX.SetDXResult(Value: HRESULT); |
||
310 | begin |
||
311 | FDXResult := Value; |
||
312 | if FDXResult<>0 then Check; |
||
313 | end; |
||
314 | |||
315 | { TDirectXDriver } |
||
316 | |||
317 | procedure TDirectXDriver.SetGUID(Value: PGUID); |
||
318 | begin |
||
319 | if not IsBadHugeReadPtr(Value, SizeOf(TGUID)) then |
||
320 | begin |
||
321 | FGUID2 := Value^; |
||
322 | FGUID := @FGUID2; |
||
323 | end else |
||
324 | FGUID := Value; |
||
325 | end; |
||
326 | |||
327 | { TDirectXDrivers } |
||
328 | |||
329 | constructor TDirectXDrivers.Create; |
||
330 | begin |
||
331 | inherited Create(TDirectXDriver); |
||
332 | end; |
||
333 | |||
334 | function TDirectXDrivers.GetDriver(Index: Integer): TDirectXDriver; |
||
335 | begin |
||
336 | Result := (inherited Items[Index]) as TDirectXDriver; |
||
337 | end; |
||
338 | |||
339 | { TDXForm } |
||
340 | |||
341 | var |
||
342 | SetAppExStyleCount: Integer; |
||
343 | |||
344 | constructor TDXForm.Create(AOnwer: TComponent); |
||
345 | var |
||
346 | ExStyle: Integer; |
||
347 | begin |
||
348 | inherited Create(AOnwer); |
||
349 | Inc(SetAppExStyleCount); |
||
350 | ExStyle := GetWindowLong(Application.Handle, GWL_EXSTYLE); |
||
351 | ExStyle := ExStyle or WS_EX_TOOLWINDOW; |
||
352 | SetWindowLong(Application.Handle, GWL_EXSTYLE, ExStyle); |
||
353 | end; |
||
354 | |||
355 | destructor TDXForm.Destroy; |
||
356 | var |
||
357 | ExStyle: Integer; |
||
358 | begin |
||
359 | Dec(SetAppExStyleCount); |
||
360 | if SetAppExStyleCount=0 then |
||
361 | begin |
||
362 | ExStyle := GetWindowLong(Application.Handle, GWL_EXSTYLE); |
||
363 | ExStyle := ExStyle and (not WS_EX_TOOLWINDOW); |
||
364 | SetWindowLong(Application.Handle, GWL_EXSTYLE, ExStyle); |
||
365 | end; |
||
366 | inherited Destroy; |
||
367 | end; |
||
368 | |||
369 | procedure TDXForm.CreateParams(var Params: TCreateParams); |
||
370 | begin |
||
371 | inherited CreateParams(Params); |
||
372 | Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW; |
||
373 | end; |
||
374 | |||
375 | procedure TDXForm.RestoreWindow; |
||
376 | begin |
||
377 | if FStoreWindow then |
||
378 | begin |
||
379 | SetWindowPlacement(Handle, @FWindowPlacement); |
||
380 | FStoreWindow := False; |
||
381 | end; |
||
382 | end; |
||
383 | |||
384 | procedure TDXForm.StoreWindow; |
||
385 | begin |
||
386 | FWindowPlacement.Length := SizeOf(FWindowPlacement); |
||
387 | FStoreWindow := GetWindowPlacement(Handle, @FWindowPlacement); |
||
388 | end; |
||
389 | |||
390 | procedure TDXForm.WMSYSCommand(var Msg: TWMSYSCommand); |
||
391 | begin |
||
392 | if Msg.CmdType = SC_MINIMIZE then |
||
393 | begin |
||
394 | DefaultHandler(Msg); |
||
395 | WindowState := wsMinimized; |
||
396 | end else |
||
397 | inherited; |
||
398 | end; |
||
399 | |||
400 | { TCustomDXTimer } |
||
401 | |||
402 | constructor TCustomDXTimer.Create(AOwner: TComponent); |
||
403 | begin |
||
404 | inherited Create(AOwner); |
||
405 | FActiveOnly := True; |
||
406 | FEnabled := True; |
||
407 | Interval := 1000; |
||
408 | Application.HookMainWindow(AppProc); |
||
409 | end; |
||
410 | |||
411 | destructor TCustomDXTimer.Destroy; |
||
412 | begin |
||
413 | Finalize; |
||
414 | Application.UnHookMainWindow(AppProc); |
||
415 | inherited Destroy; |
||
416 | end; |
||
417 | |||
418 | procedure TCustomDXTimer.AppIdle(Sender: TObject; var Done: Boolean); |
||
419 | var |
||
420 | t, t2: DWORD; |
||
421 | LagCount, i: Integer; |
||
422 | begin |
||
423 | Done := False; |
||
424 | |||
425 | t := TimeGetTime; |
||
426 | t2 := t-FOldTime; |
||
427 | if t2>=FInterval then |
||
428 | begin |
||
429 | FOldTime := t; |
||
430 | |||
431 | LagCount := t2 div FInterval2; |
||
432 | if LagCount<1 then LagCount := 1; |
||
433 | |||
434 | Inc(FNowFrameRate); |
||
435 | |||
436 | i := Max(t-FOldTime2, 1); |
||
437 | if i>=1000 then |
||
438 | begin |
||
439 | FFrameRate := Round(FNowFrameRate*1000/i); |
||
440 | FNowFrameRate := 0; |
||
441 | FOldTime2 := t; |
||
442 | end; |
||
443 | |||
444 | DoTimer(LagCount); |
||
445 | end; |
||
446 | end; |
||
447 | |||
448 | function TCustomDXTimer.AppProc(var Message: TMessage): Boolean; |
||
449 | begin |
||
450 | Result := False; |
||
451 | case Message.Msg of |
||
452 | CM_ACTIVATE: |
||
453 | begin |
||
454 | DoActivate; |
||
455 | if FInitialized and FActiveOnly then Resume; |
||
456 | end; |
||
457 | CM_DEACTIVATE: |
||
458 | begin |
||
459 | DoDeactivate; |
||
460 | if FInitialized and FActiveOnly then Suspend; |
||
461 | end; |
||
462 | end; |
||
463 | end; |
||
464 | |||
465 | procedure TCustomDXTimer.DoActivate; |
||
466 | begin |
||
467 | if Assigned(FOnActivate) then FOnActivate(Self); |
||
468 | end; |
||
469 | |||
470 | procedure TCustomDXTimer.DoDeactivate; |
||
471 | begin |
||
472 | if Assigned(FOnDeactivate) then FOnDeactivate(Self); |
||
473 | end; |
||
474 | |||
475 | procedure TCustomDXTimer.DoTimer(LagCount: Integer); |
||
476 | begin |
||
477 | if Assigned(FOnTimer) then FOnTimer(Self, LagCount); |
||
478 | end; |
||
479 | |||
480 | procedure TCustomDXTimer.Finalize; |
||
481 | begin |
||
482 | if FInitialized then |
||
483 | begin |
||
484 | Suspend; |
||
485 | FInitialized := False; |
||
486 | end; |
||
487 | end; |
||
488 | |||
489 | procedure TCustomDXTimer.Initialize; |
||
490 | begin |
||
491 | Finalize; |
||
492 | |||
493 | if ActiveOnly then |
||
494 | begin |
||
495 | if Application.Active then |
||
496 | Resume; |
||
497 | end else |
||
498 | Resume; |
||
499 | FInitialized := True; |
||
500 | end; |
||
501 | |||
502 | procedure TCustomDXTimer.Loaded; |
||
503 | begin |
||
504 | inherited Loaded; |
||
505 | if (not (csDesigning in ComponentState)) and FEnabled then |
||
506 | Initialize; |
||
507 | end; |
||
508 | |||
509 | procedure TCustomDXTimer.Resume; |
||
510 | begin |
||
511 | FOldTime := TimeGetTime; |
||
512 | FOldTime2 := TimeGetTime; |
||
513 | Application.OnIdle := AppIdle; |
||
514 | end; |
||
515 | |||
516 | procedure TCustomDXTimer.SetActiveOnly(Value: Boolean); |
||
517 | begin |
||
518 | if FActiveOnly<>Value then |
||
519 | begin |
||
520 | FActiveOnly := Value; |
||
521 | |||
522 | if Application.Active and FActiveOnly then |
||
523 | if FInitialized and FActiveOnly then Suspend; |
||
524 | end; |
||
525 | end; |
||
526 | |||
527 | procedure TCustomDXTimer.SetEnabled(Value: Boolean); |
||
528 | begin |
||
529 | if FEnabled<>Value then |
||
530 | begin |
||
531 | FEnabled := Value; |
||
532 | if ComponentState*[csReading, csLoading]=[] then |
||
533 | if FEnabled then Initialize else Finalize; |
||
534 | end; |
||
535 | end; |
||
536 | |||
537 | procedure TCustomDXTimer.SetInterval(Value: Cardinal); |
||
538 | begin |
||
539 | if FInterval<>Value then |
||
540 | begin |
||
541 | FInterval := Max(Value, 0); |
||
542 | FInterval2 := Max(Value, 1); |
||
543 | end; |
||
544 | end; |
||
545 | |||
546 | procedure TCustomDXTimer.Suspend; |
||
547 | begin |
||
548 | Application.OnIdle := nil; |
||
549 | end; |
||
550 | |||
551 | { TControlSubClass } |
||
552 | |||
553 | constructor TControlSubClass.Create(Control: TControl; |
||
554 | WindowProc: TControlSubClassProc); |
||
555 | begin |
||
556 | inherited Create; |
||
557 | FControl := Control; |
||
558 | FDefWindowProc := FControl.WindowProc; |
||
559 | FControl.WindowProc := WndProc; |
||
560 | FWindowProc := WindowProc; |
||
561 | end; |
||
562 | |||
563 | destructor TControlSubClass.Destroy; |
||
564 | begin |
||
565 | FControl.WindowProc := FDefWindowProc; |
||
566 | inherited Destroy; |
||
567 | end; |
||
568 | |||
569 | procedure TControlSubClass.WndProc(var Message: TMessage); |
||
570 | begin |
||
571 | FWindowProc(Message, FDefWindowProc); |
||
572 | end; |
||
573 | |||
574 | { THashCollectionItem } |
||
575 | |||
576 | function MakeHashCode(const Str: string): Integer; |
||
577 | var |
||
578 | s: string; |
||
579 | begin |
||
580 | s := AnsiLowerCase(Str); |
||
581 | Result := Length(s)*16; |
||
582 | if Length(s)>=2 then |
||
583 | Result := Result + (Ord(s[1]) + Ord(s[Length(s)-1])); |
||
584 | Result := Result and 255; |
||
585 | end; |
||
586 | |||
587 | constructor THashCollectionItem.Create(Collection: TCollection); |
||
588 | begin |
||
589 | inherited Create(Collection); |
||
590 | FIndex := inherited Index; |
||
591 | AddHash; |
||
592 | end; |
||
593 | |||
594 | destructor THashCollectionItem.Destroy; |
||
595 | var |
||
596 | i: Integer; |
||
597 | begin |
||
598 | for i:=FIndex+1 to Collection.Count-1 do |
||
599 | Dec(THashCollectionItem(Collection.Items[i]).FIndex); |
||
600 | DeleteHash; |
||
601 | inherited Destroy; |
||
602 | end; |
||
603 | |||
604 | procedure THashCollectionItem.Assign(Source: TPersistent); |
||
605 | begin |
||
606 | if Source is THashCollectionItem then |
||
607 | begin |
||
608 | Name := THashCollectionItem(Source).Name; |
||
609 | end else |
||
610 | inherited Assign(Source); |
||
611 | end; |
||
612 | |||
613 | procedure THashCollectionItem.AddHash; |
||
614 | var |
||
615 | Item: THashCollectionItem; |
||
616 | begin |
||
617 | FHashCode := MakeHashCode(FName); |
||
618 | |||
619 | Item := THashCollection(Collection).FHash[FHashCode]; |
||
620 | if Item<>nil then |
||
621 | begin |
||
622 | Item.FLeft := Self; |
||
623 | Self.FRight := Item; |
||
624 | end; |
||
625 | |||
626 | THashCollection(Collection).FHash[FHashCode] := Self; |
||
627 | end; |
||
628 | |||
629 | procedure THashCollectionItem.DeleteHash; |
||
630 | begin |
||
631 | if FLeft<>nil then |
||
632 | begin |
||
633 | FLeft.FRight := FRight; |
||
634 | if FRight<>nil then |
||
635 | FRight.FLeft := FLeft; |
||
636 | end else |
||
637 | begin |
||
638 | if FHashCode<>-1 then |
||
639 | begin |
||
640 | THashCollection(Collection).FHash[FHashCode] := FRight; |
||
641 | if FRight<>nil then |
||
642 | FRight.FLeft := nil; |
||
643 | end; |
||
644 | end; |
||
645 | FLeft := nil; |
||
646 | FRight := nil; |
||
647 | end; |
||
648 | |||
649 | function THashCollectionItem.GetDisplayName: string; |
||
650 | begin |
||
651 | Result := Name; |
||
652 | if Result='' then Result := inherited GetDisplayName; |
||
653 | end; |
||
654 | |||
655 | procedure THashCollectionItem.SetIndex(Value: Integer); |
||
656 | begin |
||
657 | if FIndex<>Value then |
||
658 | begin |
||
659 | FIndex := Value; |
||
660 | inherited SetIndex(Value); |
||
661 | end; |
||
662 | end; |
||
663 | |||
664 | procedure THashCollectionItem.SetName(const Value: string); |
||
665 | begin |
||
666 | if FName<>Value then |
||
667 | begin |
||
668 | FName := Value; |
||
669 | DeleteHash; |
||
670 | AddHash; |
||
671 | end; |
||
672 | end; |
||
673 | |||
674 | { THashCollection } |
||
675 | |||
676 | function THashCollection.IndexOf(const Name: string): Integer; |
||
677 | var |
||
678 | Item: THashCollectionItem; |
||
679 | begin |
||
680 | Item := FHash[MakeHashCode(Name)]; |
||
681 | while Item<>nil do |
||
682 | begin |
||
683 | if AnsiCompareText(Item.Name, Name)=0 then |
||
684 | begin |
||
685 | Result := Item.FIndex; |
||
686 | Exit; |
||
687 | end; |
||
688 | Item := Item.FRight; |
||
689 | end; |
||
690 | Result := -1; |
||
691 | end; |
||
692 | |||
693 | initialization |
||
694 | InitCosinTable; |
||
695 | finalization |
||
696 | FreeLibList; |
||
697 | end. |