Dynamische Listboxbreite

Post a reply


In an effort to prevent automatic submissions, we require that you complete the following challenge.
Smilies
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :| :mrgreen: :geek: :ugeek: :arrow: :angel: :clap: :crazy: :eh: :lolno: :problem: :shh: :shifty: :sick: :silent: :think: :thumbup: :thumbdown: :salute: :wave: :wtf: :yawn: :facepalm: :bravo: :dance: :beard: :morebeard: :xmas: :HeHe: :trollface: :cookie: :rainbow: :monkeysee: :monkeysay: :happybday: :headwall: :offtopic: :superhappy: :terms: :beer:
View more smilies

BBCode is ON
[img] is OFF
[flash] is OFF
[url] is ON
Smilies are ON

Topic review
   

Expand view Topic review: Dynamische Listboxbreite

Re: Dynamische Listboxbreite

Post by LuckyJoe » 18 May 2019, 10:16

Hallo just me,

perfekt! Herzlichen Dank! :-)
Ich habe noch den Parameter "fontName" im Aufruf aufgenommen, so dass das Ganze auch mit unterschiedlichen Fonts funktioniert:

Code: Select all

Width := GetTextWidth(StrSplit(Liste, "|"), "s12 Italic", "Cooper Black") + 8 + VSBW
Ebenfalls ein schönes Wochenende.

HG - Lucky Joe

Re: Dynamische Listboxbreite

Post by just me » 18 May 2019, 03:11

Moin,

leider gibt es keine 'dynamischen' Controlbreiten. Wenn keine Vorgaben gemacht werden, berechnet AHK für manche Controls wie z.B. Text die benötigte Größe für den vorgegebenen Text automatisch. Andere Controls werden dagegen mit Standardbreiten und -höhen dargestellt.

Ich habe in meinem Fundus ein Skript gefunden, das Dein Problem lösen sollte. Ich weiß nicht, wieviel davon auf meinem Mist gewachsen ist. In die z.Zt. 'festen' Zuschläge 8 und VSBW könnte mannoch ein Paar Gedanken investieren.

Code: Select all

#NoEnv
#SingleInstance, Force
SetWorkingDir %A_ScriptDir%

SysGet, VSBW, 2 ; width of a vertical scroll bar, in pixels

ClipV1 := "Hallo"
ClipV2 := "Welt"
ClipV3 := "mit"
ClipV4 := "einer"
ClipV5 := "sehr langen Textzeile"
ClipV6 := "und noch einer viel längeren Textzeile"

Liste = %ClipV1%|%ClipV2%|%ClipV3%|%ClipV4%|%ClipV5%|%ClipV6%

Width := GetTextWidth(StrSplit(Liste, "|"), "s12 Italic") + 8 + VSBW

Gui, Font, s12 Italic
Gui, Add, ListBox, w%Width% vMyListBox gMyListBox Choose1, %Liste%
Gui, Add, Button, Hidden Default, OK
Gui -Border -Caption
Gui, Show, AutoSize
Return

MyListBox:
	If A_GuiEvent = DoubleClick
		Goto ButtonOK
Return

ButtonOK:
	GuiControlGet, MyAuswahl,, MyListBox

ListBoxRoutine:
	Msgbox Auswahl: %MyAuswahl%

GuiClose:
GuiEscape:
Gui Destroy
ExitApp

; ----------------------------------------------------------------------------------------------------------------------
; GetTextWidth() : Calculates the width of a single-line string as drawn with the specified font
; ----------------------------------------------------------------------------------------------------------------------
GetTextWidth(Strings, FontOpts := "", FontName := "") {
   ; DrawText format: DT_SINGLELINE = 0x0020, DT_NOCLIP = 0x0100, DT_EXTERNALLEADING = 0x0200, DT_CALCRECT = 0x0400,
   ;                  DT_NOPREFIX = 0x0800, DT_EDITCONTROL = 0x2000
   StrArr := IsObject(Strings) ? Strings : [Strings]
   Width := 0
   Gui, GetTextWidthGui: Font, %FontOpts%, %FontName%
   Gui, GetTextWidthGui: Add, Text, hwndHTX
   HFNT := DllCall("SendMessage", "Ptr", HTX, "Int", 0x31, "Ptr", 0, "Ptr", 0, "Ptr") ; WM_GETFONT
   HDC := DllCall("GetDC", "Ptr", HTX, "UPtr")
   DllCall("SelectObject", "Ptr", HDC, "Ptr", HFNT)
   For Each, Str In StrArr {
      VarSetCapacity(RECT, 16, 0)
      DllCall("DrawText", "Ptr", HDC, "Str", Str . " ", "Int", -1, "Ptr", &RECT, "UInt", 0x2F20) ; 0x0D20
      Width := Max(Width, NumGet(RECT, 8, "Int"))
   }
   DllCall("ReleaseDC", "Ptr", HTX, "Ptr", HDC)
   Gui, GetTextWidthGui: Destroy
   Return Width
}
Schönes Wochenende!
just me

Dynamische Listboxbreite

Post by LuckyJoe » 17 May 2019, 09:24

Hallo zusammen,

ich suche eine Möglichkeit, die Breite meiner Listbox bzw. meines Gui's dynamisch berechnen zu lassen. Meine Listbox wird mit Texten aus der Zwischenablage gefüllt und anschließend weiterverarbeitet. In meinen nachfolgenden Beispiel habe ich die Inhalte mit den Dummies "ClipV1-ClipV6" ersetzt.

Wie erreiche ich es, dass sich die Breite meiner Listbox an den Text bzw. die Textbreite anpasst? Diese ist ja vom Font und dem Inhalt abhängig.
Hier zunächst mein Beispiel-Script:

Code: Select all

#NoEnv
#SingleInstance force

#ä::
	ClipV1 := "Hallo"
	ClipV2 := "Welt"
	ClipV3 := "mit"
	ClipV4 := "einer"
	ClipV5 := "sehr langen Textzeile"
	ClipV6 := "und noch einer viel längeren Textzeile"

	Liste = %ClipV1%|%ClipV2%|%ClipV3%|%ClipV4%|%ClipV5%|%ClipV6%

	ListBoxWidth := 200
	ListBoxHigh  := 106
	GuiWidth	 := ListBoxWidth + 24
	GuiHigh		 := ListBoxHigh + 20

	Gui, New, +HwndGuiNr, Veränderte Zwischenablage einfügen:
		Gui, Font, s10, Segoe UI
		Gui, Add, ListBox, Choose1 w%ListBoxWidth% H%ListBoxHigh% vMyListBox gMyListBox, %Liste%
		Gui, Add, Button, Hidden Default, OK
		Gui -SysMenu +AlwaysOnTop
		Gui, Show, x1100 y350 W%GuiWidth% H%GuiHigh%
	Return

	MyListBox:
		If A_GuiEvent = DoubleClick
		{
			GuiControlGet, MyListBox
			Zeile = %MyListBox%
			Gosub ListBoxRoutine
		}
	Return

	ButtonOK:
		GuiControlGet, MyListBox
		Zeile = %MyListBox%

	ListBoxRoutine:
		MsgBox, % Zeile
		Clipboard := MyListBox
		Goto GuiClose
	Return

	GuiClose:
	GuiEscape:
		Gui Destroy
		GuiNr =
	Return

Return
Im Internet (https://stackoverflow.com/questions/49335431/autohotkey-dynamic-resize-control-based-on-text) habe ich u.a. folgende vielversprechende Lösung für das Problem gefunden:

Code: Select all

MyText := "Kurzer Text"
MyText := "Das ist eine ziemlich lange Textzeile"
Gui, Font, s10, Segoe UI
Gui, Add, Text,HwndTimeHwnd, MyText

SetTextAndResize(TimeHwnd, MyText)
Gui, Show, NoActivate Center AutoSize

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
}
Mein Problem: Wie kann ich dieses Script so anpassen, dass ich es für mein Script "umbauen" kann, bzw. wie integriere ich es in mein Script?
Ich habe auch schon überlegt, das Ganze als Function einzubinden und die Variable "w", die ja offensichtlich die Textbreite berechnet, zu verwenden ... aber wie? Ich würde mich über einen Denkanstoß freuen.

HG - Lucky Joe

Top