private void PrepareSend() { IntPtr hWnd = NativeMethods.GetForegroundWindowHandle(); m_swiCurrent = GetWindowInfo(hWnd); EnsureSameKeyboardLayout(); }
private void InitForEnv() { #if DEBUG Stopwatch sw = Stopwatch.StartNew(); #endif try { m_hklCurrent = NativeMethods.GetKeyboardLayout(0); m_hklOriginal = m_hklCurrent; Debug.Assert(m_hklOriginal != IntPtr.Zero); Process[] vProcesses = Process.GetProcesses(); foreach (Process p in vProcesses) { if (p == null) { Debug.Assert(false); continue; } try { string strName = SiWindowInfo.GetProcessName(p); // If the Neo keyboard layout is being used, we must // send Unicode characters; keypresses are converted // and thus do not lead to the expected result if (SiWindowInfo.ProcessNameMatches(strName, "Neo20")) { FileVersionInfo fvi = p.MainModule.FileVersionInfo; if (((fvi.ProductName ?? string.Empty).Trim().Length == 0) && ((fvi.FileDescription ?? string.Empty).Trim().Length == 0)) { m_osmEnforced = SiSendMethod.UnicodePacket; } else { Debug.Assert(false); } } else if (SiWindowInfo.ProcessNameMatches(strName, "KbdNeo_Ahk")) { m_osmEnforced = SiSendMethod.UnicodePacket; } } catch (Exception) { Debug.Assert(false); } try { p.Dispose(); } catch (Exception) { Debug.Assert(false); } } } catch (Exception) { Debug.Assert(false); } #if DEBUG sw.Stop(); Debug.Assert(sw.ElapsedMilliseconds < 100); #endif }
private SiSendMethod GetSendMethod(SiWindowInfo swi) { if (m_osmEnforced.HasValue) { return(m_osmEnforced.Value); } return(swi.SendMethod); }
private SiWindowInfo PrepareSend() { IntPtr hWnd = NativeMethods.GetForegroundWindowHandle(); SiWindowInfo swi = GetWindowInfo(hWnd); EnsureSameKeyboardLayout(swi); return(swi); }
private SiWindowInfo GetWindowInfo(IntPtr hWnd) { SiWindowInfo swi; if (m_dWindowInfos.TryGetValue(hWnd, out swi)) { return(swi); } swi = new SiWindowInfo(hWnd); m_dWindowInfos[hWnd] = swi; return(swi); }
private SiWindowInfo GetWindowInfo(IntPtr hWnd) { SiWindowInfo swi; if (m_dWindowInfos.TryGetValue(hWnd, out swi)) { return(swi); } swi = new SiWindowInfo(hWnd); Process p = null; try { uint uPID; uint uTID = NativeMethods.GetWindowThreadProcessId(hWnd, out uPID); swi.KeyboardLayout = NativeMethods.GetKeyboardLayout(uTID); p = Process.GetProcessById((int)uPID); string strName = GetProcessName(p); foreach (KeyValuePair <string, SiSendMethod> kvp in g_dProcessSendMethods) { if (ProcessNameMatches(strName, kvp.Key)) { swi.SendMethod = kvp.Value; break; } } } catch (Exception) { Debug.Assert(false); } finally { try { if (p != null) { p.Dispose(); } } catch (Exception) { Debug.Assert(false); } } m_dWindowInfos[hWnd] = swi; return(swi); }
public override void SendCharImpl(char ch, bool?bDown) { SiWindowInfo swi = PrepareSend(); if (TrySendCharByKeypresses(ch, bDown, swi)) { return; } if (bDown.HasValue) { SendCharNative(ch, bDown.Value); return; } SendCharNative(ch, true); SendCharNative(ch, false); }
private void EnsureSameKeyboardLayout(SiWindowInfo swi) { if (!Program.Config.Integration.AutoTypeAdjustKeyboardLayout) { return; } IntPtr hklTarget = swi.KeyboardLayout; Debug.Assert(hklTarget != IntPtr.Zero); Debug.Assert(NativeMethods.GetKeyboardLayout(0) == m_hklCurrent); if ((m_hklCurrent != hklTarget) && (hklTarget != IntPtr.Zero)) { if (NativeMethods.ActivateKeyboardLayout(hklTarget, 0) != m_hklCurrent) { Debug.Assert(false); } m_hklCurrent = hklTarget; Thread.Sleep(1); Application.DoEvents(); } }
private bool TrySendCharByKeypresses(char ch, bool? bDown, SiWindowInfo swi) { if(ch == char.MinValue) { Debug.Assert(false); return false; } SiSendMethod sm = GetSendMethod(swi); if(sm == SiSendMethod.UnicodePacket) return false; if(m_vForcedUniChars == null) m_vForcedUniChars = new char[] { // All of the following diacritics are spacing / non-combining '\u00B4', // Acute accent '\u02DD', // Double acute accent '\u0060', // Grave accent '\u02D8', // Breve '\u00B8', // Cedilla '\u005E', // Circumflex ^ '\u00A8', // Diaeresis '\u02D9', // Dot above '\u00AF', // Macron above, long '\u02C9', // Macron above, modifier, short '\u02CD', // Macron below, modifier, short '\u02DB', // Ogonek // E.g. for US-International; // https://sourceforge.net/p/keepass/discussion/329220/thread/5708e5ef/ '\u0027', // Apostrophe '\u0022', // Quotation mark '\u007E' // Tilde }; if(sm != SiSendMethod.KeyEvent) // If Unicode packets allowed { if(Array.IndexOf<char>(m_vForcedUniChars, ch) >= 0) return false; } IntPtr hKL = swi.KeyboardLayout; ushort u = ((hKL == IntPtr.Zero) ? NativeMethods.VkKeyScan(ch) : NativeMethods.VkKeyScanEx(ch, hKL)); if(u == 0xFFFFU) return false; int vKey = (int)(u & 0xFFU); Keys kMod = Keys.None; int nMods = 0; if((u & 0x100U) != 0U) { ++nMods; kMod |= Keys.Shift; } if((u & 0x200U) != 0U) { ++nMods; kMod |= Keys.Control; } if((u & 0x400U) != 0U) { ++nMods; kMod |= Keys.Alt; } if((u & 0x800U) != 0U) return false; // Hankaku unsupported // Do not send a key combination that is registered as hot key; // https://sourceforge.net/p/keepass/bugs/1235/ // Windows shortcut hot keys involve at least 2 modifiers if(nMods >= 2) { Keys kFull = (kMod | (Keys)vKey); if(HotKeyManager.IsHotKeyRegistered(kFull, true)) return false; } Keys kModDiff = (kMod & ~m_kModCur); if(kModDiff != Keys.None) { // Send RAlt for better AltGr compatibility; // https://sourceforge.net/p/keepass/bugs/1475/ SetKeyModifierImplEx(kModDiff, true, true); Thread.Sleep(1); Application.DoEvents(); } SendKeyImpl(vKey, null, bDown); if(kModDiff != Keys.None) { Thread.Sleep(1); Application.DoEvents(); SetKeyModifierImplEx(kModDiff, false, true); } return true; }
private SiWindowInfo GetWindowInfo(IntPtr hWnd) { SiWindowInfo swi; if(m_dWindowInfos.TryGetValue(hWnd, out swi)) return swi; swi = new SiWindowInfo(hWnd); Process p = null; try { uint uPID; uint uTID = NativeMethods.GetWindowThreadProcessId(hWnd, out uPID); swi.KeyboardLayout = NativeMethods.GetKeyboardLayout(uTID); p = Process.GetProcessById((int)uPID); string strName = GetProcessName(p); foreach(KeyValuePair<string, SiSendMethod> kvp in g_dProcessSendMethods) { if(ProcessNameMatches(strName, kvp.Key)) { swi.SendMethod = kvp.Value; break; } } } catch(Exception) { Debug.Assert(false); } finally { try { if(p != null) p.Dispose(); } catch(Exception) { Debug.Assert(false); } } m_dWindowInfos[hWnd] = swi; return swi; }
private SiSendMethod GetSendMethod(SiWindowInfo swi) { if(m_osmEnforced.HasValue) return m_osmEnforced.Value; return swi.SendMethod; }
private void EnsureSameKeyboardLayout(SiWindowInfo swi) { if(!Program.Config.Integration.AutoTypeAdjustKeyboardLayout) return; IntPtr hklTarget = swi.KeyboardLayout; Debug.Assert(hklTarget != IntPtr.Zero); Debug.Assert(NativeMethods.GetKeyboardLayout(0) == m_hklCurrent); if((m_hklCurrent != hklTarget) && (hklTarget != IntPtr.Zero)) { if(NativeMethods.ActivateKeyboardLayout(hklTarget, 0) != m_hklCurrent) { Debug.Assert(false); } m_hklCurrent = hklTarget; Thread.Sleep(1); Application.DoEvents(); } }
private SiWindowInfo GetWindowInfo(IntPtr hWnd) { SiWindowInfo swi; if (m_dWindowInfos.TryGetValue(hWnd, out swi)) { return(swi); } swi = new SiWindowInfo(hWnd); Process p = null; try { uint uPID; uint uTID = NativeMethods.GetWindowThreadProcessId(hWnd, out uPID); swi.KeyboardLayout = NativeMethods.GetKeyboardLayout(uTID); p = Process.GetProcessById((int)uPID); string strName = GetProcessName(p); foreach (KeyValuePair <string, SiSendMethod> kvp in g_dProcessSendMethods) { if (ProcessNameMatches(strName, kvp.Key)) { swi.SendMethod = kvp.Value; break; } } // The workaround attempt for Edge below doesn't work; // Edge simply ignores Unicode packets for '@', Euro sign, etc. /* if(swi.SendMethod == SiSendMethod.Default) * { * string strTitle = NativeMethods.GetWindowText(hWnd, true); * * // Workaround for Edge; * // https://sourceforge.net/p/keepass/discussion/329220/thread/fd3a6776/ * // The window title is: * // Page name + Space + U+200E (left-to-right mark) + "- Microsoft Edge" * if(strTitle.EndsWith("- Microsoft Edge", StrUtil.CaseIgnoreCmp)) * swi.SendMethod = SiSendMethod.UnicodePacket; * } */ } catch (Exception) { Debug.Assert(false); } finally { try { if (p != null) { p.Dispose(); } } catch (Exception) { Debug.Assert(false); } } m_dWindowInfos[hWnd] = swi; return(swi); }
private bool TrySendCharByKeypresses(char ch, bool?bDown, SiWindowInfo swi) { if (ch == char.MinValue) { Debug.Assert(false); return(false); } SiSendMethod sm = GetSendMethod(swi); if (sm == SiSendMethod.UnicodePacket) { return(false); } if (m_vForcedUniChars == null) { m_vForcedUniChars = new char[] { // All of the following diacritics are spacing / non-combining '\u00B4', // Acute accent '\u02DD', // Double acute accent '\u0060', // Grave accent '\u02D8', // Breve '\u00B8', // Cedilla '\u005E', // Circumflex ^ '\u00A8', // Diaeresis '\u02D9', // Dot above '\u00AF', // Macron above, long '\u02C9', // Macron above, modifier, short '\u02CD', // Macron below, modifier, short '\u02DB', // Ogonek // E.g. for US-International; // https://sourceforge.net/p/keepass/discussion/329220/thread/5708e5ef/ '\u0027', // Apostrophe '\u0022', // Quotation mark '\u007E' // Tilde } } ; if (sm != SiSendMethod.KeyEvent) // If Unicode packets allowed { if (Array.IndexOf <char>(m_vForcedUniChars, ch) >= 0) { return(false); } } IntPtr hKL = swi.KeyboardLayout; ushort u = ((hKL == IntPtr.Zero) ? NativeMethods.VkKeyScan(ch) : NativeMethods.VkKeyScanEx(ch, hKL)); if (u == 0xFFFFU) { return(false); } int vKey = (int)(u & 0xFFU); Keys kMod = Keys.None; int nMods = 0; if ((u & 0x100U) != 0U) { ++nMods; kMod |= Keys.Shift; } if ((u & 0x200U) != 0U) { ++nMods; kMod |= Keys.Control; } if ((u & 0x400U) != 0U) { ++nMods; kMod |= Keys.Alt; } if ((u & 0x800U) != 0U) { return(false); // Hankaku unsupported } // Do not send a key combination that is registered as hot key; // https://sourceforge.net/p/keepass/bugs/1235/ // Windows shortcut hot keys involve at least 2 modifiers if (nMods >= 2) { Keys kFull = (kMod | (Keys)vKey); if (HotKeyManager.IsHotKeyRegistered(kFull, true)) { return(false); } } Keys kModDiff = (kMod & ~m_kModCur); if (kModDiff != Keys.None) { // Send RAlt for better AltGr compatibility; // https://sourceforge.net/p/keepass/bugs/1475/ SetKeyModifierImplEx(kModDiff, true, true); Thread.Sleep(1); Application.DoEvents(); } SendKeyImpl(vKey, null, bDown); if (kModDiff != Keys.None) { Thread.Sleep(1); Application.DoEvents(); SetKeyModifierImplEx(kModDiff, false, true); } return(true); }