⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hidcontrollerclass.pas

📁 基于DELPHI的API
💻 PAS
📖 第 1 页 / 共 3 页
字号:
        begin
          // create HID device object and add it to the device list
          HidDev := TJvHidDevice.Create(PChar(@FunctionClassDeviceData.DevicePath), DevData.DevInst, OnDeviceUnplug);
          HidDev.FMyController := Self;
          List.Add(HidDev);
          Inc(devn);
        end;
        FreeMem(FunctionClassDeviceData);
      end;
    end;
  until not Success;
  SetupDiDestroyDeviceInfoList(PnPHandle);
end;

// the controller fills its list on creation and connects the event pipe

constructor TJvHidDeviceController.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FDeviceChangeEvent := nil;
  FEnumerateEvent    := nil;
  FDevUnplugEvent    := nil;
  FList              := nil;
  FDeviceChangeFired := False;
  HidD_GetHidGuid(FHidGuid);
  Inc(GlobalInstanceCount);
  if GlobalInstanceCount > 1 then
     raise EControllerError.Create('Only one TJvHidDeviceController allowed per program');
  // nothing done at design time
  if not (csDesigning in ComponentState) then
  begin
    FillInList(FList);
    Application.HookMainWindow(EventPipe);
  end;
end;

procedure TJvHidDeviceController.Loaded;
var
   i:   Integer;
   dev: TJvHidDevice;
begin
  inherited Loaded;

  // after read in of properties
  // propagate the OnUnplug event to the device objects
  if FList <> nil then
     for i := 0 to FList.Count-1 do
     begin
       dev := FList.Items[i];
       dev.OnUnplug := FDevUnplugEvent;
     end;
end;

// unplug or kill all controlled TJvHidDevices on controller destruction

destructor TJvHidDeviceController.Destroy;
var
  i:      Integer;
  HidDev: TJvHidDevice;
begin
  Dec(GlobalInstanceCount);
  // nothing done at design time
  if not (csDesigning in ComponentState) then
  begin
    // unhook event pipe
    Application.UnhookMainWindow(EventPipe);
    for i := 0 to FList.Count-1 do
    begin
      HidDev := FList.Items[i];
      with HidDev do
      begin
        // set to uncontrolled
        FMyController := nil;
        if IsCheckedOut then
          // pull the plug for checked out TJvHidDevices
          DoUnplug
        else
          // kill TJvHidDevices which are not checked out
          Free;
      end;
    end;
  end;
  FList.Free;

  inherited Destroy;
end;

// gets all the windows events/messages directly

function TJvHidDeviceController.EventPipe(var Msg: TMessage): Boolean;
begin
  Result := False;
  // sort out WM_DEVICECHANGE : DBT_DEVNODES_CHANGED
  if (Msg.Msg = WM_DEVICECHANGE) and (TWMDeviceChange(Msg).Event = DBT_DEVNODES_CHANGED) then
    DoDeviceChange;
end;

// implements OnDeviceChange event

procedure TJvHidDeviceController.DoDeviceChange;
var
  i:       Integer;
  j:       Integer;
  NewList: TList;
  HidDev:  TJvHidDevice;
  Changed: Boolean;
begin
  Changed := False;
  // get new device list
  FillInList(NewList);

  // unplug devices in FList which are not in NewList
  for i := 0 to FList.Count-1 do
  begin
    HidDev := FList.Items[i];
    for j := 0 to NewList.Count-1 do
      if (TJvHidDevice(NewList.Items[j]).FDevRegKey = HidDev.FDevRegKey) and HidDev.IsPluggedIn then
      begin
        HidDev := nil;
        Break;
      end;
    if HidDev <> nil then
    begin
      HidDev.DoUnplug;
      // prepare for deletion from list
      if not HidDev.IsCheckedOut then
         FList.Items[i] := nil;
      Changed := True;
    end;
  end;

  // delete the nil elements from FList
  i := 0;
  while i < FList.Count do
  begin
    if FList.Items[i] = nil then
       FList.Delete(i)
    else
       Inc(i);
  end;

  // delete devices from NewList which are in FList
  for i := 0 to NewList.Count-1 do
    for j := 0 to FList.Count-1 do
      if (TJvHidDevice(NewList[i]).FDevRegKey = TJvHidDevice(FList[j]).FDevRegKey) and TJvHidDevice(FList[j]).IsPluggedIn then
      begin
        TJvHidDevice(NewList[i]).FMyController := nil; // prevent Free/Destroy from accessing this controller
        TJvHidDevice(NewList[i]).Free;
        NewList[i] := nil;
        Break;
      end;

  // add the remains in NewList to FList
  for i := 0 to NewList.Count-1 do
    if NewList[i] <> nil then
    begin
      FList.Add(NewList[i]);
      Changed := True;
    end;

  // throw away helper list
  NewList.Free;

  if Assigned(FDeviceChangeEvent) and Changed then
    FDeviceChangeEvent(Self);
end;

// assign OnDeviceChange and immediately fire if needed

procedure TJvHidDeviceController.SetDeviceChangeEvent(const value: TNotifyEvent);
begin
  if @value <> @FDeviceChangeEvent then
  begin
    FDeviceChangeEvent := value;
    if Assigned(FDeviceChangeEvent) and not FDeviceChangeFired then
      FDeviceChangeEvent(Self);
    FDeviceChangeFired := True;
  end;
end;

// implement OnEnumerate event

function TJvHidDeviceController.DoEnumerate(HidDev: TJvHidDevice; Index: Integer): Boolean;
begin
  Result := False;
  if Assigned(FEnumerateEvent) then
  begin
    HidDev.FIsEnumerated := True;
    Result := FEnumerateEvent(HidDev, Index);
    HidDev.FIsEnumerated := False;
    if not HidDev.FIsCheckedOut then
      HidDev.CloseFile;
  end;
end;

// assign OnEnumerate event

procedure TJvHidDeviceController.SetEnumerate(const value: TJvHidEnumerateEvent);
begin
  if @value <> @FEnumerateEvent then
    FEnumerateEvent := value;
end;

// assign OnDevUnplug event

procedure TJvHidDeviceController.SetDevUnplug(const value: TJvHidUnplugEvent);
var
   i  : Integer;
   dev: TJvHidDevice;
begin
  if @value <> @FDevUnplugEvent then
  begin
    // change all OnUnplug events with the same old value
    if not (csDesigning in ComponentState) then
      for i := 0 to FList.Count-1 do
      begin
        dev := FList.Items[i];
        if @dev.FUnplug = @FDevUnplugEvent then
          dev.OnUnplug := value;
      end;
    FDevUnplugEvent := value;
  end;
end;

// send an OnEnumerate event for ALL controlled HidDevices
// it is explicitly allowed to check out any device in the event

function TJvHidDeviceController.Enumerate: Integer;
var
   i: Integer;
begin
  Result := 0;
  for i := 0 to FList.Count-1 do
    if TJvHidDevice(FList[i]).IsPluggedIn then
    begin
      Inc(Result);
      if not DoEnumerate(FList[i], i) then
        Break;
    end;
end;

//-- TJvHidDeviceController methods -----------------------------------

// internal worker function to check out a TJvHidDevice

function TJvHidDeviceController.CheckThisOut(var HidDev: TJvHidDevice; Index: Integer; Check: Boolean): Boolean;
begin
  Result := Check and not TJvHidDevice(FList.Items[Index]).IsCheckedOut;
  if Result then
  begin
    HidDev := FList[Index];
    HidDev.FIsCheckedOut := True;
  end;
end;

// method CheckOutByProductName hands out the first HidDevice with the right ProductName

function TJvHidDeviceController.CheckOutByProductName(var HidDev: TJvHidDevice; ProductName: string): Boolean;
var
  i: Integer;
begin
  Result := False;
  HidDev := nil;
  for i := 0 to FList.Count-1 do
  begin
    Result := CheckThisOut(HidDev, i, (ProductName = TJvHidDevice(FList[i]).ProductName) and (ProductName <> ''));
    if Result then
      Break;
  end;
end;

// method CheckOutByVendorName hands out the first HidDevice with the right VendorName

function TJvHidDeviceController.CheckOutByVendorName(var HidDev: TJvHidDevice; VendorName: string): Boolean;
var
  i: Integer;
begin
  Result := False;
  HidDev := nil;
  for i := 0 to FList.Count-1 do
  begin
    Result := CheckThisOut(HidDev, i, (VendorName = TJvHidDevice(FList[i]).VendorName) and (VendorName <> ''));
    if Result then
      Break;
  end;
end;

// method CheckOutByClass hands out the first HidDevice with the right Class
// Class comes from the registry (examples: 'Mouse', 'Keyboard')

function TJvHidDeviceController.CheckOutByClass(var HidDev: TJvHidDevice; ClassName: string): Boolean;
var
  i: Integer;
begin
  Result := False;
  HidDev := nil;
  for i := 0 to FList.Count-1 do
  begin
    Result := CheckThisOut(HidDev, i, (ClassName = TJvHidDevice(FList[i]).RegClass) and (ClassName <> ''));
    if Result then
      Break;
  end;
end;

// method CheckOutByID hands out the first HidDevice with the right VendorID and ProductID
// Pid = -1 matches all ProductIDs

function TJvHidDeviceController.CheckOutByID(var HidDev: TJvHidDevice; Vid, Pid: Integer): Boolean;
var
   i: Integer;
begin
  Result := False;
  HidDev := nil;
  for i := 0 to FList.Count-1 do
  begin
    Result := CheckThisOut(HidDev, i, (Vid = TJvHidDevice(FList[i]).Attributes.VendorID) and ((Pid = TJvHidDevice(FList[i]).Attributes.ProductID) or (Pid = -1)));
    if Result then
      Break;
  end;
end;

// method CheckOutByIndex hands out the HidDevice in the list with the right index
// this is mainly for check out during OnEnumerate                                

function TJvHidDeviceController.CheckOutByIndex(var HidDev: TJvHidDevice; const Index: Integer): Boolean;
begin
  Result := False;
  HidDev := nil;
  if (Index >= 0) and (Index < FList.Count) then
    Result := CheckThisOut(HidDev, Index, True);
end;

// method CheckOut simply hands out the first HidDevice in the list

function TJvHidDeviceController.CheckOut(var HidDev: TJvHidDevice): Boolean;
var
  i: Integer;
begin
  Result := False;
  HidDev := nil;
  for i := 0 to FList.Count-1 do
  begin
    Result := CheckThisOut(HidDev, i, True);
    if Result then
      Break;
  end;
end;

// method CheckIn hands a checked out HidDevice back in

procedure TJvHidDeviceController.CheckIn(var HidDev: TJvHidDevice);
begin
  HidDev.CloseFile;
  if HidDev.IsPluggedIn then
    HidDev.FIsCheckedOut := False
  else
    HidDev.Free;
  HidDev := nil;
end;

procedure Register;
begin
  RegisterComponents('Project JEDI', [TJvHidDeviceController]);
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -