i32 CKeyboard::SetLocalization(xst_castring& strLang) { //Find this locale LangMap::iterator Itr = m_mLangs.find( LangStr( strLang ) ); if( Itr == m_mLangs.end() ) { XST_LOG_ERR( "Could not find language: " << strLang << ". If you want to use this language add it first." ); return XST_FAIL; } /*HKL aBuff[10]; GetKeyboardLayoutList( 10, aBuff ); for(u32 i = 0; i < 10; ++i) { XST::CDebug::PrintDebugLN( XST::StringUtil::ToString( aBuff[ i ] ) ); }*/ m_WinHKL = LoadKeyboardLayoutA( Itr->second.data(), KLF_ACTIVATE ); if( m_WinHKL == xst_null ) { XST_LOG_ERR( "Failed to set keybaord localization: " << GetLastError() ); return XST_FAIL; } if( ActivateKeyboardLayout( m_WinHKL, KLF_RESET ) == 0 ) { XST_LOG_ERR( "Failed to activate the keyboard localization: " << GetLastError() ); return XST_FAIL; } m_strCurrLang = strLang; return XST_OK; }
void NativeTextfieldWin::HandleKeystroke() { const MSG* msg = GetCurrentMessage(); ScopedFreeze freeze(this, GetTextObjectModel()); TextfieldController* controller = textfield_->GetController(); bool handled = false; if(controller) { KeyEvent event(*msg); handled = controller->HandleKeyEvent(textfield_, event); } if(!handled) { OnBeforePossibleChange(); if(msg->wParam==ui::VKEY_HOME || msg->wParam==ui::VKEY_END) { // DefWindowProc() might reset the keyboard layout when it receives a // keydown event for VKEY_HOME or VKEY_END. When the window was created // with WS_EX_LAYOUTRTL and the current keyboard layout is not a RTL one, // if the input text is pure LTR text, the layout changes to the first RTL // keyboard layout in keyboard layout queue; if the input text is // bidirectional text, the layout changes to the keyboard layout of the // first RTL character in input text. When the window was created without // WS_EX_LAYOUTRTL and the current keyboard layout is not a LTR one, if // the input text is pure RTL text, the layout changes to English; if the // input text is bidirectional text, the layout changes to the keyboard // layout of the first LTR character in input text. Such keyboard layout // change behavior is surprising and inconsistent with keyboard behavior // elsewhere, so reset the layout in this case. HKL layout = GetKeyboardLayout(0); DefWindowProc(msg->message, msg->wParam, msg->lParam); ActivateKeyboardLayout(layout, KLF_REORDER); } else { DefWindowProc(msg->message, msg->wParam, msg->lParam); } // CRichEditCtrl automatically turns on IMF_AUTOKEYBOARD when the user // inputs an RTL character, making it difficult for the user to control // what language is set as they type. Force this off to make the edit's // behavior more stable. const int lang_options = SendMessage(EM_GETLANGOPTIONS, 0, 0); if(lang_options & IMF_AUTOKEYBOARD) { SendMessage(EM_SETLANGOPTIONS, 0, lang_options&~IMF_AUTOKEYBOARD); } OnAfterPossibleChange(true); } }
void CIme::DisableIme() { while( ImmIsIME( GetKeyboardLayout( 0 ))) ActivateKeyboardLayout(( HKL )HKL_NEXT, 0 );//如果ime打开通过循环切换到下一个关闭 m_bIme = false; m_szImeName[ 0 ] = 0; m_szCompStr[ 0 ] = 0; m_szCompReadStr[ 0 ] = 0; m_szCandList[ 0 ] = 0; m_nImeCursor = 0; }
static int load_kb_layout(lua_State *L) { const char* pnL1 = luaL_checkstring(L, -1); HKL hkl = LoadKeyboardLayout(pnL1, KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL); if (!hkl){ lua_pushboolean(L, false); return 1; } ActivateKeyboardLayout(hkl, KLF_REORDER); lua_pushboolean(L, true); return 1; }
void KeyboardLayout::setActiveKeyboardLayout(int langCode, int subCode) { if (langCode == 0 || langCode == LOWORD(GetKeyboardLayout(0))) return; qApp->setOverrideCursor(Qt::WaitCursor); LCID dwLang = MAKELANGID(langCode, subCode); WCHAR szBuf[32]; wsprintf(szBuf, L"%.8x", dwLang); HKL result = ActivateKeyboardLayout(LoadKeyboardLayout(szBuf, KLF_ACTIVATE | KLF_REPLACELANG), KLF_REORDER); if (result<=0) qWarning() << "unable to set keyboard layout " << GetLastError(); else qDebug() << "Keyboard layout set to "<< langCode; qApp->restoreOverrideCursor(); }
LRESULT CALLBACK KeyboardProc( int code, WPARAM wParam, LPARAM lParam ) { if(code>=0 && sharedStruct->hLayout.handle!=NULL) { CWPSTRUCT *params = (PCWPSTRUCT)lParam; if( params->hwnd == sharedStruct->dstWindow.handle && params->message == WM_KEYDOWN && params->wParam == VK_CAPITAL ) { ActivateKeyboardLayout(sharedStruct->hLayout.handle, KLF_SETFORPROCESS); sharedStruct->hLayout.handle = NULL; return 1; // Do not show the message to anyone else } } return CallNextHookEx(sharedStruct->HOOKHANDLE, code, wParam, lParam); }
BOOL ConsoleSetFocus( HWND hWnd, HANDLE hConsole, HKL hKL ) { PCONSOLE_TABLE ConTbl; HKL OldhKL; ConTbl = SearchConsole(hConsole); if (ConTbl == NULL) { DBGPRINT(("CONIME: Error! Cannot found registed Console\n")); return FALSE; } if ( gfDoNotKillFocus ){ gfDoNotKillFocus = FALSE; } OldhKL = ConTbl->hklActive ; ConTbl->hklActive = hKL; ActivateKeyboardLayout(ConTbl->hklActive, 0); ImmAssociateContext(hWnd, ConTbl->hIMC_Current); if (OldhKL == 0) { GetIMEName( ConTbl ); ConTbl->ImmGetProperty = ImmGetProperty(ConTbl->hklActive , IGP_PROPERTY); } //v-hirshi Jun.13.1996 #if defined(LATER_DBCS) // kazum ImmSetActiveContextConsoleIME(hWnd, TRUE); //v-hirshi Jun.13.1996 #endif LastConsole = hConsole; #ifdef DEBUG_MODE DisplayInformation(hWnd, hConsole); #endif ImeUISetOpenStatus( hWnd ); if (ConTbl->lpCompStrMem != NULL) ReDisplayCompositionStr( hWnd ); return TRUE; }
LRESULT CSearchBarCtrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if ( WM_INPUTLANGCHANGEREQUEST == message ) { if(GetKeyboardLayout(0) == (HKL)lParam) return 0; UINT count = GetKeyboardLayoutList(0,NULL); if(count == 0) return 0; HKL* lpList = new HKL[count]; count = GetKeyboardLayoutList(count,lpList); BOOL bFound = FALSE; for(int i=0;i<count;i++) { if((HKL)lParam == lpList[i]) { bFound = TRUE; break; } } if(lpList) { delete[] lpList; lpList = NULL; } if(!bFound) { CString sID; sID.Format( L"%08x",lParam ); LoadKeyboardLayout(sID,KLF_ACTIVATE); } else { ActivateKeyboardLayout((HKL)lParam,KLF_REORDER); } return 0; } return CWnd::WindowProc(message, wParam, lParam); }
VOID KbdTestGetKeyNameText() { WCHAR text[20]; HWND hForegroundWnd = NULL; DWORD threadId = 0; HKL hCurrKL = NULL; BYTE btKeyState[256]; UINT scanCode = 21; GUITHREADINFO threadInfo; DWORD focusThread = NULL; hForegroundWnd = GetForegroundWindow(); threadId = GetWindowThreadProcessId(hForegroundWnd, NULL); DebugPrint(L"hForegroundWnd=%x, threadId=%x\n", hForegroundWnd, threadId); memset(&threadInfo, 0, sizeof(threadInfo)); threadInfo.cbSize = sizeof(threadInfo); if (!GetGUIThreadInfo(threadId, &threadInfo)) { DebugPrint(L"GetGUIThreadInfo failed with err=%x for threadId=%x", GetLastError(), threadId); } DebugPrint(L"thread.hwndFocus=%x\n", threadInfo.hwndFocus); focusThread = GetWindowThreadProcessId(threadInfo.hwndFocus, NULL); DebugPrint(L"focusThread=%x\n", focusThread); hCurrKL = GetKeyboardLayout(threadId); DebugPrint(L"Thread hKL=%x\n", hCurrKL); for (int i = 0; i < 10; i++) { hCurrKL = ActivateKeyboardLayout((HKL)HKL_NEXT, 0); DebugPrint(L"ActivateKeyboardLayout:prevHKL=%x\n", hCurrKL); hCurrKL = GetKeyboardLayout(0); DebugPrint(L"Curr thread hKL=%x\n", hCurrKL); //GetKeyboardState(btKeyState); memset(btKeyState, 0, sizeof(btKeyState)); memset(text, 0, sizeof(text)); ToUnicodeEx(MapVirtualKey(scanCode, MAPVK_VSC_TO_VK_EX), scanCode, btKeyState, text, RTL_NUMBER_OF(text), 0, hCurrKL); DebugPrint(L"ToUnicodeEx text is=%ws, unicode=%x\n", text, (USHORT)text[0]); } }
BOOL InputLangchange( HWND hWnd, DWORD CharSet, HKL hkl ) { PCONSOLE_TABLE ConTbl; ConTbl = SearchConsole(LastConsole); if (ConTbl == NULL) { DBGPRINT(("CONIME: Error! Cannot found registed Console\n")); return FALSE; } ConTbl->hklActive = hkl; ActivateKeyboardLayout(ConTbl->hklActive, 0); GetIMEName( ConTbl ); ImeUIOpenStatusWindow(hWnd); return TRUE; }
int ChangeLayout(HWND hTextWnd, BYTE TextOperation, BOOL CurrentWord) { HKL hklCurLay, hklToLay; LPTSTR ptszInText, ptszOutText, ptszMBox, ptszPopupText, ptszTemp; CHARRANGE crSelection, crTemp; DWORD dwStartWord, dwEndWord; int i, iRes; BYTE WindowType = WTYPE_Unknown; BOOL WindowIsReadOnly, TwoWay; if (hTextWnd == NULL) hTextWnd = GetFocus(); if (hTextWnd == NULL) return 0; //--------------Определяем тип окна----------------- IEVIEWEVENT ieEvent = { 0 }; ieEvent.cbSize = sizeof(IEVIEWEVENT); ieEvent.iType = IEE_GET_SELECTION; if (ServiceExists(MS_HPP_EG_EVENT)) { // То же самое для History++ ieEvent.hwnd = hTextWnd; ptszInText = (TCHAR*)CallService(MS_HPP_EG_EVENT, 0, (LPARAM)&ieEvent); if (!IsBadStringPtr(ptszInText, MaxTextSize)) WindowType = WTYPE_HistoryPP; } if ((WindowType == WTYPE_Unknown) && (ServiceExists(MS_IEVIEW_EVENT))) { // Извращенное определение хэндла IEView ieEvent.hwnd = GetParent(GetParent(hTextWnd)); ptszInText = (TCHAR*)CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&ieEvent); if (!IsBadStringPtr(ptszInText, MaxTextSize)) WindowType = WTYPE_IEView; } if (WindowType == WTYPE_Unknown) { ptszTemp = (LPTSTR)mir_alloc(255 * sizeof(TCHAR)); i = GetClassName(hTextWnd, ptszTemp, 255); ptszTemp[i] = 0; if (_tcsstr(CharUpper(ptszTemp), _T("RICHEDIT")) != NULL) { WindowType = WTYPE_RichEdit; SendMessage(hTextWnd, EM_EXGETSEL, 0, (LPARAM)&crSelection); } mir_free(ptszTemp); } if (WindowType == WTYPE_Unknown) { SendMessage(hTextWnd, EM_GETSEL, (WPARAM)&crSelection.cpMin, (LPARAM)&crSelection.cpMax); if ((SendMessage(hTextWnd, WM_GETDLGCODE, 0, 0)&(DLGC_HASSETSEL)) && (crSelection.cpMin >= 0)) WindowType = WTYPE_Edit; } // Получим текст из Рича или обычного Едита if (WindowType == WTYPE_RichEdit || WindowType == WTYPE_Edit) { dwStartWord = dwEndWord = -1; SendMessage(hTextWnd, WM_SETREDRAW, FALSE, 0); // Бэкап выделения crTemp = crSelection; // Если имеется выделенный текст, то получим его if (crSelection.cpMin != crSelection.cpMax) { if (WindowType == WTYPE_RichEdit) { EditStreamData esdData; EDITSTREAM esStream = { 0 }; esStream.dwCookie = (DWORD)&esdData; esStream.pfnCallback = EditStreamOutRtf; if (SendMessage(hTextWnd, EM_STREAMOUT, SF_TEXT | SF_UNICODE | SFF_SELECTION, (LPARAM)&esStream) > 0) ptszInText = GeTStringFromStreamData(&esdData); else { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } if (WindowType == WTYPE_Edit) { ptszTemp = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); ptszInText = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); iRes = SendMessage(hTextWnd, WM_GETTEXT, (WPARAM)MaxTextSize, (LPARAM)ptszTemp); if (!IsBadStringPtr(ptszInText, MaxTextSize) && (iRes > 0)) { _tcsncpy(ptszInText, &ptszTemp[crSelection.cpMin], crSelection.cpMax - crSelection.cpMin); ptszInText[crSelection.cpMax - crSelection.cpMin] = 0; mir_free(ptszTemp); } else { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } } // Если выделения нет, то получим нужный текст else { // Получаем весь текст в поле if (WindowType == WTYPE_RichEdit) { crTemp.cpMin = 0; crTemp.cpMax = -1; SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crTemp); EditStreamData esdData; EDITSTREAM esStream = { 0 }; esStream.dwCookie = (DWORD)&esdData; esStream.pfnCallback = EditStreamOutRtf; if (SendMessage(hTextWnd, EM_STREAMOUT, SF_TEXT | SF_UNICODE | SFF_SELECTION, (LPARAM)&esStream) != 0) ptszInText = GeTStringFromStreamData(&esdData); else { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } if (WindowType == WTYPE_Edit) { ptszInText = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); iRes = SendMessage(hTextWnd, WM_GETTEXT, (WPARAM)MaxTextSize, (LPARAM)ptszInText); if (!IsBadStringPtr(ptszInText, MaxTextSize) && (iRes > 0)) { crTemp.cpMin = 0; crTemp.cpMax = (int)_tcslen(ptszInText); } else { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } // Получаем текущее слово if (CurrentWord) { for (dwStartWord = crSelection.cpMin; (dwStartWord > 0) && (_tcschr(ptszSeparators, ptszInText[dwStartWord - 1]) == NULL); dwStartWord--); for (dwEndWord = crSelection.cpMin; (dwEndWord < (_tcslen(ptszInText))) && (_tcschr(ptszSeparators, ptszInText[dwEndWord]) == NULL); dwEndWord++); crTemp.cpMin = dwStartWord; crTemp.cpMax = dwEndWord; if (WindowType == WTYPE_RichEdit) { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crTemp); EditStreamData esdData; EDITSTREAM esStream = { 0 }; esStream.dwCookie = (DWORD)&esdData; esStream.pfnCallback = EditStreamOutRtf; if (SendMessage(hTextWnd, EM_STREAMOUT, SF_TEXT | SF_UNICODE | SFF_SELECTION, (LPARAM)&esStream) != 0) ptszInText = GeTStringFromStreamData(&esdData); else { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } if (WindowType == WTYPE_Edit) { ptszTemp = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); _tcsncpy(ptszTemp, &ptszInText[crTemp.cpMin], crTemp.cpMax - crTemp.cpMin); ptszTemp[crTemp.cpMax - crTemp.cpMin] = 0; _tcscpy(ptszInText, ptszTemp); mir_free(ptszTemp); if (_tcslen(ptszInText) == 0) { mir_free(ptszInText); SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); return 1; } } } } } //---------------Выдаем результаты-------------------- WindowIsReadOnly = FALSE; if (WindowType == WTYPE_IEView || WindowType == WTYPE_HistoryPP) WindowIsReadOnly = TRUE; // if ((SendMessage(hTextWnd, EM_GETOPTIONS, 0, 0)&ECO_READONLY)) if (WindowType == WTYPE_RichEdit || WindowType == WTYPE_Edit) if (GetWindowLongPtr(hTextWnd, GWL_STYLE) & ES_READONLY) WindowIsReadOnly = TRUE; // Лог Иевью и ХисториПП в режиме эмуляции Иевью и поля только для чтения. if (WindowType != WTYPE_Unknown && !IsBadStringPtr(ptszInText, MaxTextSize)) if (WindowIsReadOnly) { ptszMBox = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); ptszMBox[0] = 0; if (TextOperation == TOT_Layout) { hklCurLay = GetLayoutOfText(ptszInText); hklToLay = GetNextLayout(hklCurLay); TwoWay = (moOptions.TwoWay) && (bLayNum == 2); if (bLayNum == 2) { ptszMBox = ChangeTextLayout(ptszInText, hklCurLay, hklToLay, TwoWay); } else { for (i = 0; i < bLayNum; i++) if (hklLayouts[i] != hklCurLay) { if (_tcslen(ptszMBox) != 0) _tcscat(ptszMBox, _T("\n\n")); ptszTemp = GetShortNameOfLayout(hklLayouts[i]); _tcscat(ptszMBox, ptszTemp); _tcscat(ptszMBox, _T(":\n")); ptszOutText = ChangeTextLayout(ptszInText, hklCurLay, hklLayouts[i], FALSE); _tcscat(ptszMBox, ptszOutText); mir_free(ptszTemp); mir_free(ptszOutText); } } } else if (TextOperation == TOT_Case) { ptszMBox = ChangeTextCase(ptszInText); } mir_free(ptszInText); if ((WindowType == WTYPE_Edit) || (WindowType == WTYPE_RichEdit)) { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); } if (TextOperation == TOT_Layout) SkinPlaySound(SND_ChangeLayout); else if (TextOperation == TOT_Case) SkinPlaySound(SND_ChangeCase); if (moOptions.CopyToClipboard) CopyTextToClipboard(ptszMBox); //-------------------------------Покажем попапы------------------------------------------ if (moOptions.ShowPopup) { ptszPopupText = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); _tcscpy(ptszPopupText, ptszMBox); POPUPDATAT_V2 pdtData = { 0 }; pdtData.cbSize = sizeof(pdtData); _tcsncpy(pdtData.lptzContactName, TranslateT(ModuleName), MAX_CONTACTNAME); _tcsncpy(pdtData.lptzText, ptszPopupText, MAX_SECONDLINE); switch (poOptions.bColourType) { case PPC_POPUP: pdtData.colorBack = pdtData.colorText = 0; break; case PPC_WINDOWS: pdtData.colorBack = GetSysColor(COLOR_BTNFACE); pdtData.colorText = GetSysColor(COLOR_WINDOWTEXT); break; case PPC_CUSTOM: pdtData.colorBack = poOptions.crBackColour; pdtData.colorText = poOptions.crTextColour; break; } switch (poOptions.bTimeoutType) { case PPT_POPUP: pdtData.iSeconds = 0; break; case PPT_PERMANENT: pdtData.iSeconds = -1; break; case PPC_CUSTOM: pdtData.iSeconds = poOptions.bTimeout; break; } pdtData.PluginData = ptszPopupText; pdtData.PluginWindowProc = (WNDPROC)CKLPopupDlgProc; pdtData.lchIcon = hPopupIcon; poOptions.paActions[0].lchIcon = hCopyIcon; pdtData.lpActions = poOptions.paActions; pdtData.actionCount = 1; if (CallService(MS_POPUP_ADDPOPUPT, (WPARAM)&pdtData, APF_NEWDATA) < 0) { mir_free(ptszPopupText); MessageBox(NULL, ptszMBox, TranslateT(ModuleName), MB_ICONINFORMATION); } } mir_free(ptszMBox); } //------------------Редактируемые поля ---------------------------- else { if (TextOperation == TOT_Layout) { hklCurLay = GetLayoutOfText(ptszInText); hklToLay = GetNextLayout(hklCurLay); TwoWay = (moOptions.TwoWay) && (bLayNum == 2); ptszOutText = ChangeTextLayout(ptszInText, hklCurLay, hklToLay, TwoWay); } else if (TextOperation == TOT_Case) { ptszOutText = ChangeTextCase(ptszInText); } if (WindowType == WTYPE_RichEdit) { SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crTemp); SendMessage(hTextWnd, EM_REPLACESEL, FALSE, (LPARAM)ptszOutText); SendMessage(hTextWnd, EM_EXSETSEL, 0, (LPARAM)&crSelection); } else { ptszTemp = (LPTSTR)mir_alloc(MaxTextSize*sizeof(TCHAR)); SendMessage(hTextWnd, WM_GETTEXT, (WPARAM)MaxTextSize, (LPARAM)ptszTemp); for (i = crTemp.cpMin; i < crTemp.cpMax; i++) ptszTemp[i] = ptszOutText[i - crTemp.cpMin]; SendMessage(hTextWnd, WM_SETTEXT, 0, (LPARAM)ptszTemp); SendMessage(hTextWnd, EM_SETSEL, crSelection.cpMin, crSelection.cpMax); mir_free(ptszTemp); } // Переключим раскладку или изменим состояние Caps Lock if (TextOperation == TOT_Layout && hklToLay != NULL && moOptions.ChangeSystemLayout) ActivateKeyboardLayout(hklToLay, KLF_SETFORPROCESS); else if (TextOperation == TOT_Case) { // Если нужно инвертнуть if (moOptions.bCaseOperations == 0) { keybd_event(VK_CAPITAL, 0x45, 0, 0); keybd_event(VK_CAPITAL, 0x45, KEYEVENTF_KEYUP, 0); } // Если нужно отключить else if (moOptions.bCaseOperations == 1) { if (GetKeyState(VK_CAPITAL) & 0x0001) { keybd_event(VK_CAPITAL, 0x45, 0, 0); keybd_event(VK_CAPITAL, 0x45, KEYEVENTF_KEYUP, 0); } } } SendMessage(hTextWnd, WM_SETREDRAW, TRUE, 0); InvalidateRect(hTextWnd, NULL, FALSE); if (TextOperation == TOT_Layout) SkinPlaySound(SND_ChangeLayout); else if (TextOperation == TOT_Case) SkinPlaySound(SND_ChangeCase); mir_free(ptszInText); mir_free(ptszOutText); } return 0; }
BOOL WINAPI PlugServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam) { BOOL lbRc = FALSE; //HANDLE hPipe = (HANDLE)ahPipe; //CESERVER_REQ *pIn=NULL; //BYTE cbBuffer[64]; // Для большей части команд нам хватит //DWORD cbRead = 0, cbWritten = 0, dwErr = 0; BOOL fSuccess = FALSE; MSectionThread SCT(csTabs); // Send a message to the pipe server and read the response. //fSuccess = ReadFile(hPipe, cbBuffer, sizeof(cbBuffer), &cbRead, NULL); //dwErr = GetLastError(); //if (!fSuccess && (dwErr != ERROR_MORE_DATA)) //{ // _ASSERTE("ReadFile(pipe) failed"==NULL); // CloseHandle(hPipe); // return 0; //} //pIn = (CESERVER_REQ*)cbBuffer; // Пока cast, если нужно больше - выделим память //_ASSERTE(pIn->hdr.cbSize>=sizeof(CESERVER_REQ_HDR) && cbRead>=sizeof(CESERVER_REQ_HDR)); //_ASSERTE(pIn->hdr.nVersion == CESERVER_REQ_VER); if (pIn->hdr.cbSize < sizeof(CESERVER_REQ_HDR) || /*in.nSize < cbRead ||*/ pIn->hdr.nVersion != CESERVER_REQ_VER) { //CloseHandle(hPipe); gpPlugServer->BreakConnection(pInst); return FALSE; } //int nAllSize = pIn->hdr.cbSize; //pIn = (CESERVER_REQ*)Alloc(nAllSize,1); //_ASSERTE(pIn!=NULL); //if (!pIn) //{ // CloseHandle(hPipe); // return 0; //} //memmove(pIn, cbBuffer, cbRead); //_ASSERTE(pIn->hdr.nVersion==CESERVER_REQ_VER); //LPBYTE ptrData = ((LPBYTE)pIn)+cbRead; //nAllSize -= cbRead; //while(nAllSize>0) //{ // //_tprintf(TEXT("%s\n"), chReadBuf); // // Break if TransactNamedPipe or ReadFile is successful // if (fSuccess) // break; // // Read from the pipe if there is more data in the message. // fSuccess = ReadFile( // hPipe, // pipe handle // ptrData, // buffer to receive reply // nAllSize, // size of buffer // &cbRead, // number of bytes read // NULL); // not overlapped // // Exit if an error other than ERROR_MORE_DATA occurs. // if (!fSuccess && ((dwErr = GetLastError()) != ERROR_MORE_DATA)) // break; // ptrData += cbRead; // nAllSize -= cbRead; //} //TODO("Может возникнуть ASSERT, если консоль была закрыта в процессе чтения"); //_ASSERTE(nAllSize==0); //if (nAllSize>0) //{ // if (((LPVOID)cbBuffer) != ((LPVOID)pIn)) // Free(pIn); // CloseHandle(hPipe); // return 0; // удалось считать не все данные //} UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR); // Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат //fSuccess = WriteFile( hPipe, pOut, pOut->nSize, &cbWritten, NULL); if (pIn->hdr.nCmd == CMD_LANGCHANGE) { _ASSERTE(nDataSize>=4); //-V112 // LayoutName: "00000409", "00010409", ... // А HKL от него отличается, так что передаем DWORD // HKL в x64 выглядит как: "0x0000000000020409", "0xFFFFFFFFF0010409" DWORD hkl = pIn->dwData[0]; DWORD dwLastError = 0; HKL hkl1 = NULL, hkl2 = NULL; if (hkl) { WCHAR szLoc[10]; _wsprintf(szLoc, SKIPLEN(countof(szLoc)) L"%08x", hkl); hkl1 = LoadKeyboardLayout(szLoc, KLF_ACTIVATE|KLF_REORDER|KLF_SUBSTITUTE_OK|KLF_SETFORPROCESS); hkl2 = ActivateKeyboardLayout(hkl1, KLF_SETFORPROCESS|KLF_REORDER); if (!hkl2) dwLastError = GetLastError(); else fSuccess = TRUE; } pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = fSuccess; ppReply->dwData[1] = fSuccess ? ((DWORD)(LONG)(LONG_PTR)hkl2) : dwLastError; } } //} else if (pIn->hdr.nCmd == CMD_DEFFONT) { // // исключение - асинхронный, результат не требуется // SetConsoleFontSizeTo(FarHwnd, 4, 6); // MoveWindow(FarHwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 1); // чтобы убрать возможные полосы прокрутки... else if (pIn->hdr.nCmd == CMD_REQTABS || pIn->hdr.nCmd == CMD_SETWINDOW) { MSectionLock SC; SC.Lock(csTabs, FALSE, 1000); DWORD nSetWindowWait = (DWORD)-1; if (pIn->hdr.nCmd == CMD_SETWINDOW) { ResetEvent(ghSetWndSendTabsEvent); // Для FAR2 - сброс QSearch выполняется в том же макро, в котором актирируется окно if (gFarVersion.dwVerMajor == 1 && pIn->dwData[1]) { // А вот для FAR1 - нужно шаманить ProcessCommand(CMD_CLOSEQSEARCH, TRUE/*bReqMainThread*/, pIn->dwData/*хоть и не нужно?*/); } // Пересылается 2 DWORD BOOL bCmdRc = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->dwData); DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW waiting...\n"); WARNING("Почему для FAR1 не ждем? Есть возможность заблокироваться в 1.7 или что?"); if ((gFarVersion.dwVerMajor >= 2) && bCmdRc) { DWORD nTimeout = 2000; #ifdef _DEBUG if (IsDebuggerPresent()) nTimeout = 120000; #endif nSetWindowWait = WaitForSingleObject(ghSetWndSendTabsEvent, nTimeout); } DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW finished\n"); } if (gpTabs) { //fSuccess = WriteFile(hPipe, gpTabs, gpTabs->hdr.cbSize, &cbWritten, NULL); pcbReplySize = gpTabs->hdr.cbSize; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { memmove(ppReply->Data, gpTabs->Data, pcbReplySize - sizeof(ppReply->hdr)); lbRc = TRUE; } } SC.Unlock(); } else if (pIn->hdr.nCmd == CMD_FARSETCHANGED) { // Установить переменные окружения // Плагин это получает в ответ на CECMD_RESOURCES, посланное в GUI при загрузке плагина _ASSERTE(nDataSize>=8); FAR_REQ_FARSETCHANGED *pFarSet = (FAR_REQ_FARSETCHANGED*)pIn->Data; cmd_FarSetChanged(pFarSet); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = TRUE; } //_ASSERTE(nDataSize<sizeof(gsMonitorEnvVar)); //gbMonitorEnvVar = false; //// Плагин FarCall "нарушает" COMSPEC (копирует содержимое запускаемого процесса) //bool lbOk = false; //if (nDataSize<sizeof(gsMonitorEnvVar)) //{ // memcpy(gsMonitorEnvVar, pszName, nDataSize); // lbOk = true; //} //UpdateEnvVar(pszName); ////while (*pszName && *pszValue) { //// const wchar_t* pszChanged = pszValue; //// // Для ConEmuOutput == AUTO выбирается по версии ФАРа //// if (!lstrcmpi(pszName, L"ConEmuOutput") && !lstrcmp(pszChanged, L"AUTO")) { //// if (gFarVersion.dwVerMajor==1) //// pszChanged = L"ANSI"; //// else //// pszChanged = L"UNICODE"; //// } //// // Если в pszValue пустая строка - удаление переменной //// SetEnvironmentVariableW(pszName, (*pszChanged != 0) ? pszChanged : NULL); //// // //// pszName = pszValue + lstrlenW(pszValue) + 1; //// if (*pszName == 0) break; //// pszValue = pszName + lstrlenW(pszName) + 1; ////} //gbMonitorEnvVar = lbOk; } else if (pIn->hdr.nCmd == CMD_DRAGFROM) { #ifdef _DEBUG BOOL *pbClickNeed = (BOOL*)pIn->Data; COORD *crMouse = (COORD *)(pbClickNeed+1); #endif ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, pIn->Data); CESERVER_REQ* pCmdRet = NULL; ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet); if (pCmdRet) { //fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL); pcbReplySize = pCmdRet->hdr.cbSize; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr)); } Free(pCmdRet); } //if (gpCmdRet && gpCmdRet == pCmdRet) //{ // Free(gpCmdRet); // gpCmdRet = NULL; gpData = NULL; gpCursor = NULL; //} } else if (pIn->hdr.nCmd == CMD_EMENU) { COORD *crMouse = (COORD *)pIn->Data; #ifdef _DEBUG const wchar_t *pszUserMacro = (wchar_t*)(crMouse+1); #endif DWORD ClickArg[2] = {TRUE, MAKELONG(crMouse->X, crMouse->Y)}; // Выделить файл под курсором DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) begin\n"); BOOL lb1 = ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, ClickArg/*pIn->Data*/); DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) done\n"); // А теперь, собственно вызовем меню DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) begin\n"); BOOL lb2 = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data); DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) done\n"); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = lb1; ppReply->dwData[1] = lb1; } } else if (pIn->hdr.nCmd == CMD_ACTIVEWNDTYPE) { int nWindowType = -1; //CESERVER_REQ Out; //ExecutePrepareCmd(&Out, CMD_ACTIVEWNDTYPE, sizeof(CESERVER_REQ_HDR)+sizeof(DWORD)); if (gFarVersion.dwVerMajor>=2) nWindowType = GetActiveWindowType(); //fSuccess = WriteFile(hPipe, &Out, Out.hdr.cbSize, &cbWritten, NULL); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = nDataSize; } } else { CESERVER_REQ* pCmdRet = NULL; BOOL lbCmd = ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet); if (pCmdRet) { //fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL); pcbReplySize = pCmdRet->hdr.cbSize; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr)); } Free(pCmdRet); } //if (gpCmdRet && gpCmdRet == pCmdRet) { // Free(gpCmdRet); // gpCmdRet = NULL; gpData = NULL; gpCursor = NULL; //} } //// Освободить память //if (((LPVOID)cbBuffer) != ((LPVOID)pIn)) // Free(pIn); //CloseHandle(hPipe); return lbRc; }
// Если (anFromShowWindow != -1), значит функу зовут из ShowWindow void OnGuiWindowAttached(HWND hWindow, HMENU hMenu, LPCSTR asClassA, LPCWSTR asClassW, DWORD anStyle, DWORD anStyleEx, BOOL abStyleHidden, int anFromShowWindow/*=-1*/) { DWORD nCurStyle = (DWORD)user->getWindowLongPtrW(hWindow, GWL_STYLE); DWORD nCurStyleEx = (DWORD)user->getWindowLongPtrW(hWindow, GWL_EXSTYLE); user->allowSetForegroundWindow(ASFW_ANY); // VLC создает несколько "подходящих" окон, но ShowWindow зовет // только для одного из них. Поэтому фактический аттач делаем // только в том случае, если окно "видимое" if ((!(nCurStyle & WS_VISIBLE)) && (anFromShowWindow <= SW_HIDE)) { // Значит потом, из ShowWindow return; } ghAttachGuiClient = hWindow; gnAttachGuiClientThreadId = user->getWindowThreadProcessId(hWindow, NULL); gbForceShowGuiClient = TRUE; gbAttachGuiClient = FALSE; // Только одно окно приложения. Пока? #if 0 // Для WS_CHILDWINDOW меню нельзя указать при создании окна if (!hMenu && !ghAttachGuiClientMenu && (asClassA || asClassW)) { BOOL lbRcClass; WNDCLASSEXA wca = {sizeof(WNDCLASSEXA)}; WNDCLASSEXW wcw = {sizeof(WNDCLASSEXW)}; if (asClassA) { lbRcClass = GetClassInfoExA(GetModuleHandle(NULL), asClassA, &wca); if (lbRcClass) ghAttachGuiClientMenu = LoadMenuA(wca.hInstance, wca.lpszMenuName); } else { lbRcClass = GetClassInfoExW(GetModuleHandle(NULL), asClassW, &wcw); if (lbRcClass) ghAttachGuiClientMenu = LoadMenuW(wca.hInstance, wcw.lpszMenuName); } hMenu = ghAttachGuiClientMenu; } if (hMenu) { // Для WS_CHILDWINDOW - не работает SetMenu(hWindow, hMenu); HMENU hSys = GetSystemMenu(hWindow, FALSE); TODO("Это в принципе прокатывает, но нужно транслировать WM_SYSCOMMAND -> WM_COMMAND, соответственно, перехватывать WndProc, или хук ставить"); if (hSys) { TODO("Хотя, хорошо бы не все в Popup засоывать, а извлечь ChildPopups из hMenu"); InsertMenu(hSys, 0, MF_BYPOSITION|MF_POPUP, (UINT_PTR)hMenu, L"Window menu"); InsertMenu(hSys, 1, MF_BYPOSITION|MF_SEPARATOR, NULL, NULL); } } #endif DWORD nSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_ATTACHGUIAPP); CESERVER_REQ *pIn = ExecuteNewCmd(CECMD_ATTACHGUIAPP, nSize); gnAttachGuiClientFlags = agaf_Success; // С приложенями .Net - приходится работать как с WS_CHILD, // иначе в них "не нажимаются" тулбары и меню if (IsDotNetWindow(hWindow)) { gnAttachGuiClientFlags |= (agaf_DotNet|agaf_WS_CHILD); } // Если в окне нет меню - работаем с ним как с WS_CHILD // так не возникает проблем с активацией и т.д. else if (user->getMenu(hWindow) == NULL) { if (IsQtWindow(asClassA, asClassW)) gnAttachGuiClientFlags |= (agaf_NoMenu|agaf_QtWindow|agaf_WS_CHILD); else gnAttachGuiClientFlags |= (agaf_NoMenu|agaf_WS_CHILD); } pIn->AttachGuiApp.nFlags = gnAttachGuiClientFlags; pIn->AttachGuiApp.nPID = GetCurrentProcessId(); pIn->AttachGuiApp.hAppWindow = hWindow; pIn->AttachGuiApp.Styles.nStyle = nCurStyle; // стили могли измениться после создания окна, pIn->AttachGuiApp.Styles.nStyleEx = nCurStyleEx; // поэтому получим актуальные user->getWindowRect(hWindow, &pIn->AttachGuiApp.rcWindow); GetModuleFileName(NULL, pIn->AttachGuiApp.sAppFilePathName, countof(pIn->AttachGuiApp.sAppFilePathName)); pIn->AttachGuiApp.hkl = (DWORD)(LONG)(LONG_PTR)GetKeyboardLayout(0); wchar_t szGuiPipeName[128]; msprintf(szGuiPipeName, countof(szGuiPipeName), CEGUIPIPENAME, L".", (DWORD)ghConEmuWnd); // AttachThreadInput DWORD nConEmuTID = user->getWindowThreadProcessId(ghConEmuWnd, NULL); DWORD nTID = GetCurrentThreadId(); _ASSERTEX(nTID==gnHookMainThreadId || nTID==gnAttachGuiClientThreadId); BOOL bAttachRc = user->attachThreadInput(nTID, nConEmuTID, TRUE); DWORD nAttachErr = GetLastError(); UNREFERENCED_PARAMETER(bAttachRc); UNREFERENCED_PARAMETER(nAttachErr); HWND hPreFocus = user->getFocus(); CESERVER_REQ* pOut = ExecuteCmd(szGuiPipeName, pIn, 0/*Default timeout*/, NULL); ExecuteFreeResult(pIn); // abStyleHidden == TRUE, если окно при создании указало флаг WS_VISIBLE (т.е. не собиралось звать ShowWindow) if (pOut) { if (pOut->hdr.cbSize > sizeof(CESERVER_REQ_HDR)) { _ASSERTE((pOut->AttachGuiApp.nFlags & agaf_Success) == agaf_Success); BOOL lbRc = FALSE; _ASSERTE(pOut->AttachGuiApp.hConEmuBack && pOut->AttachGuiApp.hConEmuDc && (HWND)pOut->AttachGuiApp.hConEmuDc!=(HWND)pOut->AttachGuiApp.hConEmuBack); _ASSERTE((ghConEmuWndBack==NULL) || (pOut->AttachGuiApp.hConEmuBack==ghConEmuWndBack)); _ASSERTE(ghConEmuWnd && (ghConEmuWnd==pOut->AttachGuiApp.hConEmuWnd)); ghConEmuWnd = pOut->AttachGuiApp.hConEmuWnd; SetConEmuHkWindows(pOut->AttachGuiApp.hConEmuDc, pOut->AttachGuiApp.hConEmuBack); //gbGuiClientHideCaption = pOut->AttachGuiApp.bHideCaption; gGuiClientStyles = pOut->AttachGuiApp.Styles; #ifdef _DEBUG HWND hFocus = user->getFocus(); DWORD nFocusPID = 0; if (hFocus) { user->getWindowThreadProcessId(hFocus, &nFocusPID); DWORD nConEmuPID = 0; user->getWindowThreadProcessId(ghConEmuWnd, &nConEmuPID); if (nFocusPID != GetCurrentProcessId() && nFocusPID != nConEmuPID) { _ASSERTE(hFocus==NULL || (nFocusPID==GetCurrentProcessId() || nFocusPID == nConEmuPID)); hFocus = NULL; } } #endif if (pOut->AttachGuiApp.hkl) { LONG_PTR hkl = (LONG_PTR)(LONG)pOut->AttachGuiApp.hkl; lbRc = ActivateKeyboardLayout((HKL)hkl, KLF_SETFORPROCESS) != NULL; UNREFERENCED_PARAMETER(lbRc); } //grcAttachGuiClientPos = pOut->AttachGuiApp.rcWindow; ReplaceGuiAppWindow(abStyleHidden); //if (hPreFocus) //{ // user->setFocus(hPreFocus); //} UINT nMsgID = user->registerWindowMessageW(CONEMUMSG_RESTORECHILDFOCUS); user->postMessageW(ghConEmuWndBack, nMsgID, 0,0); //// !!! OnSetForegroundWindow не подходит - он дергает Cmd. ////user->setForegroundWindow(ghConEmuWnd); //#if 0 //wchar_t szClass[64] = {}; user->getClassNameW(hFocus, szClass, countof(szClass)); //MessageBox(NULL, szClass, L"WasFocused", MB_SYSTEMMODAL); //#endif ////if (!(nCurStyle & WS_CHILDWINDOW)) //{ // // Если ставить WS_CHILD - пропадет меню! // //nCurStyle = (nCurStyle | WS_CHILDWINDOW|WS_TABSTOP); // & ~(WS_THICKFRAME/*|WS_CAPTION|WS_MINIMIZEBOX|WS_MAXIMIZEBOX*/); // //user->setWindowLongPtrW(hWindow, GWL_STYLE, nCurStyle); // if (gnAttachGuiClientFlags & agaf_DotNet) // { // } // else // { // SetParent(hWindow, ghConEmuWndBack); // } //} // //RECT rcGui = grcAttachGuiClientPos = pOut->AttachGuiApp.rcWindow; //if (user->setWindowPos(hWindow, HWND_TOP, rcGui.left,rcGui.top, rcGui.right-rcGui.left, rcGui.bottom-rcGui.top, // SWP_DRAWFRAME | /*SWP_FRAMECHANGED |*/ (abStyleHidden ? SWP_SHOWWINDOW : 0))) //{ // if (abStyleHidden) // abStyleHidden = FALSE; //} // //// !!! OnSetForegroundWindow не подходит - он дергает Cmd. //user->setForegroundWindow(ghConEmuWnd); ////if (hFocus) ////SetFocus(hFocus ? hFocus : hWindow); // hFocus==NULL, эффекта нет ////OnSetForegroundWindow(hWindow); ////user->postMessage(ghConEmuWnd, WM_NCACTIVATE, TRUE, 0); ////user->postMessage(ghConEmuWnd, WM_NCPAINT, 0, 0); //user->postMessage(hWindow, WM_NCPAINT, 0, 0); } ExecuteFreeResult(pOut); } if (abStyleHidden) { user->showWindow(hWindow, SW_SHOW); } }
Bool window_subsystem_init( char * error_buf) { WNDCLASSW wc; HDC dc; HBITMAP hbm; OSVERSIONINFO os = { sizeof( OSVERSIONINFO)}; guts. version = GetVersion(); GetVersionEx( &os); guts. alloc_utf8_to_wchar_visual = (( os.dwMajorVersion > 5) || (os.dwMajorVersion == 5 && os.dwMinorVersion > 1)) ? alloc_utf8_to_wchar_visual : alloc_utf8_to_wchar; guts. mainThreadId = GetCurrentThreadId(); guts. errorMode = SetErrorMode( SEM_FAILCRITICALERRORS); guts. desktopWindow = GetDesktopWindow(); memset( &wc, 0, sizeof( wc)); wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wc.lpfnWndProc = ( WNDPROC) generic_app_handler; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = guts. instance; wc.hIcon = LoadIcon( guts. instance, IDI_APPLICATION); wc.hCursor = LoadCursor( NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)NULL; wc.lpszClassName = L"GenericApp"; RegisterClassW( &wc); memset( &wc, 0, sizeof( wc)); wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wc.lpfnWndProc = ( WNDPROC) generic_frame_handler; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = guts. instance; wc.hIcon = LoadIcon( guts. instance, IDI_APPLICATION); wc.hCursor = LoadCursor( NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)NULL; wc.lpszClassName = L"GenericFrame"; RegisterClassW( &wc); memset( &wc, 0, sizeof( wc)); wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wc.lpfnWndProc = ( WNDPROC) generic_view_handler; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = guts. instance; wc.hIcon = LoadIcon( guts. instance, IDI_APPLICATION); wc.hCursor = NULL; // LoadCursor( NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)NULL; wc.lpszClassName = L"Generic"; RegisterClassW( &wc); stylusMan = hash_create(); fontMan = hash_create(); patMan = hash_create(); menuMan = hash_create(); imageMan = hash_create(); regnodeMan = hash_create(); create_font_hash(); { LOGBRUSH b = { BS_HOLLOW, 0, 0}; Font f; hPenHollow = CreatePen( PS_NULL, 0, 0); hBrushHollow = CreateBrushIndirect( &b); hPatHollow. dotsCount = 0; hPatHollow. dotsPtr = nil; FONTSTRUCSIZE = (char *)(&(f. name)) - (char *)(&f); } if (!( dc = dc_alloc())) return false; guts. displayResolution. x = GetDeviceCaps( dc, LOGPIXELSX); guts. displayResolution. y = GetDeviceCaps( dc, LOGPIXELSY); { LOGFONT lf; HFONT sfont; // getting most common font name memset( &lf, 0, sizeof( lf)); lf. lfCharSet = OEM_CHARSET; lf. lfOutPrecision = OUT_DEFAULT_PRECIS; lf. lfClipPrecision = CLIP_DEFAULT_PRECIS; lf. lfQuality = PROOF_QUALITY; lf. lfPitchAndFamily = DEFAULT_PITCH; sfont = SelectObject( dc, CreateFontIndirect( &lf)); GetTextFace( dc, 256, guts. defaultSystemFont); // getting common fixed font name lf. lfHeight = 320; lf. lfPitchAndFamily = FIXED_PITCH; DeleteObject( SelectObject( dc, CreateFontIndirect( &lf))); GetTextFace( dc, 256, guts. defaultFixedFont); // getting common variable font name lf. lfPitchAndFamily = VARIABLE_PITCH; DeleteObject( SelectObject( dc, CreateFontIndirect( &lf))); GetTextFace( dc, 256, guts. defaultVariableFont); DeleteObject( SelectObject( dc, sfont)); // getting system font presets memset( &guts. windowFont, 0, sizeof( Font)); strcpy( guts. windowFont. name, DEFAULT_WIDGET_FONT); guts. windowFont. size = DEFAULT_WIDGET_FONT_SIZE; guts. windowFont. width = guts. windowFont. height = C_NUMERIC_UNDEF; #ifdef FONT_CHECK guts. windowFont. size = 12; #endif apc_font_pick( nilHandle, &guts. windowFont, &guts. windowFont); guts. ncmData. cbSize = sizeof( NONCLIENTMETRICS); SystemParametersInfo( SPI_GETNONCLIENTMETRICS, sizeof( NONCLIENTMETRICS), ( PVOID) &guts. ncmData, 0); font_logfont2font( &guts. ncmData. lfMenuFont, &guts. menuFont, &guts. displayResolution); font_logfont2font( &guts. ncmData. lfMessageFont, &guts. msgFont, &guts. displayResolution); font_logfont2font( &guts. ncmData. lfCaptionFont, &guts. capFont, &guts. displayResolution); } memset( &guts. displayBMInfo, 0, sizeof( guts. displayBMInfo)); guts. displayBMInfo. bmiHeader. biSize = sizeof( BITMAPINFO); if ( !( hbm = GetCurrentObject( dc, OBJ_BITMAP))) { apiErr; dc_free(); return false; } if ( !GetDIBits( dc, hbm, 0, 0, NULL, &guts. displayBMInfo, DIB_PAL_COLORS)) { guts. displayBMInfo. bmiHeader. biBitCount = GetDeviceCaps( dc, BITSPIXEL); guts. displayBMInfo. bmiHeader. biPlanes = GetDeviceCaps( dc, PLANES); } dc_free(); guts. insertMode = true; guts. iconSizeSmall. x = GetSystemMetrics( SM_CXSMICON); guts. iconSizeSmall. y = GetSystemMetrics( SM_CYSMICON); guts. iconSizeLarge. x = GetSystemMetrics( SM_CXICON); guts. iconSizeLarge. y = GetSystemMetrics( SM_CYICON); guts. pointerSize. x = GetSystemMetrics( SM_CXCURSOR); guts. pointerSize. y = GetSystemMetrics( SM_CYCURSOR); list_create( &guts. transp, 8, 8); list_create( &guts. files, 8, 8); list_create( &guts. sockets, 8, 8); // selecting locale layout, more or less latin-like { char buf[ KL_NAMELENGTH * 2] = ""; HKL current = GetKeyboardLayout( 0); int i, j, size = GetKeyboardLayoutList( 0, nil); HKL * kl = ( HKL *) malloc( sizeof( HKL) * size); guts. keyLayout = nil; if ( !GetKeyboardLayoutName( buf)) apiErr; for ( j = 0; j < ( sizeof( keyLayouts) / sizeof( char*)); j++) { if ( strncmp( buf + 4, keyLayouts[ j], 4) == 0) { guts. keyLayout = current; goto found_1; } } if ( kl) { GetKeyboardLayoutList( size, kl); for ( i = 0; i < size; i++) { ActivateKeyboardLayout( kl[ i], 0); if ( !GetKeyboardLayoutName( buf)) apiErr; for ( j = 0; j < ( sizeof( keyLayouts) / sizeof( char*)); j++) { if ( strncmp( buf + 4, keyLayouts[ j], 4) == 0) { guts. keyLayout = kl[ i]; goto found_2; } } } found_2:; ActivateKeyboardLayout( current, 0); } found_1:; free( kl); } guts. currentKeyState = guts. keyState; memset( guts. emptyKeyState, 0, sizeof( guts. emptyKeyState)); guts. smDblClk. x = GetSystemMetrics( SM_CXDOUBLECLK); guts. smDblClk. y = GetSystemMetrics( SM_CYDOUBLECLK); return true; }
//------------------------------------------------- LRESULT CALLBACK MyKeyHook(int code, WPARAM wParam, LPARAM lParam) { int keyType; unsigned short charBuf; if (!pShMem->Initialized) return 0; if (code < 0) return CallNextHookEx(pShMem->keyHook,code,wParam,lParam); // determine if current window is a console, if so returns TCHAR className[128]; className[0] = 0; GetClassName(GetForegroundWindow(), className, 128); if (_tcscmp(className, _T("ConsoleWindowClass")) == 0) return CallNextHookEx(pShMem->keyHook,code,wParam,lParam); GetKeyboardState(KeyState); HKL curLayout = GetKeyboardLayout(0); if (curLayout != OriginalLayout && curLayout != ViKeyboardLayout) OriginalLayout = curLayout; if (CheckSwitchKey(wParam,lParam) || CheckShortcuts(wParam, lParam)) return 1; if ((pShMem->vietKey || (pShMem->options.macroEnabled && pShMem->options.alwaysMacro)) && code == HC_ACTION && !ClipboardIsEmpty) { if (wParam != PasteKey1 && wParam != PasteKey2 && !(lParam & IsReleased)) { // postpone this key keybd_event(wParam, HIBYTE(LOWORD(lParam)), (lParam & IsExtended)? KEYEVENTF_EXTENDEDKEY : 0, 0); return 1; } if (wParam == PasteKey2 && (lParam & IsReleased)) { ClearClipboard(); } } if (CheckBack(wParam)) return 1; if ((pShMem->vietKey || (pShMem->options.macroEnabled && pShMem->options.alwaysMacro)) && (code == HC_ACTION) && !(lParam & IsReleased)) { // if (CheckBack(wParam)) return 1; if (PuttingBacks) { if (wParam != VK_BACK) { keybd_event(wParam, HIBYTE(LOWORD(lParam)), (lParam & IsExtended)? KEYEVENTF_EXTENDEDKEY : 0, 0); return 1; } return CallNextHookEx(pShMem->keyHook,code,wParam,lParam); } if (pShMem->keyMode != WINCP1258_CHARSET && LayoutChangeForced) { ActivateKeyboardLayout(OriginalLayout, 0); LayoutChangeForced = 0; } // HKL curLayout = GetKeyboardLayout(0); if (((KeyState[VK_CONTROL] & 0x80) == 0 && (KeyState[VK_MENU] & 0x80) == 0) || ( curLayout != UsKeyboardLayout && ClipboardIsEmpty)) { //(pShMem->inMethod == VIQR_INPUT || pShMem->inMethod == VIQR_STAR_INPUT) && int remap = 0; keyType = ToAscii(wParam,UINT(HIWORD(lParam)),KeyState, &charBuf, 0); if (keyType == 1 && UsKeyboardLayout && ViKeyboardLayout && (KeyState[VK_CONTROL] & 0x80) == 0 && (KeyState[VK_MENU] & 0x80) == 0 && curLayout == ViKeyboardLayout) { //need to remap unsigned short mappedChar; int res = ToAsciiEx(wParam, UINT(HIWORD(lParam)), KeyState, &mappedChar, 0, UsKeyboardLayout); if (res == 1 && ((unsigned char)mappedChar) != ((unsigned char)charBuf)) { charBuf = mappedChar; remap = 1; } } if (keyType == 1 || keyType < 0) { unsigned char c = (unsigned char)charBuf; if (wParam >= VK_NUMPAD0 && wParam <= VK_NUMPAD9) VnKbd.putChar(c); // don't process numeric keypad else { VnKbd.process(c); if (VnKbd.backs!=0 || VnKbd.keysPushed!=0) { if (keyType < 0) //dead key, one more back VnKbd.backs++; PushBacks(); return 1; } if (remap) { SHORT scanCode = VkKeyScan((unsigned char)charBuf); lParam = (scanCode << 16) + 1; PostMessage(GetFocus(), (pShMem->options.useIME)? WM_IME_CHAR : WM_CHAR, (unsigned char)charBuf, lParam); return 1; } } } else { if (wParam!=VK_SHIFT && wParam!=VK_INSERT && wParam != VK_MENU && wParam != VK_CONTROL && ClipboardIsEmpty) { ResetBuffer(); } } } else { if (wParam != VK_MENU && wParam != VK_CONTROL && ClipboardIsEmpty) { ResetBuffer(); } } } else if ((code == HC_ACTION) && !(lParam & IsReleased)) { if (LayoutChangeForced && OriginalLayout && GetKeyboardLayout(0) == ViKeyboardLayout && OriginalLayout != ViKeyboardLayout) { ActivateKeyboardLayout(OriginalLayout, 0); LayoutChangeForced = 0; if (ToAsciiEx(wParam, UINT(HIWORD(lParam)), KeyState, &charBuf, 0, OriginalLayout) == 1) { SHORT scanCode = VkKeyScan((unsigned char)charBuf); lParam = (scanCode << 16) + 1; PostMessage(GetFocus(), (pShMem->options.useIME)? WM_IME_CHAR : WM_CHAR, (unsigned char)charBuf, lParam); return 1; } } } return CallNextHookEx(pShMem->keyHook,code,wParam,lParam); }
//------------------------------------------------- void PushBuffer(HWND wndFocused) { SHORT scanCode; WPARAM lParam; PostMessage(wndFocused,WM_KEYUP,VK_PAUSE, (LPARAM(VK_PAUSE_SCAN)<<16)+LPARAM(IsReleased)+1); if (pShMem->keyMode == UNICODE_CHARSET && pShMem->codeTable.encoding == UNICODE_UCS2) { if (!pShMem->options.useUnicodeClipboard && pShMem->unicodePlatform && IsWindowUnicode(wndFocused)) { for (int i=0; i<VnKbd.keysPushed; i++) { scanCode = VkKeyScanW(VnKbd.uniPush[i]); lParam = (scanCode << 16) + 1; PostMessageW(wndFocused, (pShMem->options.useIME)? WM_IME_CHAR : WM_CHAR, VnKbd.uniPush[i], lParam); } } else { OpenClipboard(pShMem->hMainDlg); EmptyClipboard(); VnKbd.uniPush[VnKbd.keysPushed] = 0; // null-terminated VnKbd.ansiPush[VnKbd.keysPushed] = 0; VnKbd.keysPushed++; HGLOBAL hBuf = GlobalAlloc(GMEM_MOVEABLE, sizeof(WORD) * VnKbd.keysPushed); HGLOBAL hBufAnsi = GlobalAlloc(GMEM_MOVEABLE, VnKbd.keysPushed); LPVOID pBuf = GlobalLock(hBuf); LPVOID pBufAnsi = GlobalLock(hBufAnsi); memcpy(pBuf, VnKbd.uniPush, sizeof(WORD) * VnKbd.keysPushed); memcpy(pBufAnsi, VnKbd.ansiPush, VnKbd.keysPushed); GlobalUnlock(hBuf); GlobalUnlock(hBufAnsi); SetClipboardData(CF_UNICODETEXT, hBuf); SetClipboardData(CF_TEXT, hBufAnsi); CloseClipboard(); sendPasteCmd(); ClipboardIsEmpty = 0; } } else if (pShMem->keyMode == DECOMPOSED_UNICODE_CHARSET) { if (pShMem->unicodePlatform && IsWindowUnicode(wndFocused)) { for (int i=0; i<VnKbd.keysPushed; i++) { scanCode = VkKeyScanW(VnKbd.uniPush[i]); lParam = (scanCode << 16) + 1; PostMessageW(wndFocused, (pShMem->options.useIME)? WM_IME_CHAR : WM_CHAR, VnKbd.uniPush[i],lParam); } } else { if (ViKeyboardLayout != NULL) { ActivateKeyboardLayout(ViKeyboardLayout, 0); LayoutChangeForced = 1; } int count = WideCharToMultiByte(1258, 0, VnKbd.uniPush, VnKbd.keysPushed, (char *)VnKbd.ansiPush, VnKbd.keysPushed, 0, 0); for (int i=0; i<count; i++) { scanCode = VkKeyScan(VnKbd.ansiPush[i]); lParam = (scanCode << 16) + 1; PostMessage(wndFocused, (pShMem->options.useIME)? WM_IME_CHAR : WM_CHAR, VnKbd.ansiPush[i], lParam); } } } else { if (pShMem->keyMode == WINCP1258_CHARSET && ViKeyboardLayout!=NULL) { ActivateKeyboardLayout(ViKeyboardLayout, 0); LayoutChangeForced = 1; } for (int i=0; i<VnKbd.keysPushed; i++) { scanCode = VkKeyScan(VnKbd.ansiPush[i]); lParam = (scanCode << 16) + 1; // PostMessage(wndFocused, WM_IME_CHAR, VnKbd.ansiPush[i], lParam); PostMessage(wndFocused, (pShMem->options.useIME)? WM_IME_CHAR : WM_CHAR, VnKbd.ansiPush[i], lParam); } } return; }
// Для облегчения жизни - сервер кеширует данные, калбэк может использовать ту же память (*pcbMaxReplySize) BOOL WINAPI HookServerCommand(LPVOID pInst, CESERVER_REQ* pCmd, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam) { WARNING("Собственно, выполнение команд!"); BOOL lbRc = FALSE, lbFRc; switch (pCmd->hdr.nCmd) { case CECMD_ATTACHGUIAPP: { // При 'внешнем' аттаче инициированном юзером из ConEmu _ASSERTEX(pCmd->AttachGuiApp.hConEmuWnd && ghConEmuWnd==pCmd->AttachGuiApp.hConEmuWnd); //ghConEmuWndDC = pOut->AttachGuiApp.hConEmuWndDC; -- еще нету AttachGuiWindow(pCmd->AttachGuiApp.hAppWindow); // Результат pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD); lbRc = ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize); if (lbRc) ppReply->dwData[0] = (DWORD)ghAttachGuiClient; } // CECMD_ATTACHGUIAPP break; case CECMD_SETFOCUS: break; case CECMD_SETPARENT: break; case CECMD_CTRLBREAK: if (CHECK_CMD_SIZE(pCmd,2*sizeof(DWORD))) { lbFRc = GenerateConsoleCtrlEvent(pCmd->dwData[0], pCmd->dwData[1]); pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD); lbRc = ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize); if (lbRc) ppReply->dwData[0] = lbFRc; } // CECMD_CTRLBREAK break; case CECMD_SETGUIEXTERN: if (ghAttachGuiClient && (pCmd->DataSize() >= sizeof(CESERVER_REQ_SETGUIEXTERN))) { SetGuiExternMode(pCmd->SetGuiExtern.bExtern, NULL/*pCmd->SetGuiExtern.bDetach ? &pCmd->SetGuiExtern.rcOldPos : NULL*/); pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD); lbRc = ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize); if (lbRc) ppReply->dwData[0] = gbGuiClientExternMode; if (pCmd->SetGuiExtern.bExtern && pCmd->SetGuiExtern.bDetach) { gbAttachGuiClient = gbGuiClientAttached = FALSE; ghAttachGuiClient = ghConEmuWndDC = ghConEmuWnd = NULL; gnServerPID = 0; } } // CECMD_SETGUIEXTERN break; case CECMD_LANGCHANGE: { LONG_PTR hkl = (LONG_PTR)(LONG)pCmd->dwData[0]; BOOL lbRc = ActivateKeyboardLayout((HKL)hkl, KLF_SETFORPROCESS) != NULL; DWORD nErrCode = lbRc ? 0 : GetLastError(); pcbReplySize = sizeof(CESERVER_REQ_HDR)+2*sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize)) { ppReply->dwData[0] = lbRc; ppReply->dwData[1] = nErrCode; } } // CECMD_LANGCHANGE break; case CECMD_MOUSECLICK: { BOOL bProcessed = FALSE; if ((gReadConsoleInfo.InReadConsoleTID || gReadConsoleInfo.LastReadConsoleInputTID) && (pCmd->DataSize() >= 4*sizeof(WORD))) { bProcessed = OnReadConsoleClick(pCmd->wData[0], pCmd->wData[1], (pCmd->wData[2] != 0), (pCmd->wData[3] != 0)); } lbRc = TRUE; pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize)) { ppReply->dwData[0] = bProcessed; } } // CECMD_MOUSECLICK break; case CECMD_PROMPTCMD: { BOOL bProcessed = FALSE; if ((gReadConsoleInfo.InReadConsoleTID || gReadConsoleInfo.LastReadConsoleInputTID) && (pCmd->DataSize() >= 2*sizeof(wchar_t))) { bProcessed = OnExecutePromptCmd((LPCWSTR)pCmd->wData); } lbRc = TRUE; pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize)) { ppReply->dwData[0] = bProcessed; } } break; case CECMD_STARTSERVER: { int nErrCode = -1; wchar_t szSelf[MAX_PATH+16], *pszNamePtr, szArgs[128]; PROCESS_INFORMATION pi = {}; STARTUPINFO si = {sizeof(si)}; if (GetModuleFileName(ghOurModule, szSelf, MAX_PATH) && ((pszNamePtr = (wchar_t*)PointToName(szSelf)) != NULL)) { // Запускаем сервер той же битности, что и текущий процесс _wcscpy_c(pszNamePtr, 16, WIN3264TEST(L"ConEmuC.exe",L"ConEmuC64.exe")); if (gnImageSubsystem==IMAGE_SUBSYSTEM_WINDOWS_GUI) { _ASSERTEX(pCmd->NewServer.hAppWnd!=0); _wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /GID=%u /GHWND=%08X /GUIATTACH=%08X /PID=%u", pCmd->NewServer.nGuiPID, (DWORD)pCmd->NewServer.hGuiWnd, (DWORD)pCmd->NewServer.hAppWnd, GetCurrentProcessId()); gbAttachGuiClient = TRUE; } else { _ASSERTEX(pCmd->NewServer.hAppWnd==0); _wsprintf(szArgs, SKIPLEN(countof(szArgs)) L" /GID=%u /GHWND=%08X /ATTACH /PID=%u", pCmd->NewServer.nGuiPID, (DWORD)pCmd->NewServer.hGuiWnd, GetCurrentProcessId()); } lbRc = CreateProcess(szSelf, szArgs, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); if (lbRc) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); nErrCode = 0; } else { nErrCode = HRESULT_FROM_WIN32(GetLastError()); } } lbRc = true; // Вернуть результат однозначно pcbReplySize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_START); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pCmd->hdr.nCmd, pcbReplySize)) { ppReply->dwData[0] = pi.dwProcessId; ppReply->dwData[1] = (DWORD)nErrCode; } } // CECMD_STARTSERVER break; } // Если (lbRc == FALSE) - в пайп будет отдана "пустышка" ((DWORD)0) return lbRc; }
BOOL ConImeInputLangchange( HWND hWnd, HANDLE hConsole, HKL hkl ) { PCONSOLE_TABLE ConTbl; LPCONIME_UIMODEINFO lpModeInfo; COPYDATASTRUCT CopyData; INT counter ; LPHKL_TABLE lphklListNew ; ConTbl = SearchConsole(hConsole); if (ConTbl == NULL) { // cannot find specified console. // It might be last console lost focus. // try Last Console. ConTbl = SearchConsole(LastConsole); if (ConTbl == NULL) { DBGPRINT(("CONIME: Error! Cannot found registed Console\n")); return FALSE; } } if (ConTbl->lphklList == NULL) { return FALSE; } if (IS_IME_KBDLAYOUT(ConTbl->hklActive)) { for (counter = 0 ; counter < ConTbl->hklListMax ;counter ++) { if (ConTbl->lphklList[counter].hkl == 0 || ConTbl->lphklList[counter].hkl == ConTbl->hklActive) { break; } } if (counter >= ConTbl->hklListMax) { ASSERT(counter == ConTbl->hklListMax); // reallocation lphklListNew = LocalAlloc(LPTR, sizeof(HKL_TABLE) * (ConTbl->hklListMax + HKL_TABLE_INCREMENT) ) ; if (lphklListNew != NULL) { CopyMemory(lphklListNew , ConTbl->lphklList , sizeof(HKL_TABLE) * ConTbl->hklListMax) ; ConTbl->hklListMax += HKL_TABLE_INCREMENT ; LocalFree(ConTbl->lphklList); ConTbl->lphklList = lphklListNew; } else { return FALSE ; } } ASSERT(ConTbl->lphklList != NULL); ConTbl->lphklList[counter].hkl = ConTbl->hklActive; ConTbl->lphklList[counter].dwConversion = ConTbl->dwConversion | (ConTbl->fOpen ? IME_CMODE_OPEN : 0) ; } ActivateKeyboardLayout(hkl, 0); ConTbl->hklActive = hkl; GetIMEName( ConTbl ); ImeUIOpenStatusWindow(hWnd); ConTbl->ImmGetProperty = ImmGetProperty(ConTbl->hklActive , IGP_PROPERTY); lpModeInfo = (LPCONIME_UIMODEINFO)LocalAlloc( LPTR, sizeof(CONIME_UIMODEINFO) ) ; if ( lpModeInfo == NULL) { return FALSE; } CopyData.dwData = CI_CONIMEMODEINFO ; CopyData.cbData = sizeof(CONIME_UIMODEINFO) ; CopyData.lpData = lpModeInfo ; if (IS_IME_KBDLAYOUT(hkl)) { for (counter=0; counter < ConTbl->hklListMax ; counter++) { if (ConTbl->lphklList[counter].hkl == hkl) { SetNLSMode(hWnd, hConsole,ConTbl->lphklList[counter].dwConversion ) ; ImeUIOpenStatusWindow(hWnd) ; if (ImeUIMakeInfoString(ConTbl, lpModeInfo)) { ConsoleImeSendMessage( ConTbl->hWndCon, (WPARAM)hWnd, (LPARAM)&CopyData ) ; } } } } else { SetNLSMode(hWnd, hConsole,ConTbl->dwConversion & ~IME_CMODE_OPEN ) ; lpModeInfo->ModeStringLen = 0 ; lpModeInfo->Position = VIEW_RIGHT ; ConsoleImeSendMessage( ConTbl->hWndCon, (WPARAM)hWnd, (LPARAM)&CopyData ) ; } LocalFree( lpModeInfo ); return TRUE; }
BOOL WINAPI PlugServerCommand(LPVOID pInst, CESERVER_REQ* pIn, CESERVER_REQ* &ppReply, DWORD &pcbReplySize, DWORD &pcbMaxReplySize, LPARAM lParam) { BOOL lbRc = FALSE; BOOL fSuccess = FALSE; MSectionThread SCT(csTabs); if (pIn->hdr.cbSize < sizeof(CESERVER_REQ_HDR) || /*in.nSize < cbRead ||*/ pIn->hdr.nVersion != CESERVER_REQ_VER) { gpPlugServer->BreakConnection(pInst); return FALSE; } UINT nDataSize = pIn->hdr.cbSize - sizeof(CESERVER_REQ_HDR); // Все данные из пайпа получены, обрабатываем команду и возвращаем (если нужно) результат switch (pIn->hdr.nCmd) { case CMD_LANGCHANGE: { _ASSERTE(nDataSize>=4); //-V112 // LayoutName: "00000409", "00010409", ... // А HKL от него отличается, так что передаем DWORD // HKL в x64 выглядит как: "0x0000000000020409", "0xFFFFFFFFF0010409" DWORD hkl = pIn->dwData[0]; DWORD dwLastError = 0; HKL hkl1 = NULL, hkl2 = NULL; if (hkl) { WCHAR szLoc[10]; _wsprintf(szLoc, SKIPLEN(countof(szLoc)) L"%08x", hkl); hkl1 = LoadKeyboardLayout(szLoc, KLF_ACTIVATE|KLF_REORDER|KLF_SUBSTITUTE_OK|KLF_SETFORPROCESS); hkl2 = ActivateKeyboardLayout(hkl1, KLF_SETFORPROCESS|KLF_REORDER); if (!hkl2) dwLastError = GetLastError(); else fSuccess = TRUE; } pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = fSuccess; ppReply->dwData[1] = fSuccess ? ((DWORD)(LONG)(LONG_PTR)hkl2) : dwLastError; } break; } // CMD_LANGCHANGE #if 0 case CMD_DEFFONT: { // исключение - асинхронный, результат не требуется SetConsoleFontSizeTo(FarHwnd, 4, 6); MoveWindow(FarHwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), 1); // чтобы убрать возможные полосы прокрутки... break; } CMD_DEFFONT #endif case CMD_REQTABS: case CMD_SETWINDOW: { MSectionLock SC; SC.Lock(csTabs, FALSE, 1000); DWORD nSetWindowWait = (DWORD)-1; if (pIn->hdr.nCmd == CMD_SETWINDOW) { ResetEvent(ghSetWndSendTabsEvent); // Для FAR2 - сброс QSearch выполняется в том же макро, в котором актирируется окно if (gFarVersion.dwVerMajor == 1 && pIn->dwData[1]) { // А вот для FAR1 - нужно шаманить Plugin()->ProcessCommand(CMD_CLOSEQSEARCH, TRUE/*bReqMainThread*/, pIn->dwData/*хоть и не нужно?*/); } // Пересылается 2 DWORD BOOL bCmdRc = Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->dwData); DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW waiting...\n"); WARNING("Почему для FAR1 не ждем? Есть возможность заблокироваться в 1.7 или что?"); if ((gFarVersion.dwVerMajor >= 2) && bCmdRc) { DWORD nTimeout = 2000; #ifdef _DEBUG if (IsDebuggerPresent()) nTimeout = 120000; #endif nSetWindowWait = WaitForSingleObject(ghSetWndSendTabsEvent, nTimeout); } if (nSetWindowWait == WAIT_TIMEOUT) { gbForceSendTabs = TRUE; DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW timeout !!!\n"); } else { DEBUGSTRCMD(L"Plugin: PlugServerThreadCommand: CMD_SETWINDOW finished\n"); } } if (gpTabs && (nSetWindowWait != WAIT_TIMEOUT)) { //fSuccess = WriteFile(hPipe, gpTabs, gpTabs->hdr.cbSize, &cbWritten, NULL); pcbReplySize = gpTabs->hdr.cbSize; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { memmove(ppReply->Data, gpTabs->Data, pcbReplySize - sizeof(ppReply->hdr)); lbRc = TRUE; } } SC.Unlock(); break; } // CMD_REQTABS, CMD_SETWINDOW case CMD_FARSETCHANGED: { // Установить переменные окружения // Плагин это получает в ответ на CECMD_RESOURCES, посланное в GUI при загрузке плагина _ASSERTE(nDataSize>=8); FAR_REQ_FARSETCHANGED *pFarSet = (FAR_REQ_FARSETCHANGED*)pIn->Data; cmd_FarSetChanged(pFarSet); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = TRUE; } //_ASSERTE(nDataSize<sizeof(gsMonitorEnvVar)); //gbMonitorEnvVar = false; //// Плагин FarCall "нарушает" COMSPEC (копирует содержимое запускаемого процесса) //bool lbOk = false; //if (nDataSize<sizeof(gsMonitorEnvVar)) //{ // memcpy(gsMonitorEnvVar, pszName, nDataSize); // lbOk = true; //} //UpdateEnvVar(pszName); ////while (*pszName && *pszValue) { //// const wchar_t* pszChanged = pszValue; //// // Для ConEmuOutput == AUTO выбирается по версии ФАРа //// if (!lstrcmpi(pszName, L"ConEmuOutput") && !lstrcmp(pszChanged, L"AUTO")) { //// if (gFarVersion.dwVerMajor==1) //// pszChanged = L"ANSI"; //// else //// pszChanged = L"UNICODE"; //// } //// // Если в pszValue пустая строка - удаление переменной //// SetEnvironmentVariableW(pszName, (*pszChanged != 0) ? pszChanged : NULL); //// // //// pszName = pszValue + lstrlenW(pszValue) + 1; //// if (*pszName == 0) break; //// pszValue = pszName + lstrlenW(pszName) + 1; ////} //gbMonitorEnvVar = lbOk; break; } // CMD_FARSETCHANGED case CMD_DRAGFROM: { #ifdef _DEBUG BOOL *pbClickNeed = (BOOL*)pIn->Data; COORD *crMouse = (COORD *)(pbClickNeed+1); #endif Plugin()->ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, pIn->Data); CESERVER_REQ* pCmdRet = NULL; Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet); if (pCmdRet) { //fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL); pcbReplySize = pCmdRet->hdr.cbSize; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr)); } Free(pCmdRet); } break; } // CMD_DRAGFROM case CMD_EMENU: { COORD *crMouse = (COORD *)pIn->Data; #ifdef _DEBUG const wchar_t *pszUserMacro = (wchar_t*)(crMouse+1); #endif DWORD ClickArg[2] = {(DWORD)TRUE, (DWORD)MAKELONG(crMouse->X, crMouse->Y)}; // Выделить файл под курсором DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) begin\n"); BOOL lb1 = Plugin()->ProcessCommand(CMD_LEFTCLKSYNC, TRUE/*bReqMainThread*/, ClickArg/*pIn->Data*/); DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_LEFTCLKSYNC) done\n"); // А теперь, собственно вызовем меню DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) begin\n"); BOOL lb2 = Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data); DEBUGSTRMENU(L"\n*** ServerThreadCommand->ProcessCommand(CMD_EMENU) done\n"); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD)*2; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = lb1; ppReply->dwData[1] = lb1; } break; } // CMD_EMENU case CMD_ACTIVEWNDTYPE: { int nWindowType = -1; //CESERVER_REQ Out; //ExecutePrepareCmd(&Out, CMD_ACTIVEWNDTYPE, sizeof(CESERVER_REQ_HDR)+sizeof(DWORD)); if (gFarVersion.dwVerMajor>=2) nWindowType = Plugin()->GetActiveWindowType(); //fSuccess = WriteFile(hPipe, &Out, Out.hdr.cbSize, &cbWritten, NULL); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = nDataSize; } break; } // CMD_ACTIVEWNDTYPE case CECMD_ATTACH2GUI: { BOOL bAttached = Plugin()->Attach2Gui(); pcbReplySize = sizeof(CESERVER_REQ_HDR) + sizeof(DWORD); if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; ppReply->dwData[0] = bAttached; } break; } // CECMD_ATTACH2GUI default: { CESERVER_REQ* pCmdRet = NULL; BOOL lbCmd = Plugin()->ProcessCommand(pIn->hdr.nCmd, TRUE/*bReqMainThread*/, pIn->Data, &pCmdRet); if (pCmdRet) { //fSuccess = WriteFile(hPipe, pCmdRet, pCmdRet->hdr.cbSize, &cbWritten, NULL); pcbReplySize = pCmdRet->hdr.cbSize; if (ExecuteNewCmd(ppReply, pcbMaxReplySize, pIn->hdr.nCmd, pcbReplySize)) { lbRc = TRUE; memmove(ppReply->Data, pCmdRet->Data, pCmdRet->hdr.cbSize - sizeof(ppReply->hdr)); } Free(pCmdRet); } } // default } // switch (pIn->hdr.nCmd) return lbRc; }
//************************************************************************ // CLCDInput::ProcessKeyEvent //************************************************************************ LRESULT CLCDInput::ProcessKeyEvent(int Code, WPARAM wParam, LPARAM lParam) { // Event verarbeiten if(Code == HC_ACTION) { KBDLLHOOKSTRUCT *key = (KBDLLHOOKSTRUCT *)(lParam); bool bKeyDown = !(key->flags & LLKHF_UP); bool bToggled = (m_acKeyboardState[key->vkCode] & 0x0F) != 0; if(bKeyDown) bToggled = !bToggled; m_acKeyboardState[key->vkCode] = (bKeyDown?0x80:0x00) | (bToggled?0x01:0x00); if(key->vkCode == VK_LSHIFT || key->vkCode == VK_RSHIFT) m_acKeyboardState[VK_SHIFT] = m_acKeyboardState[key->vkCode]; else if(key->vkCode == VK_LCONTROL || key->vkCode == VK_RCONTROL) m_acKeyboardState[VK_CONTROL] = m_acKeyboardState[key->vkCode]; else if(key->vkCode == VK_LMENU || key->vkCode == VK_RMENU) m_acKeyboardState[VK_MENU] = m_acKeyboardState[key->vkCode]; /* if(bKeyDown) TRACE(_T("Key pressed: %i\n"),key->vkCode); else TRACE(_T("Key released: %i\n"),key->vkCode); */ // Only handle Keyup if(bKeyDown) { // Actions with Control/Menu keys if((m_acKeyboardState[VK_LMENU] & 0x80 || m_acKeyboardState[VK_CONTROL] & 0x80) && m_acKeyboardState[VK_SHIFT] & 0x80) { ActivateKeyboardLayout((HKL)HKL_NEXT,0);//KLF_SETFORPROCESS); TRACE(_T("Keyboardlayout switched!\n")); return 1; } int res = 0,size = 0,dir = MARKER_HORIZONTAL,scroll = 0; /* if(key->vkCode == VK_DELETE) { dir = MARKER_HOLD; res = -1; if(m_strText[m_Marker[0].iPosition] == '\r') res = -2; if(m_strText.length() >= m_Marker[0].iPosition + -res) { m_strText.erase(m_Marker[0].iPosition,-res); scroll = 1; size = 1; } else { res = 0; } } else */if(key->vkCode == VK_BACK ) { if(m_Marker[0].iPosition != 0) { res = -1; if(m_strText[m_Marker[0].iPosition+res] == '\n') res = -2; m_strText.erase(m_Marker[0].iPosition+res,-res); scroll = 1; size = res; } } // Marker navigation else if (key->vkCode == VK_INSERT) { m_bInsert = !m_bInsert; } else if(key->vkCode == VK_HOME) { res = m_vLineOffsets[m_Marker[0].iLine].iOffset - m_Marker[0].iPosition; scroll = 1; } else if(key->vkCode == VK_END) { if(m_vLineOffsets.size()-1 == m_Marker[0].iLine) res = (int)m_strText.length() - m_Marker[0].iPosition; else res = (m_vLineOffsets[m_Marker[0].iLine+1].iOffset - 1 - m_vLineOffsets[m_Marker[0].iLine+1].bLineBreak) -m_Marker[0].iPosition; scroll = 1; } else if(key->vkCode == VK_UP) { res = -1; dir = MARKER_VERTICAL; } else if(key->vkCode == VK_DOWN) { res = 1; dir = MARKER_VERTICAL; } else if(key->vkCode == VK_LEFT) res = -1; else if(key->vkCode == VK_RIGHT) res = 1; else { #ifdef _UNICODE TCHAR output[4]; #else unsigned char output[2]; #endif if(key->vkCode == VK_RETURN) { bool bCtrlDown = (m_acKeyboardState[VK_CONTROL] & 0x80) != 0; if( bCtrlDown != (m_iBreakKeys == KEYS_RETURN)) { DeactivateInput(); //m_pParent->OnInputFinished(); return 1; } else { res = 2; output[0] = '\r'; output[1] = '\n'; output[2] = 0; } } else { #ifdef _UNICODE res = ToUnicode(key->vkCode,key->scanCode,m_acKeyboardState,output,4,0); #else res = ToAscii( key->vkCode,key->scanCode,m_acKeyboardState,(WORD*)output,0); #endif } if(res <= 0) res = 0; else { if(output[0] != '\r' && output[0] <= 0x001F) return 1; if(m_bInsert || m_strText[m_Marker[0].iPosition] == '\r') m_strText.insert(m_Marker[0].iPosition,(TCHAR*)output,res); else m_strText.replace(m_Marker[0].iPosition,res,(TCHAR*)output); scroll = 1; size = res; } } if(res != 0) { if(dir != MARKER_HOLD) { MoveMarker(dir,res); } UpdateOffsets(size); UpdateMarker(); ScrollToMarker(); m_lInputTime = GetTickCount(); } //WrapLine(); // ---- // Block this KeyEvent } return 1; } return CallNextHookEx(m_hKBHook, Code, wParam, lParam); }
int OnButtonPressed(WPARAM, LPARAM lParam) { CustomButtonClickData *cbcd = (CustomButtonClickData *)lParam; int iType; if (!mir_strcmp(cbcd->pszModule, "Switch Layout and Send")) iType = 1; else if (!mir_strcmp(cbcd->pszModule, "Translit and Send")) iType = 2; else if (!mir_strcmp(cbcd->pszModule, "Invert Case and Send")) iType = 3; else return 0; HWND hEdit = GetDlgItem(cbcd->hwndFrom, IDC_MESSAGE); if (!hEdit) hEdit = GetDlgItem(cbcd->hwndFrom, IDC_CHATMESSAGE); BYTE byKeybState[256]; GetKeyboardState(byKeybState); byKeybState[VK_CONTROL] = 128; SetKeyboardState(byKeybState); SendMessage(hEdit, WM_KEYDOWN, VK_UP, 0); byKeybState[VK_CONTROL] = 0; SetKeyboardState(byKeybState); TCHAR *sel = Message_GetFromStream(hEdit, SF_TEXT | SF_UNICODE); size_t slen = mir_tstrlen(sel); if (slen != 0) { switch (iType) { case 3: Invert(sel); break; case 2: Transliterate(sel); break; case 1: DWORD dwProcessID; DWORD dwThreadID = GetWindowThreadProcessId(cbcd->hwndFrom, &dwProcessID); HKL hkl = GetKeyboardLayout(dwThreadID); memset(&smgp, 0, sizeof(smgp)); smgp.cbSize = sizeof(smgp); smgp.str = sel; smgp.flag = SAFL_TCHAR; if (ServiceExists(MS_SMILEYADD_BATCHPARSE)) smileyPrs = (SMADD_BATCHPARSERES *)CallService(MS_SMILEYADD_BATCHPARSE, 0, (LPARAM)&smgp); ActivateKeyboardLayout((HKL)HKL_PREV, KLF_ACTIVATE); for (int i = 0; i < (int)slen; i++) { TCHAR tchr; BYTE keys[256] = { 0 }; SHORT vks = VkKeyScanEx(sel[i], hkl); keys[VK_SHIFT] = (HIBYTE(vks) & 1) ? 0xFF : 0x00; // shift keys[VK_CONTROL] = (HIBYTE(vks) & 2) ? 0xFF : 0x00; // ctrl keys[VK_MENU] = (HIBYTE(vks) & 4) ? 0xFF : 0x00; // alt if (!isItSmiley(i)) { if (ToUnicodeEx(LOBYTE(vks), 0, keys, &tchr, 1, 0, GetKeyboardLayout(dwThreadID)) == 1) sel[i] = tchr; } } if (smileyPrs != NULL) CallService(MS_SMILEYADD_BATCHFREE, 0, (LPARAM)smileyPrs); break; } } ptrT tszSymbol(db_get_tsa(NULL, "TranslitSwitcher", "ResendSymbol")); if (tszSymbol == NULL) { SetWindowText(hEdit, sel); SendMessage(hEdit, EM_SETSEL, 0, (LPARAM)slen); SendMessage(cbcd->hwndFrom, WM_COMMAND, IDOK, 0); } else if (_tcsncmp(sel, tszSymbol, mir_tstrlen(tszSymbol)) == 0) { SetWindowText(hEdit, sel); SendMessage(hEdit, EM_SETSEL, 0, (LPARAM)slen); SendMessage(cbcd->hwndFrom, WM_COMMAND, IDOK, 0); } else { CMString tszFinal(FORMAT, _T("%s %s"), tszSymbol, sel); SetWindowText(hEdit, tszFinal.GetString()); SendMessage(hEdit, EM_SETSEL, 0, tszFinal.GetLength()); SendMessage(cbcd->hwndFrom, WM_COMMAND, IDOK, 0); } mir_free(sel); return 1; }
void SwitchLayout(bool lastword) { HWND hwnd = GetForegroundWindow(); if (hwnd == NULL) return; DWORD dwProcessID; DWORD dwThreadID = GetWindowThreadProcessId(hwnd, &dwProcessID); HWND hwnd2 = GetFocus(); if (hwnd2 == NULL) return; TCHAR szClassName[MAX_PATH]; GetClassName(hwnd2, szClassName, _countof(szClassName)); if ((mir_tstrcmp(szClassName, _T("THppRichEdit.UnicodeClass")) == 0 || mir_tstrcmp(szClassName, _T("THistoryGrid.UnicodeClass")) == 0 || mir_tstrcmp(szClassName, _T("TExtHistoryGrid.UnicodeClass")) == 0 || mir_tstrcmp(szClassName, _T("Internet Explorer_Server")) == 0) && ServiceExists(MS_POPUP_SHOWMESSAGE)) { // make popup here TCHAR buf[2048]; if (mir_tstrcmp(szClassName, _T("Internet Explorer_Server")) == 0) { IEVIEWEVENT event; HWND hwnd3 = GetParent(GetParent(hwnd2)); memset(&event, 0, sizeof(event)); event.cbSize = sizeof(IEVIEWEVENT); event.hContact = 0; event.dwFlags = 0; event.iType = IEE_GET_SELECTION; event.hwnd = hwnd3; TCHAR *selected = (TCHAR *)CallService(MS_IEVIEW_EVENT, 0, (LPARAM)&event); mir_tstrncpy(buf, selected, _countof(buf)); } else GetWindowText(hwnd2, buf, _countof(buf)); // gimme, gimme, gimme... size_t slen = mir_tstrlen(buf); if (slen != 0) { HKL hkl; ActivateKeyboardLayout((HKL)HKL_NEXT, KLF_ACTIVATE); // go to next layout before.... hkl = GetKeyboardLayout(dwThreadID); ActivateKeyboardLayout((HKL)HKL_PREV, KLF_ACTIVATE); // return to prev layout if (ServiceExists(MS_SMILEYADD_BATCHPARSE)) { memset(&smgp, 0, sizeof(smgp)); smgp.cbSize = sizeof(smgp); smgp.str = buf; smgp.flag = SAFL_TCHAR; smileyPrs = (SMADD_BATCHPARSERES *)CallService(MS_SMILEYADD_BATCHPARSE, 0, (LPARAM)&smgp); } for (size_t i = 0; i < slen; i++) { SHORT vks; BYTE keys[256] = { 0 }; vks = VkKeyScanEx(buf[i], hkl); keys[VK_SHIFT] = (HIBYTE(vks) & 1) ? 0xFF : 0x00; // shift keys[VK_CONTROL] = (HIBYTE(vks) & 2) ? 0xFF : 0x00; // ctrl keys[VK_MENU] = (HIBYTE(vks) & 4) ? 0xFF : 0x00; // alt if (!isItSmiley(DWORD(i))) { TCHAR tchr; if (ToUnicodeEx(LOBYTE(vks), 0, keys, &tchr, 1, 0, GetKeyboardLayout(dwThreadID)) == 1) buf[i] = tchr; } } if (smileyPrs != NULL) CallService(MS_SMILEYADD_BATCHFREE, 0, (LPARAM)smileyPrs); POPUPDATAT pd = { 0 }; pd.lchIcon = IcoLib_GetIcon("Switch Layout and Send"); mir_tstrncpy(pd.lptzText, buf, _countof(pd.lptzText)); mir_tstrncpy(pd.lptzContactName, TranslateT("TranslitSwitcher"), _countof(pd.lptzContactName)); PUAddPopupT(&pd); } } else if (mir_tstrcmpi(szClassName, _T("RichEdit50W")) == 0) { size_t i, start = 0, end = 0; SHORT vks; BYTE keys[256] = { 0 }; HKL hkl = GetKeyboardLayout(dwThreadID); DWORD dwStart, dwEnd, dwFlags = SF_TEXT | SF_UNICODE; SendMessage(hwnd2, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd); bool somethingIsSelected = (dwStart != dwEnd); if (somethingIsSelected) dwFlags += SFF_SELECTION; TCHAR *sel = Message_GetFromStream(hwnd2, dwFlags); size_t slen = mir_tstrlen(sel); if (slen != 0) { if (ServiceExists(MS_SMILEYADD_BATCHPARSE)) { memset(&smgp, 0, sizeof(smgp)); smgp.cbSize = sizeof(smgp); smgp.str = sel; smgp.flag = SAFL_TCHAR; smileyPrs = (SMADD_BATCHPARSERES *)CallService(MS_SMILEYADD_BATCHPARSE, 0, (LPARAM)&smgp); } end = slen; if (lastword && !somethingIsSelected) { end = (size_t)dwStart; while (end < slen) { if (_istspace(sel[end]) || isItSmiley((int)end)) break; end++; } start = dwStart - 1; while (start > 0 && start < dwStart) { if ((_istspace(sel[start]) && !_istspace(sel[start + 1])) || isItSmiley((int)start)) break; start--; } } ActivateKeyboardLayout((HKL)HKL_PREV, KLF_ACTIVATE); for (i = start; i < end; i++) { vks = VkKeyScanEx(sel[i], hkl); keys[VK_SHIFT] = (HIBYTE(vks) & 1) ? 0xFF : 0x00; // shift keys[VK_CONTROL] = (HIBYTE(vks) & 2) ? 0xFF : 0x00; // ctrl keys[VK_MENU] = (HIBYTE(vks) & 4) ? 0xFF : 0x00; // alt if (!isItSmiley((int)i)) { TCHAR tchr; if (ToUnicodeEx(LOBYTE(vks), 0, keys, &tchr, 1, 0, GetKeyboardLayout(dwThreadID)) == 1) sel[i] = tchr; } } if (smileyPrs != NULL) CallService(MS_SMILEYADD_BATCHFREE, 0, (LPARAM)smileyPrs); if (somethingIsSelected) SendMessage(hwnd2, EM_REPLACESEL, false, (LPARAM)sel); else SetWindowText(hwnd2, sel); SendMessage(hwnd2, EM_SETSEL, (WPARAM)dwStart, (LPARAM)dwEnd); } mir_free(sel); } }
DWORD WINAPI DllStart(LPVOID /*apParm*/) { wchar_t *szModule = (wchar_t*)calloc((MAX_PATH+1),sizeof(wchar_t)); if (!GetModuleFileName(NULL, szModule, MAX_PATH+1)) _wcscpy_c(szModule, MAX_PATH+1, L"GetModuleFileName failed"); const wchar_t* pszName = PointToName(szModule); #if defined(SHOW_EXE_TIMINGS) || defined(SHOW_EXE_MSGBOX) wchar_t szTimingMsg[512]; UNREFERENCED_PARAMETER(szTimingMsg); HANDLE hTimingHandle = GetStdHandle(STD_OUTPUT_HANDLE); if (!lstrcmpi(pszName, SHOW_EXE_MSGBOX_NAME)) { gbShowExeMsgBox = true; } #endif // ******************* begin ********************* print_timings(L"DllStart: InitializeHookedModules"); InitializeHookedModules(); //HANDLE hStartedEvent = (HANDLE)apParm; #if defined(SHOW_EXE_MSGBOX) if (gbShowExeMsgBox) { STARTUPINFO si = {sizeof(si)}; GetStartupInfo(&si); LPCWSTR pszCmd = GetCommandLineW(); // GuiMessageBox еще не прокатит, ничего не инициализировано HMODULE hUser = LoadLibrary(user32); typedef int (WINAPI* MessageBoxW_t)(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType); if (hUser) { MessageBoxW_t MsgBox = (MessageBoxW_t)GetProcAddress(hUser, "MessageBoxW"); if (MsgBox) { wchar_t szMsg[128]; lstrcpyn(szMsg, pszName, 96); lstrcat(szMsg, L" loaded!"); wchar_t szTitle[64]; msprintf(szTitle, countof(szTitle), L"ConEmuHk, PID=%u, TID=%u", GetCurrentProcessId(), GetCurrentThreadId()); MsgBox(NULL, szMsg, szTitle, MB_SYSTEMMODAL); } FreeLibrary(hUser); } } #endif #ifdef _DEBUG { wchar_t szCpInfo[128]; DWORD nCP = GetConsoleOutputCP(); _wsprintf(szCpInfo, SKIPLEN(countof(szCpInfo)) L"Current Output CP = %u", nCP); print_timings(szCpInfo); } #endif if ((lstrcmpi(pszName, L"powershell.exe") == 0) || (lstrcmpi(pszName, L"powershell") == 0)) { HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); if (IsOutputHandle(hStdOut)) { gbPowerShellMonitorProgress = true; MY_CONSOLE_SCREEN_BUFFER_INFOEX csbi = {sizeof(csbi)}; if (apiGetConsoleScreenBufferInfoEx(hStdOut, &csbi)) { gnConsolePopupColors = csbi.wPopupAttributes; } else { WARNING("Получить Popup атрибуты из мэппинга"); //gnConsolePopupColors = ...; gnConsolePopupColors = 0; } } } // Поскольку процедура в принципе может быть кем-то перехвачена, сразу найдем адрес // iFindAddress = FindKernelAddress(pi.hProcess, pi.dwProcessId, &fLoadLibrary); //HMODULE hKernel = ::GetModuleHandle(L"kernel32.dll"); //if (hKernel) //{ // gfnLoadLibrary = (UINT_PTR)::GetProcAddress(hKernel, "LoadLibraryW"); // _ASSERTE(gfnLoadLibrary!=NULL); //} //else //{ // _ASSERTE(hKernel!=NULL); // gfnLoadLibrary = NULL; //} if (!GetLoadLibraryAddress()) { _ASSERTE(gfnLoadLibrary!=0); } ghUser32 = GetModuleHandle(user32); if (ghUser32) ghUser32 = LoadLibrary(user32); // если подлинкован - увеличить счетчик WARNING("Попробовать не создавать LocalSecurity при старте"); //#ifndef TESTLINK gpLocalSecurity = LocalSecurity(); //gnMsgActivateCon = RegisterWindowMessage(CONEMUMSG_ACTIVATECON); //#endif //wchar_t szSkipEventName[128]; //msprintf(szSkipEventName, SKIPLEN(countof(szSkipEventName)) CEHOOKDISABLEEVENT, GetCurrentProcessId()); //HANDLE hSkipEvent = OpenEvent(EVENT_ALL_ACCESS , FALSE, szSkipEventName); ////BOOL lbSkipInjects = FALSE; //if (hSkipEvent) //{ // gbSkipInjects = (WaitForSingleObject(hSkipEvent, 0) == WAIT_OBJECT_0); // CloseHandle(hSkipEvent); //} //else //{ // gbSkipInjects = FALSE; //} WARNING("Попробовать не ломиться в мэппинг, а взять все из переменной ConEmuData"); // Открыть мэппинг консоли и попытаться получить HWND GUI, PID сервера, и пр... if (ghConWnd) { print_timings(L"OnConWndChanged"); OnConWndChanged(ghConWnd); //GetConMap(); } if (ghConEmuWnd) { #ifdef SHOW_INJECT_MSGBOX wchar_t* szDbgMsg = (wchar_t*)calloc(1024, sizeof(wchar_t)); wchar_t* szTitle = (wchar_t*)calloc(128, sizeof(wchar_t)); msprintf(szTitle, 1024, L"ConEmuHk, PID=%u", GetCurrentProcessId()); msprintf(szDbgMsg, 128, L"SetAllHooks, ConEmuHk, PID=%u\n%s", GetCurrentProcessId(), szModule); GuiMessageBox(ghConEmuWnd, szDbgMsg, szTitle, MB_SYSTEMMODAL); free(szDbgMsg); free(szTitle); #endif } //if (!gbSkipInjects && ghConWnd) //{ // InitializeConsoleInputSemaphore(); //} print_timings(L"GetImageSubsystem"); // Необходимо определить битность и тип (CUI/GUI) процесса, в который нас загрузили gnImageBits = WIN3264TEST(32,64); gnImageSubsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; // Определим тип (CUI/GUI) GetImageSubsystem(gnImageSubsystem, gnImageBits); // Проверка чего получилось _ASSERTE(gnImageBits==WIN3264TEST(32,64)); _ASSERTE(gnImageSubsystem==IMAGE_SUBSYSTEM_WINDOWS_GUI || gnImageSubsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI); //BOOL lbGuiWindowAttach = FALSE; // Прицепить к ConEmu гуевую программу (notepad, putty, ...) #ifdef USE_PIPE_SERVER _ASSERTEX(gpHookServer==NULL); print_timings(L"gpHookServer"); gpHookServer = (PipeServer<CESERVER_REQ>*)calloc(1,sizeof(*gpHookServer)); if (gpHookServer) { wchar_t szPipeName[128]; msprintf(szPipeName, countof(szPipeName), CEHOOKSPIPENAME, L".", GetCurrentProcessId()); gpHookServer->SetMaxCount(3); gpHookServer->SetOverlapped(true); gpHookServer->SetLoopCommands(false); gpHookServer->SetDummyAnswerSize(sizeof(CESERVER_REQ_HDR)); if (!gpHookServer->StartPipeServer(szPipeName, (LPARAM)gpHookServer, LocalSecurity(), HookServerCommand, HookServerFree, NULL, NULL, HookServerReady)) { _ASSERTEX(FALSE); // Ошибка запуска Pipes? gpHookServer->StopPipeServer(); free(gpHookServer); gpHookServer = NULL; } } else { _ASSERTEX(gpHookServer!=NULL); } #endif WARNING("Попробовать не ломиться в мэппинг, а взять все из переменной ConEmuData"); if (ghConWnd) { print_timings(L"CShellProc"); CShellProc* sp = new CShellProc; if (sp) { if (sp->LoadGuiMapping()) { wchar_t *szExeName = (wchar_t*)calloc((MAX_PATH+1),sizeof(wchar_t)); //BOOL lbDosBoxAllowed = FALSE; if (!GetModuleFileName(NULL, szExeName, MAX_PATH+1)) szExeName[0] = 0; if (sp->GetUseInjects() == 2) { // Можно ли использовать облегченную версию хуков (только для exe-шника)? if (!gbSelfIsRootConsoleProcess && !IsFarExe(szExeName)) { gbHookExecutableOnly = true; } } CESERVER_REQ* pIn = sp->NewCmdOnCreate(eInjectingHooks, L"", szExeName, GetCommandLineW(), NULL, NULL, NULL, NULL, // flags gnImageBits, gnImageSubsystem, GetStdHandle(STD_INPUT_HANDLE), GetStdHandle(STD_OUTPUT_HANDLE), GetStdHandle(STD_ERROR_HANDLE)); if (pIn) { //HWND hConWnd = GetConsoleWindow(); CESERVER_REQ* pOut = ExecuteGuiCmd(ghConWnd, pIn, ghConWnd); ExecuteFreeResult(pIn); if (pOut) ExecuteFreeResult(pOut); } free(szExeName); } delete sp; } } else if (gnImageSubsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { print_timings(L"IMAGE_SUBSYSTEM_WINDOWS_GUI"); DWORD dwConEmuHwnd = 0; BOOL bAttachExistingWindow = FALSE; wchar_t szVar[64], *psz; ConEmuGuiMapping* GuiMapping = (ConEmuGuiMapping*)calloc(1,sizeof(*GuiMapping)); if (GuiMapping && LoadGuiMapping(gnSelfPID, *GuiMapping)) { gnGuiPID = GuiMapping->nGuiPID; ghConEmuWnd = GuiMapping->hGuiWnd; bAttachExistingWindow = gbAttachGuiClient = TRUE; //ghAttachGuiClient = } SafeFree(GuiMapping); // Если аттачим существующее окно - таб в ConEmu еще не готов if (!bAttachExistingWindow) { if (!dwConEmuHwnd && GetEnvironmentVariable(ENV_CONEMUHWND_VAR_W, szVar, countof(szVar))) { if (szVar[0] == L'0' && szVar[1] == L'x') { dwConEmuHwnd = wcstoul(szVar+2, &psz, 16); if (!user->isWindow((HWND)dwConEmuHwnd)) dwConEmuHwnd = 0; else if (!user->getClassNameW((HWND)dwConEmuHwnd, szVar, countof(szVar))) dwConEmuHwnd = 0; else if (lstrcmp(szVar, VirtualConsoleClassMain) != 0) dwConEmuHwnd = 0; } } if (dwConEmuHwnd) { // Предварительное уведомление ConEmu GUI, что запущено GUI приложение // и оно может "захотеть во вкладку ConEmu". DWORD nSize = sizeof(CESERVER_REQ_HDR)+sizeof(CESERVER_REQ_ATTACHGUIAPP); CESERVER_REQ *pIn = (CESERVER_REQ*)malloc(nSize); ExecutePrepareCmd(pIn, CECMD_ATTACHGUIAPP, nSize); pIn->AttachGuiApp.nPID = GetCurrentProcessId(); GetModuleFileName(NULL, pIn->AttachGuiApp.sAppFileName, countof(pIn->AttachGuiApp.sAppFileName)); pIn->AttachGuiApp.hkl = (DWORD)(LONG)(LONG_PTR)GetKeyboardLayout(0); wchar_t szGuiPipeName[128]; msprintf(szGuiPipeName, countof(szGuiPipeName), CEGUIPIPENAME, L".", dwConEmuHwnd); CESERVER_REQ* pOut = ExecuteCmd(szGuiPipeName, pIn, 10000, NULL); free(pIn); if (pOut) { if (pOut->hdr.cbSize > sizeof(CESERVER_REQ_HDR)) { if (pOut->AttachGuiApp.nFlags & agaf_Success) { user->allowSetForegroundWindow(pOut->hdr.nSrcPID); // PID ConEmu. _ASSERTEX(gnGuiPID==0 || gnGuiPID==pOut->hdr.nSrcPID); gnGuiPID = pOut->hdr.nSrcPID; //ghConEmuWnd = (HWND)dwConEmuHwnd; _ASSERTE(ghConEmuWnd==NULL || gnGuiPID!=0); _ASSERTE(pOut->AttachGuiApp.hConEmuWnd==(HWND)dwConEmuHwnd); ghConEmuWnd = pOut->AttachGuiApp.hConEmuWnd; ghConEmuWndDC = pOut->AttachGuiApp.hConEmuWndDC; ghConWnd = pOut->AttachGuiApp.hSrvConWnd; _ASSERTE(ghConEmuWndDC && user->isWindow(ghConEmuWndDC)); grcConEmuClient = pOut->AttachGuiApp.rcWindow; gnServerPID = pOut->AttachGuiApp.nPID; if (pOut->AttachGuiApp.hkl) { LONG_PTR hkl = (LONG_PTR)(LONG)pOut->AttachGuiApp.hkl; BOOL lbRc = ActivateKeyboardLayout((HKL)hkl, KLF_SETFORPROCESS) != NULL; UNREFERENCED_PARAMETER(lbRc); } OnConWndChanged(ghConWnd); gbAttachGuiClient = TRUE; } } ExecuteFreeResult(pOut); } } } } //if (!gbSkipInjects) { //gnRunMode = RM_APPLICATION; #ifdef _DEBUG //wchar_t szModule[MAX_PATH+1]; szModule[0] = 0; //GetModuleFileName(NULL, szModule, countof(szModule)); _ASSERTE((gnImageSubsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI) || (lstrcmpi(pszName, L"DosBox.exe")==0) || gbAttachGuiClient); //if (!lstrcmpi(pszName, L"far.exe") || !lstrcmpi(pszName, L"mingw32-make.exe")) //if (!lstrcmpi(pszName, L"as.exe")) // MessageBoxW(NULL, L"as.exe loaded!", L"ConEmuHk", MB_SYSTEMMODAL); //else if (!lstrcmpi(pszName, L"cc1plus.exe")) // MessageBoxW(NULL, L"cc1plus.exe loaded!", L"ConEmuHk", MB_SYSTEMMODAL); //else if (!lstrcmpi(pszName, L"mingw32-make.exe")) // MessageBoxW(NULL, L"mingw32-make.exe loaded!", L"ConEmuHk", MB_SYSTEMMODAL); //if (!lstrcmpi(pszName, L"g++.exe")) // MessageBoxW(NULL, L"g++.exe loaded!", L"ConEmuHk", MB_SYSTEMMODAL); //{ #endif print_timings(L"StartupHooks"); gbHooksWasSet = StartupHooks(ghOurModule); print_timings(L"StartupHooks - done"); #ifdef _DEBUG //} #endif // Если NULL - значит это "Detached" консольный процесс, посылать "Started" в сервер смысла нет if (ghConWnd != NULL) { print_timings(L"SendStarted"); SendStarted(); //#ifdef _DEBUG //// Здесь это приводит к обвалу _chkstk, //// похоже из-за того, что dll-ка загружена НЕ из известных модулей, //// а из специально сформированного блока памяти // -- в одной из функций, под локальные переменные выделялось слишком много памяти // -- переделал в malloc/free, все заработало //TestShellProcessor(); //#endif } } //else //{ // gbHooksWasSet = FALSE; //} //delete sp; /* #ifdef _DEBUG if (!lstrcmpi(pszName, L"mingw32-make.exe")) GuiMessageBox(ghConEmuWnd, L"mingw32-make.exe DllMain finished", L"ConEmuHk", MB_SYSTEMMODAL); #endif */ SafeFree(szModule); //if (hStartedEvent) // SetEvent(hStartedEvent); print_timings(L"DllStart - done"); return 0; }
bool CCommonWidget::winEvent (MSG* msg, long *result) { switch(msg->message) { case WM_INPUTLANGCHANGEREQUEST: { HKL hkl = (HKL)msg->lParam; //激活对应输入法 ActivateKeyboardLayout(hkl, KLF_REPLACELANG); //不允许默认处理,否则某些输入法会导致程序卡死 *result = 0; } return true; case WM_GETMINMAXINFO: { MINMAXINFO *mmi = (MINMAXINFO *)msg->lParam; const QRect rect = QApplication::desktop()->availableGeometry(); RECT clientRect,wndRect; POINT point = {0,0}; ::GetClientRect(winId(),&clientRect); ::ClientToScreen(winId(),&point); ::OffsetRect(&clientRect,point.x,point.y); ::GetWindowRect(winId(),&wndRect); if(clientRect.right - clientRect.left > 0) { int leftOffset = clientRect.left - wndRect.left; int topOffset = clientRect.top - wndRect.top; int rightOffset = wndRect.right - clientRect.right; int bottomOffset = wndRect.bottom - clientRect.bottom; m_oMaxMargins.setLeft(leftOffset); m_oMaxMargins.setTop(topOffset); m_oMaxMargins.setRight(rightOffset); m_oMaxMargins.setBottom(bottomOffset); mmi->ptMaxPosition.x = rect.left() - leftOffset; mmi->ptMaxPosition.y = rect.top() - topOffset; mmi->ptMaxSize.x = rect.width() + leftOffset + rightOffset; mmi->ptMaxSize.y = rect.height() + topOffset + bottomOffset; mmi->ptMaxTrackSize.x = mmi->ptMaxSize.x; mmi->ptMaxTrackSize.y = mmi->ptMaxSize.y; } else { mmi->ptMaxPosition.x = rect.left() - m_oMaxMargins.left(); mmi->ptMaxPosition.y = rect.top() - m_oMaxMargins.top(); mmi->ptMaxSize.x = rect.width() + m_oMaxMargins.left() + m_oMaxMargins.right(); mmi->ptMaxSize.y = rect.height() + m_oMaxMargins.top() + m_oMaxMargins.bottom(); mmi->ptMaxTrackSize.x = mmi->ptMaxSize.x; mmi->ptMaxTrackSize.y = mmi->ptMaxSize.y; } } break; case WM_NCHITTEST: { QPoint absPos(LOWORD(msg->lParam), HIWORD(msg->lParam)); QPoint pos = mapFromGlobal(absPos); int x = pos.x(); int y = pos.y(); int w = width(); int h = height(); if(x >= 0 && x <= w && y >= 0 && y <= h) { if((m_lWndFlag & enum_GGWndResizeHint) && !isMaximized() && !isMinimized()) { if(x < DEF_NOCLIENT_SIZE) { if(y < DEF_NOCLIENT_SIZE) { *result = HTTOPLEFT; } else if(y > h - DEF_NOCLIENT_SIZE) { *result = HTBOTTOMLEFT; } else { *result = HTLEFT; } } else if(x > w - DEF_NOCLIENT_SIZE) { if(y < DEF_NOCLIENT_SIZE) { *result = HTTOPRIGHT; } else if(y > h - DEF_NOCLIENT_SIZE) { *result = HTBOTTOMRIGHT; } else { *result = HTRIGHT; } } else if(y < DEF_NOCLIENT_SIZE) { *result = HTTOP; } else if(y > h - DEF_NOCLIENT_SIZE) { *result = HTBOTTOM; } else if(y < TITLE_HEIGHT) { if(m_pTitleLabel) { const QRect rcTitle = m_pTitleLayout->geometry(); if(x > rcTitle.x() && x < rcTitle.right() && y > rcTitle.y() && y < rcTitle.bottom()) { *result = HTCAPTION; } else { *result = HTCLIENT; } } else { *result = HTCLIENT; } } else { *result = HTCLIENT; } } else { if(y < TITLE_HEIGHT) { if(m_pTitleLabel) { const QRect rcTitle = m_pTitleLayout->geometry(); if(x > rcTitle.x() && x < rcTitle.right() && y > rcTitle.y() && y < rcTitle.bottom()) { *result = HTCAPTION; } else { *result = HTCLIENT; } } else { *result = HTCLIENT; } } else { *result = HTCLIENT; } } } else { return false; } } return true; case WM_NCLBUTTONDBLCLK: { BOOL bCaption = FALSE; if((m_lWndFlag & (enum_GGWndResizeHint | enum_GGWndMaximizeButtonHint))) { QPoint absPos(LOWORD(msg->lParam), HIWORD(msg->lParam)); QPoint pos = mapFromGlobal(absPos); int x = pos.x(); int y = pos.y(); int w = width(); int h = height(); if(y < TITLE_HEIGHT && x >= DEF_NOCLIENT_SIZE && x <= w - DEF_NOCLIENT_SIZE) { if(m_pTitleLabel) { const QRect rcTitle = m_pTitleLayout->geometry(); if(x > rcTitle.x() && x < rcTitle.right() && y > rcTitle.y() && y < rcTitle.bottom()) { bCaption = TRUE; } } } } if(bCaption) { if(isMaximized()) { showNormal(); } else if(isMinimized()) { showNormal(); } else { showMaximized(); } } } return true; case WM_NCLBUTTONDOWN: if(isMaximized()) { if(!COSInfo::IsAboveWinXP()) return true; } break; case WM_NCCALCSIZE: if(msg->wParam) { NCCALCSIZE_PARAMS* lpncsp = (NCCALCSIZE_PARAMS*)msg->lParam; if(lpncsp->rgrc[0].right - lpncsp->rgrc[0].left > 10) { lpncsp->rgrc[0].left += 1; lpncsp->rgrc[0].top += 1; lpncsp->rgrc[0].right -= 1; lpncsp->rgrc[0].bottom -= 1; } //*result = WVR_ALIGNTOP | WVR_ALIGNLEFT | WVR_ALIGNBOTTOM | WVR_ALIGNRIGHT; } *result = 0; return true; case WM_ACTIVATE: { MARGINS margins = {-1}; HINSTANCE hInst = LoadLibraryW(L"dwmapi.dll"); if (hInst) { typedef HRESULT (WINAPI * TmpFun)(HWND,MARGINS*); TmpFun DwmExtendFrameIntoClientArea = (TmpFun)::GetProcAddress(hInst, "DwmExtendFrameIntoClientArea"); if (DwmExtendFrameIntoClientArea) { DwmExtendFrameIntoClientArea(winId(),&margins); } FreeLibrary(hInst); } ::SetWindowLongA(winId(),GWL_EXSTYLE, WS_EX_LEFT); } break; case WM_NCACTIVATE: case 0x00AE: case 0x00AF: *result = 0; return false; } return false; }
static void win32_setup_keymap(void) { default_keymap = GetKeyboardLayout(0); us_keymap = LoadKeyboardLayout("00000409", KLF_ACTIVATE|KLF_REPLACELANG|KLF_NOTELLSHELL); ActivateKeyboardLayout(default_keymap,0); }
LRESULT MainDialogProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam) { HKL hKl; switch (Msg) { case WM_INITDIALOG: { WCHAR Buf[255]; UpdateData(hDlg); hMainDlg = hDlg; SubclassWnd(GetDlgItem(hDlg, IDC_LIST), L"List"); SubclassWnd(GetDlgItem(hDlg, IDC_EDIT1), L"Edit1"); SubclassWnd(GetDlgItem(hDlg, IDC_KLID), L"Klid"); SubclassWnd(GetDlgItem(hDlg, ID_CANCEL), L"CancelB"); SubclassWnd(GetDlgItem(hDlg, IDC_ACTIVATE), L"ActivateB"); SubclassWnd(GetDlgItem(hDlg, IDC_REFRESH), L"RefreshB"); SubclassWnd(GetDlgItem(hDlg, IDC_UNLOAD), L"UnloadB"); SubclassWnd(GetDlgItem(hDlg, IDC_LOAD), L"LoadB"); CheckRadioButton(hDlg, IDC_FROMLIST, IDC_FROMEDIT, IDC_FROMLIST); SetWindowText(GetDlgItem(hDlg, IDC_KLID), L"00000419"); swprintf(Buf, L"Current thread id: %d", GetCurrentThreadId()); SetWindowText(GetDlgItem(hDlg, IDC_CURTHREAD), Buf); SetWindowText(GetDlgItem(hDlg, IDC_DELAY), L"0"); return 0; } /* WM_INITDIALOG */ case WM_COMMAND: { switch(LOWORD(wParam)) { case ID_CANCEL: { EndDialog(hDlg, ERROR_CANCELLED); break; } case IDC_ACTIVATE: { if((hKl = GetActivateHandle(hDlg)) != INVALID_HANDLE_VALUE) { Sleep(GetDelayMilliseconds(hDlg)); if(!(hKl = ActivateKeyboardLayout(hKl, GetActivateFlags(hDlg)))) FormatBox(hDlg, MB_ICONERROR, L"Error", L"ActivateKeyboardLayout() failed. %d", GetLastError()); else UpdateData(hDlg); //FormatBox(hDlg, 0, L"Activated", L"Prev - %x, err - %d.", hKl, // GetLastError()); } else MessageBox(hDlg, L"No item selected", L"Error", MB_ICONERROR); break; } case IDC_UNLOAD: { if((hKl = GetSelectedLayout(hDlg)) != INVALID_HANDLE_VALUE) { Sleep(GetDelayMilliseconds(hDlg)); if(!UnloadKeyboardLayout(hKl)) FormatBox(hDlg, MB_ICONERROR, L"Error", L"UnloadKeyboardLayout() failed. %d", GetLastError()); else UpdateData(hDlg); } else MessageBox(hDlg, L"No item selected", L"Error", MB_ICONERROR); break; } case IDC_LOAD: { WCHAR buf[255]; GetWindowText(GetDlgItem(hDlg, IDC_KLID), buf, sizeof(buf)); Sleep(GetDelayMilliseconds(hDlg)); if(!LoadKeyboardLayout(buf, GetLoadFlags(hDlg))) FormatBox(hDlg, MB_ICONERROR, L"Error", L"LoadKeyboardLayout() failed. %d", GetLastError()); else UpdateData(hDlg); break; } case IDC_REFRESH: { UpdateData(hDlg); break; } case IDC_NEWTHREAD: { if(!CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL)) { FormatBox(hDlg, MB_ICONERROR, L"Error!", L"Can not create thread (%d).", GetLastError()); } } case IDC_LIST: { if(HIWORD(wParam) == LBN_SELCHANGE) { WCHAR buf[25]; if((hKl = GetSelectedLayout(hDlg)) != NULL) { swprintf(buf, L"%x", hKl); SetWindowText(GetDlgItem(hDlg, IDC_HANDLE), buf); } } break; } } return TRUE; } /* WM_COMMAND */ case WM_INPUTLANGCHANGE: { FormatMsg(L"dlg WM_INPUTLANGCHANGE lParam=%x wParam=%x\n", lParam, wParam); return FALSE; } case WM_INPUTLANGCHANGEREQUEST: { FormatMsg(L"dlg WM_INPUTLANGCHANGEREQUEST lParam=%x wParam=%x\n", lParam, wParam); UpdateData(hDlg); return FALSE; } case WM_CLOSE: { EndDialog(hDlg, ERROR_CANCELLED); return TRUE; } /* WM_CLOSE */ default: return FALSE; } }
//************************************************ //*主程序 //************************************************ int APIENTRY t1::_tWinMain(HINSTANCE &hInstance, HINSTANCE &hPrevInstance, LPTSTR &lpCmdLine, int &nCmdShow, HWND &_hWnd, std::string winClassName, std::string winName) { // 初始化句柄和状态 bool bUnClosedLastWin = true; hWnd = _hWnd; gHinstance = hInstance; ShowCursor(FALSE); //g_nThreadExitCount = 0; //获得传递的命令行参数,得到被试着名字和任务编号 char *pdest; int result; int pos1; pdest = strrchr(lpCmdLine, ' '); pos1 = pdest - lpCmdLine; if (pos1>0) { strncpy(m_TaskNumStr, lpCmdLine, pos1); } else { strcpy(m_TaskNumStr, ""); } pdest = strrchr(lpCmdLine, '-'); result = pdest - lpCmdLine; if (result>0) { strncpy(m_TesterName, lpCmdLine + pos1 + 1, result - pos1 - 1); } else { strcpy(m_TesterName, ""); } if (pos1>0) { strcpy(m_DataName, lpCmdLine + pos1 + 1); } else { strcpy(m_DataName, ""); } //读取任务设置 if (!ReadSetting()) { MessageBox(hWnd, "任务设置文件格式错误!", "测试任务", MB_OK); return 0; } //注册窗口类 WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS, MsgProc, 0L, 0L, hInstance, NULL, NULL, NULL, NULL, std::to_string(nCmdShow).c_str(), NULL }; RegisterClassEx(&wc); x_resolution = GetSystemMetrics(SM_CXSCREEN); y_resolution = GetSystemMetrics(SM_CYSCREEN); rec_x_begin = (x_resolution - 1024) / 2; rec_y_begin = (y_resolution - 768) / 2; rec_x_end = (x_resolution + 1024) / 2; rec_y_end = (y_resolution + 768) / 2; _hWnd = hWnd = CreateWindow(std::to_string(nCmdShow).c_str(), std::to_string(nCmdShow).c_str(), WS_VISIBLE | WS_POPUP, 0, 0, x_resolution, y_resolution, NULL, NULL, hInstance, NULL); //显示主窗口 SetFocus(hWnd); //创建DirectX设备 if (FAILED(DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&m_lpkDInput, NULL))) { return 0; } float m_JoySpeedMax; if (m_HardSetting.m_JoySpeedMax > 0) { m_JoySpeedMax = m_HardSetting.m_JoySpeedMax; } else { m_JoySpeedMax = 200; } //关闭输入法 HKL hkl; hkl = LoadKeyboardLayout("00000804", KLF_ACTIVATE); if (hkl != NULL) { ActivateKeyboardLayout(hkl, KLF_SETFORPROCESS); } //ShowCursor(FALSE); //设置操纵杆变化范围 if (JoystickInit(hWnd, -m_JoySpeedMax, m_JoySpeedMax, 1)) { JoystickUpdate(); } else { MessageBox(hWnd, "请检查操纵杆连接是否正确!", "测试任务", MB_OK); return 0; } // declare a variable of our data structure to pass to the ThreadProcedure MYDATA MyThreadData; MyThreadData.nTime = 7509843; MyThreadData.nNumber = 39; //创建操纵杆输入线程 // declare a DWORD to hold our thread's new generated ID HANDLE h = CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)InputThreadProcedure, (LPVOID)&MyThreadData, NULL, &dwInputThreadID); // SetPriorityClass(h,NORMAL_PRIORITY_CLASS); // SetThreadPriority(h,THREAD_PRIORITY_ABOVE_NORMAL); // actually create and start the thread now! // the thread will run until we send it our own WM_THREADSTOP message srand((unsigned)time(NULL)); //初始化随机种子 //初始化Direct3D bool b_InitD3d = SUCCEEDED(InitD3D(hWnd)); if (b_InitD3d) { //进入消息循环 MSG msg; ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT) { if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { //处理外部消息 TranslateMessage(&msg); DispatchMessage(&msg); } else { //执行测试过程 UpdateState(); if (m_bDisplayReady) { //渲染图形 Render(); hideLastWindow(bUnClosedLastWin, winClassName, winName, hInstance); } } Sleep(1); // 当按下“下一个任务”或“退出”时,终止消息循环 if (m_TestState == STATE_NEXT || m_TestState == STATE_EXIT) { break; } } } ShowCursor(TRUE); CloseHandle(h); return rtn; }
void CIme::NextIme(){ if( m_bIme )ActivateKeyboardLayout(( HKL )HKL_NEXT, 0 ); }
void CMSWindowsKeyState::getKeyMap(CKeyMap& keyMap) { // update keyboard groups if (getGroups(m_groups)) { m_groupMap.clear(); SInt32 numGroups = (SInt32)m_groups.size(); for (SInt32 g = 0; g < numGroups; ++g) { m_groupMap[m_groups[g]] = g; } } HKL activeLayout = GetKeyboardLayout(0); // clear table memset(m_virtualKeyToButton, 0, sizeof(m_virtualKeyToButton)); m_keyToVKMap.clear(); CKeyMap::KeyItem item; SInt32 numGroups = (SInt32)m_groups.size(); for (SInt32 g = 0; g < numGroups; ++g) { item.m_group = g; ActivateKeyboardLayout(m_groups[g], 0); // clear tables memset(m_buttonToVK, 0, sizeof(m_buttonToVK)); memset(m_buttonToNumpadVK, 0, sizeof(m_buttonToNumpadVK)); // map buttons (scancodes) to virtual keys for (KeyButton i = 1; i < 256; ++i) { UINT vk = MapVirtualKey(i, 1); if (vk == 0) { // unmapped continue; } // deal with certain virtual keys specially switch (vk) { case VK_SHIFT: vk = VK_LSHIFT; break; case VK_CONTROL: vk = VK_LCONTROL; break; case VK_MENU: vk = VK_LMENU; break; case VK_NUMLOCK: vk = VK_PAUSE; break; case VK_NUMPAD0: case VK_NUMPAD1: case VK_NUMPAD2: case VK_NUMPAD3: case VK_NUMPAD4: case VK_NUMPAD5: case VK_NUMPAD6: case VK_NUMPAD7: case VK_NUMPAD8: case VK_NUMPAD9: case VK_DECIMAL: // numpad keys are saved in their own table m_buttonToNumpadVK[i] = vk; continue; case VK_LWIN: case VK_RWIN: // add extended key only for these on 95 family if (m_is95Family) { m_buttonToVK[i | 0x100u] = vk; continue; } break; case VK_RETURN: case VK_PRIOR: case VK_NEXT: case VK_END: case VK_HOME: case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: case VK_INSERT: case VK_DELETE: // also add extended key for these m_buttonToVK[i | 0x100u] = vk; break; } if (m_buttonToVK[i] == 0) { m_buttonToVK[i] = vk; } } // now map virtual keys to buttons. multiple virtual keys may map // to a single button. if the virtual key matches the one in // m_buttonToVK then we use the button as is. if not then it's // either a numpad key and we use the button as is or it's an // extended button. for (UINT i = 1; i < 255; ++i) { // skip virtual keys we don't want switch (i) { case VK_LBUTTON: case VK_RBUTTON: case VK_MBUTTON: case VK_XBUTTON1: case VK_XBUTTON2: case VK_SHIFT: case VK_CONTROL: case VK_MENU: continue; } // get the button KeyButton button = static_cast<KeyButton>(MapVirtualKey(i, 0)); if (button == 0) { continue; } // deal with certain virtual keys specially switch (i) { case VK_NUMPAD0: case VK_NUMPAD1: case VK_NUMPAD2: case VK_NUMPAD3: case VK_NUMPAD4: case VK_NUMPAD5: case VK_NUMPAD6: case VK_NUMPAD7: case VK_NUMPAD8: case VK_NUMPAD9: case VK_DECIMAL: m_buttonToNumpadVK[button] = i; break; default: // add extended key if virtual keys don't match if (m_buttonToVK[button] != i) { m_buttonToVK[button | 0x100u] = i; } break; } } // add alt+printscreen if (m_buttonToVK[0x54u] == 0) { m_buttonToVK[0x54u] = VK_SNAPSHOT; } // set virtual key to button table if (GetKeyboardLayout(0) == m_groups[g]) { for (KeyButton i = 0; i < 512; ++i) { if (m_buttonToVK[i] != 0) { if (m_virtualKeyToButton[m_buttonToVK[i]] == 0) { m_virtualKeyToButton[m_buttonToVK[i]] = i; } } if (m_buttonToNumpadVK[i] != 0) { if (m_virtualKeyToButton[m_buttonToNumpadVK[i]] == 0) { m_virtualKeyToButton[m_buttonToNumpadVK[i]] = i; } } } } // add numpad keys for (KeyButton i = 0; i < 512; ++i) { if (m_buttonToNumpadVK[i] != 0) { item.m_id = getKeyID(m_buttonToNumpadVK[i], i); item.m_button = i; item.m_required = KeyModifierNumLock; item.m_sensitive = KeyModifierNumLock | KeyModifierShift; item.m_generates = 0; item.m_client = m_buttonToNumpadVK[i]; addKeyEntry(keyMap, item); } } // add other keys BYTE keys[256]; memset(keys, 0, sizeof(keys)); for (KeyButton i = 0; i < 512; ++i) { if (m_buttonToVK[i] != 0) { // initialize item item.m_id = getKeyID(m_buttonToVK[i], i); item.m_button = i; item.m_required = 0; item.m_sensitive = 0; item.m_client = m_buttonToVK[i]; // get flags for modifier keys CKeyMap::initModifierKey(item); if (item.m_id == 0) { // translate virtual key to a character with and without // shift, caps lock, and AltGr. struct Modifier { UINT m_vk1; UINT m_vk2; BYTE m_state; KeyModifierMask m_mask; }; static const Modifier modifiers[] = { { VK_SHIFT, VK_SHIFT, 0x80u, KeyModifierShift }, { VK_CAPITAL, VK_CAPITAL, 0x01u, KeyModifierCapsLock }, { VK_CONTROL, VK_MENU, 0x80u, KeyModifierControl | KeyModifierAlt } }; static const size_t s_numModifiers = sizeof(modifiers) / sizeof(modifiers[0]); static const size_t s_numCombinations = 1 << s_numModifiers; KeyID id[s_numCombinations]; bool anyFound = false; KeyButton button = static_cast<KeyButton>(i & 0xffu); for (size_t j = 0; j < s_numCombinations; ++j) { for (size_t k = 0; k < s_numModifiers; ++k) { //if ((j & (1 << k)) != 0) { // http://msdn.microsoft.com/en-us/library/ke55d167.aspx if ((j & (1i64 << k)) != 0) { keys[modifiers[k].m_vk1] = modifiers[k].m_state; keys[modifiers[k].m_vk2] = modifiers[k].m_state; } else { keys[modifiers[k].m_vk1] = 0; keys[modifiers[k].m_vk2] = 0; } } id[j] = getIDForKey(item, button, m_buttonToVK[i], keys, m_groups[g]); if (id[j] != 0) { anyFound = true; } } if (anyFound) { // determine what modifiers we're sensitive to. // we're sensitive if the KeyID changes when the // modifier does. item.m_sensitive = 0; for (size_t k = 0; k < s_numModifiers; ++k) { for (size_t j = 0; j < s_numCombinations; ++j) { //if (id[j] != id[j ^ (1u << k)]) { // http://msdn.microsoft.com/en-us/library/ke55d167.aspx if (id[j] != id[j ^ (1ui64 << k)]) { item.m_sensitive |= modifiers[k].m_mask; break; } } } // save each key. the map will automatically discard // duplicates, like an unshift and shifted version of // a key that's insensitive to shift. for (size_t j = 0; j < s_numCombinations; ++j) { item.m_id = id[j]; item.m_required = 0; for (size_t k = 0; k < s_numModifiers; ++k) { if ((j & (1i64 << k)) != 0) { item.m_required |= modifiers[k].m_mask; } } addKeyEntry(keyMap, item); } } } else { // found in table switch (m_buttonToVK[i]) { case VK_TAB: // add kKeyLeftTab, too item.m_id = kKeyLeftTab; item.m_required |= KeyModifierShift; item.m_sensitive |= KeyModifierShift; addKeyEntry(keyMap, item); item.m_id = kKeyTab; item.m_required &= ~KeyModifierShift; break; case VK_CANCEL: item.m_required |= KeyModifierControl; item.m_sensitive |= KeyModifierControl; break; case VK_SNAPSHOT: item.m_sensitive |= KeyModifierAlt; if ((i & 0x100u) == 0) { // non-extended snapshot key requires alt item.m_required |= KeyModifierAlt; } break; } addKeyEntry(keyMap, item); } } } } // restore keyboard layout ActivateKeyboardLayout(activeLayout, 0); }
INT_PTR CALLBACK DlgStdInProc(HWND hDlg, UINT uMsg,WPARAM wParam,LPARAM lParam) { static DWORD dwOldIcon = 0; HICON hIcon = 0; switch(uMsg){ case WM_INITDIALOG: g_hDlgPass = hDlg; hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_DLGPASSWD)); dwOldIcon = SetClassLongPtr(hDlg, GCLP_HICON, (LONG)hIcon); // set alt+tab icon SendDlgItemMessage(hDlg,IDC_EDIT1,EM_LIMITTEXT,MAXPASSLEN,0); if (IsAeroMode()) { SetWindowLongPtr(hDlg, GWL_STYLE, GetWindowLongPtr(hDlg, GWL_STYLE) | WS_DLGFRAME | WS_SYSMENU); SetWindowLongPtr(hDlg, GWL_EXSTYLE, GetWindowLongPtr(hDlg, GWL_EXSTYLE) | WS_EX_TOOLWINDOW); RECT rect; GetClientRect(hDlg, &rect); SetWindowPos(hDlg, 0, 0, 0, rect.right, rect.bottom + GetSystemMetrics(SM_CYCAPTION), SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOZORDER); } SendDlgItemMessage(hDlg, IDC_HEADERBAR, WM_SETICON, 0, (LPARAM)hIcon); SetDlgItemText(hDlg, IDC_HEADERBAR, TranslateT("Miranda NG is locked.\nEnter password to unlock it.")); TranslateDialogDefault(hDlg); oldLangID = 0; SetTimer(hDlg,1,200,NULL); oldLayout = GetKeyboardLayout(0); if (MAKELCID((WORD)oldLayout & 0xffffffff, SORT_DEFAULT) != (LCID)0x00000409) ActivateKeyboardLayout((HKL)0x00000409, 0); LanguageChanged(hDlg); return TRUE; case WM_CTLCOLORSTATIC: if (GetWindowLongPtr((HWND)lParam, GWLP_ID) != IDC_LANG) break; SetTextColor((HDC)wParam, GetSysColor(COLOR_HIGHLIGHTTEXT)); SetBkMode((HDC)wParam, TRANSPARENT); return (INT_PTR)GetSysColorBrush(COLOR_HIGHLIGHT); case WM_COMMAND: { UINT uid = LOWORD(wParam); if (uid == IDOK){ char password[MAXPASSLEN + 1] = {0}; int passlen = GetDlgItemTextA(hDlg,IDC_EDIT1,password,MAXPASSLEN+1); if (passlen == 0) { SetDlgItemText(hDlg, IDC_HEADERBAR, TranslateT("Miranda NG is locked.\nEnter password to unlock it.")); SendDlgItemMessage(hDlg, IDC_HEADERBAR, WM_NCPAINT, 0, 0); break; } else if (lstrcmpA(password, g_password)) { SetDlgItemText(hDlg, IDC_HEADERBAR, TranslateT("Password is not correct!\nPlease, enter correct password.")); SendDlgItemMessage(hDlg, IDC_HEADERBAR, WM_NCPAINT, 0, 0); SetDlgItemText(hDlg, IDC_EDIT1, _T("")); break; } else EndDialog(hDlg, IDOK); } else if (uid == IDCANCEL) EndDialog(hDlg, IDCANCEL); } case WM_TIMER: LanguageChanged(hDlg); break; case WM_DESTROY: KillTimer(hDlg, 1); if (GetKeyboardLayout(0) != oldLayout) ActivateKeyboardLayout(oldLayout, 0); SetClassLongPtr(hDlg, GCLP_HICON, (long)dwOldIcon); DestroyIcon(hIcon); break; } return FALSE; }