paperlined.org
apps > autohotkey > quickies
document updated 16 years ago, on May 7, 2008
; =================================================================================================
; Some controls don't allow themselves to be Ctrl+C copied, but their text can still be read by
; other applications.
;
; This allows you to copy those "uncopyable" controls.
; =================================================================================================

title := "Copy text from controls that don't allow Ctrl+C."

MsgBox,,%title%,Instructions: After pressing okay:`n1. Move your mouse over the desired control.`n2. Press the Left Shift key.`n`nDesired text will be placed in the clipboard.

;DetectHiddenText,On

CoordMode, Mouse, Screen
Loop {
    ;MouseGetPos,,,hwnd,2

    MouseGetPos, m_x, m_y
    hwnd := DllCall( "WindowFromPoint", "int", m_x, "int", m_y )

    if (!hwnd)
        ToolTip,No window found.  (%m_x%`, %m_y%)
    else {
        ; at this point, some or all of the following may be warranted, to narrow down the hWnd:
        ;       ChildWindowFromPoint()
        ;       ChildWindowFromPointEx()
        ;       RealChildWindowFromPoint()

        ; find the lowest-level child window that contains any text
;        Loop {
;            hwnd := DllCall( "ChildWindowFromPoint", "int", hwnd, "int", m_x, "int", m_y )
;            
;            if (hwnd == 0)
;                Break
;
;            ct := GetText(hwnd)
;            if (StrLen(ct) > 0)
;                ctext := ct
;        }

        ctext := GetText(hwnd)

        if (StrLen(ctext) <= 0)
            ToolTip,<NO TEXT FOUND>
        else if (StrLen(ctext) > 20) {
            tt := SubStr(ctext,1,15) . "... (" . StrLen(ctext) . " chars)"
            ;tt := SubStr(ctext,1,15) . "... (" . StrLen(ctext) . " chars) (hwnd " . hwnd . ") (class " . GetClassName(hwnd) . ")"
            ToolTip,%tt%
        }
        else
            ToolTip,%ctext%
    }

    if (GetKeyState("Shift", "P")) {
        Clipboard := ctext
        notice := StrLen(ctext) . " characters copied to the clipboard"
        MsgBox,,%title%,%notice%
        ExitApp
    }
    if (GetKeyState("Escape", "P")) {
        SplashTextOn,200,70,%title%,`nExiting
        Sleep,500
        SplashTextOff
        ExitApp
    }

    ;Sleep,200
}
ExitApp


GetText(hwnd) {
    ; we could use ControlGetText or WinGetText...  but I'm more confident in the below code instead

    VarSetCapacity(contents, maxlen := 8192)
    SendMessage, WM_GETTEXT:=13, maxlen, &contents, , ahk_id %hwnd%

    VarSetCapacity(title, maxlen := 8192)
    DllCall("GetWindowText"
        ,"UInt",hwnd
        ,"Str", title
        ,"UInt",maxlen)

    if (contents == title)
        return contents
    else if (StrLen(contents)>0  && StrLen(title)>0)
        return title . "`n" . contents
    else
        return title . contents
}


GetClassName(hwnd) {
    VarSetCapacity(classname, 256)  ; the most a classname can *ever* be is 256 chars
    DllCall("GetClassName",  "UInt", hwnd,  "Str", classname,  "UInt", 256)
    return classname
}