AutoHotkey:基于文本的动态调整大小控件

AutoHotkey: Dynamic resize control based on text

考虑以下片段:

FormatTime, time,
Gui, Add, Text, vcTime, 
GuiControl, , cTime, % time 
Gui, Show, NoActivate Center AutoSize

AutoSize 基于 Gui, Add, Text, vcTime 的初始值,而不是 GuiControl, , cTime, % time 设置的新值。根据月份等,%time% 长度可能会有所不同。如何自动调整 window 的大小以适应 %time% 的更新值? `

AutoSize is actually based on the current control sizes when Gui Show is called. The issue is that the "blank" subcommand to GuiControl for text controls does not automatically resize the control;它只是更改了文本,您仍然需要自己调用 GuiControl Move 并使用新的尺寸。因此,在您的示例中,如果将 AutoSize 替换为 w200,文本仍将在同一点被截断。

据我所知,并没有真正的 "built-in" 自动方法来根据新文本调整文本控件的大小。最接近的方法是在创建文本控件时使用AHK的初始大小计算:用想要的文本创建一个新的文本控件,使用GuiControlGet获取新控件的大小,最后设置原控件的大小使用 GuiControl Move 到那个大小。这是一个执行此操作的示例函数,改编自 here:

SetTextAndResize(controlHwnd, newText, fontOptions := "", fontName := "") {
    Gui 9:Font, %fontOptions%, %fontName%
    Gui 9:Add, Text, R1, %newText%
    GuiControlGet T, 9:Pos, Static1
    Gui 9:Destroy

    GuiControl,, %controlHwnd%, %newText%
    GuiControl Move, %controlHwnd%, % "h" TH " w" TW
}

哪个适合您的示例:

FormatTime, time,
Gui, Add, Text, HwndTimeHwnd vcTime,
SetTextAndResize(TimeHwnd, time)
Gui, Show, NoActivate Center AutoSize

现在,无论何时您使用 SetTextAndResize 而不是仅仅设置文本,您都可以使用 Gui Show, AutoSize 自动正确调整 window 的大小。请注意,如果您在添加文本控件之前使用 Gui Font 更改了字体,则必须将这些相同的选项传递给 SetTextAndResize.

或者,当提供 none 时,我查看了 AHK 本身如何计算 Gui Add, Text 文本控件的初始大小,发现它使用 Windows API函数 DrawTextDT_CALCRECT。这是我直接使用它编写的 SetTextAndResize 的另一个实现:

SetTextAndResize(controlHwnd, newText) {
    dc := DllCall("GetDC", "Ptr", controlHwnd)

    ; 0x31 = WM_GETFONT
    SendMessage 0x31,,,, ahk_id %controlHwnd%
    hFont := ErrorLevel
    oldFont := 0
    if (hFont != "FAIL")
        oldFont := DllCall("SelectObject", "Ptr", dc, "Ptr", hFont)

    VarSetCapacity(rect, 16, 0)
    ; 0x440 = DT_CALCRECT | DT_EXPANDTABS
    h := DllCall("DrawText", "Ptr", dc, "Ptr", &newText, "Int", -1, "Ptr", &rect, "UInt", 0x440)
    ; width = rect.right - rect.left
    w := NumGet(rect, 8, "Int") - NumGet(rect, 0, "Int")

    if oldFont
        DllCall("SelectObject", "Ptr", dc, "Ptr", oldFont)
    DllCall("ReleaseDC", "Ptr", controlHwnd, "Ptr", dc)

    GuiControl,, %controlHwnd%, %newText%
    GuiControl Move, %controlHwnd%, % "h" h " w" w
}

我不确定它在性能方面与第一种方法相比如何,但一个优点是它根据控件本身获取字体,而不必自己将其提供给函数。