是否可以根据输入语言改变光标指示器的颜色?

是否可以根据输入语言改变光标指示器的颜色?

在 Windows 10 上,有一个选项可以更改光标指示器颜色(Win+I -> 轻松访问 -> 文本光标)。

我很想(如果有应用程序的话,我甚至愿意付费)根据所选的输入语言更改文本光标颜色。我经常使用英语和希腊语,并经常在它们之间切换。大多数时候,我开始快速输入第一个单词,然后删除所有单词,更改语言,然后重新开始。我希望可以避免这种情况。我知道通知区域有一个指示器,但它很小,通常我只是忽略它。

我使用 Autohotkey,我的键盘可以执行宏。任何想法都欢迎。

答案1

假设来自的其他代码user3419297对于检测语言是正确的(我没有测试过),下面的附加功能将改变光标指示器的颜色。

我放了几种颜色供您测试——您可以在代码中定义自己的颜色,或者如果您想使用 GUI 中的颜色选择器(通常会更改颜色,即“轻松访问”设置),可以从注册表项中读取颜色。我假设数字字段可能是蓝色/绿色/红色(十六进制,每种颜色一个字节),但也没有检查……至少,红色是最低字节。或者,如果您愿意,也可以直接使用十六进制代码,而不是定义命名的颜色,但我通常喜欢用英语定义几种颜色,这样我就可以在它们之间进行切换,而不必使用十六进制值。

#SingleInstance Force
    SetTimer, ChangeCursor, 100
return

ChangeCursor:
    If GetKeyboardLanguage(WinActive("A")) = 0x0409  ; English  (0x0408 ; Greek)
        cursorIndicatorColorSet("gold")
    Else 
        cursorIndicatorColorSet()   ; set to black (note, this doesn't turn the cursor indicator off, just sets to black
return

; https://www.autohotkey.com/board/topic/116538-detect-which-language-is-currently-on/#entry672197

GetKeyboardLanguage(_hWnd=0){
    if !_hWnd
        ThreadId=0
    else
        if !ThreadId := DllCall("user32.dll\GetWindowThreadProcessId", "Ptr", _hWnd, "UInt", 0, "UInt")
            return false
    if !KBLayout := DllCall("user32.dll\GetKeyboardLayout", "UInt", ThreadId, "UInt")
        return false
    return KBLayout & 0xFFFF
}

cursorIndicatorColorSet(color:="") {
    hexColor := (color="Red")   ? "0xFF"
              : (color="Gold")  ? "0xBFFF"
              : (color="Black") ? "0x00"
              : "0x00"  ; default for no argument is black
    RegWrite, REG_DWORD, HKEY_CURRENT_USER, % "SOFTWARE\Microsoft\Accessibility\CursorIndicator", IndicatorColor, % hexColor
}

如果您想找到其他类似的辅助功能设置以便通过编程方式进行修改,请下载 SysInternals Procmon 实用程序,然后过滤以仅显示SystemSettings.exe(或您要查看的任何程序,如果它不是系统设置)。开始登录 Procmon,在系统设置中切换要捕获的项目,然后停止登录 Procmon 并查看在您更改设置时系统设置尝试打开或更改的注册表项。

在上述情况下,我刚刚打开了辅助功能设置,找到了您想要使用的设置(光标指示器颜色),切换了颜色,然后查看了读取或修改了哪些注册表项。

例如,要扩展此代码,可能只需为一种语言设置光标指示器颜色,然后为另一种语言完全关闭它即可。这是辅助功能设置中的一个单独开关,用于打开/关闭它,而不是仅设置颜色,因此,如果您打开/关闭它,辅助功能设置将写入不同的注册表项(您可能想使用也可能不想使用,但它很容易找到——仅作为示例)。

同样的事情也发生在鼠标光标颜色上(可能有不同的用途,我不是指其他 AutoHotkey 示例中的光标形状,而是指辅助功能中可用的鼠标颜色选项)。

无论如何,一旦您知道如何记录注册表项,您就可以直接使用 RegEdit 戳注册表以查看它是否执行您想要的操作(Procmon 将允许您从捕获的任何条目直接跳转到注册表位置,然后您可以手动编辑,或通过更改设置并点击刷新来观察值的变化),然后,如果直接在 RegEdit 中戳它有效,那么您可以将该键/值的注册表读/写语句添加到您可能想要采取的任何类型的脚本操作中(如上所示)。

答案2

尝试这个 AHK 脚本

#Persistent
#SingleInstance Force

SetTimer, ChangeCursor, 100
OnExit("ExitFunc")
return

ChangeCursor:
If GetKeyboardLanguage(WinActive("A")) = 0x0409  ; English  (0x0408 ; Greek)
&& A_Cursor = "IBeam"
    applied ?: SetSystemCursor("IDC_SIZENS"), applied := true
else 
    (!applied) ?: RestoreCursors(), applied := false
return


 ; https://www.autohotkey.com/board/topic/116538-detect-which-language-is-currently-on/#entry672197

GetKeyboardLanguage(_hWnd=0){
    if !_hWnd
        ThreadId=0
    else
        if !ThreadId := DllCall("user32.dll\GetWindowThreadProcessId", "Ptr", _hWnd, "UInt", 0, "UInt")
            return false    
    if !KBLayout := DllCall("user32.dll\GetKeyboardLayout", "UInt", ThreadId, "UInt")
        return false    
    return KBLayout & 0xFFFF
}


ExitFunc(ExitReason, ExitCode){
    if ExitReason not in Logoff,Shutdown
        RestoreCursors()
}


; https://autohotkey.com/board/topic/32608-changing-the-system-cursor/
SetSystemCursor( Cursor = "", cx = 0, cy = 0 ) 
{
    BlankCursor := 0, SystemCursor := 0, FileCursor := 0 ; init

    SystemCursors = 32512IDC_ARROW,32513IDC_IBEAM,32514IDC_WAIT,32515IDC_CROSS
    ,32516IDC_UPARROW,32640IDC_SIZE,32641IDC_ICON,32642IDC_SIZENWSE
    ,32643IDC_SIZENESW,32644IDC_SIZEWE,32645IDC_SIZENS,32646IDC_SIZEALL
    ,32648IDC_NO,32649IDC_HAND,32650IDC_APPSTARTING,32651IDC_HELP

    If Cursor = ; empty, so create blank cursor 
    {
        VarSetCapacity( AndMask, 32*4, 0xFF ), VarSetCapacity( XorMask, 32*4, 0 )
        BlankCursor = 1 ; flag for later
    }
    Else If SubStr( Cursor,1,4 ) = "IDC_" ; load system cursor
    {
        Loop, Parse, SystemCursors, `,
        {
            CursorName := SubStr( A_Loopfield, 6, 15 ) ; get the cursor name, no trailing space with substr
            CursorID := SubStr( A_Loopfield, 1, 5 ) ; get the cursor id
            SystemCursor = 1
            If ( CursorName = Cursor )
            {
                CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )   
                Break                   
            }
        }   
        If CursorHandle = ; invalid cursor name given
        {
            Msgbox,, SetCursor, Error: Invalid cursor name
            CursorHandle = Error
        }
    }   
    Else If FileExist( Cursor )
    {
        SplitPath, Cursor,,, Ext ; auto-detect type
        If Ext = ico 
            uType := 0x1    
        Else If Ext in cur,ani
            uType := 0x2        
        Else ; invalid file ext
        {
            Msgbox,, SetCursor, Error: Invalid file type
            CursorHandle = Error
        }       
        FileCursor = 1
    }
    Else
    {   
        Msgbox,, SetCursor, Error: Invalid file path or cursor name
        CursorHandle = Error ; raise for later
    }
    If CursorHandle != Error 
    {
        Loop, Parse, SystemCursors, `,
        {
            If BlankCursor = 1 
            {
                Type = BlankCursor
                %Type%%A_Index% := DllCall( "CreateCursor"
                , Uint,0, Int,0, Int,0, Int,32, Int,32, Uint,&AndMask, Uint,&XorMask )
                CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )
                DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )
            }           
            Else If SystemCursor = 1
            {
                Type = SystemCursor
                CursorHandle := DllCall( "LoadCursor", Uint,0, Int,CursorID )   
                %Type%%A_Index% := DllCall( "CopyImage"
                , Uint,CursorHandle, Uint,0x2, Int,cx, Int,cy, Uint,0 )     
                CursorHandle := DllCall( "CopyImage", Uint,%Type%%A_Index%, Uint,0x2, Int,0, Int,0, Int,0 )
                DllCall( "SetSystemCursor", Uint,CursorHandle, Int,SubStr( A_Loopfield, 1, 5 ) )
            }
            Else If FileCursor = 1
            {
                Type = FileCursor
                %Type%%A_Index% := DllCall( "LoadImageA"
                , UInt,0, Str,Cursor, UInt,uType, Int,cx, Int,cy, UInt,0x10 ) 
                DllCall( "SetSystemCursor", Uint,%Type%%A_Index%, Int,SubStr( A_Loopfield, 1, 5 ) )         
            }          
        }
    }   
}

RestoreCursors() 
{
   SPI_SETCURSORS := 0x57
   DllCall( "SystemParametersInfo", UInt,SPI_SETCURSORS, UInt,0, UInt,0, UInt,0 )
}

或者创建/下载图标文件并使用加载该文件

Cursor = %A_ScriptDir%\mycursor.ani
CursorHandle := DllCall( "LoadCursorFromFile", Str,Cursor )

https://www.autohotkey.com/board/topic/32608-changing-the-system-cursor/

答案3

您还可以使用 SKAN 的功能设置光标方案(方案)

#Persistent
#SingleInstance Force

SetTimer, ChangeCursor, 100
OnExit("ExitFunc")
return

ChangeCursor:
If GetKeyboardLanguage(WinActive("A")) = 0x0409  ; English  (0x0408 ; Greek)
&& A_Cursor = "IBeam"
   SetCursorScheme("Magnified")
else 
    SetCursorScheme("Windows Default")
return

 ; https://www.autohotkey.com/board/topic/116538-detect-which-language-is-currently-on/#entry672197
GetKeyboardLanguage(_hWnd=0){
    if !_hWnd
        ThreadId=0
    else
        if !ThreadId := DllCall("user32.dll\GetWindowThreadProcessId", "Ptr", _hWnd, "UInt", 0, "UInt")
            return false    
    if !KBLayout := DllCall("user32.dll\GetKeyboardLayout", "UInt", ThreadId, "UInt")
        return false    
    return KBLayout & 0xFFFF
}

; https://www.autohotkey.com/boards/viewtopic.php?t=82431
SetCursorScheme( Scheme )               { ; By SKAN on D3AO/D3AO @ tiny.cc/setcursorscheme
Local
  Cursors := "Arrow,Help,AppStarting,Wait,Crosshair,IBeam,NWPen,No,SizeNS,"
           . "SizeWE,SizeNWSE,SizeNESW,SizeAll,UpArrow,Hand,Pin,Person"
  SchemePath2 := "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Control Panel\Cursors"
  SchemePath1 := "HKCU\Control Panel\Cursors"
  SetRegView, 64
  If ( Scheme="Windows Default" )
  {
      RegWrite, REG_SZ,    %SchemePath1%,, Windows Default
      RegWrite, REG_DWORD, %SchemePath1%, Scheme Source, 2
      Loop, Parse, Cursors, CSV
      {
          RegRead, Val, %SchemePath2%\Default, %A_LoopField%
          If (! ErrorLevel )
          RegWrite, REG_EXPAND_SZ, %SchemePath1%, %A_LoopField%, %Val%
      }
      SetRegView, Default
      Return DllCall("SystemParametersInfo", "Int",0x57, "Int", 0, "Ptr", 0, "Int", 0)
  }
  SchemeSource := 2
  RegRead, Val, %SchemePath2%\Schemes, %Scheme%
  If ( ErrorLevel )
  {
      SchemeSource := 1
      RegRead, Val, %SchemePath1%\Schemes, %Scheme%
  }
  If ( ErrorLevel )
      SchemeSource := 0,    Scheme := ""
  Cur := StrSplit(Val, ",")
  RegWrite, REG_DWORD, %SchemePath1%, Scheme Source, %SchemeSource%
  RegWrite, REG_SZ, %SchemePath1%,, %Scheme%
  Loop, Parse, Cursors, CSV
  {
      RegRead, Val, %SchemePath2%\Default, %A_LoopField%
      If (! ErrorLevel )
          RegWrite, REG_EXPAND_SZ, %SchemePath1%, %A_LoopField%, % Cur[A_Index]
  }
  SetRegView, Default
Return DllCall("SystemParametersInfo", "Int",0x57, "Int", 0, "Ptr", 0, "Int", 0)
}

ExitFunc(ExitReason, ExitCode){
    if ExitReason not in Logoff,Shutdown
        SetCursorScheme("Windows Default")
}

相关内容