MenuHeight() liefert falsche Ergebnisse

Hier werden, insbesondere in den Beta-Phasen, Bugmeldungen gepostet. Das offizielle BugForum ist allerdings hier.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

MenuHeight() liefert falsche Ergebnisse

Beitrag von NicTheQuick »

Bei folgendem Code wird ein Menü erstellt, das mehr als eine Zeile
ausfüllt, trotzdem zeigt 'MenuHeight()' die selbe Zahl an wie bei einem
einzeiligen Menü.

Außerdem stört mich ein bisschen, dass man bei 'MenuHeight()' nicht
angeben kann, von welchem Menü man die Höhe wissen möchte.

Bei einer Applikation, die mit mehreren Fenstern arbeitet, die Menüs
beinhalten, und die alle in der Größe änderbar sind, kann es passieren,
dass ein Fenster so klein gezogen wird, dass ein Menü wie im Beispiel
mehrzeilig wird. Und durch den falschen Rückgabewert von 'MenuHeight()'
kann man so nicht ordentlich alle Gadgets im Fenster resizen, weil
eigentlich weniger Platz zur Verfügung steht als 'MenuHeight()' sagt.

Code: Alles auswählen

If OpenWindow(0, 200, 200, 200, 100, "Menu Example")
  If CreateMenu(0, WindowID(0))
    MenuTitle("Project")
    MenuTitle("tadattattattette")
    MenuTitle("tadattattattettes")
  EndIf
  Debug MenuHeight()
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Die Menühöhe ist eigentlich fest im OS vorgegeben (Einstellungen,
Style o. ä.). Menüs unterschiedlicher Höhe gibts meines Wissens
nach nicht.

Eine Function zum feststellen ob das Menü umgebrochen bzw.
mehrmals umgebrochen ist halte ich allerdings auch für Sinnvoll.
Multiplizieren können wir dann selber :wink:
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag von Ligatur »

Hallo,
MenuHeight greift wohl auf GetSystemMetrics(#SM_CYMENU) zurück.
MSDN hat geschrieben: SM_CYMENU Height, in pixels, of a single-line menu bar.
Beim Resizen sollte es doch eigendlich keine Probleme geben da das Menü nicht zum Client - Bereich des Fensters zählt nach dem man sich doch beim Resizen und Anordnen der Gadgets richtet (und der z.B. von WindowHeight() und WindowWidth zurückgegeben wird.). Als kleine Demo zum experimentieren:

Code: Alles auswählen

hwnd = OpenWindow(0, 0, 0, 640, 480, "Gross", #WS_OVERLAPPEDWINDOW)

CreateMenu(0, hwnd)
For i = 0 To 10
	MenuTitle("Test " + Str(i))
Next i

Repeat
	event = WaitWindowEvent()
	If event = #PB_Event_SizeWindow
		SetWindowTitle(0, "w: " + Str(WindowWidth(0)) + " h:" + Str(WindowHeight(0)))
	EndIf
Until event = #PB_Event_CloseWindow
Wenn man wissen möchte ob das Menü umgebrochen wurde müsste es doch möglich sein, mit GetWindowRect_() die Abmessung des gesamten Fensters zu ermitteln, von dessen Höhe den Clientbereich, 2* die Rahmenhöhe und die Titelbarhöhe abzuziehen und den Rest durch MenuHeight zu teilen um herauszubekommen, aus wie vielen Zeilen ein Menü besteht.

Gruß,
Ligatur
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

@Ligatur:
Danke für die Aufklärung. Danke deinem Hinweis funktioniert folgender
Code also:

Code: Alles auswählen

hwnd = OpenWindow(0, 0, 0, 640, 480, "Gross", #WS_OVERLAPPEDWINDOW)

CreateMenu(0, hwnd)
For i = 0 To 10
   MenuTitle("Test " + Str(i))
Next i

CreateGadgetList(WindowID(0))
ButtonGadget(0, 0, 0, 1, 1, "Test")

Repeat
  event = WaitWindowEvent()
  If event = #PB_Event_SizeWindow
    ResizeGadget(0, 0, 0, WindowWidth(0), WindowHeight(0) - MenuHeight())
    SetWindowTitle(0, "w: " + Str(WindowWidth(0)) + " h:" + Str(WindowHeight(0) - MenuHeight()))
  EndIf
Until event = #PB_Event_CloseWindow
Aber dann könnte man es auch gleich so machen, dass bei
'WindowHeight(0)' die Menühöhe abgezogen wird, wenn eins existiert.
Das hat nur den Nachteil, dass man bei einem mehrzeiligen Menü gar nicht
mehr weiß, wie hoch das Fenster wirklich ist, sondern nur die ClientArea.
Im Grunde wäre ich also immer noch für ein 'MenuRows(#WindowID)' und
ein 'MenuHeight(#WindowID)'.
Benutzeravatar
Ligatur
Beiträge: 196
Registriert: 09.07.2006 00:41

Beitrag von Ligatur »

Hallo,
weiß jemand warum der Wert, den man bei WindowHeight() zurückbekommt sich so unlogisch verhält, wenn das Fenster ein Menü besitzt.

Code: Alles auswählen

Enumeration
	#txt_ClientWidth
	#txt_ClientHeight
	#txt_WindowWidth
	#txt_WindowHeight
	#txt_PBWidth
	#txt_PBHeight
	#txt_MenuHeight
	#txt_PBH_MenHight
	#str_ClientWidth
	#str_ClientHeight
	#str_WindowWidth
	#str_WindowHeight
	#str_PBWidth
	#str_PBHeight
	#str_MenuHeight
	#str_PBH_MenHight
	#chk_Menu
EndEnumeration

hwnd = OpenWindow(0, 0, 0, 640, 480, "Client Window", #WS_OVERLAPPEDWINDOW)
CreateGadgetList(hwnd)
TextGadget(#txt_ClientWidth, 5,5, 70, 20, "ClientWidth")
StringGadget(#str_ClientWidth, 80, 5, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_ClientHeight, 115,5, 70, 20, "ClientHeight")
StringGadget(#str_ClientHeight, 190, 5, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_WindowWidth, 5, 30, 70, 20, "WindowWidth")
StringGadget(#str_WindowWidth, 80, 30, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_WindowHeight, 115, 30, 70, 20, "WindowHeight")
StringGadget(#str_WindowHeight, 190, 30, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_PBWidth, 5, 55, 70, 20, "PBWidth")
StringGadget(#str_PBWidth, 80, 55, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_PBHeight, 115, 55, 70, 20, "PBHeight")
StringGadget(#str_PBHeight, 190, 55, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_MenuHeight, 5, 80, 70, 20, "MenuHeigh")
StringGadget(#str_MenuHeight, 80, 80, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_PBH_MenHight, 115, 80, 70, 20, "PBH - MH")
StringGadget(#str_PBH_MenHight, 190, 80, 30, 20, "", #PB_String_ReadOnly)
CheckBoxGadget(#chk_Menu, 5, 105, 60, 20, "Menu")
SetGadgetState(#chk_Menu, #True)

CreateMenu(0, hwnd) 
For i = 0 To 20 
   MenuTitle("Test " + Str(i)) 
Next i 

SetGadgetText(#str_MenuHeight, Str(MenuHeight()))

Repeat
	event = WaitWindowEvent()
	Select event
		Case #PB_Event_SizeWindow
			GetClientRect_(hwnd, @rc.RECT)
			SetGadgetText(#str_ClientHeight, Str(rc\bottom - rc\top))
			SetGadgetText(#str_ClientWidth, Str(rc\right - rc\left))
			GetWindowRect_(hwnd, @rc)
			SetGadgetText(#str_WindowHeight, Str(rc\bottom - rc\top))
			SetGadgetText(#str_WindowWidth, Str(rc\right - rc\left))
			SetGadgetText(#str_PBHeight, Str(WindowHeight(0)))
			SetGadgetText(#str_PBWidth, Str(WindowWidth(0)))
			SetGadgetText(#str_PBH_MenHight, Str(WindowHeight(0) - MenuHeight()))
		Case #PB_Event_Gadget
			If EventGadget() = #chk_Menu
				If GetGadgetState(#chk_Menu)
					HideMenu(0, #False)
				Else
					HideMenu(0, #True)
				EndIf
			EndIf
	EndSelect
Until event = #PB_Event_CloseWindow
Ohne Menü entspricht der Wert dem Client - Bereich des Fensters, den man auch über GetClientRect_() erhält. Ist aber ein Menü da entspricht der Wert der Höhe des Clientbereiches - der Höhe einer Menüzeile wie dies ja auch NicTheQuick gemacht hat, ein Wert, mit dem man doch eigendlich direk nicht viel anfangen kann. Über GetClientRect_() erhält man auh mit Menü den richtigen Wert und auch wenn man ein Windowcalback benutzt sind die bei WM_SIZE in lParam übergebenen Werte richtig.

Gruß,
Ligatur
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Das Verhalten mein ich ja.
Ich bin der Meinung das Verhalten von 'WindowHeight()' ist so, damit es
kompatibel mit 'ResizeWindow()' ist.

Ich hab den Code um einen Button erweitert.
Solange das Menü einzeilig ist, wird wie gewünscht die Höhe des Fensters
um einen Pixel vergrößert. Ist das Menü aber mehrzeilig, verliert das
Fenster an Höhe, was sicherlich nicht so erwünscht ist.

Code: Alles auswählen

Enumeration
  #txt_ClientWidth
  #txt_ClientHeight
  #txt_WindowWidth
  #txt_WindowHeight
  #txt_PBWidth
  #txt_PBHeight
  #txt_MenuHeight
  #txt_PBH_MenHight
  #str_ClientWidth
  #str_ClientHeight
  #str_WindowWidth
  #str_WindowHeight
  #str_PBWidth
  #str_PBHeight
  #str_MenuHeight
  #str_PBH_MenHight
  #chk_Menu
  #btn_Resize
EndEnumeration

hwnd = OpenWindow(0, 0, 0, 640, 480, "Client Window", #WS_OVERLAPPEDWINDOW)
CreateGadgetList(hwnd)
TextGadget(#txt_ClientWidth, 5,5, 70, 20, "ClientWidth")
StringGadget(#str_ClientWidth, 80, 5, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_ClientHeight, 115,5, 70, 20, "ClientHeight")
StringGadget(#str_ClientHeight, 190, 5, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_WindowWidth, 5, 30, 70, 20, "WindowWidth")
StringGadget(#str_WindowWidth, 80, 30, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_WindowHeight, 115, 30, 70, 20, "WindowHeight")
StringGadget(#str_WindowHeight, 190, 30, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_PBWidth, 5, 55, 70, 20, "PBWidth")
StringGadget(#str_PBWidth, 80, 55, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_PBHeight, 115, 55, 70, 20, "PBHeight")
StringGadget(#str_PBHeight, 190, 55, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_MenuHeight, 5, 80, 70, 20, "MenuHeigh")
StringGadget(#str_MenuHeight, 80, 80, 30, 20, "", #PB_String_ReadOnly)
TextGadget(#txt_PBH_MenHight, 115, 80, 70, 20, "PBH - MH")
StringGadget(#str_PBH_MenHight, 190, 80, 30, 20, "", #PB_String_ReadOnly)
CheckBoxGadget(#chk_Menu, 5, 105, 60, 20, "Menu")
SetGadgetState(#chk_Menu, #True)
ButtonGadget(#btn_Resize, 5, 130, 60, 20, "Resize!")

CreateMenu(0, hwnd)
For i = 0 To 20
  MenuTitle("Test " + Str(i))
Next i

SetGadgetText(#str_MenuHeight, Str(MenuHeight()))

Repeat
  event = WaitWindowEvent()
  Select event
    Case #PB_Event_SizeWindow
      GetClientRect_(hwnd, @rc.RECT)
      SetGadgetText(#str_ClientHeight, Str(rc\bottom - rc\top))
      SetGadgetText(#str_ClientWidth, Str(rc\right - rc\left))
      GetWindowRect_(hwnd, @rc)
      SetGadgetText(#str_WindowHeight, Str(rc\bottom - rc\top))
      SetGadgetText(#str_WindowWidth, Str(rc\right - rc\left))
      SetGadgetText(#str_PBHeight, Str(WindowHeight(0)))
      SetGadgetText(#str_PBWidth, Str(WindowWidth(0)))
      SetGadgetText(#str_PBH_MenHight, Str(WindowHeight(0) - MenuHeight()))
    Case #PB_Event_Gadget
      Select EventGadget()
        Case #chk_Menu
          If GetGadgetState(#chk_Menu)
            HideMenu(0, #False)
          Else
            HideMenu(0, #True)
          EndIf
        Case #btn_Resize
          ResizeWindow(0, #PB_Ignore, #PB_Ignore, #PB_Ignore, WindowHeight(0) + 1)
        EndSelect
    EndSelect
  Until event = #PB_Event_CloseWindow
Antworten