Subversion Repositories spacemission

Rev

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.