rabbit icon indicating copy to clipboard operation
rabbit copied to clipboard

我想实现切换焦点关闭输入窗口,但怎么样重置rime的输入状态?

Open vvyoko opened this issue 2 months ago • 4 comments

目前切换窗口焦点输入法不会消失,且不能上屏.... 只能按ESC关闭再重新输入

于是我想自己来实现这个 目前我窗口隐藏了... 但是输入状态仍然保留着...

我甚至想手动发送esc键来取消... 但好像不管用(不知道是不接受脚本快捷键还是啥),这的确不是一个好办法于是我放弃了

于是我想请教怎么样正确的重置输入状态?

; https://learn.microsoft.com/zh-cn/windows/win32/winauto/event-constants
EVENT_SYSTEM_FOREGROUND := "0x0003" ;前景窗口已更改
EVENT_OBJECT_FOCUS := "0x8005" ;对象已接收键盘焦点


WINEVENT_OUTOFCONTEXT := 0x0000 ;默认值。 回调函数在 Hook 进程之外的一个 单独线程 中被调用。这是最常用的模式。
WINEVENT_INCONTEXT := 0x0001  ;回调函数 注入 到事件发生所在的进程的 线程 中执行。这速度更快,但需要 Hook 进程和目标进程的位数匹配。
WINEVENT_SKIPOWNPROCESS := 0x0002 ;阻止 Hook 函数接收来自 Hook 进程本身 的事件。
WINEVENT_SKIPOWNTHREAD := 0x0004 ;阻止 Hook 函数接收来自 Hook 进程的线程 的事件。

class Hook
{
    static RegisterHook()
    {
        local cb := CallbackCreate(WinEventHandler)
        this.hHook := DllCall("user32\SetWinEventHook",
            "uint", EVENT_SYSTEM_FOREGROUND,      ; eventMin (EVENT_OBJECT_DESTROY)
            "uint", EVENT_SYSTEM_FOREGROUND,      ; eventMax
            "ptr", 0,            ; hmodWinEventProc (不用模块)
            "ptr", cb, ; lpfnWinEventProc (回调函数地址)
            "uint", 0,           ; idProcess (0 = 所有进程)
            "uint", 0,           ; idThread (0 = 所有线程)
            "uint", WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS)      ; dwFlags

        OnExit((*) => this.UnregisterHook())

        WinEventHandler(hHook, event, hwnd, idObject, idChild, dwmsEventTime)
        {
            switch event {
                case EVENT_SYSTEM_FOREGROUND:
                    if !CandidateBox.isHidden
                    {
                        ; Send("{Esc}")
                        ; Send("{Escape}")

                        box.hide()

                        ; if status := rime.get_status(session_id)
                        ;     rime.free_status(status)
                        ; if commit := rime.get_commit(session_id)
                        ;     rime.free_commit(commit)
                        ; if context := rime.get_context(session_id)
                        ;     rime.free_context(context)
                    }
                default:
            }

        }
    }

    static UnregisterHook()
    {
        DllCall("user32\UnhookWinEvent", "ptr", this.hHook)
    }
}

vvyoko avatar Oct 19 '25 10:10 vvyoko

你好,感谢关注玉兔毫,这个问题我也发现了。因为个人时间问题,暂时没有去研究修复方式,可能要等我有假期了再看看。

amorphobia avatar Oct 19 '25 10:10 amorphobia

问了下AI 最终找到了RimeClearComposition 通过它找到了包装里已存在的方法.... 暂时测试好像没问题,但是我也不大确定 顺便在github的回复里.好像光标定位不准导致窗口出现的问题也不对

rime.clear_composition(session_id)
box.hide()

vvyoko avatar Oct 19 '25 12:10 vvyoko

既然重新打开了,我顺便反馈一些较严重的问题吧

CAPS好像失效了在中文模式下它会在输入窗口中输入大写,但是切换到英文,它没任何作用了

还有一个就是长按好像全没有了.. 这个太致命了.. 我测试了好几个游戏.走路都走不动了(英文模式) 是不是可以在注册快捷键的时候大部分按键添加个hotif仅在中文模式下生效?? 除了切换中英好像英文模式没任何必要接管? 这也不是输入法,也没必要接管切换输入法的快捷键 不过这也很难改善... 在游戏中谁会没事切换中英状态呀... 这种还是得注册成输入法...应该会有特定的事件... 而不是在程序未需求输入法时全部都是输入....

光标不准这种都是小事了...

vvyoko avatar Oct 20 '25 09:10 vvyoko

你好, 可以使用suspend_hotkey

rawbx avatar Oct 24 '25 09:10 rawbx