Kết hợp Autohotkey và Goldendict để select text to translate - QuânSysAd's Blog

23 tháng 12 2019

Kết hợp Autohotkey và Goldendict để select text to translate

Đôi khi sử dụng GoldenDict để dịch bạn muốn bôi đen text thì GoldenDict sẽ tự dịch từ đó cho ta. Và một điều khó chịu khác là chức năng translate pop up trong Window của GoldenDict không hoạt động, mà dùng phím tắt Ctrl+C+C để dịch thì đôi khi bạn không thích lắm.
Bạn hãy soạn file autohotkey sau:
; Translate selected text for GoldenDict
GetInstallPath(ProgramName) {
    SoftwareKey := (A_Is64bitOS = 0 ? "Software" : "Software\WOW6432Node")
    RegRead, FullFileName, HKEY_LOCAL_MACHINE, %SoftwareKey%\Microsoft\Windows\CurrentVersion\Uninstall\%ProgramName%, UninstallString
    SplitPath, FullFileName,, InstallPath
    return %InstallPath%
}
GoldenDict := "Duong\Dan\Toi\File\GoldenDict.exe"
run, %GoldenDict%

GroupAdd, DontActiveGroup, ahk_class ExploreWClass  ; Disable Explorer window. Unused on Vista and later
GroupAdd, DontActiveGroup, ahk_class CabinetWClass  ; Disable Explorer window.
GroupAdd, DontActiveGroup, ahk_class Progman        ; Disable desktop window.
GroupAdd, DontActiveGroup, ahk_class WorkerW        ; Disable desktop window.
GroupAdd, DontActiveGroup, ahk_class ConsoleWindowClass ; Disable console window.

GetArrowState() {
    arrowstate_result = 0
    GetKeyState, keystate, Left, P
    if keystate = D
        arrowstate_result += 1
    GetKeyState, keystate, Up, P
    if keystate = D
        arrowstate_result += 2
    GetKeyState, keystate, Right, P
    if keystate = D
        arrowstate_result += 4
    GetKeyState, keystate, Down, P
    if keystate = D
        arrowstate_result += 8
    return arrowstate_result
}

#IfWinNotActive ahk_group DontActiveGroup
~Lshift::
TimeButtonDown = %A_TickCount%
arrow_state = 0
; Wait for it to be released
Loop
{
    Sleep 10
    if arrow_state = 0
        arrow_state = GetArrowState()
    GetKeyState, LshiftState, Lshift, P
    if LshiftState = U  ; Button has been released.
        break
    elapsed = %A_TickCount%
    elapsed -= %TimeButtonDown%
    if elapsed > 200  ; Button was held down long enough
    {
        x0 = A_CaretX
        y0 = A_CaretY
        Loop
        {
            Sleep 10                    ; yield time to others
            if arrow_state = 0
                arrow_state = GetArrowState()
            GetKeyState, keystate, Lshift
            IfEqual keystate, U, {
                x = A_CaretX
                y = A_CaretY
                break
            }
        }
        if (arrow_state <> 0 and (x-x0 > 5 or x-x0 < -5 or y-y0 > 5 or y-y0 < -5))
        {   ; Caret has moved
            GoSub, TranslateRoutine
        }
        return
    }
}

#IfWinNotActive ahk_group DontActiveGroup
~LButton::
TimeButtonDown = %A_TickCount%
MouseGetPos x0, y0            ; save start mouse position
; Wait for it to be released
Loop
{
    Sleep 10
    GetKeyState, LButtonState, LButton, P
    if LButtonState = U  ; Button has been released.
        break
    elapsed = %A_TickCount%
    elapsed -= %TimeButtonDown%
    if elapsed > 200  ; Button was held down too long, so assume it's not a double-click.
    {
        Loop
        {
            Sleep 20                    ; yield time to others
            GetKeyState, keystate, LButton
            IfEqual keystate, U, {
                MouseGetPos x, y          ; position when button released
                break
            }
        }
        if (x-x0 > 5 or x-x0 < -5 or y-y0 > 5 or y-y0 < -5)
        {   ; mouse has moved
            GoSub, TranslateRoutine
        }
        return
    }
}
; Otherwise, button was released quickly enough.  Wait to see if it's a double-click:
TimeButtonUp = %A_TickCount%
Loop
{
    Sleep 10
    GetKeyState, LButtonState, LButton, P
    if LButtonState = D  ; Button has been pressed down again.
        break
    elapsed = %A_TickCount%
    elapsed -= %TimeButtonUp%
    if elapsed > 350  ; No click has occurred within the allowed time, so assume it's not a double-click.
    {
        ;MouseClick, Left
        return
    }
}

; Since above didn't return, it's a double-click:
Sleep, 100
;Send, ^c
GoSub, TranslateRoutine
return

TranslateRoutine:
{
    WinGetActiveTitle active_title
    OutputDebug Current active window title is %active_title%.

    old_clip := ClipBoardAll    ; save old clipboard
    ClipBoard =                 ; clear current clipboard
    send, ^c                    ; selection -> clipboard
    ClipWait, 1                 ; retrieve new clipboard
    if ErrorLevel
    {
        selected = ""
    }
    else
    {
        selected = %ClipBoard%
    }
    SetEnv, ClipBoard, %old_clip%   ; restore old clipboard

    IfEqual selected,, return
    selected := Trim(selected, " `t`r`n")
    StringLen, sel_len, selected
    if (sel_len <= 0 or sel_len > 50)
    {
        return
    }
    selected := """" . selected . """"
    run, %GoldenDict% %selected%
}
return
Ở dòng thứ 8 hãy khai báo đường dẫn tới file GoldenDict.exe và sau đó hãy chạy script này.
Chúc các bạn thành công.

3 nhận xét:

Hồng Ngọc nói...

Cảm ơn bạn nhiều!
Mình đã thử chạy script này và thành công.
Cho mình hỏi một việc nữa, mình muốn click đúp chuột hoặc clip nút giữa chuột hoặc dùng 1 phím tắt duy nhất để multi search 1 từ
Mình đã viết 1 đoạn script trong autohotkey như này:

;***Copy + Run web***

F2:: ;press Ctrl+Tab

{

Send, ^c

Sleep 50

Run, https://www.google.com/search?as_st=y&tbm=isch&hl=en&as_q=%clipboard%&as_epq=&as_oq=&as_eq=&imgsz=&imgar=&imgc=&imgcolor=&imgtype=&cr=countryUS&as_sitesearch=&safe=images&as_filetype=&tbs=

Run, https://vi.glosbe.com/en/vi/%clipboard%

Run, https://learnersdictionary.com/definition/%clipboard%


Return

}

Chạy thử thì oke sau khi bôi đen 1 từ và bấm F2 thì nó tự động search từ đó trong các trang mà mình chỉ định
Nhưng vấn đề là sau khi search xong 1 từ search tiếp từ tiếp theo thì các tab mới lại mở lên, chỉ search 10 từ thôi là google của mình đã hiện vài chục tab, mình lại phải xóa đi cho đỡ chậm máy

Mình muốn hỏi là bạn có cách nào mà để cách tab mới không hiện chồng chéo không, nghĩa là search xong 1 từ thì khi search từ tiếp theo những tab trước đó tự xóa đi
Nếu bạn biết thì viết giúp mình 1 script nhé! Mong nhận được hồi âm, cảm ơn ạ!

Nguyễn Tiến Quân nói...

Trình duyệt bạn gọi http request tới các từ điển online, mà mỗi khi bạn gọi từ chương trình khác như AHK thì nó hiểu là tạo session mới nên nó hiện tab mới.
Bạn tham khảo dòng code search dưới đây
chrome := "- Google Chrome"
found := "false"
tabSearch := "gmail.com - Gmail"
curWinNum := 0

SetTitleMatchMode, 2

WinGet, numOfChrome, Count, %chrome% ; Get the number of chrome windows

WinActivateBottom, %chrome% ; Activate the least recent window

WinWaitActive %chrome% ; Wait until the window is active

ControlFocus, Chrome_RenderWidgetHostHWND1 ; Set the focus to tab control ???

; Loop until all windows are tried, or until we find it
while (curWinNum < numOfChrome and found = "false") {
WinGetTitle, firstTabTitle, A ; The initial tab title
title := firstTabTitle
Loop
{
if(InStr(title, tabSearch)>0){
found := "true"
break
}
Send {Ctrl down}{Tab}{Ctrl up}
Sleep, 50
WinGetTitle, title, A ;get active window title
if(title = firstTabTitle){
break
}
}
WinActivateBottom, %chrome%
curWinNum := curWinNum + 1
}

; If we did not find it, start it
if(found = "false"){
Run "https://gmail.com"
}

return

Unknown nói...

Từ khi Win 10 chặn chức năng scan popup của GoldenDict thì việc tra từ trên ứng dụng khác rất bất tiện. Mình khá 'gà' về tin học nên phải tìm nhiều tháng trời mới ra bài viết của bạn. Cám ơn bạn rất nhiều vì đã chia sẻ thông tin hữu ích này cho mọi người :D