ソースを参照

先判断一下键盘的逻辑代码

张洋 1 週間 前
コミット
ece35e63bb

BIN
bin/Win32/Release/zhipuzi_pos_windows/DuiLib.dll


BIN
dll/release/DuiLib.dll


+ 207 - 6
zhipuzi_pos_windows/helper/CSystem.cpp

@@ -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());
 }

+ 13 - 2
zhipuzi_pos_windows/helper/CSystem.h

@@ -5,8 +5,13 @@
 class CSystem
 {
 public:
-    CSystem();
-    ~CSystem();
+	CSystem()
+	{
+	}
+
+	~CSystem()
+	{
+	}
 
     static int get_CPU_core_num();
 
@@ -73,4 +78,10 @@ public:
 
 	//隐藏虚拟键盘,跟系统设置无关
 	static void HideSystemKeyboard();
+
+	// 检测系统当前是否存在键盘设备(有线/蓝牙都算)
+	static bool HasKeyboardDevice();
+
+	// 打印当前系统枚举到的键盘输入设备名称
+	static void ShowKeyboardDeviceNames();
 };

+ 1 - 0
zhipuzi_pos_windows/page/CDiandanPageUI.cpp

@@ -825,6 +825,7 @@ void CDiandanPageUI::HandleClickMsg(TNotifyUI& msg)
 	}
 	else if (name == L"btn_diandan_qingkong")
 	{
+		CSystem::ShowKeyboardDeviceNames();
 		this->ClickQingkong();
 	}
 	else if (name == L"btn_diandan_zhengdanbeizhu")

BIN
zhipuzi_pos_windows/resource/skin.zip


+ 5 - 1
zhipuzi_pos_windows/ui/CModalWnd.cpp

@@ -22,7 +22,11 @@ void CModalWnd::Notify(DuiLib::TNotifyUI& msg)
 
 	if (msg.sType == _T("setfocus"))
 	{
-		CSystem::ShowSystemKeyboard(m_hWnd);
+		// 只有没有物理键盘时,才弹虚拟键盘
+		if (!CSystem::HasKeyboardDevice())
+		{
+			CSystem::ShowSystemKeyboard(m_hWnd);
+		}
 	}
 	else if (msg.sType == _T("killfocus"))
 	{

+ 5 - 1
zhipuzi_pos_windows/wnd/CLoginWnd.cpp

@@ -160,7 +160,11 @@ void CLoginWnd::Notify(TNotifyUI& msg)
 	{
 		if (senderClassName == L"EditUI")
 		{
-			CSystem::ShowSystemKeyboard(m_hWnd);
+			// 只有没有物理键盘时,才弹虚拟键盘
+			if (!CSystem::HasKeyboardDevice())
+			{
+				CSystem::ShowSystemKeyboard(m_hWnd);
+			}
 		}
 	}
 }

+ 5 - 1
zhipuzi_pos_windows/wnd/CMainWnd.cpp

@@ -271,7 +271,11 @@ void CMainWnd::Notify(TNotifyUI& msg)
 	{
 		if (senderClassName == L"EditUI")
 		{
-			CSystem::ShowSystemKeyboard(m_hWnd);
+			// 只有没有物理键盘时,才弹虚拟键盘
+			if (!CSystem::HasKeyboardDevice())
+			{
+				CSystem::ShowSystemKeyboard(m_hWnd);
+			}
 		}
 	}
 }

+ 2 - 2
zhipuzi_pos_windows/zhipuzi_pos_windows.vcxproj

@@ -138,7 +138,7 @@ copy $(ProjectDir)conf\ $(SolutionDir)bin\$(Platform)\$(Configuration)\conf\</Co
       <SubSystem>Windows</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(SolutionDir)lib\debug</AdditionalLibraryDirectories>
-      <AdditionalDependencies>dbghelp.lib;winmm.lib;setupapi.lib;version.lib;urlmon.lib;Wininet.lib;paho-mqtt3a-static.lib;paho-mqttpp3-static.lib;opencv_world4120d.lib;libboost_date_time-vc142-mt-gd-x32-1_90.lib;libboost_regex-vc142-mt-gd-x32-1_90.lib;log4cplusUD.lib;qrencoded.lib;alibabacloud-oss-cpp-sdk.lib;libcurl-d_imp.lib;libcrypto.lib;libssl.lib;DuiLib_d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>dbghelp.lib;winmm.lib;setupapi.lib;hid.lib;version.lib;urlmon.lib;Wininet.lib;paho-mqtt3a-static.lib;paho-mqttpp3-static.lib;opencv_world4120d.lib;libboost_date_time-vc142-mt-gd-x32-1_90.lib;libboost_regex-vc142-mt-gd-x32-1_90.lib;log4cplusUD.lib;qrencoded.lib;alibabacloud-oss-cpp-sdk.lib;libcurl-d_imp.lib;libcrypto.lib;libssl.lib;DuiLib_d.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <IgnoreSpecificDefaultLibraries>
       </IgnoreSpecificDefaultLibraries>
       <Version>
@@ -187,7 +187,7 @@ copy $(SolutionDir)res\ai\ $(SolutionDir)bin\$(Platform)\$(Configuration)\$(Proj
       <OptimizeReferences>true</OptimizeReferences>
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <AdditionalLibraryDirectories>$(SolutionDir)lib\release</AdditionalLibraryDirectories>
-      <AdditionalDependencies>dbghelp.lib;winmm.lib;urlmon.lib;Wininet.lib;setupapi.lib;version.lib;libboost_date_time-vc142-mt-x32-1_90.lib;libboost_regex-vc142-mt-x32-1_90.lib;log4cplusU.lib;qrencode.lib;alibabacloud-oss-cpp-sdk.lib;libcurl_imp.lib;libcrypto.lib;libssl.lib;paho-mqtt3a-static.lib;paho-mqttpp3-static.lib;opencv_world4120.lib;DuiLib.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <AdditionalDependencies>dbghelp.lib;winmm.lib;urlmon.lib;Wininet.lib;setupapi.lib;hid.lib;version.lib;libboost_date_time-vc142-mt-x32-1_90.lib;libboost_regex-vc142-mt-x32-1_90.lib;log4cplusU.lib;qrencode.lib;alibabacloud-oss-cpp-sdk.lib;libcurl_imp.lib;libcrypto.lib;libssl.lib;paho-mqtt3a-static.lib;paho-mqttpp3-static.lib;opencv_world4120.lib;DuiLib.lib;%(AdditionalDependencies)</AdditionalDependencies>
       <AdditionalOptions>/ignore:4099 %(AdditionalOptions)</AdditionalOptions>
       <UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
     </Link>