// pRCon may be NULL, pszChars may be NULL const ConEmuHotKey* CConEmuCtrl::ProcessHotKey(DWORD VkState, bool bKeyDown, const wchar_t *pszChars, CRealConsole* pRCon) { UINT vk = ConEmuHotKey::GetHotkey(VkState); if (!(vk >= '0' && vk <= '9')) ResetDoubleKeyConsoleNum(); const ConEmuHotKey* pHotKey = gpSetCls->GetHotKeyInfo(VkState, bKeyDown, pRCon); gpCurrentHotKey = pHotKey; if (pHotKey && (pHotKey != ConEmuSkipHotKey)) { bool bEnabled = true; if (pHotKey->Enabled) { bEnabled = pHotKey->Enabled(); if (!bEnabled) { pHotKey = NULL; } } if (pHotKey) { // Чтобы у консоли не сносило крышу (FAR может выполнить макрос на Alt) if (((VkState & cvk_ALLMASK) == cvk_LAlt) || ((VkState & cvk_ALLMASK) == cvk_RAlt)) { if (pRCon && gpSet->isFixAltOnAltTab) pRCon->PostKeyPress(VK_CONTROL, LEFT_ALT_PRESSED, 0); } // Теперь собственно действие if (pHotKey->fkey) { bool bApps = (VkState & cvk_Apps) == cvk_Apps; if (bApps) gpConEmu->SkipOneAppsRelease(true); pHotKey->fkey(VkState, false, pHotKey, pRCon); if (bApps && !isPressed(VK_APPS)) gpConEmu->SkipOneAppsRelease(false); } else { _ASSERTE(pHotKey->fkey!=NULL); } } } gpCurrentHotKey = NULL; return pHotKey; }
// pRCon may be NULL, pszChars may be NULL const ConEmuHotKey* CConEmuCtrl::ProcessHotKey(const ConEmuChord& VkState, bool bKeyDown, const wchar_t *pszChars, CRealConsole* pRCon) { // For testing and checking purposes // User may disable "GuiMacro" processing with "ConEmu /NoHotkey" if (gpConEmu->DisableAllHotkeys) { return NULL; } UINT vk = VkState.Vk; if (!(vk >= '0' && vk <= '9')) ResetDoubleKeyConsoleNum(); const ConEmuHotKey* pHotKey = gpSetCls->GetHotKeyInfo(VkState, bKeyDown, pRCon); gpCurrentHotKey = pHotKey; if (pHotKey == NULL && pRCon && pRCon->isSelectionPresent()) { pHotKey = pRCon->ProcessSelectionHotKey(VkState, bKeyDown, pszChars); } if (pHotKey && (pHotKey != ConEmuSkipHotKey)) { // For testing and checking purposes // User may disable "GuiMacro" processing with "ConEmu /NoMacro" if (pHotKey && gpConEmu->DisableAllMacro) { if ((pHotKey->HkType == chk_Macro) || (pHotKey->GuiMacro && *pHotKey->GuiMacro)) { pHotKey = NULL; } } bool bEnabled = true; if (pHotKey && pHotKey->Enabled) { bEnabled = pHotKey->Enabled(); if (!bEnabled) { pHotKey = NULL; } } if (pHotKey) { // Чтобы у консоли не сносило крышу (FAR может выполнить макрос на Alt) if (((VkState.Mod & cvk_ALLMASK) == cvk_LAlt) || ((VkState.Mod & cvk_ALLMASK) == cvk_RAlt)) { if (pRCon && gpSet->isFixAltOnAltTab) pRCon->PostKeyPress(VK_CONTROL, LEFT_ALT_PRESSED, 0); } // Теперь собственно действие if (pHotKey->fkey) { bool bApps = (VkState.Mod & cvk_Apps) == cvk_Apps; if (bApps) gpConEmu->SkipOneAppsRelease(true); pHotKey->fkey(VkState, false, pHotKey, pRCon); if (bApps && !isPressed(VK_APPS)) gpConEmu->SkipOneAppsRelease(false); } else { _ASSERTE(pHotKey->fkey!=NULL); } } } gpCurrentHotKey = NULL; return pHotKey; }
// true - запретить передачу в консоль, сами обработали // pRCon may be NULL, pszChars may be NULL bool CConEmuCtrl::ProcessHotKeyMsg(UINT messg, WPARAM wParam, LPARAM lParam, const wchar_t *pszChars, CRealConsole* pRCon) { _ASSERTE((messg == WM_KEYDOWN || messg == WM_SYSKEYDOWN) || (messg == WM_KEYUP || messg == WM_SYSKEYUP)); WARNING("CConEmuCtrl:: Наверное нужно еще какие-то пляски с бубном при отпускании хоткеев"); WARNING("CConEmuCtrl:: Ибо в CConEmuMain::OnKeyboard была запутанная логика с sm_SkipSingleHostkey, sw_SkipSingleHostkey, sl_SkipSingleHostkey"); // Обновить и подготовить "r.Event.KeyEvent.dwControlKeyState" UpdateControlKeyState(); DWORD vk = (DWORD)(wParam & 0xFF); bool bKeyDown = (messg == WM_KEYDOWN || messg == WM_SYSKEYDOWN); bool bKeyUp = (messg == WM_KEYUP || messg == WM_SYSKEYUP); if (mn_DoubleKeyConsoleNum && (!(vk >= '0' && vk <= '9'))) { //if (!(vk >= '0' && vk <= '9')) // ResetDoubleKeyConsoleNum(); int nNewIdx = -1; // попытка активации одной кнопкой if (mn_DoubleKeyConsoleNum>='1' && mn_DoubleKeyConsoleNum<='9') nNewIdx = mn_DoubleKeyConsoleNum - '1'; else if (mn_DoubleKeyConsoleNum=='0') nNewIdx = 9; ResetDoubleKeyConsoleNum(); if (nNewIdx >= 0) gpConEmu->ConActivate(nNewIdx); } if (bKeyUp) { if ((mb_InWinTabSwitch && (vk == VK_RWIN || vk == VK_LWIN)) || (mb_InCtrlTabSwitch && (vk == VK_CONTROL || vk == VK_LCONTROL || vk == VK_RCONTROL))) { mb_InWinTabSwitch = mb_InCtrlTabSwitch = FALSE; gpConEmu->TabCommand(ctc_SwitchCommit); WARNING("CConEmuCtrl:: В фар отпускание кнопки таки пропустим?"); } } // На сами модификаторы - действий не вешается if (vk == VK_LWIN || vk == VK_RWIN /*|| vk == VK_APPS*/ || vk == VK_SHIFT || vk == VK_LSHIFT || vk == VK_RSHIFT || vk == VK_CONTROL || vk == VK_LCONTROL || vk == VK_RCONTROL || vk == VK_MENU || vk == VK_LMENU || vk == VK_RMENU) { if (pRCon) { // Однако, если это был одиночный обработанный модификатор - его нужно "пофиксить", // чтобы на его отпускание не выполнился Far-макрос например if (bKeyUp) { FixSingleModifier(vk, pRCon); } else { _ASSERTE(bKeyDown); int ModCount = 0; if (bLAlt) ModCount++; if (bRAlt) ModCount++; if (bLCtrl) ModCount++; if (bRCtrl) ModCount++; if (bLShift || bRShift) ModCount++; if ((ModCount == 1) && (vk != VK_APPS) && (vk != VK_LWIN)) { mb_LastSingleModifier = FALSE; mn_LastSingleModifier = (vk == VK_LMENU || vk == VK_RMENU || vk == VK_MENU) ? VK_MENU : (vk == VK_LCONTROL || vk == VK_RCONTROL || vk == VK_CONTROL) ? VK_CONTROL : (vk == VK_LSHIFT || vk == VK_RSHIFT || vk == VK_SHIFT) ? VK_SHIFT : 0; if (!mn_LastSingleModifier) { // Win и прочие модификаторы здесь не интересуют } else { mn_SingleModifierFixState = dwControlKeyState; switch (mn_LastSingleModifier) { case VK_MENU: mn_SingleModifierFixKey = VK_CONTROL; mn_SingleModifierFixState |= (LEFT_CTRL_PRESSED); break; case VK_CONTROL: mn_SingleModifierFixKey = VK_MENU; mn_SingleModifierFixState |= (RIGHT_ALT_PRESSED); break; case VK_SHIFT: mn_SingleModifierFixKey = VK_MENU; mn_SingleModifierFixState |= RIGHT_ALT_PRESSED; break; } } } else if (ModCount > 1) { // Больше не нужно mb_LastSingleModifier = FALSE; mn_LastSingleModifier = mn_SingleModifierFixKey = mn_SingleModifierFixState = 0; } } } return false; } ConEmuChord VkState = ChordFromVk(vk); if (bKeyDown) m_SkippedMsg = 0; const ConEmuHotKey* pHotKey = ProcessHotKey(VkState, bKeyDown, pszChars, pRCon); // Для "одиночных" if (pHotKey && mn_LastSingleModifier) { if (pHotKey != ConEmuSkipHotKey) { mb_LastSingleModifier = TRUE; } } else if (!pHotKey && !(VkState.Mod & (cvk_Ctrl|cvk_Alt|cvk_Shift))) { if (bKeyDown) { // Раз мы попали сюда - значит сам Apps у нас не хоткей, но может быть модификатором? if ((vk == VK_APPS) && gpSet->isModifierExist(vk)) { m_SkippedMsg = messg; m_SkippedMsgWParam = wParam; m_SkippedMsgLParam = lParam; // Откладываем либо до // *) нажатия другой кнопки, не перехватываемой нами (например Apps+U) // *) отпускания самого Apps return ConEmuSkipHotKey; } } else if ((vk == VK_APPS) && m_SkippedMsg && pRCon) { // Отпускается Apps. Сначала нужно "дослать" в консоль ее нажатие pRCon->ProcessKeyboard(m_SkippedMsg, m_SkippedMsgWParam, m_SkippedMsgLParam, NULL); } } if (((VkState.Mod & cvk_ALLMASK) == cvk_Win) && (vk == VK_DOWN || vk == VK_LEFT || vk == VK_RIGHT)) { //120821 - в режиме HideCaption почему-то не выходит из Maximized по Win+Down if (gpSet->isCaptionHidden()) { if (vk == VK_DOWN) { if (::IsZoomed(ghWnd)/*тут нужен реальный Zoomed*/) { gpConEmu->SetWindowMode(wmNormal); } } } } return (pHotKey != NULL); }