Window position and size just before maximize

Just starting out? Need help? Post your questions and find answers here.
Jeromyal
Enthusiast
Enthusiast
Posts: 216
Joined: Wed Jul 17, 2013 8:49 am

Window position and size just before maximize

Post by Jeromyal »

I am trying to save a windows x, y and width, height into integers just before maximization, so the window can be restore capable after application restart if closed while maximized.
I thought there would be an event that could be accessed just before maximize when the maximize gadget is pressed.

am I missing something? Thank you.
User avatar
JHPJHP
Addict
Addict
Posts: 2250
Joined: Sat Oct 09, 2010 3:47 am

Re: Window position and size just before maximize

Post by JHPJHP »

Hi Jeromyal,

For Windows only, but can be used at any stage:
WINDOWPLACEMENT structure
GetWindowPlacement function

Code: Select all

lpwndpl.WINDOWPLACEMENT
GetWindowPlacement_(WindowID(#MainWindow), @lpwndpl)
X = lpwndpl\rcNormalPosition\left
Y = lpwndpl\rcNormalPosition\top
W = lpwndpl\rcNormalPosition\right - lpwndpl\rcNormalPosition\left
H = lpwndpl\rcNormalPosition\bottom - lpwndpl\rcNormalPosition\top

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
Jeromyal
Enthusiast
Enthusiast
Posts: 216
Joined: Wed Jul 17, 2013 8:49 am

Re: Window position and size just before maximize

Post by Jeromyal »

Thanks,
I see how that should work for me but then I guess I still am messing things up.
I will post my program before it get much bigger for review if you dare try to follow my insane code style.
maybe you can spot it. It won't run as is due to other files not included. Sorry.

Code: Select all

EnableExplicit

#APP_NAME         = "Vintage Story Portable Launcher"
#APP_VERSION      = "0.1.0"
#APP_AUTHOR       = "Jeromy Alexander"
#APP_AUTHOR_EMAIL = "kyja72@hotmail.com"
#USE_ON_ERROR     = #True
#Space$           = Chr(32)
#Dark             = $191919
#Light            = $F0F0F0

Global *Mutex = CreateMutex_(#Null, 1, ReplaceString(#APP_NAME, #Space$, "_"))
If *Mutex <> 0 And GetLastError_() = #ERROR_ALREADY_EXISTS
  CloseHandle_(*Mutex)
  End #ERROR_ALREADY_EXISTS
EndIf

XIncludeFile("Vintage Story Portable_Declares.pbi")
XIncludeFile("OnError.pbi")
XIncludeFile("ObjectTheme.pbi")
UseModule ObjectTheme

Macro DQ_String(String)
  #DQUOTE$ + string + #DQUOTE$
EndMacro

CreateDirectory("installs")

Enumeration
  #Window
  #installWindow
  #progress
  #installtext
  #about
  #options
  #help
  #statusbar
  #field
  #oCheckDark
  #editHelp
  #editAbout
EndEnumeration

Global wx, wy, ww, wh, wm, event
Global x, y, w, h, dm

If FileSize("VSPL.ini") = -1
  If CreateFile(0, "VSPL.ini")
    CloseFile(0)
  EndIf
EndIf

OpenPreferences("VSPL.ini")

wx = ReadPreferenceInteger("wx", 0)
wy = ReadPreferenceInteger("wy", 0)
ww = ReadPreferenceInteger("ww", 640)
wh = ReadPreferenceInteger("wh", 480)
wm = ReadPreferenceInteger("wm", 0)

OpenWindow(#Window, wx, wy, ww, wh, #APP_NAME + #Space$ + #APP_VERSION, #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget | #PB_Window_Invisible)
CreateStatusBar(#statusbar, WindowID(#window))
AddStatusBarField(#PB_Ignore)
StatusBarText(#statusbar, 0, "No Selection")
CreateMenu(0, WindowID(#Window))
MenuTitle("File")
MenuItem(1, "&Install...")
MenuItem(2, "&Uninstall...")
MenuBar()
MenuItem(3, "&Preferences")
MenuBar()
MenuItem(4, "&Quit")
MenuTitle("Help")
MenuItem(5, "&Help")
MenuBar()
MenuItem(6, "&About")
DisableMenuItem(0, 2, 1)

ListIconGadget(#field, 0, 0, WindowWidth(#Window), WindowHeight(#Window) - StatusBarHeight(#statusbar) - MenuHeight(), "huh?", WindowWidth(#Window), #PB_ListIcon_AlwaysShowSelection)
SetGadgetAttribute(#field, #PB_ListIcon_DisplayMode, #PB_ListIcon_LargeIcon)
ResizeWindow(#window, wx, wy, ww, wh)
WindowBounds(#Window, 400, 200, #PB_Ignore, #PB_Ignore)
If wm = 16777216
  SetWindowState(#Window, 16777216)
EndIf
BindEvent(#PB_Event_SizeWindow, @WindowResize(), #Window)
BindEvent(#PB_Event_MaximizeWindow, @maximized(), #Window)
BindEvent(#PB_Event_RestoreWindow, @restored(), #Window)
If ReadPreferenceInteger("dm", 0)
  SetObjectTheme(#ObjectTheme_Auto, #Dark)
Else
  SetObjectTheme(#ObjectTheme_Auto, #light)
EndIf
HideWindow(#Window, #False)
loadfield()

Repeat
  event = WaitWindowEvent(10)
  Select EventWindow()
    Case #Window
      Select event
        Case #PB_Event_CloseWindow
          quiting()
          Break
        Case #PB_Event_Menu
          Select EventMenu()
            Case 1 ; install
              DisableWindow(#Window, #True)
              install()
            Case 2 ; uninstall
              DisableWindow(#Window, #True)
              Uninstall()
            Case 3 ; preferences
              DisableWindow(#Window, #True)
              preferences()
            Case 4 ; quit
              quiting()
              Break
            Case 5 ; help
              DisableWindow(#Window, #True)
              help()
            Case 6 ; about
              DisableWindow(#Window, #True)
              about()
          EndSelect
      EndSelect
    Case #about
      Select event
        Case #PB_Event_CloseWindow
          CloseWindow(#about)
          DisableWindow(#Window, #False)
          SetActiveWindow(#Window)
      EndSelect
    Case #options
      Select event
        Case #PB_Event_CloseWindow
          CloseWindow(#options)
          DisableWindow(#Window, #False)
          SetActiveWindow(#Window)
        Case #PB_Event_Gadget
          If EventGadget() = #oCheckDark
            If GetGadgetState(#oCheckDark)
              SetObjectTheme(#ObjectTheme_Auto, #Dark)
              WritePreferenceInteger("dm", 1)
            Else
              SetObjectTheme(#ObjectTheme_Auto, #light)
              WritePreferenceInteger("dm", 0)
            EndIf
          EndIf
          
      EndSelect
    Case #help
      Select event
        Case #PB_Event_CloseWindow
          CloseWindow(#help)
          DisableWindow(#Window, #False)
          SetActiveWindow(#Window)
      EndSelect
  EndSelect
ForEver

Procedure WindowResize()
  ResizeGadget(#field, 0, 0, WindowWidth(#Window), WindowHeight(#Window) - StatusBarHeight(#statusbar) - MenuHeight())
  wx = x : wy = y : ww = w : wh = h
EndProcedure

Procedure install()
  If FileSize("innounp.exe") > 0
    Protected installer$ = OpenFileRequester("Select Vintage Story installer", GetUserDirectory(#PB_Directory_Downloads), "Vintage Story Installer|vs_install_win*.exe|Any Executable|*.exe", 0)
    If installer$
      If RunProgram(".\innounp.exe", " -q -x -b -y " + DQ_String(installer$) + " -d" + DQ_String("..\installs") + " install_script.iss", "installs", #PB_Program_Wait | #PB_Program_Hide)
        OpenPreferences(".\installs\install_script.iss")
        PreferenceGroup("Setup")
        Protected appname.s = ReadPreferenceString("AppName", "Unknown")
        Protected appversion.s = ReadPreferenceString("AppVersion", "Unknown")
        OpenPreferences("VSPL.ini")
        Protected file
        If ReadFile(file, ".\installs\install_script.iss")
          Protected string.s = ReadString(file, #PB_File_IgnoreEOL)
          CloseFile(file)
        EndIf
        Protected comp, s
        Protected line.s
        OpenWindow(#installWindow, 0, 0, 500, 120, "Inatalling", #PB_Window_WindowCentered | #PB_Window_TitleBar, WindowID(#Window))
        TextGadget(#installtext, 5, 5, WindowWidth(#installWindow) - 10, 80, "Installing " + appname + " " + appversion)
        ProgressBarGadget(#progress, 5 , WindowHeight(#installWindow) - 30, WindowWidth(#installWindow) - 10, 24, 0, CountString(string, "Source:") + 1)
        comp = RunProgram(".\innounp.exe", "-x -b -y " + DQ_String(installer$) + " -d" + DQ_String("..\installs"), "installs", $E | #PB_Program_Hide)
        If comp : s = 0
          While ProgramRunning(comp)
            If AvailableProgramOutput(comp)
              line = ReadProgramString(comp)
              s = s + 1
              SetGadgetState(#progress, s)
              SetGadgetText(#installtext, "Installing " + appname + " " + appversion + Chr(13) + Chr(13) + Str(s) + " of " + Str(CountString(string, "Source:") + 1)+ " files." + Chr(13) + Chr(13) + GetFilePart(line))
            EndIf
            WindowEvent()
          Wend
          CloseProgram(comp)
          CloseWindow(#installWindow)
          DeleteDirectory(".\installs\{autofonts}", "*.*", #PB_FileSystem_Recursive)
          DeleteDirectory(".\installs\{tmp}", "*.*", #PB_FileSystem_Recursive)
          DeleteFile(".\installs\install_script.iss")
          RenameFile(".\installs\{app}", ".\installs\" + appname + " " + appversion)
        EndIf
      EndIf
      
    EndIf
    loadfield()
  Else
    MessageRequester("Error", ~"innounp.exe is missing.\n\nInstalls can not be done.", #PB_MessageRequester_Error | #PB_MessageRequester_Ok, WindowID(#Window))
  EndIf
  DisableWindow(#Window, #False)
EndProcedure

Procedure Uninstall()
  
  loadfield()
  DisableWindow(#Window, #False)
EndProcedure

Procedure help()
  OpenWindow(#help, 0, 0, 500, 400, #APP_NAME + " - Help", #PB_Window_WindowCentered | #PB_Window_Tool | #PB_Window_SystemMenu, WindowID(#Window))
  EditorGadget(#editHelp, 0, 0, 500, 400, #PB_Editor_ReadOnly | #PB_Editor_WordWrap)
  
EndProcedure

Procedure about()
  OpenWindow(#about, 0, 0, 500, 400, #APP_NAME + " - About", #PB_Window_WindowCentered | #PB_Window_Tool | #PB_Window_SystemMenu, WindowID(#Window))
  EditorGadget(#editAbout, 0, 0, 500, 400, #PB_Editor_ReadOnly | #PB_Editor_WordWrap)
  
EndProcedure

Procedure preferences()
  OpenWindow(#options, 0, 0, 500, 400, #APP_NAME + " - Preferences", #PB_Window_WindowCentered | #PB_Window_Tool | #PB_Window_SystemMenu, WindowID(#Window))
  CheckBoxGadget(#oCheckDark, 5, 5, 480, 24, "Use Darkmode")
  dm = ReadPreferenceInteger("dm", GetGadgetState(#oCheckDark))
  SetGadgetState(#oCheckDark, dm)
  If GetGadgetState(#oCheckDark)
    SetObjectTheme(#ObjectTheme_Auto, #Dark)
    WritePreferenceInteger("dm", 1)
  Else
    SetObjectTheme(#ObjectTheme_Auto, #light)
    WritePreferenceInteger("dm", 0)
  EndIf
EndProcedure

Procedure maximized()
  Protected lpwndpl.WINDOWPLACEMENT
  GetWindowPlacement_(WindowID(#Window), @lpwndpl)
  X  = lpwndpl\rcNormalPosition\left
  Y  = lpwndpl\rcNormalPosition\top
  W  = lpwndpl\rcNormalPosition\right - lpwndpl\rcNormalPosition\left
  H  = lpwndpl\rcNormalPosition\bottom - lpwndpl\rcNormalPosition\top
  wx = x : wy = y : ww = w : wh = h
EndProcedure

Procedure restored()
  
EndProcedure

Procedure loadfield()
  
EndProcedure

Procedure quiting()
  
  WritePreferenceInteger("wx", WindowX(#Window))
  WritePreferenceInteger("wy", WindowY(#Window))
  WritePreferenceInteger("ww", WindowWidth(#Window))
  WritePreferenceInteger("wh", WindowHeight(#Window))
  WritePreferenceInteger("wm", GetWindowState(#window))
  
  ClosePreferences()
EndProcedure
Jeromyal
Enthusiast
Enthusiast
Posts: 216
Joined: Wed Jul 17, 2013 8:49 am

Re: Window position and size just before maximize

Post by Jeromyal »

oh I am a dummy.

found it.

the following change now works along with the code you gave me. Thank you.

Code: Select all

Procedure quiting()
  
  WritePreferenceInteger("wx", wx)
  WritePreferenceInteger("wy", wy)
  WritePreferenceInteger("ww", ww)
  WritePreferenceInteger("wh", wh)
  WritePreferenceInteger("wm", GetWindowState(#window))
  
  ClosePreferences()
EndProcedure
AZJIO
Addict
Addict
Posts: 2141
Joined: Sun May 14, 2017 1:48 am

Re: Window position and size just before maximize

Post by AZJIO »

And if the window is minimized to the taskbar, what will you do? You must remember the last window state before exiting the program.
You don't need to remember the size when maximizing the window, otherwise the user will be forced to manually configure the normal mode each time.

Code: Select all

If GetWindowState(#window) = #PB_Window_Maximize
	wm = 1
Else
	wm = 0
EndIf

wm = Bool(GetWindowState(#window)) = #PB_Window_Maximize)

; ...
If wm
	SetWindowState(#window, #PB_Window_Maximize)
EndIf

Code: Select all

	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_MaximizeWindow
				win\wm = 1
			Case #PB_Event_RestoreWindow
				win\wm = 0

Code: Select all

EnableExplicit

#Window = 0

Structure win
	x.i
	y.i
	w.i
	h.i
	m.i
EndStructure

Global win.win
win\w = 222
win\h = 111

Procedure WinCallback(hWnd, Message, WParam, LParam)
	Protected w, h
	Protected *Rest.RECT = LParam
	Protected Result = #PB_ProcessPureBasicEvents
	
	Select Message
		Case #WM_SIZE
			w = LParam & $FFFF ; LoWord
			h = LParam >> 16   ; HiWord
			ResizeGadget(1, #PB_Ignore, #PB_Ignore, w-20,  h-20)
		Case #WM_EXITSIZEMOVE
			If Not win\m
				win\w = WindowWidth(#Window)
				win\h = WindowHeight(#Window)
			EndIf
			w = WindowWidth(#Window)
			h = WindowHeight(#Window)
			ResizeGadget(1, #PB_Ignore, #PB_Ignore, w-20,  h-20)
		Case #WM_MOVING
			win\x = *Rest\left
			win\y = *Rest\top
	EndSelect
	
	
	ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure


win\x = 222
win\y = 222

Global ini$ = Left(ProgramFilename(), Len(ProgramFilename()) - 3) + "ini"
If FileSize(ini$) = -1
	If CreatePreferences(ini$)
		PreferenceGroup("Set")
		WritePreferenceInteger("x",  win\x)
		WritePreferenceInteger("y",  win\y)
		WritePreferenceInteger("width",  win\w)
		WritePreferenceInteger("height",  win\h)
		WritePreferenceInteger("maxim",  win\m)
		ClosePreferences()
	EndIf
Else
	If OpenPreferences(ini$)
		PreferenceGroup("Set")
		win\x = ReadPreferenceInteger("x", win\x)
		win\y = ReadPreferenceInteger("y", win\y)
		win\w = ReadPreferenceInteger("width", win\w)
		win\h = ReadPreferenceInteger("height", win\h)
		win\m = ReadPreferenceInteger("maxim", win\m)
		ClosePreferences()
	EndIf
EndIf

Procedure Exit()
	If OpenPreferences(ini$)
		PreferenceGroup("Set")
		WritePreferenceInteger("x",  win\x)
		WritePreferenceInteger("y",  win\y)
		WritePreferenceInteger("width",  win\w)
		WritePreferenceInteger("height",  win\h)
		WritePreferenceInteger("maxim",  win\m)
		ClosePreferences()
	EndIf
EndProcedure


If OpenWindow(#Window, win\x, win\y, win\w, win\h, "Example...",
              #PB_Window_SystemMenu | #PB_Window_MaximizeGadget | #PB_Window_SizeGadget)
	ButtonGadget(1, 10, 10, win\w - 20, win\h - 20, "Button")
	If win\m
		SetWindowState(#window, #PB_Window_Maximize)
	EndIf
	
; 	BindEvent(#PB_Event_SizeWindow, @SizeWindowHandler())
	SetWindowCallback(@WinCallback())
	
	;- Loop
	Repeat
		Select WaitWindowEvent()
			Case #PB_Event_MaximizeWindow
				win\m = 1
				ResizeGadget(1, #PB_Ignore, #PB_Ignore, WindowWidth(#Window) - 20,  WindowHeight(#Window)-20)
			Case #PB_Event_RestoreWindow
				win\m = 0
			Case #PB_Event_Gadget
				Select EventGadget()
					Case 1
						Debug 1
				EndSelect
			Case #PB_Event_CloseWindow
				CloseWindow(#Window)
				Exit()
				End
		EndSelect
	ForEver
EndIf
You will also need _SetCoor (to check if the screen size is smaller than the specified coordinates)
User avatar
JHPJHP
Addict
Addict
Posts: 2250
Joined: Sat Oct 09, 2010 3:47 am

Re: Window position and size just before maximize

Post by JHPJHP »

Hi AZJIO,

I agree that it make more sense positioning the code before the window is closed to return the last window (re)size, but your assumption is wrong about the GetWindowPlacement API; see my previous post for links to documentation.
JHPJHP wrote:can be used at any stage
Try the following:
• Minimize the example and close it from the Taskbar.

Code: Select all

Macro ScaleFactor
  DesktopResolutionX()
EndMacro

Macro ScaleFactorD(value)
  (value) / ScaleFactor
EndMacro

If OpenWindow(0, 0, 0, 500, 400, "GetWindowPlacement", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_MinimizeGadget)
  Debug WindowX(0)
  Debug WindowY(0)
  Debug WindowWidth(0, #PB_Window_FrameCoordinate)
  Debug WindowHeight(0, #PB_Window_FrameCoordinate)

  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

  lpwndpl.WINDOWPLACEMENT
  GetWindowPlacement_(WindowID(0), @lpwndpl)
  X = ScaleFactorD(lpwndpl\rcNormalPosition\left)
  Y = ScaleFactorD(lpwndpl\rcNormalPosition\top)
  W = ScaleFactorD(lpwndpl\rcNormalPosition\right - lpwndpl\rcNormalPosition\left)
  H = ScaleFactorD(lpwndpl\rcNormalPosition\bottom - lpwndpl\rcNormalPosition\top)

  Debug "---"
  Debug X
  Debug Y
  Debug W
  Debug H
EndIf
Last edited by JHPJHP on Tue Oct 15, 2024 5:52 pm, edited 1 time in total.

If you're not investing in yourself, you're falling behind.

My PureBasic StuffFREE STUFF, Scripts & Programs.
My PureBasic Forum ➤ Questions, Requests & Comments.
User avatar
ChrisR
Addict
Addict
Posts: 1466
Joined: Sun Jan 08, 2017 10:27 pm
Location: France

Re: Window position and size just before maximize

Post by ChrisR »

Thanks for the GetWindowPlacement Api
Great, it indeed recovers the good positions whatever the state normal, minimized or maximized.
I will be able to improve the save part in my example Keep Windows Size & Position Between Run (Win), it's really much better than

Code: Select all

If GetWindowState(Window) <> #PB_Window_Normal
  SetWindowState(Window, #PB_Window_Normal)
EndIf
GetWindowRect_(WindowID(Window), @WinRect)
AZJIO
Addict
Addict
Posts: 2141
Joined: Sun May 14, 2017 1:48 am

Re: Window position and size just before maximize

Post by AZJIO »

I am aware of GetWindowPlacement, but it cannot open a window beautifully if it is saved on one monitor and opened on another with smaller dimensions. In this case, you will get a window outside the viewport of the screen.
Post Reply