📄 hidcontrollerclass.pas
字号:
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetData(ReportTypeParam, DataList, DataLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetUsages(UsageList: PUsage; var UsageLength: ULONG; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetUsages(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetButtons(UsageList: PUsage; var UsageLength: ULONG; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetButtons(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetUsagesEx(UsageList: PUsageAndPage; var UsageLength: ULONG; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetUsagesEx(ReportTypeParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetButtonsEx(UsageList: PUsageAndPage; var UsageLength: ULONG; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetButtonsEx(ReportTypeParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetUsages(UsageList: PUsage; var UsageLength: ULONG; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetUsages(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetButtons(UsageList: PUsage; var UsageLength: ULONG; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetButtons(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.UnsetUsages(UsageList: PUsage; var UsageLength: ULONG; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_UnsetUsages(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.UnsetButtons(UsageList: PUsage; var UsageLength: ULONG; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_UnsetButtons(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageList, UsageLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetUsageValue(var UsageValue: ULONG; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetUsageValue(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetScaledUsageValue(var UsageValue: Integer; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetScaledUsageValue(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.GetUsageValueArray(UsageValue: PChar; UsageValueByteLength: WORD; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_GetUsageValueArray(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, UsageValueByteLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetUsageValue(UsageValue: ULONG; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetUsageValue(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetScaledUsageValue(UsageValue: Integer; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetScaledUsageValue(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.SetUsageValueArray(UsageValue: PChar; UsageValueByteLength: WORD; var Report; ReportLength: ULONG): NTSTATUS;
begin
Result := HIDP_STATUS_NULL; // for not plugged in
if IsAccessible then
Result := HidP_SetUsageValueArray(ReportTypeParam, UsagePageParam, LinkCollectionParam, UsageParam,
UsageValue, UsageValueByteLength, PreparsedData, Report, ReportLength);
end;
function TJvHidDevice.DeviceIoControl(IoControlCode: DWORD; InBuffer: Pointer; InSize: DWORD;
OutBuffer: Pointer; OutSize: DWORD; var BytesReturned: DWORD): Boolean;
begin
Result := False;
if OpenFile then
Result := Windows.DeviceIoControl(HidFileHandle, IoControlCode, InBuffer, InSize, OutBuffer, OutSize, BytesReturned, nil);
end;
function TJvHidDevice.ReadFile(var Report; ToRead: DWORD; var BytesRead: DWORD): Boolean;
begin
Result := False;
if OpenFile then
Result := Windows.ReadFile(HidFileHandle, Report, ToRead, BytesRead, nil);
end;
function TJvHidDevice.WriteFile(var Report; ToWrite: DWORD; var BytesWritten: DWORD): Boolean;
begin
Result := False;
if OpenFile then
Result := Windows.WriteFile(HidFileHandle, Report, ToWrite, BytesWritten, nil);
end;
// the TOverlapped structure is not needed externally
// the hEvent element is used to transport the device object
// to the callback function
// Better not implement a Delphi event with that
function TJvHidDevice.ReadFileEx(var Report; ToRead: DWORD; CallBack: TPROverlappedCompletionRoutine): Boolean;
var
Ovl: TOverlapped;
begin
Result := False;
if OpenFileEx then
begin
FillChar(Ovl, SizeOf(TOverlapped), #0);
Ovl.hEvent := DWORD(Self);
Result := HidControllerClass.ReadFileEx(HidOverlappedHandle, Report, ToRead, Ovl, CallBack);
end;
end;
function TJvHidDevice.WriteFileEx(var Report; ToWrite: DWORD; CallBack: TPROverlappedCompletionRoutine): Boolean;
var
Ovl: TOverlapped;
begin
Result := False;
if OpenFileEx then
begin
FillChar(Ovl, SizeOf(TOverlapped), #0);
Ovl.hEvent := DWORD(Self);
Result := HidControllerClass.WriteFileEx(HidOverlappedHandle, Report, ToWrite, Ovl, CallBack);
end;
end;
//== TJvHidDeviceController ===========================================
// internal worker function to find all Hid devices and create their objects
procedure TJvHidDeviceController.FillInList(var List: TList);
var
PnPHandle: HDEVINFO;
DevData: TSPDevInfoData;
DeviceInterfaceData: TSPDeviceInterfaceData;
FunctionClassDeviceData: PSPDeviceInterfaceDetailData;
Success: LongBool;
Devn: Integer;
BytesReturned: DWORD;
HidDev: TJvHidDevice;
begin
// create list
List := TList.Create;
// Get a handle for the Plug and Play node and request currently active HID devices
PnPHandle := SetupDiGetClassDevs(@FHidGuid, nil, 0, DIGCF_PRESENT or DIGCF_DEVICEINTERFACE);
if PnPHandle = Pointer(INVALID_HANDLE_VALUE) then
Exit;
Devn := 0;
repeat
DeviceInterfaceData.cbSize := SizeOf(TSPDeviceInterfaceData);
// Is there a HID device at this table entry?
Success := SetupDiEnumDeviceInterfaces(PnPHandle, nil, FHidGuid, Devn, DeviceInterfaceData);
if Success then
begin
DevData.cbSize := SizeOf(DevData);
BytesReturned := 0;
SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, nil, 0, @BytesReturned, @DevData);
if (BytesReturned <> 0) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) then
begin
FunctionClassDeviceData := AllocMem(BytesReturned);
FunctionClassDeviceData.cbSize := 5;
if SetupDiGetDeviceInterfaceDetail(PnPHandle, @DeviceInterfaceData, FunctionClassDeviceData, BytesReturned, @BytesReturned, @DevData) then
begin
// create HID device object and add it to the device list
HidDev := TJvHidDevice.Create(PChar(@FunctionClassDeviceData.DevicePath), DevData.DevInst,
GetRegistryProperty(PnPHandle, DevData, SPDRP_DEVICEDESC),
GetRegistryProperty(PnPHandle, DevData, SPDRP_CLASS),
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;
FNumCheckedInDevices := 0;
FNumCheckedOutDevices := 0;
FNumUnpluggedDevices := 0;
FDeviceChangeFired := False;
HidD_GetHidGuid(FHidGuid);
// this is just to remind you that one controller is sufficient
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);
FNumCheckedInDevices := FList.Count;
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);
// to prevent strange problems
FDeviceChangeEvent := nil;
FDevUnplugEvent := nil;
OnEnumerate := nil;
// 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]).DeviceID = HidDev.DeviceID) and HidDev.IsPluggedIn then
begin
HidDev := nil;
Break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -