您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關c++如何調用windows鍵盤代碼,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
windows
管這個長得有點兒丑的叫屏幕鍵盤
windows
管這個長得好看的叫觸摸鍵盤
當然上面的截圖是win10的鍵盤效果,在win7上是有一些差別的,這里就不截圖放出來了
似乎很簡單,我們用Spy++
抓下窗口,找到窗口句柄所關聯的進程句柄,再查看下是哪個進程以及命令行信息,然后我們就可以愉快地執行命令調用進程了
屏幕鍵盤進程信息:
觸摸鍵盤進程信息:
命令行走起,運行exe,此時如果兩個鍵盤你都能順利調起的話,我只能告訴你,你被你的系統蒙蔽了雙眼
當系統版本大于等于win10 10.0.14393.0時,觸摸鍵盤你調用TabTip.exe
并不會顯示出來,也就是說它的內部實現方式變了。
到這里你會不會覺得很詫異,這不是標準玩法嗎?為什么毫無預兆就不行了呢?
我只能說你太傻太天真,微軟官網本身就沒有說明鍵盤調用的正確姿勢,也就是說觸摸鍵盤對微軟來說并非開放給你的。當然互聯網無所不能,有大神還是想方法逆向了觸摸鍵盤調用的方式
// 4ce576fa-83dc-4F88-951c-9d0782b4e376 DEFINE_GUID(CLSID_UIHostNoLaunch, 0x4CE576FA, 0x83DC, 0x4f88, 0x95, 0x1C, 0x9D, 0x07, 0x82, 0xB4, 0xE3, 0x76); // 37c994e7_432b_4834_a2f7_dce1f13b834b DEFINE_GUID(IID_ITipInvocation, 0x37c994e7, 0x432b, 0x4834, 0xa2, 0xf7, 0xdc, 0xe1, 0xf1, 0x3b, 0x83, 0x4b); struct ITipInvocation : IUnknown { virtual HRESULT STDMETHODCALLTYPE Toggle(HWND wnd) = 0; }; namespace { constexpr auto kKeyboardWindowClass = L"IPTip_Main_Window"; constexpr auto kWindowParentClass = L"ApplicationFrameWindow"; constexpr auto kWindowClass = L"Windows.UI.Core.CoreWindow"; constexpr auto kWindowCaption = L"Microsoft Text Input Application"; constexpr auto kTabTipPath = L"C:\\Program Files\\Common Files\\Microsoft Shared\\ink\\TabTip.exe"; constexpr auto kTabletTipSubKey = "Software\\Microsoft\\TabletTip"; constexpr auto kTabletTipOption = "EnableDesktopModeAutoInvoke"; }
調用屏幕鍵盤
bool ScreenKeyBoard::OpenOskKeyboard() { if (!PublicUtils::Process::FindProcess("osk.exe").empty()) { return true; } PVOID OldValue = NULL; //64位系統中32位程序要訪問本機system32文件夾,需取消重定向到Syswow64 BOOL bRet = Wow64DisableWow64FsRedirection(&OldValue); ShellExecuteW(NULL, L"open", L"osk.exe", NULL, NULL, SW_SHOWNORMAL); if (bRet) { Wow64RevertWow64FsRedirection(OldValue); return true; } else { std::cerr << "Wow64DisableWow64FsRedirection fail err code:" << GetLastError() << std::endl; return false; } }
調用觸摸鍵盤
bool ScreenKeyBoard::OpenTabTipByProcess(const std::wstring& tabTipPath) { //將進程TabTip.exe拉起,如果是進程存在的情況下,再次調用會直接顯示鍵盤界面 if (!ShellExecuteW(NULL, L"open", tabTipPath.c_str(), NULL, NULL, SW_SHOWNORMAL)) { std::cerr << "ShellExecuteW tabTip err:" << GetLastError() << std::endl; return false; } std::cout << "ShellExecuteW tabTip success"; return true; }
調用觸摸鍵盤
COM調用方式,不知道COM的需要自己惡補下知識,和windows打交道還是很香的,但坑也多
bool ScreenKeyBoard::OpenTabTipByProcess(const std::wstring& tabTipPath) { //將進程TabTip.exe拉起,如果是進程存在的情況下,再次調用會直接顯示鍵盤界面 if (!ShellExecuteW(NULL, L"open", tabTipPath.c_str(), NULL, NULL, SW_SHOWNORMAL)) { std::cerr << "ShellExecuteW tabTip err:" << GetLastError() << std::endl; return false; } std::cout << "ShellExecuteW tabTip success"; return true; }
根據系統版本選擇調用觸摸鍵盤的方式
bool ScreenKeyBoard::OpenScreenKeyboard() { if (!IsTabTipAutoInvokeOnDesktopMode()) { return OpenTabTip(); } //觸摸鍵盤有一設置項:不處于平板電腦模式且未連接鍵盤時顯示觸摸鍵盤,增加延遲避開系統調用鍵盤 std::thread([]() { PublicUtils::Sleep(std::chrono::milliseconds(500)); OpenTabTip(); }).detach(); return true; } bool ScreenKeyBoard::OpenTabTip() { auto version = PublicUtils::Environment::OsVersion(); std::cout << "os version:" << version.ToString() << std::endl; if (IsNewTabTipKeyboardVisable() || IsOldTabTipKeyboardVisable()) { std::cout << "keyboard is visible" << std::endl; return true; } //系統版本大于等于win10 10.0.14393.0,需要使用com組件的接口才能將鍵盤界面顯示出來 if (10 == version.GetMajor() && version.GetPatch() >= 14393) { return OpenTabTipByCom(kTabTipPath); } else { return OpenTabTipByProcess(kTabTipPath); } }
在調用觸摸鍵盤前有一個代碼片段用來判斷觸摸鍵盤是否處于顯示狀態,這是為什么呢?
因為觸摸鍵盤TabTip沒有明確的接口區分顯示和隱藏,當調用時會根據當前的狀態決定下一個狀態,即隱藏時調用會顯示,顯示時調用會隱藏,所以就需要我們自己判斷鍵盤狀態
判斷鍵盤狀態,Spy++抓觸摸鍵盤窗口,自己分析一些特性
需要注意觸摸鍵盤這個設置項的作用,在代碼中需要做處理(這個設置開啟后系統會檢測到有輸入框聚焦時自動調起觸摸鍵盤,如果你在代碼中去調用的話,可能會存在一些沖突)
![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/233c5a6ce0804795be5ed48a207fbeb2~tplv-k3u1fbpfcp-watermark.image) bool ScreenKeyBoard::IsNewTabTipKeyboardVisable() { //win10下父窗口是ApplicationFrameWindow子窗口是Windows.UI.Core.CoreWindow HWND parent = FindWindowExW(NULL, NULL, kWindowParentClass, NULL); if (!parent) { std::cerr << "no more windows, keyboard state is unknown. class:" << PublicUtils::CharsetUtils::UnicodeToUTF8(kWindowParentClass) << std::endl; return false; } HWND wnd = FindWindowExW(parent, NULL, kWindowClass, kWindowCaption); if (!wnd) { std::cerr << "it's a child of a WindowParentClass1709 window - the keyboard is open. class:" << PublicUtils::CharsetUtils::UnicodeToUTF8(kWindowClass) << " caption" << PublicUtils::CharsetUtils::UnicodeToUTF8(kWindowCaption) << std::endl; return false; } //觸摸鍵盤顯示和隱藏不能用IsWindowVisible判斷,判斷方式可參考 https://stackoverflow.com/questions/32149880/how-to-identify-windows-10-background-store-processes-that-have-non-displayed-wi int cloaked = 0; if (DwmGetWindowAttribute(wnd, DWMWA_CLOAKED, &cloaked, DWM_CLOAKED_INHERITED) != S_OK) { std::cerr << "DwmGetWindowAttribute err:" << GetLastError() << std::endl; return false; } std::cout << "DwmGetWindowAttribute cloaked=" << cloaked; return 0 == cloaked; } bool ScreenKeyBoard::IsOldTabTipKeyboardVisable() { HWND touchhWnd = FindWindowW(kKeyboardWindowClass, NULL); if (!touchhWnd) { std::cerr << "without window:" << PublicUtils::CharsetUtils::UnicodeToUTF8(kKeyboardWindowClass) << std::endl; return false; } unsigned long style = GetWindowLong(touchhWnd, GWL_STYLE); // 由于有的系統在鍵盤不顯示時候只是多返回一個WS_DISABLED這個字段。所以加一個它的判斷 std::cout << "WS_CLIPSIBLINGS:" << (style & WS_CLIPSIBLINGS) << " WS_VISIBLE:" << (style & WS_VISIBLE) << " WS_POPUP:" << (style & WS_POPUP) << " WS_DISABLED:" << !(style & WS_DISABLED) << std::endl; return (style & WS_CLIPSIBLINGS) && (style & WS_VISIBLE) && (style & WS_POPUP) && !(style & WS_DISABLED); }
關于“c++如何調用windows鍵盤代碼”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。