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 0x4090409
constante (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 ^z
invocar Send ^y
apenas 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 0x4090409
pelo 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