|
|
@@ -4,15 +4,20 @@
|
|
|
#include <direct.h>
|
|
|
#include "tlhelp32.h"
|
|
|
|
|
|
-CSystem::CSystem()
|
|
|
-{
|
|
|
-}
|
|
|
+#include <hidsdi.h>
|
|
|
+#include <hidpi.h>
|
|
|
|
|
|
+#ifndef RIDI_DEVICENAME
|
|
|
+#define RIDI_DEVICENAME 0x2000000B
|
|
|
+#endif
|
|
|
|
|
|
-CSystem::~CSystem()
|
|
|
-{
|
|
|
-}
|
|
|
+#ifndef RIDI_DEVICEFRIENDLYNAME
|
|
|
+#define RIDI_DEVICEFRIENDLYNAME 0x2000000C
|
|
|
+#endif
|
|
|
|
|
|
+#ifndef RIDI_PREPARSEDDATA
|
|
|
+#define RIDI_PREPARSEDDATA 0x20000005
|
|
|
+#endif
|
|
|
|
|
|
int CSystem::get_CPU_core_num()
|
|
|
{
|
|
|
@@ -598,4 +603,200 @@ void CSystem::HideSystemKeyboard()
|
|
|
{
|
|
|
::PostMessageW(hTabTipWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+// 判断是否是真正物理键盘,排除鼠标侧键虚拟键盘接口
|
|
|
+static bool IsRealKeyboard(HANDLE hRawDevice)
|
|
|
+{
|
|
|
+ UINT pathLen = 0;
|
|
|
+ UINT ret = GetRawInputDeviceInfoW(hRawDevice, RIDI_DEVICENAME, nullptr, &pathLen);
|
|
|
+ if (ret == (UINT)-1 || pathLen == 0)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ std::wstring devPath(pathLen, L'\0');
|
|
|
+ ret = GetRawInputDeviceInfoW(hRawDevice, RIDI_DEVICENAME, devPath.data(), &pathLen);
|
|
|
+ if (ret == (UINT)-1)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ //截断末尾'\0',纯STL,不依赖wcslen
|
|
|
+ size_t realLen = devPath.find(L'\0');
|
|
|
+ if (realLen != std::wstring::npos)
|
|
|
+ {
|
|
|
+ devPath.resize(realLen);
|
|
|
+ }
|
|
|
+
|
|
|
+ //微软蓝牙键盘特殊路径,无法CreateFile打开,直接判定真实键盘
|
|
|
+ if (devPath.find(L"Microsoft Keyboard RID") != std::wstring::npos)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ HANDLE hHid = CreateFileW(
|
|
|
+ devPath.c_str(),
|
|
|
+ 0, // 不要GENERIC_READ!仅获取HID描述,不需要访问权限
|
|
|
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
+ nullptr,
|
|
|
+ OPEN_EXISTING,
|
|
|
+ 0,
|
|
|
+ nullptr
|
|
|
+ );
|
|
|
+ if (hHid == INVALID_HANDLE_VALUE)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ PHIDP_PREPARSED_DATA pPreparsed = nullptr;
|
|
|
+ BOOL bOk = HidD_GetPreparsedData(hHid, &pPreparsed);
|
|
|
+ CloseHandle(hHid);
|
|
|
+
|
|
|
+ if (!bOk || pPreparsed == nullptr)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ HIDP_CAPS caps{};
|
|
|
+ LONG status = HidP_GetCaps(pPreparsed, &caps);
|
|
|
+ HidD_FreePreparsedData(pPreparsed);
|
|
|
+
|
|
|
+ if (status != 0)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (caps.UsagePage == 0x01 && caps.Usage == 0x06)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+bool CSystem::HasKeyboardDevice()
|
|
|
+{
|
|
|
+ UINT deviceCount = 0;
|
|
|
+ UINT ret = ::GetRawInputDeviceList(nullptr, &deviceCount, sizeof(RAWINPUTDEVICELIST));
|
|
|
+ if (ret == (UINT)-1 || deviceCount == 0)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::vector<RAWINPUTDEVICELIST> devices(deviceCount);
|
|
|
+ ret = ::GetRawInputDeviceList(devices.data(), &deviceCount, sizeof(RAWINPUTDEVICELIST));
|
|
|
+ if (ret == (UINT)-1)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool hasRealKeyboard = false;
|
|
|
+ for (UINT i = 0; i < deviceCount; ++i)
|
|
|
+ {
|
|
|
+ if (devices[i].dwType == RIM_TYPEKEYBOARD)
|
|
|
+ {
|
|
|
+ if (IsRealKeyboard(devices[i].hDevice))
|
|
|
+ {
|
|
|
+ hasRealKeyboard = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return hasRealKeyboard;
|
|
|
+}
|
|
|
+
|
|
|
+void CSystem::ShowKeyboardDeviceNames()
|
|
|
+{
|
|
|
+ UINT deviceCount = 0;
|
|
|
+ UINT ret = ::GetRawInputDeviceList(nullptr, &deviceCount, sizeof(RAWINPUTDEVICELIST));
|
|
|
+ std::wostringstream oss;
|
|
|
+
|
|
|
+ if (ret == (UINT)-1 || deviceCount == 0)
|
|
|
+ {
|
|
|
+ oss << L"HasKeyboardDevice:\r\n";
|
|
|
+ oss << L"GetRawInputDeviceList 返回错误 或者 设备数量=0\r\n";
|
|
|
+ CLewaimaiLog::OutputMessageBox(oss.str());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::vector<RAWINPUTDEVICELIST> devices(deviceCount);
|
|
|
+ ret = ::GetRawInputDeviceList(devices.data(), &deviceCount, sizeof(RAWINPUTDEVICELIST));
|
|
|
+ if (ret == (UINT)-1)
|
|
|
+ {
|
|
|
+ oss << L"HasKeyboardDevice:\r\n";
|
|
|
+ oss << L"GetRawInputDeviceList 获取设备列表失败\r\n";
|
|
|
+ CLewaimaiLog::OutputMessageBox(oss.str());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ bool hasRealKeyboard = false;
|
|
|
+ oss << L"=== RawInput 键盘枚举结果 ===\r\n";
|
|
|
+ oss << L"总RawInput设备数:" << deviceCount << L"\r\n\r\n";
|
|
|
+
|
|
|
+ for (UINT i = 0; i < deviceCount; ++i)
|
|
|
+ {
|
|
|
+ oss << L"[" << i << L"] dwType=" << devices[i].dwType;
|
|
|
+ if (devices[i].dwType == RIM_TYPEKEYBOARD)
|
|
|
+ {
|
|
|
+ oss << L" (RIM_TYPEKEYBOARD)\r\n";
|
|
|
+ bool realKb = IsRealKeyboard(devices[i].hDevice);
|
|
|
+ oss << L" IsRealKeyboard: " << (realKb ? L"YES(真实键盘)" : L"NO(鼠标侧键/虚拟键盘)") << L"\r\n";
|
|
|
+
|
|
|
+ if (realKb)
|
|
|
+ {
|
|
|
+ hasRealKeyboard = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ UINT nameLen = 0;
|
|
|
+ UINT riRet = GetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICENAME, nullptr, &nameLen);
|
|
|
+ if (riRet != (UINT)-1 && nameLen > 0)
|
|
|
+ {
|
|
|
+ std::wstring devName(nameLen, L'\0');
|
|
|
+ riRet = GetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICENAME, devName.data(), &nameLen);
|
|
|
+ if (riRet != (UINT)-1)
|
|
|
+ {
|
|
|
+ size_t realLen = devName.find(L'\0');
|
|
|
+ if (realLen != std::wstring::npos)
|
|
|
+ devName.resize(realLen);
|
|
|
+ oss << L" DevicePath: " << devName.c_str() << L"\r\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ UINT friendlyLen = 0;
|
|
|
+ riRet = GetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICEFRIENDLYNAME, nullptr, &friendlyLen);
|
|
|
+ if (riRet != (UINT)-1 && friendlyLen > 0)
|
|
|
+ {
|
|
|
+ std::wstring friendlyName(friendlyLen, L'\0');
|
|
|
+ riRet = GetRawInputDeviceInfoW(devices[i].hDevice, RIDI_DEVICEFRIENDLYNAME, friendlyName.data(), &friendlyLen);
|
|
|
+ if (riRet != (UINT)-1)
|
|
|
+ {
|
|
|
+ size_t realLen = friendlyName.find(L'\0');
|
|
|
+ if (realLen != std::wstring::npos)
|
|
|
+ friendlyName.resize(realLen);
|
|
|
+ oss << L" FriendlyName: " << friendlyName.c_str() << L"\r\n";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ oss << L" FriendlyName: (获取失败)\r\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ oss << L" FriendlyName: (无)\r\n";
|
|
|
+ }
|
|
|
+ oss << L"\r\n";
|
|
|
+ }
|
|
|
+ else if (devices[i].dwType == RIM_TYPEMOUSE)
|
|
|
+ {
|
|
|
+ oss << L" (RIM_TYPEMOUSE)\r\n\r\n";
|
|
|
+ }
|
|
|
+ else if (devices[i].dwType == RIM_TYPEHID)
|
|
|
+ {
|
|
|
+ oss << L" (RIM_TYPEHID)\r\n\r\n";
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ oss << L" (其他类型)\r\n\r\n";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ oss << L"============================\r\n";
|
|
|
+ oss << L"检测到真实物理键盘:" << (hasRealKeyboard ? L"是" : L"否") << L"\r\n";
|
|
|
+ CLewaimaiLog::OutputMessageBox(oss.str());
|
|
|
}
|