Windows のドイツ語とロシア語のキーボード レイアウト間での元に戻す (Ctrl-Z) とやり直し (Ctrl-Y) ショートカットの物理的な位置を修正しました。

Windows のドイツ語とロシア語のキーボード レイアウト間での元に戻す (Ctrl-Z) とやり直し (Ctrl-Y) ショートカットの物理的な位置を修正しました。

私は、類似しているがわずかに異なる問題に悩まされている、キーボード レイアウトの混乱の別の被害者を真似しています。

私は Windows 10 ワークステーションでドイツ語とロシア語のキーボード レイアウトを頻繁に使用しており、それらを頻繁に切り替えています。問題は、ドイツ語のキーボード レイアウトでは、標準の英語 QWERTY レイアウトと比較して、文字 Y と Z が入れ替わっていることに関係しています。

ドイツ語レイアウトを使用する場合、元に戻すショートカット (Ctrl + Z) は、T と U の間の最初の文字行の中央にあるキー Z にバインドされます。やり直し (Ctrl + Y) は、ドイツ語 QWERTZ レイアウトの文字の下の行の X の左側にあるキー Y にバインドされます。

レイアウトをロシア語に切り替えると、突然悪いことが起こります。元に戻すショートカットとやり直しショートカットのキーボード上の位置が相互に変更されます。元に戻す (Ctrl-Z) は Y (下段、X の左) に、やり直しは Z (上段、T と U の間) に配置されます。この位置は、標準の英語キーボード レイアウトの Ctrl-Z と Ctrl-Y の位置と同じです。

つまり、キーボード レイアウトを切り替えるたびに、元に戻すショートカットとやり直しショートカットの位置が常に逆方向に変わります。ご想像のとおり、2 つの相反するパターンを学習することは不可能なので、常に間違ったショートカットを押しています (少なくとも私の背骨の脳は反対しています)。元に戻すショートカットとやり直しショートカットを頻繁に使用するので、この動作には非常にイライラします。

Windows アプリケーション全体のやり直しおよび元に戻すショートカットの物理的な場所 (キー) をドイツ語またはより適切な英語レイアウトに修正したいと考えています。

ラテン語ベースのテキストすべてに英語レイアウトを永続的に使用すると、元に戻す/やり直しのショートカットのジャンプに関する問題は解決しますが、すべてのウムラウトと ß を含むドイツ語のテキストを入力する必要があるため、これは私にとっては選択肢ではありません (アクセントを入力するための国際レイアウトは提案しません。ドイツ語が私の第一言語であり、1 回のキーストロークでネイティブの文字を入力したいためです)。

参照した質問の同僚がすでに述べたように、インターネット上には明確な答えはありません。Ubuntu では、カスタム キーボード レイアウトを作成することで同じ問題が解決されます。Windows 用のカスタム レイアウトの作成や、現在のレイアウトのパッチ適用に関する情報は見つかりません。

この動作は、私が知っているすべてのバージョンの Windows で一貫しており、初期のキーボード レイアウト設計に深く関連しています。これは、私のようにドイツ語とロシア語の言語ペアを使用するユーザーにとっては互換性がありません。

優れたソリューションは、追加のソフトウェアなしで、または無料のオープンソース ソフトウェアのみを使用して Windows に直接実装する必要があります。AutoHotKey を使用する実用的なソリューションは歓迎されます。

@miroxlav の助けを借りて、この半分動作する AHK スクリプトを作成しました。

; Undo
$^z::
    hWnd := WinExist("A")
    ThreadID := DllCall("GetWindowThreadProcessId", "UInt", hWnd, "UInt", 0)
    hKL := DllCall("GetKeyboardLayout", "UInt", ThreadID, "UInt")
    If (hKL = 0x4070409)   ; revert undo-redo hotkey mapping if in German layout
        Send ^y
    Else
        Send ^н            ; pass the keystroke through
Return

; Redo
$^y::
    hWnd := WinExist("A")
    ThreadID := DllCall("GetWindowThreadProcessId", "UInt", hWnd, "UInt", 0)
    hKL := DllCall("GetKeyboardLayout", "UInt", ThreadID, "UInt")
    If (hKL = 0x4070409)   ; revert undo-redo hotkey mapping if in German layout
        Send ^z
    Else
        Send ^я            ; pass the keystroke through
Return

このスクリプトは、ドイツ語レイアウトで Ctrl-Y <-> Ctrl-Z を完全に再マップしますが、ロシア語レイアウトでは両方のホットキーが壊れます。ロシア語レイアウトで Ctrl-Y または Ctrl-Z スキャンコードに相当するものをエミュレートすることを期待して ^н と ^я を使用しましたが、機能しません (Ctrl-Y に対して н が生成され、Ctrl-Z に対しては何も表示されません)。ロシア語で ^z と ^y を使用しても機能せず、それぞれ文字 z と y が生成されます。

Miroxlavの回答とは異なり、ループを回避してラベルを削除するにはキーボードフック($)を使用する必要がありました(おそらくコピー&ペーストのミス)

ウィリアムズが提案した解決策:

^SC02c::Send ^y
^SC015::Send ^z

残念ながら、どちらも機能しません。ロシア語レイアウトではプレーンな文字「y」と「z」が生成され、ドイツ語レイアウトでは変更されません (Ctrl-Z と Ctrl-Y は元のマッピングで渡されます)。

まだ解決策を探しています。

答え1

独自のキーボードレイアウトを作成するには、Microsoft 公式ダウンロード センターからの Microsoft Keyboard Layout Creator 1.4

Youtubeでは使い方のビデオチュートリアルが多数提供されています(例えばこれロシア語ロケールのキーボード レイアウト (名前を検索するだけです) を複製し、必要に応じて変更します。基本的には、既存のキーボード レイアウトの 1 つを複製し、必要に応じて変更します。

AutoHotKeyソリューション:

(注:0x4090409定数 (US キーボード) を、レイアウトに適用される値に置き換えます)

$^z::
    hWnd := WinExist("A")
    ThreadID := DllCall("GetWindowThreadProcessId", "UInt", hWnd, "UInt", 0)
    hKL := DllCall("GetKeyboardLayout", "UInt", ThreadID, "UInt")
    If (hKL = 0x4090409)
        Send ^z
    Else
        Send ^y
Return

$^y::
    hWnd := WinExist("A")
    ThreadID := DllCall("GetWindowThreadProcessId", "UInt", hWnd, "UInt", 0)
    hKL := DllCall("GetKeyboardLayout", "UInt", ThreadID, "UInt")
    If (hKL = 0x4090409)
        Send ^y
    Else
        Send ^z
Return

Send ^z再帰、つまりSend ^y別の AHK マクロの呼び出しを回避するには、フック ($) が必要です。

キーボード検出条件をテストしたところ、うまく機能しました。

もちろん、キーボード検出を関数に配置して、コードなどを最適化することもできます。私はそれをするのが面倒でした。 :)

答え2

ようやく私にとって有効な解決策を見つけました (AutoHotKey スクリプト):

; Undo Ctrl-Z
^sc02C::
    Send, ^{sc015}
Return

; Redo Ctrl-Y
^sc015::
    Send, ^{sc02C}
Return

キーボード レイアウトとは関係なく、元に戻すキー (Ctrl-Z) を論理的な位置 (左下列) に完全に保持します。

解決策の材料を提供してくれた @Miroxlav と @Williams に感謝します。

答え3

Anton の回答に基づいて、コードを AHK v2 に更新し、Ctrl + Shift バリアントのサポートを追加しました。これは、現在多くのプログラムが Redo にこれを使用しているためです。

#Requires AutoHotkey v2.0

;Remapping upper mid Y/Z key (Y in EN layout)
^sc015::Send "^{sc02C}"
^+sc015::Send "^+{sc02C}"

;Remapping lower left Y/Z key (Z in EN layout)
^sc02C::Send "^{sc015}"
^+sc02C::Send "^+{sc015}"

このスクリプトのポイントは、異なるレイアウト (QWERTZ と QWERTY) では Z が上部中央に移動するため、元に戻すアクションを左下の Y/Z キーに固定することですが、これは実用的ではありません。やり直しについても同様で、上部中央の Y/Z キーに固定されています。

元に戻す/やり直しは通常 Ctrl+Z/Y で実行されるため、押されたキーをキャプチャし、「正しい」キーを再発行することでこれを実現できます。これらは行です^sc0**^+sc0**多くのプログラムではやり直しに Ctrl+Shift+Z を使用しているため、これらの行は Ctrl+Shift+Z/Y イベントを再発行するためのものです。

「正しい」キーが引用符で囲まれているのは、スクリプトを見ると、実際には Ctrl(+Shift)+Y/Z をあらゆる場所で反転しているだけなので、何も達成されないからです。しかし、実際にはそうではなく、ただ機能するだけです... 私と元の作者の知る限りでは、その理由はわかりませんが。

これがなぜうまくいくのか、あるいはうまくいかないのか、何かお分かりでしたら、ぜひお聞かせください。

答え4

受け入れられた回答は機能するという事実にもかかわらず、その時点で選択されたレイアウトがドイツ語レイアウトである場合にのみ機能し、それ以外の場合は他のすべてのレイアウトで元に戻す機能が反転します。

0x4090409これを解決するには、米国のコードをドイツのコードに置き換えるだけです0x4070407。また、if ステートメントを次のように変更する必要があります。

$^z::
    hWnd := WinExist("A")
    ThreadID := DllCall("GetWindowThreadProcessId", "UInt", hWnd, "UInt", 0)
    hKL := DllCall("GetKeyboardLayout", "UInt", ThreadID, "UInt")
    If (hKL = 0x4070407)
        Send ^y
    Else
        Send ^z
Return

$^y::
    hWnd := WinExist("A")
    ThreadID := DllCall("GetWindowThreadProcessId", "UInt", hWnd, "UInt", 0)
    hKL := DllCall("GetKeyboardLayout", "UInt", ThreadID, "UInt")
    If (hKL = 0x4070407)
        Send ^z
    Else
        Send ^y
Return

関連情報