Corrija a localização física dos atalhos Desfazer (Ctrl-Z) e Refazer (Ctrl-Y) entre layouts de teclado alemão e russo no Windows

Corrija a localização física dos atalhos Desfazer (Ctrl-Z) e Refazer (Ctrl-Y) entre layouts de teclado alemão e russo no Windows

Estou imitando outra vítima do caos no layout do teclado, que sofre de um problema semelhante, mas um pouco diferente.

Estou usando extensivamente layouts de teclado alemão e russo em minha estação de trabalho Windows 10 e alterno frequentemente entre eles. O problema está relacionado ao fato de que as letras Y e Z são trocadas no layout do teclado alemão em comparação com o layout QWERTY padrão do inglês.

Se eu usar o layout alemão, o atalho Desfazer (Ctrl-Z) está vinculado à tecla Z, que está localizada no meio da primeira linha de letras entre T e U. O Refazer (Ctrl-Y) está vinculado à tecla Y , que está localizado à esquerda do X na linha inferior de letras no layout QWERTZ alemão.

Se você mudar o layout para o russo, de repente algo ruim acontecerá. Os atalhos Desfazer e Refazer alteram mutuamente sua posição no teclado. Desfazer (Ctrl-Z) está localizado agora em Y (linha inferior, da esquerda para X) e Refazer em Z (linha superior, entre T e U). Este local é idêntico ao local de Ctrl-Z e Ctrl-Y no layout de teclado padrão em inglês.

Isso significa que a localização dos atalhos Desfazer e Refazer muda para o oposto sempre que mudo o layout do teclado. Como você pode imaginar, estou sempre pressionando o atalho errado, porque é impossível aprender dois padrões oscilantes opostos, pelo menos protesta minha coluna-cérebro. Como uso os atalhos Desfazer e Refazer com frequência, esse comportamento me irrita muito.

Quero corrigir a localização física (teclas) dos atalhos Refazer e Desfazer em todo o conjunto de aplicativos do Windows para o layout alemão ou melhor em inglês.

Usar o layout em inglês permanentemente para todos os tipos de textos baseados em latim, embora resolva o problema de pular atalhos de Desfazer/Refazer, mas não é uma opção para mim, porque preciso digitar textos em alemão com todos os tremas e ß (não sugira um layout internacional para inserir acentos, porque o alemão é meu idioma principal e quero digitar suas letras nativas com um toque de tecla).

Como já mencionou o colega na pergunta referenciada, não existe uma resposta óbvia na Internet. O mesmo problema é resolvido no Ubuntu criando um layout de teclado personalizado. Não consigo encontrar nenhuma informação sobre como criar um layout personalizado para Windows ou corrigir o atual.

Esse comportamento é consistente em todas as versões do Windows que conheço e está profundamente relacionado aos designs iniciais de layout do teclado, que são incompatíveis para usuários que usam o par de idiomas alemão-russo como eu.

Uma boa solução deve ser implementada diretamente no Windows, sem qualquer software adicional, ou apenas software de código aberto gratuito. Soluções de trabalho envolvendo AutoHotKey são bem-vindas.

Com a ajuda de @miroslav, criei este script AHK parcialmente funcional:

; 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

Este script remapeia perfeitamente Ctrl-Y <-> Ctrl-Z no layout alemão, mas corrompe ambas as teclas de atalho no layout russo. Eu uso ^н e ^я com a esperança de emular equivalentes de código de varredura Ctrl-Y ou Ctrl-Z para layout russo, mas não funciona (gera н para Ctrl-Y e nada visível para Ctrl-Z). Usar ^z e ^y para russo também não funciona, gerando as letras z e y respectivamente.

Diferente da resposta do Miroslav, tive que usar o gancho do teclado ($) para evitar loops e remover rótulos (provavelmente erro de copiar e colar)

Solução sugerida por Williams:

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

infelizmente também não funciona. Ele gera letras simples 'y' e 'z' no layout russo e nenhuma alteração no layout alemão (Ctrl-Z e Ctrl-Y passados ​​no mapeamento original).

Ainda procurando a solução.

Responder1

Você pode simplesmente criar seu próprio layout de teclado usandoMicrosoft Keyboard Layout Creator 1.4 do Centro de Download Oficial da Microsoft.

O Youtube oferece vários tutoriais em vídeo sobre como usá-lo (comoessecom localidade russa) - basta procurar seu nome. Mas basicamente você clona um dos layouts de teclado existentes e o modifica de acordo com suas necessidades.

Solução AutoHotKey:

(nota: substitua 0x4090409constante (teclado dos EUA) pelo valor que se aplica ao seu layout)

$^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

Hook ($) é necessário para evitar recursão, ou seja, Send ^zinvocar Send ^yapenas outra macro AHK.

Testei essa condição de detecção do teclado e funcionou bem.

Claro, você pode colocar a detecção do teclado em funcionamento e, portanto, otimizar o código, etc. :)

Responder2

Finalmente encontrei uma solução funcional para mim (script AutoHotKey):

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

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

Ele mantém perfeitamente a tecla de desfazer (Ctrl-Z) em seu lugar lógico - linha inferior esquerda - independentemente do layout do teclado.

Obrigado @Miroxlav e @Williams por trazer peças para a solução.

Responder3

Com base na resposta de Anton, atualizei o código para AHK v2 e adicionei suporte para a variante Ctrl+Shift, já que muitos programas agora usam isso para Refazer.

#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}"

O objetivo deste script é corrigir a ação Desfazer na tecla Y/Z inferior esquerda, uma vez que diferentes layouts (QWERTZ vs QWERTY) movem o Z para o meio superior, o que é impraticável. O mesmo vale para Refazer, que agora está fixado na tecla Y/Z média superior.

Como Desfazer/Refazer geralmente são executados por Ctrl+Z/Y, isso pode ser conseguido capturando a tecla pressionada e reemitindo a tecla "correta". Essas são as ^sc0**linhas. As ^+sc0**linhas são para reemitir eventos Ctrl+Shift+Z/Y, já que muitos programas usam Ctrl+Shift+Z para Refazer.

A chave "correta" está entre aspas porque se você olhar o script, na verdade deveria estar apenas girando Ctrl(+Shift)+Y/Z em todos os lugares... portanto, não conseguindo nada. No entanto, não é isso que acontece e simplesmente funciona... embora eu e o AFAIK, o autor original, não saibamos por quê.

Se você tiver alguma ideia de por que isso funciona ou não para você... fale

Responder4

Apesar de a resposta aceita funcionar, ela só funciona se o layout selecionado no momento for o layout alemão, caso contrário, inverte a função de desfazer em todos os outros layouts.

Para resolver isso basta substituir o código dos EUA 0x4090409pelo código alemão 0x4070407. Além disso, você alterou a instrução if assim:

$^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

informação relacionada