Search Tips Advanced Search |
| Delphi Graphics and Game Programming Exposed with DirectX 7.0 by John Ayres Wordware Publishing, Inc. ISBN: 1556226373 Pub Date: 12/01/99
Search this book:
Previous | Table of Contents | Next
Apart from the various members that denote the number of available objects, the dwFlags member may be of particular interest. This member contains a combination of flags that denote various attributes of the overall device. You can check to see if this member contains DIDC_ATTACHED, indicating that a game controller is physically attached to the machine. Checking it for DIDC_FORCEFEEDBACK indicates that the device supports force feedback. In addition to retrieving the capabilities of the overall input device, we may also want to retrieve information on a specific object on that device. This is accomplished by calling the IDirectInputDevice’s GetObjectInfo method. GetObjectInfo is defined as:
    function GetObjectInfo(

    var pdidoi: TDIDeviceObjectInstance;     // a TDIDeviceObjectInstance structure

    dwObj: DWORD;                            // object identifier

    dwHow: DWORD                             // object identification method

    ): HResult;                              // returns a DirectX error code
The first parameter takes a pointer to a TDIDeviceObjectInstance structure that will contain information about the desired object when the function returns. The second parameter is the device object identifier whose information we wish to retrieve. The final parameter should be set to DIPH_BYOFFSET. The TDIDeviceObjectInstance structure is another large structure that we will use again later when we construct our custom data format. The TDIDeviceObjectInstance structure is defined as:
    TDIDeviceObjectInstance = packed record

      dwSize: DWORD;                             // size of the structure

      guidType: TGUID;                           // object type GUID

      dwOfs: DWORD;                              // offset (also object identifier)

      dwType: DWORD;                             // object type

      dwFlags: DWORD;                            // attribute flags

      tszName: Array [0..MAX_PATH-1] of CHAR;    // object name

      dwFFMaxForce: DWORD;                       // maximum force magnitude

      dwFFForceResolution: DWORD;                // force resolution

      wCollectionNumber: WORD;                   // link collection number

      wDesignatorIndex: WORD;                    // designator index

      wUsagePage: WORD;                          // usage page

      wUsage: WORD;                              // usage

      dwDimension: DWORD;                        // dimensional units

      wExponent: WORD;                           // dimension exponent

      wReserved: WORD;                           // reserved

    end;
Incidentally, this method can be used to simply detect the existence of a specific object. If the return value is not DI_OK for a specific object, then we know it doesn’t exist on the input device. The following example demonstrates creating the object, retrieving device capabilities, and using the aforementioned technique to determine if any rotational axes are available on the device. Listing 7-12: Creating the input device and querying capabilities
    procedure TestForRotationalAxis(Offset: Integer; AxisName: string;

                                    Panel: TPanel; Shape: TShape);

    var

      ObjectInst: TDIDeviceObjectInstance;

    begin

      {we will be retrieving information on a device object, so prepare a

       data structure}

      FillChar(ObjectInst, SizeOf(TDIDeviceObjectInstance), 0);

      ObjectInst.dwSize := SizeOf(TDIDeviceObjectInstance);

      {this simply determines if the specified object exists. we are using this

       here to specifically test for rotational axes (see where this function

       is called), but we could also use it to determine the existence of

       other axes or even buttons}

      if FDirectInputDevice.GetObjectInfo(

         ObjectInst, Offset, DIPH_BYOFFSET) = DI_OK then

      with frmJoyTestBed.memControllerInfo.Lines do

      begin

        Add(     +AxisName+’ rotational axis’);

        Panel.Color := clMaroon;

      end

      else

      begin

        Panel.Color := clBtnFace;

        Shape.Width := 0;

      end;

    end;

    procedure TfrmJoyTestBed.FormActivate(Sender: TObject);

    var

      FJoyList: TStringList;

      iCount: Integer;

      DevCaps: TDIDevCaps;

      TempDevice: IDirectInputDevice;

        .

        .

        .

    begin

      {create the DirectInput object}

      DirectInputCreate(hInstance, DIRECTINPUT_VERSION, FDirectInput, nil);

      {create a list to hold information on each available game controller}

      FJoyList := TStringList.Create;

      {enumerate attached game controllers}

      FDirectInput.EnumDevices(DIDEVTYPE_JOYSTICK, EnumInputDevs, FJoyList,

                               DIEDFL_ATTACHEDONLY);

      {we’ll add this information to a list box in a dialog box, and display this

       to the user so they can choose their desired input controller}

      frmDevices := TfrmDevices.Create(Self);

      for iCount := 0 to FJoyList.Count-1 do

        frmDevices.lbxJoyDevices.Items.Add(FJoyList[iCount]);

      frmDevices.ShowModal;

      {create the input device based on the input controller specified by the user}

      DXCheck( FDirectInput.CreateDevice(PGUID(FJoyList.Objects[0])^, TempDevice,

                                         nil) );

      {close this dialog box, and delete the list of GUIDs}

      frmDevices.Release;

      for iCount := 0 to FJoyList.Count-1 do

        Dispose(PGUID(FJoyList.Objects[0]));

      FJoyList.Free;

      {we need the new version of the input device interface, so retrieve it}

      try

        DXCheck(TempDevice.QueryInterface(IDirectInputDevice2, FDirectInputDevice));

      finally

        TempDevice := nil

      end;

      {retrieve the capabilities of this device}

      DevCaps.dwSize := SizeOf(DevCaps);

      FDirectInputDevice.GetCapabilities(DevCaps);

        .

        .

        .

      {determine if the controller is unplugged}

      if (DevCaps.dwFlags and DIDC_ATTACHED) <> DIDC_ATTACHED then

        ShowMessage(Controller is unplugged’);

      {create button indicators}

      for iCount := 0 to DevCaps.dwButtons-1 do

      begin

        ButtonLights[iCount]              := TShape.Create(GroupBox2);

        ButtonLights[iCount].Left         := 96+((iCount mod 5)*(49+5));

        ButtonLights[iCount].Top          := 48+((iCount div 5)*(17+5));

        ButtonLights[iCount].Width        := 49;

        ButtonLights[iCount].Height       := 17;

        ButtonLights[iCount].Brush.Color  := clMaroon;

        ButtonLights[iCount].Parent       := GroupBox2;

      end;

      {indicate if a POV is available}

      if DevCaps.dwPOVs > 0 then

      begin

        Label9.Enabled := TRUE;

        Panel2.Color := clWhite;

      end

      else

      begin

        Label9.Enabled := FALSE;

        Panel2.Color := clBtnFace;

      end;

      {display controller capabilities}

      with DevCaps, memControllerInfo.Lines do

      begin

        Add(Number of buttons: +IntToStr(dwButtons));

        Add(Number of axes: +IntToStr(dwAxes));

        Add(Number of POVs: +IntToStr(dwPOVs));

        Add(’);

        Add(Rotational Axes:’);

        TestForRotationalAxis(DIJOFS_RX, RX’, pnlRXBar, shpRXBarPos);

        TestForRotationalAxis(DIJOFS_RY, RY’, pnlRYBar, shpRYBarPos);

        TestForRotationalAxis(DIJOFS_RZ, RZ’, pnlRZBar, shpRZBarPos);

      end;

        .

        .

        .

    end;
Setting the Data Format Now that the device has been created and its capabilities have been determined, we need to set the data format. As mentioned earlier, we must generate our own data format programmatically to ensure that the greatest number of input devices are supported. We begin by declaring a variable of type TDIDataFormat. TDIDataFormat is defined as:
    TDIDataFormat = packed record

      dwSize: DWORD;                      // size of this structure

      dwObjSize: DWORD;                   // size of a TDIObjectDataFormat structure

      dwFlags: DWORD;                     // attribute flags

      dwDataSize: DWORD;                  // size of data packet

      dwNumObjs: DWORD;                   // number of objects in the array

      rgodf: PDIObjectDataFormat;         // array of TDIObjectDataFormat structures

    end;
Previous | Table of Contents | Next

Products | Contact Us | About Us | Privacy | Ad Info | Home Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.