📄 hidcontrollerclass.pas
字号:
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 + -