windows 如何在C#中隐藏所有窗口的鼠标光标?

gopyfrb3  于 2023-11-21  发布在  Windows
关注(0)|答案(1)|浏览(213)

TLDR:如何以编程方式隐藏鼠标光标为整个桌面,无论应用程序有焦点?
即使我在Windows鼠标选项中启用了“键入时隐藏指针”,它也不适用于大多数窗口。它似乎只适用于使用标准Windows文本框控件的窗口(如notepad.exe)。在其他任何地方,光标都停留在我键入的内容上方。
当我执行特定操作(例如,按下热键)时,我希望通过编程方式在整个桌面上隐藏鼠标光标**,无论哪个应用程序具有焦点。然后,当移动鼠标时,我希望光标重新出现。
我可以处理热键等,我只需要知道如何隐藏光标。
我所尝试的:

目前我的解决办法是听空格键被按下(暗示我键入了几个字符),然后将鼠标光标移动到桌面的顶部角落,不碍事。然而,这不是一个理想的解决方案,因为它需要移动鼠标很多才能返回到原始位置,以及在Sketchup等应用程序中输入包含空间的尺寸时弄乱鼠标位置。我更希望光标在当前位置变得不可见,然后在移动鼠标时重新出现在同一位置,因为它应该与“键入时隐藏指针”选项一起使用。
我不依赖于C#,但它很容易编译成Windows的可执行文件,我可以在Windows启动时启动它。
感谢您的帮助!

0sgqnhkj

0sgqnhkj1#

这是AutoHotkey解决方案,虽然这只是调用Windows API(对于隐藏/显示部分,否则脚本在使用UIA框架跟踪可编辑字段时会有点复杂,当您不输入时不会隐藏指针,并且还跟踪鼠标移动和其他与键绑定相关的机器),但您可以将其转换为C#(或者只需在Windows start上启动AHK脚本)
它使用了Jimi建议的相同逻辑(遍历系统光标并将其指针替换为空白图像),尽管有一个调整来解决指针的比例大小> 1时的问题(如果您只是尝试替换它,它会变得模糊)
它也不适用于自定义应用程序鼠标指针,只有那些你在系统设置中看到的
还没有找到一个解决方案。如何隐藏自定义应用程序指针,虽然这是可能的,因为像AutoHideMouseCursor这样的应用程序可以做到这一点。
Full standalone script source及其所依赖的库
隐藏指针的函数

sys🖰Pointer(OnOff := On) {
      global is🖰PointerHidden
      static C := win32Constant.Misc ; various win32 API constants
    
      static hCur,AndMask,XorMask
      , isInit  := false, toShow := 1, toHide := 2
      , lrDef   := C.lrShared | C.lrDefColor                ; lrDefSz
      , lcDef   := C.lrShared | C.lrDefColor | C.lrCcSrc    ; lrDefSz
    
      if ( (OnOff = Off)
        or (OnOff = Toggle and (not is🖰PointerHidden
                             or not isInit)) ) { ; hide on first init call as well
        ; dbgTT(dbgMin:=0, Text:='toHide', Time:=1,id:=6,X:=0,Y:=150)
        changeTo := toHide  ; use hCur_blank cursors
      } else {
        ; dbgTT(dbgMin:=0, Text:='toShow', Time:=1,id:=8,X:=0,Y:=250)
        changeTo := toShow  ; use hCur_saved cursors
      }
    
      static curSID     := [ ;system_cursors learn.microsoft.com/en-us/windows/win32/menurc/about-cursors
          Arrow         := 32512    ; IDC_ARROW     MAKEINTRESOURCE(32512)   Normal select
        , Ibeam         := 32513    ; IDC_IBEAM     MAKEINTRESOURCE(32513)   Text select
        , Wait          := 32514    ; IDC_WAIT      MAKEINTRESOURCE(32514)   Busy
        , Cross         := 32515    ; IDC_CROSS     MAKEINTRESOURCE(32515)   Precision select
        , UpArrow       := 32516    ; IDC_UPARROW   MAKEINTRESOURCE(32516)   Alternate select
        , Size⤡         := 32642    ; IDC_SIZENWSE  MAKEINTRESOURCE(32642)   Diagonal resize 1
        , Size⤢         := 32643    ; IDC_SIZENESW  MAKEINTRESOURCE(32643)   Diagonal resize 2
        , Size↔         := 32644    ; IDC_SIZEWE    MAKEINTRESOURCE(32644)   Horizontal resize
        , Size↕         := 32645    ; IDC_SIZENS    MAKEINTRESOURCE(32645)   Vertical resize
        , Size⤨         := 32646    ; IDC_SIZEALL   MAKEINTRESOURCE(32646)   Move
        , No            := 32648    ; IDC_NO        MAKEINTRESOURCE(32648)   Unavailable
        , Hand          := 32649    ; IDC_HAND      MAKEINTRESOURCE(32649)   Link select
        ; ↓ not in      OCR_NORMAL  so can't be a restore target? learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setsystemcursor. Or just a doc omission?
        , AppStarting   := 32650    ; IDC_APPSTARTING   MAKEINTRESOURCE(32650)   Working in background
        , Help          := 32651    ; IDC_HELP          MAKEINTRESOURCE(32651)   Help select
        , Pin           := 32671    ; IDC_PIN           MAKEINTRESOURCE(32671)   Location select
        , Person        := 32672    ; IDC_PERSON        MAKEINTRESOURCE(32672)   Person select
        ;, _handwrite   := 32631    ;                   MAKEINTRESOURCE(32631)   Handwriting
      ]
       , hCursors := Array()
      hCursors.Capacity := curSID.Length
    
      static sys := helperSystem
      ; Get mouse pointer actual size (https://stackoverflow.com/a/65534381)
        ; GetIconInfo will return a bitmap sized for the primary display only
          ; If your main display is 150%, but the cursor is on a 100% secondary monitor, you'll get an incorrect 48x48 bitmap instead of 32x32
        ; 1 get monitor DPI         via GetDpiForMonitor
        ; 2 get proper icon size    via GetSystemMetricsForDpi
        ; 3 scale by the "cursor magnification" settings from accessibility
      dpi🖥️        := sys.getDPI🖥️(), dpi🖥️x:=dpi🖥️[1], dpi🖥️y:=dpi🖥️[2]                                          ; 1) monitor dpi
      sysCurMagniF  := RegRead('HKEY_CURRENT_USER\SOFTWARE\Microsoft\Accessibility','CursorSize',1)                 ; 2) pointer size @ Settings/Ease of Access/Mouse pointer
      dpi🖰Pointer  := sys.getDPI🖰Pointer(dpi🖥️x), width🖰Pointer:=dpi🖰Pointer[1], height🖰Pointer:=dpi🖰Pointer[2]  ;  3) get dpi-scaled system metric for mouse cursor size learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsystemmetricsfordpi
      cx            := sysCurMagniF * width🖰Pointer, cy := sysCurMagniF * height🖰Pointer ; LoadImageW
      cxc           := 0, cyc := 0 ; copy
      ; cxc         := cx, cyc := cy ; copy
    
      if    (OnOff = Init or isInit = false) {  ; init when requested or at first call
        dbgTT(dbgMin:=3, Text:='init', Time:=2,id:=5,X:=0,Y:=450)
        hCur    := Buffer( 4*A_PtrSize, 1)      ;
        AndMask := Buffer(32*A_PtrSize, 0xFF)   ;
        XorMask := Buffer(32*A_PtrSize, 0)      ;
        loop curSID.Length {
          hCur := DllCall('LoadImageW' ; ↓ LoadImage ret HANDLE to the newly loaded image; NULL on error, use GetLastError
            , 'Ptr',0                       ; opt HINSTANCE hInst   handle to the module DLL/EXE that contains image to be loaded
            ,'uint',curSID[A_Index]         ; LPCWSTR   name        if ↑Null and fuLoad≠lrLOADFROMFILE, predefined image to load
            ,'uint',C.imgCursor             ; uint      type        type of image to be loaded
            , 'Int',cx, 'Int',cy            ; int       cx|xy       icon/cursor's width|height  px
              ; 0 & fuLoad=lrDefSz                                  use SM_CXICON/CURSOR (/Y) system metric value to set W/H
              ; 0 & not    lrDefSz                                  use actual resource height
            ,'uint',lrDef                   ; uint      fuLoad
            , 'Ptr')                        ; learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadimagew
          hCur_saved := DllCall("CopyImage" ; create a new image (icon/cursor/bitmap) and copy its attributes to the new one. Stretch the bits to fit the desired size if needed, learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-copyimage
            ,"Ptr" ,hCur                    ; HANDLE    h
            ,"uint",C.imgCursor             ; uint      type
            , "int",cxc, "int",cyc          ; int       cx|cy   0=returned image will have same width|height as original hImage
            ,"uint",lcDef                   ; uint      flags
            , 'Ptr')
          hCur_blank := DllCall("CreateCursor" ; create a monochrome cursor
            , "Ptr",0           ;opt HINSTANCE  hInst,
            , "int", 0,"int", 0 ;int        xHotSpot / yHotSpot
            , "int",32,"int",32 ;int        nWidth   / nHeight
            , 'Ptr',AndMask     ;const VOID *pvANDPlane array of bytes with bit values for the AND mask of the cursor, as in a device-dependent monochrome bitmap
            , 'Ptr',XorMask     ;const VOID *pvXORPlane array of bytes with bit values for the XOR mask of the cursor, as in a device-dependent monochrome bitmap
            , 'Ptr')
          hCursors.Push([hCur_saved, hCur_blank]) ; toShow=1 toHide=2
        }
        ; isInit    := true ; move to the end to allow hiding cursor on 1st toggle call
      }
      ; MouseGetPos(&🖰x, &🖰y) ; Get the current mouse position, and store its coordinates
      dbgOut := "changeTo=" changeTo
        . "`nsysCurMagniF=" sysCurMagniF
        . "`nmonDPIx|y`t= " dpi🖥️x " | " dpi🖥️y ;"`n" 🖰x " " 🖰y
        . "`ncurW|H_dpi`t= " width🖰Pointer " | " height🖰Pointer
        . "`ncX|Y`t= " cx " | " cy
    
      loop curSID.Length {
        hCur := DllCall("CopyImage", "Ptr", hCursors[A_Index][changeTo]
          ,"uint",C.imgCursor, "int",cxc,"int",cyc, "uint",lcDef)
        DllCall("SetSystemCursor" ; replace the contents of the system cursor specified by id with the contents of the cursor handled by hcur
          , "Ptr",hCur              ; cursor handle, destroyed via DestroyCursor, so can't be LoadCursor, use CopyCursor
          ,"uint",curSID[A_Index]   ; system cursor to replace
          )
        ; dbgOut .= "`nhCur=" hCur
        }
      is🖰PointerHidden := (changeTo = toHide) ? true : false
      dbgOut .= "`nis🖰PointerHidden=" is🖰PointerHidden
      dbgOut .= "`nOnOff=" OnOff
      if changeTo = toShow {
        restore🖰Pointers()
        sys🖰Btn(On)
      } else if changeTo = toHide {
        sys🖰Btn(Off)
      }
      dbgTT(dbgMin:=4, Text:=dbgOut, Time:=3,id:=3,X:=0,Y:=750)
      isInit    := true
    }

字符串
和恢复指针的函数

restore🖰Pointers() {
      static C := win32Constant.Misc ; various win32 API constants
      DllCall("SystemParametersInfo"
       ,'uint',C.curReload  ; uint      uiAction    system-wide parameter to be retrieved or set
       ,'uint',0            ; uint      uiParam     parameter whose usage and format depends on the system parameter being queried or set., see uiAction. Must be 0 if not otherwise indicated
       ,'uint',0            ;io PVOID   pvParam     parameter whose usage and format depends on the system parameter being queried or set, see uiAction. Must be NULL if not otherwise indicated
       ,'uint',0            ; uint      fWinIni     If a system parameter is being set, specifies whether the user profile is to be updated, and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to notify them of the change
       )
    }


P.S.“打字时隐藏指针”确实有缺陷,因为它依赖于应用程序轮询其值并隐藏指针本身,很少有应用程序这样做
P.P.S.还发现了一个更简单的C++ GUI应用程序MousePuff,尽管它也没有隐藏应用程序特定的指针

相关问题