AsphyreMouse.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:11k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit AsphyreMouse;
  2. //---------------------------------------------------------------------------
  3. // AsphyreMouse.pas                                     Modified: 28-Jan-2007
  4. // Mouse DirectInput wrapper for Asphyre                         Version 1.04
  5. //---------------------------------------------------------------------------
  6. // Important Notice:
  7. //
  8. // If you modify/use this code or one of its parts either in original or
  9. // modified form, you must comply with Mozilla Public License v1.1,
  10. // specifically section 3, "Distribution Obligations". Failure to do so will
  11. // result in the license breach, which will be resolved in the court.
  12. // Remember that violating author's rights is considered a serious crime in
  13. // many countries. Thank you!
  14. //
  15. // !! Please *read* Mozilla Public License 1.1 document located at:
  16. //  http://www.mozilla.org/MPL/
  17. //
  18. // If you require any clarifications about the license, feel free to contact
  19. // us or post your question on our forums at: http://www.afterwarp.net
  20. //---------------------------------------------------------------------------
  21. // The contents of this file are subject to the Mozilla Public License
  22. // Version 1.1 (the "License"); you may not use this file except in
  23. // compliance with the License. You may obtain a copy of the License at
  24. // http://www.mozilla.org/MPL/
  25. //
  26. // Software distributed under the License is distributed on an "AS IS"
  27. // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  28. // License for the specific language governing rights and limitations
  29. // under the License.
  30. //
  31. // The Original Code is AsphyreMouse.pas.
  32. //
  33. // The Initial Developer of the Original Code is M. Sc. Yuriy Kotsarenko.
  34. // Portions created by M. Sc. Yuriy Kotsarenko are Copyright (C) 2007,
  35. // Afterwarp Interactive. All Rights Reserved.
  36. //---------------------------------------------------------------------------
  37. interface
  38. //---------------------------------------------------------------------------
  39. uses
  40.  Windows, DirectInput, AsphyreAsserts;
  41. //---------------------------------------------------------------------------
  42. type
  43.  TAsphyreMouse = class
  44.  private
  45.   FOwnerInput : TObject;
  46.   FInputDevice: IDirectInputDevice8;
  47.   FInitialized: Boolean;
  48.   FForeground : Boolean;
  49.   FBufferSize : Integer;
  50.   FDeltaWheel : Integer;
  51.   FExclusive  : Boolean;
  52.   FDeltaX: Integer;
  53.   FDeltaY: Integer;
  54.   MEvent : THandle;
  55.   FStationaryBuffers: Boolean;
  56.   procedure SetForeground(const Value: Boolean);
  57.   procedure SetExclusive(const Value: Boolean);
  58.   procedure SetBufferSize(const Value: Integer);
  59.   function GetPressed(Button: Integer): Boolean;
  60.   function GetReleased(Button: Integer): Boolean;
  61.  protected
  62.   BufClick  : array[0..7] of Integer;
  63.   BufRelease: array[0..7] of Integer;
  64.   procedure ResetButtonState(); virtual;
  65.  public
  66.   // A reference to owner of this component; it must be TAsphyreInput.
  67.   property OwnerInput: TObject read FOwnerInput;
  68.   // Interface to DirectInput 8 device.
  69.   property InputDevice: IDirectInputDevice8 read FInputDevice;
  70.   // Indicates whether the component has been initialized properly.
  71.   property Initialized: Boolean read FInitialized;
  72.   // This indicates whether the component should have mouse acquired
  73.   // even when the application has no focus.
  74.   property Foreground: Boolean read FForeground write SetForeground;
  75.   // The buffer where mouse events are cached.
  76.   property BufferSize: Integer read FBufferSize write SetBufferSize;
  77.   // This property determines whether the mouse is to be dedicated
  78.   // exclusively to the application.
  79.   property Exclusive: Boolean read FExclusive write SetExclusive;
  80.   // Determines whether the values stored in buffers are preserved
  81.   // throughout Update() calls.
  82.   property StationaryBuffers: Boolean read FStationaryBuffers
  83.    write FStationaryBuffers;
  84.   // Mouse displacement information
  85.   property DeltaX: Integer read FDeltaX;
  86.   property DeltaY: Integer read FDeltaY;
  87.   property DeltaWheel: Integer read FDeltaWheel;
  88.   // Mouse button status
  89.   property Pressed[Button: Integer]: Boolean read GetPressed;
  90.   property Released[Button: Integer]: Boolean read GetReleased;
  91.   function Initialize(): Boolean;
  92.   procedure Finalize();
  93.   function Update(): Boolean;
  94.   constructor Create(AOwnerInput: TObject);
  95.   destructor Destroy(); override;
  96.  end;
  97. //---------------------------------------------------------------------------
  98. implementation
  99. //---------------------------------------------------------------------------
  100. uses
  101.  AsphyreInputs;
  102. //---------------------------------------------------------------------------
  103. constructor TAsphyreMouse.Create(AOwnerInput: TObject);
  104. begin
  105.  inherited Create();
  106.  FOwnerInput:= AOwnerInput;
  107.  Assert((FOwnerInput <> nil)and(FOwnerInput is TAsphyreInput), msgNoOwnerInput);
  108.  FInitialized:= False;
  109.  FForeground := True;
  110.  FBufferSize := 512;
  111.  FExclusive  := True;
  112.  FDeltaWheel := 0;
  113.  FDeltaX:= 0;
  114.  FDeltaY:= 0;
  115.  FStationaryBuffers:= False;
  116. end;
  117. //---------------------------------------------------------------------------
  118. destructor TAsphyreMouse.Destroy();
  119. begin
  120.  if (FInitialized) then Finalize();
  121.  inherited;
  122. end;
  123. //---------------------------------------------------------------------------
  124. procedure TAsphyreMouse.SetForeground(const Value: Boolean);
  125. begin
  126.  if (not FInitialized) then FForeground:= Value;
  127. end;
  128. //---------------------------------------------------------------------------
  129. procedure TAsphyreMouse.SetBufferSize(const Value: Integer);
  130. begin
  131.  if (not FInitialized) then FBufferSize:= Value;
  132. end;
  133. //---------------------------------------------------------------------------
  134. procedure TAsphyreMouse.SetExclusive(const Value: Boolean);
  135. begin
  136.  if (not FInitialized) then FExclusive:= Value;
  137. end;
  138. //---------------------------------------------------------------------------
  139. procedure TAsphyreMouse.ResetButtonState();
  140. var
  141.  i: Integer;
  142. begin
  143.  for i:= Low(BufClick) to High(BufClick) do
  144.   begin
  145.    BufClick[i]  := 0;
  146.    BufRelease[i]:= 0;
  147.   end;
  148. end;
  149. //---------------------------------------------------------------------------
  150. function TAsphyreMouse.Initialize(): Boolean;
  151. var
  152.  Input : TAsphyreInput;
  153.  DIProp: TDIPropDWord;
  154.  Flags : Cardinal;
  155. begin
  156.  Assert(not FInitialized, msgAlreadyInitialized);
  157.  // (1) Acquire a valid TAsphyreInput reference.
  158.  Input:= TAsphyreInput(FOwnerInput);
  159.  // (2) Make sure that TAsphyreInput is also initialized
  160.  if (not Input.Initialized) then
  161.   begin
  162.    Result:= Input.Initialize();
  163.    if (not Result) then Exit;
  164.   end;
  165.  // (3) Create Mouse DirectInput device.
  166.  Result:= Succeeded(Input.DirectInput8.CreateDevice(GUID_SysMouse,
  167.   FInputDevice, nil));
  168.  if (not Result) then Exit;
  169.  // (4) Set Keyboard data format.
  170.  Result:= Succeeded(FInputDevice.SetDataFormat(c_dfDIMouse));
  171.  if (not Result) then
  172.   begin
  173.    FInputDevice:= nil;
  174.    Exit;
  175.   end;
  176.  // (5) Define device flags.
  177.  Flags:= DISCL_FOREGROUND;
  178.  if (not FForeground) then Flags:= DISCL_BACKGROUND;
  179.  if (FExclusive) then Flags:= Flags or DISCL_EXCLUSIVE
  180.   else Flags:= Flags or DISCL_NONEXCLUSIVE;
  181.  // (6) Set cooperative level.
  182.  Result:= Succeeded(FInputDevice.SetCooperativeLevel(Input.WindowHandle,
  183.   Flags));
  184.  if (not Result) then
  185.   begin
  186.    FInputDevice:= nil;
  187.    Exit;
  188.   end;
  189.  // (7) Create a new event.
  190.  MEvent:= CreateEvent(nil, False, False, nil);
  191.  if (MEvent = 0) then
  192.   begin
  193.    FInputDevice:= nil;
  194.    Result:= False;
  195.    Exit;
  196.   end;
  197.  // (8) Set the recently created event for mouse notifications.
  198.  Result:= Succeeded(FInputDevice.SetEventNotification(MEvent));
  199.  if (not Result) then
  200.   begin
  201.    FInputDevice:= nil;
  202.    Exit;
  203.   end;
  204.  // (9) Setup property info for mouse buffer size.
  205.  FillChar(DIProp, SizeOf(DIProp), 0);
  206.  with DIProp do
  207.   begin
  208.    diph.dwSize:= SizeOf(TDIPropDWord);
  209.    diph.dwHeaderSize:= SizeOf(TDIPropHeader);
  210.    diph.dwObj:= 0;
  211.    diph.dwHow:= DIPH_DEVICE;
  212.    dwData:= FBufferSize;
  213.   end;
  214.  // (10) Update mouse buffer size.
  215.  Result:= Succeeded(FInputDevice.SetProperty(DIPROP_BUFFERSIZE, DIProp.diph));
  216.  if (not Result) then
  217.   begin
  218.    FInputDevice:= nil;
  219.    Exit;
  220.   end;
  221.  ResetButtonState();
  222.  FInitialized:= True;
  223. end;
  224. //---------------------------------------------------------------------------
  225. procedure TAsphyreMouse.Finalize();
  226. begin
  227.  if (FInputDevice <> nil) then
  228.   begin
  229.    FInputDevice.Unacquire();
  230.    FInputDevice:= nil;
  231.   end;
  232.  FInitialized:= False;
  233. end;
  234. //---------------------------------------------------------------------------
  235. function TAsphyreMouse.Update(): Boolean;
  236. var
  237.  Res: Integer;
  238.  EvCount: Cardinal;
  239.  ObjData: TDIDeviceObjectData;
  240.  EvClick: Integer;
  241.  BtnIndx: Integer;
  242.  EvRelease: Integer;
  243. begin
  244.  Result:= True;
  245.  // (1) Make sure the component is initialized.
  246.  if (not FInitialized) then
  247.   begin
  248.    Result:= Initialize();
  249.    if (not Result) then Exit;
  250.   end;
  251.  FDeltaX:= 0;
  252.  FDeltaY:= 0;
  253.  FDeltaWheel:= 0;
  254.  if (not FStationaryBuffers) then ResetButtonState();
  255.  repeat
  256.   EvCount:= 1;
  257.   // (2) Retreive Mouse Data.
  258.   Res:= FInputDevice.GetDeviceData(SizeOf(TDIDeviceObjectData), @ObjData,
  259.    EvCount, 0);
  260.   if (Res <> DI_OK)and(Res <> DI_BUFFEROVERFLOW) then
  261.    begin
  262.     if (Res <> DIERR_INPUTLOST)and(Res <> DIERR_NOTACQUIRED) then
  263.      begin
  264.       Result:= False;
  265.       Exit;
  266.      end;
  267.     // -> attempt acquiring mouse
  268.     Res:= FInputDevice.Acquire();
  269.     if (Res = DI_OK) then
  270.      begin
  271.       // acquired successfully, attempt retreiving data again
  272.       Res:= FInputDevice.GetDeviceData(SizeOf(TDIDeviceObjectData), @ObjData,
  273.        EvCount, 0);
  274.       if (Res <> DI_OK)and(Res <> DI_BUFFEROVERFLOW) then
  275.        begin
  276.         Result:= False;
  277.         Exit;
  278.        end;
  279.      end else
  280.      begin
  281.       Result:= False;
  282.       Exit;
  283.      end;
  284.    end; // if (Res <> DI_OK)
  285.   // (3) Verify if there's anything in mouse buffer.
  286.   if (EvCount < 1) then Break;
  287.   // (4) Determine event type.
  288.   case ObjData.dwOfs of
  289.    DIMOFS_X: Inc(FDeltaX, Integer(ObjData.dwData));
  290.    DIMOFS_Y: Inc(FDeltaY, Integer(ObjData.dwData));
  291.    DIMOFS_Z: Inc(FDeltaWheel, Integer(ObjData.dwData));
  292.    DIMOFS_BUTTON0..DIMOFS_BUTTON7:
  293.     begin
  294.      // -> determine click - release type
  295.      EvClick  := 0;
  296.      EvRelease:= 1;
  297.      if ((ObjData.dwData and $80) = $80) then
  298.       begin
  299.        EvClick  := 1;
  300.        EvRelease:= 0;
  301.       end;
  302.      BtnIndx:= ObjData.dwOfs - DIMOFS_BUTTON0;
  303.      BufClick[BtnIndx]  := EvClick;
  304.      BufRelease[BtnIndx]:= EvRelease;
  305.     end;
  306.   end;
  307.  until (EvCount < 1);
  308. end;
  309. //---------------------------------------------------------------------------
  310. function TAsphyreMouse.GetPressed(Button: Integer): Boolean;
  311. begin
  312.  if (Button >= 0)and(Button < 8) then
  313.   Result:= (BufClick[Button] > 0) else Result:= False;
  314. end;
  315. //---------------------------------------------------------------------------
  316. function TAsphyreMouse.GetReleased(Button: Integer): Boolean;
  317. begin
  318.  if (Button >= 0)and(Button < 8) then
  319.   Result:= (BufRelease[Button] > 0) else Result:= False;
  320. end;
  321. //---------------------------------------------------------------------------
  322. end.