EASY Prefs

Just starting out? Need help? Post your questions and find answers here.
User avatar
Piero
Addict
Addict
Posts: 1040
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

EASY Prefs

Post by Piero »

I think it would be possible, using a "preferences module", to VERY EASILY save entire windows (I mean also with SOME or ALL gadgets!)
IF ONLY there was a way to get/set ALL gadget properties (e.g., flags…)!

Did someone try?
Ideas?

Thanks
SMaag
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: EASY Prefs

Post by SMaag »

Yes! You need to enumerate all Gadgets in a List, then step trough!

For each Gadget you have to call all supported GetGadgetFunctions. With this datas you can recsonstruct the complete layout.

mk-soft published a module for PureBasic SDK Functions.
https://www.purebasic.fr/english/viewto ... 12&t=72980

and here a csv file I made to see which Gadget supports which function

Code: Select all

,Name,Type Constant,Data,Font,Color,Attribute,State,Text,ToolTip,ItemState
1,ButtonGadget,#PB_GadgetType_Button,x,x,o,o,x,x,x,o
2,ButtonImageGadget,#PB_GadgetType_ButtonImage,x,x,o,x,x,o,x,o
3,CalendarGadget,#PB_GadgetType_Calendar,x,x,x,x,x,o,x,x
4,CanvasGadget,#PB_GadgetType_Canvas,x,x,o,x,o,o,x,o
5,CheckBoxGadget,#PB_GadgetType_CheckBox,x,x,o,o,x,o,x,o
6,ComboBoxGadget,#PB_GadgetType_ComboBox,x,x,o,o,x,x,x,o
7,ContainerGadget,#PB_GadgetType_Container,x,x,x,o,o,o,x,o
8,DateGadget,#PB_GadgetType_Date,x,x,x,x,x,x,x,o
9,EditorGadget,#PB_GadgetType_Editor,x,x,x,x,o,x,x,o
10,ExplorerComboGadget,#PB_GadgetType_ExplorerCombo,x,x,o,o,o,x,o,o
11,ExplorerListGadget,#PB_GadgetType_ExplorerList,x,x,x,x,x,x,x,x
12,ExplorerTreeGadget,#PB_GadgetType_ExplorerTree,x,x,x,o,x,x,x,o
13,FrameGadget,#PB_GadgetType_Frame,x,x,o,o,o,x,o,o
14,HyperLinkGadget,#PB_GadgetType_HyperLink,x,x,x,o,o,x,x,o
15,ImageGadget,#PB_GadgetType_Image,x,x,o,o,x,o,x,o
16,IPAddressGadget,#PB_GadgetType_IPAddress,x,x,o,o,x,o,x,o
17,ListIconGadget,#PB_GadgetType_ListIcon,x,x,x,x,x,x,x,x
18,ListViewGadget,#PB_GadgetType_ListView,x,x,x,o,x,x,x,x
19,MDIGadget,#PB_GadgetType_MDI,x,x,x,o,x,o,x,o
20,OpenGLGadget,#PB_GadgetType_OpenGL,x,x,o,x,o,o,x,o
21,OptionGadget,#PB_GadgetType_Option,x,x,o,o,x,o,x,o
22,PanelGadget,#PB_GadgetType_Panel,x,x,o,x,x,o,x,o
23,ProgressBarGadget,#PB_GadgetType_ProgressBar,x,x,x,x,x,o,x,o
24,ScrollAreaGadget,#PB_GadgetType_ScrollArea,x,x,x,x,o,o,o,o
25,ScrollBarGadget,#PB_GadgetType_ScrollBar,x,x,o,x,x,o,x,o
26,ShortCutGadget,#PB_GadgetType_Shortcut,x,x,o,o,x,o,o,o
27,SpinGadget,#PB_GadgetType_Spin,x,x,x,x,x,o,x,o
28,SplitterGadget,#PB_GadgetType_Splitter,x,x,o,x,x,o,x,o
29,StringGadget,#PB_GadgetType_String,x,x,x,x,o,x,x,o
30,TextGadget,#PB_GadgetType_Text,x,x,x,o,x,x,x,o
31,TrackBarGadget,#PB_GadgetType_TrackBar,x,x,o,x,x,o,o,o
32,TreeGadget,#PB_GadgetType_Tree,x,x,x,o,o,x,x,x
33,WebGadget,#PB_GadgetType_Web,x,x,o,x,o,x,o,o
infratec
Always Here
Always Here
Posts: 7662
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: EASY Prefs

Post by infratec »

Have you tried the Dialog stuff?
There is everything stored in xml.
User avatar
Piero
Addict
Addict
Posts: 1040
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: EASY Prefs

Post by Piero »

SMaag wrote: Sun Feb 09, 2025 6:53 pmmk-soft published a module for PureBasic SDK Functions.
https://www.purebasic.fr/english/viewto ... 12&t=72980
and here a csv file I made
THANKS!
See how it works on my Mac; something has changed?

Code: Select all

CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
   
   ; PB Internal Structure Gadget MacOS
   Structure sdkGadget
      *gadget
      *container
      *vt
      UserData.i
      Window.i
      Type.i ; Flags!
      Flags.i; NOT Flags!
   EndStructure
   
   Procedure flags(Gadget)
      If IsGadget(Gadget)
         Protected *Gadget.sdkGadget = IsGadget(Gadget)
         ProcedureReturn *Gadget\Type ; NOT \Flags!
      EndIf
   EndProcedure
   
   If OpenWindow(0,0,0,270,170,"CheckBoxGadget",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
      CheckBoxGadget(0,10,10,250,20,"standard CheckBox")                   ;$000000004
      CheckBoxGadget(1,10,40,250,20,"right CheckBox",#PB_CheckBox_Right)   ;$100000004
      CheckBoxGadget(2,10,70,250,20,"center CheckBox",#PB_CheckBox_Center) ;$200000004
      CheckBoxGadget(3,10,100,250,20,"3 CheckBox",#PB_CheckBox_ThreeState) ;$400000004
      Repeat
         ev=WaitWindowEvent()
         If ev=#PB_Event_Gadget And IsGadget(EventGadget())
            if EventType() = #PB_EventType_Change or GadgetType(EventGadget()) = #PB_GadgetType_CheckBox
               ;Debug "Gadget changed: " + EventGadget()+" - Flags: " + Bin(flags(EventGadget()))
               ;Debug str(flags(EventGadget()))
               
               Debug "$"+Hex(flags(EventGadget())) ; hex results
            EndIf
         EndIf
      Until ev=#PB_Event_CloseWindow
   EndIf
   
CompilerEndIf
Thanks infratec!
Will take a look to xml too; I saw but forgot :)
User avatar
Piero
Addict
Addict
Posts: 1040
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: EASY Prefs

Post by Piero »

No xml dialogs from what I saw………

I think it would need a """low-level""" dump of the gadget data, even in binary…
Then you delete/replace the one on the window with the "binary" data in prefs…
That's Fred/Gurus-Level stuff… :shock:
SMaag
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: EASY Prefs

Post by SMaag »

Gadget implementation information you find in
\PureBasic\SDK\VisualC\PureLibraries\Gadget

Code: Select all

typedef struct
{
  int                          GadgetType;    // Gadget Type for this VT
  int                          SizeOf;        // SizeOf the VT (for future compatibility

  GadgetCallbackProc           GadgetCallback;
  FreeGadgetProc               FreeGadget;
  GetGadgetStateProc           GetGadgetState;
  SetGadgetStateProc           SetGadgetState;
  GetGadgetTextProc            GetGadgetText;
  SetGadgetTextProc            SetGadgetText;
  AddGadgetItem2Proc           AddGadgetItem2;
  AddGadgetItem3Proc           AddGadgetItem3;
  RemoveGadgetItemProc         RemoveGadgetItem;
  ClearGadgetItemsProc         ClearGadgetItems;
  ResizeGadgetProc             ResizeGadget;
  CountGadgetItemsProc         CountGadgetItems;
  GetGadgetItemStateProc       GetGadgetItemState;
  SetGadgetItemStateProc       SetGadgetItemState;
  GetGadgetItemTextProc        GetGadgetItemText;
  SetGadgetItemTextProc        SetGadgetItemText;
  OpenGadgetList2Proc          OpenGadgetList2;
  GadgetXProc                  GadgetX;
  GadgetYProc                  GadgetY;
  GadgetWidthProc              GadgetWidth;
  GadgetHeightProc             GadgetHeight;
  HideGadgetProc               HideGadget;
  AddGadgetColumnProc          AddGadgetColumn;
  RemoveGadgetColumnProc       RemoveGadgetColumn;
  GetGadgetAttributeProc       GetGadgetAttribute;
  SetGadgetAttributeProc       SetGadgetAttribute;
  GetGadgetItemAttribute2Proc  GetGadgetItemAttribute2;
  SetGadgetItemAttribute2Proc  SetGadgetItemAttribute2;
  SetGadgetColorProc           SetGadgetColor;
  GetGadgetColorProc           GetGadgetColor;
  SetGadgetItemColor2Proc      SetGadgetItemColor2;
  GetGadgetItemColor2Proc      GetGadgetItemColor2;
  SetGadgetItemDataProc        SetGadgetItemData;
  GetGadgetItemDataProc        GetGadgetItemData;
  GetRequiredSizeProc          GetRequiredSize;
  SetActiveGadgetProc          SetActiveGadget;
  GetGadgetFontProc            GetGadgetFont;
  SetGadgetFontProc            SetGadgetFont;
  SetGadgetItemImageProc       SetGadgetItemImage;
  GadgetItemIDProc             GadgetItemID;
} PB_GadgetVT;

typedef struct PB_GadgetStructure
{
  HWND         Gadget;
  PB_GadgetVT *VT;
  integer      UserData;      // for Get/SetGadgetData
  WNDPROC      OldCallback;   // for PB_Gadget_RegisterDestroy
  integer      Data[4];       // for gadget internal data. (mostly used for front/backcolor and such).
} PB_Gadget;
User avatar
spikey
Enthusiast
Enthusiast
Posts: 778
Joined: Wed Sep 22, 2010 1:17 pm
Location: United Kingdom

Re: EASY Prefs

Post by spikey »

Piero wrote: Mon Feb 10, 2025 3:29 am I think it would need a """low-level""" dump of the gadget data, even in binary…
Then you delete/replace the one on the window with the "binary" data in prefs…
I'm not at all sure I understand what you're talking about (it may be a 'lost in translation' problem or a different thinking style problem - that happens around here from time to time). But, if you do mean what I think you mean, it's very unlikely to happen and, in my opinion at least, anyone would be slightly insane to try and implement this. It more or less travels in the direct opposite of the efficiencies that using a modern graphical operating system is intended to deliver!

A window isn't a single monolithic object, a gadget isn't even a single monolithic object. Each is a pointer to a data structure which in turn points to three further data structures, as SMaag shows. A pointer to the OS object data (the 'handle'), a pointer to the function entry points that make the gadget work (the 'virtual table') and a pointer to the 'persistence data' that the gadget is actually intended to manipulate. (I've simplified this, just as a note).

None of this data has to be laid out adjacently in memory and it won't be, the OS will do as it pleases.

When you create a gadget all of these pointers will be initialised so that they make sense. However, they will only make sense on that particular run of the program. There's no guarantee that on a subsequent run the targets that the pointers indicate will still be in the same places. So when you reloaded that data you would break the gadget/form and stop it from working! (See also https://www.purebasic.fr/english/viewtopic.php?t=78254 which demonstrates a similar problem).

If you're looking for a quick way to save and restore persistence data from a form design I'd suggest designing a structure which can hold correctly all of the data that you wish to persist. Create a procedure which can wrangle the data from the form into a structured variable and then use either InsertJSONStructure or InsertXMLStructure to create a JSON or XML object which can be written to a file.

And another which can go the other way...
User avatar
Piero
Addict
Addict
Posts: 1040
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: EASY Prefs

Post by Piero »

spikey wrote: Mon Feb 10, 2025 2:30 pmSo when you reloaded that data you would break the gadget/form and stop it from working!
I hoped it was possible because I saw it on a Basic LONG time ago (but the module was encrypted)
The "gadgets" had each one their events (keydown, click etc.) and you put code there…
It made restoring entire windows RIDICULOUSLY simple
You could quickly set (in "form designer") what gadgets had to be restored just by changing a "runtime property" (label)
It's strange that PB gadgets are so much "complex" than the "object oriented" ones!

PS: Thanks, but let's hope someone proves you wrong (at least for "simple programs") ;)
User avatar
spikey
Enthusiast
Enthusiast
Posts: 778
Joined: Wed Sep 22, 2010 1:17 pm
Location: United Kingdom

Re: EASY Prefs

Post by spikey »

Are you sure you're not looking for the XML Dialog library?
Piero wrote: Mon Feb 10, 2025 3:18 pm It's strange that PB gadgets are so much "complex" than the "object oriented" ones!
This is not actually true. They just hide lots of the truth from you.
Piero wrote: Mon Feb 10, 2025 3:18 pm You could quickly set (in "form designer") what gadgets had to be restored just by changing a "runtime property" (label)
Yep, you're going to have to learn how to program properly. The upside is that you will understand actually how an operating system works when you're done. "Learnt OOP (but not C++) at school/college/university" programmers generally don't and this sometimes leads them down big rabbit holes.

I suggest that you learn some programming automation techniques. That is to say programs that help you write/build programs... It will make your life easier. The PureBasic IDE is a good example of this especially the 'DialogCompiler'. This is an area where you can leverage ChatGPT and the likes...
User avatar
Piero
Addict
Addict
Posts: 1040
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: EASY Prefs

Post by Piero »

spikey wrote: Mon Feb 10, 2025 3:44 pmyou will understand actually how an operating system works
Thanks
I know PB is better for "console, non-object-oriented stuff", but don't you think it would theoretically be possible, at least for the """non-dynamic""" properties of gadgets?
I bet the OLD thing I saw dumped (probably all) from memory, instead of reading all the properties, because it also saved "things" you couldn't read via Basic at runtime…
SMaag
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: EASY Prefs

Post by SMaag »

@Piero
Maybe i missunderstood your 1st post! Can you explain in a context what you like to do!

The goal of my answer was to get back all infos of the Gadgets by code (like it's possible in VB6).

This can be used to adapt Gadgets 'in App' by the user (an example would be Database formulars) .
Maybe moving, changing size etc.. and syving this information in a file. Later resore it!
User avatar
Piero
Addict
Addict
Posts: 1040
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: EASY Prefs

Post by Piero »

SMaag wrote: Mon Feb 10, 2025 4:13 pm@Piero
Just if there may be a way (possibly "low-level" and """multiplatform""", like reading it from memory) to dump an entire gadget in prefs (at least what is """non-memory-dynamic""") and then restore it, at least for simple PB programs
User avatar
Piero
Addict
Addict
Posts: 1040
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

EASY Prefs

Post by Piero »

Here's how it worked 2000 years ago in another (Object-Oriented) multi-platform Basic…
I simplified the usage of the (encrypted) "RectControl (Gadget) saver" module:

Save and Restore your Window(s) with TWO Lines of Code!
Just drop the ForPrefs folder on your project, create an application class and put
In your application class:

Code: Select all

Sub Open()
  PrefFileName = "Piero's Prefs" // Put pref file name here
  ReadPrefs
End Sub

Sub Close()
  WritePrefs  // Use when you want to save to disk
End Sub
In your windows:

Code: Select all

Function CancelClose() As Boolean
  storewin(me,false)
End Function
That “false” means that if the name of your RectControl ends with “xx” it will not be saved (it will reopen with default values), and you can easily reverse this (using “true”) saving only RectControls whose name ends with “xx”.

Code: Select all

Sub Open()
  getwin(me,true)
End Sub
That “true” is to restore window size and position: use “false” for defaults.
These functions are based on window title, so give to your titles a unique name.

…and obviously you could also save any kind of variable…
SMaag
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Jan 14, 2023 6:55 pm
Location: Bavaria/Germany

Re: EASY Prefs

Post by SMaag »

But for saving only the Window befor closing:
It's the: X,Y Postion on the Screen and the Width, Height
only 4 values!
That could not be a problem

Code: Select all


Structure TWindowData
  Titel.s
  X.i
  Y.i
  W.i
  H.i
EndStructure


Procedure CollectWindowData(PbWinNo, *WinData.TWindowData)
  If *WinData
    If IsWindow(PbWinNo)  
      With *WinData
        \X = WindowX(PbWinNo)
        \Y = WindowY(PbWinNo)
        \W = WindowWidth(PbWinNo)
        \H = WindowHeight(PbWinNo)
        \Titel = GetWindowTitle(PbWinNo)
      EndWith    
    EndIf
  EndIf
  
  ProcedureReturn *WinData  
EndProcedure


Macro DebugWinData(TWindowData)
    Debug "Titel = " + TWindowData\Titel
    Debug " X = " + TWindowData\X
    Debug " Y = " + TWindowData\Y
    Debug "Width = " + TWindowData\W
    Debug "Height = " + TWindowData\H
EndMacro

If OpenWindow(0, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)

  MessageRequester("Information", "Click to move the Window", 0)
  ResizeWindow(0, 200, 200, #PB_Ignore, #PB_Ignore)   ; Move the window to the coordinate 200,200
  
  MessageRequester("Information", "Click to resize the Window", 0)
  ResizeWindow(0, #PB_Ignore, #PB_Ignore, 320, 200) ; Resize the window to 320,200
  
  ;
  ; This is the 'event loop'. All the user actions are processed here.
  ; It's very easy to understand: when an action occurs, the Event
  ; isn't 0 and we just have to see what have happened...
  ;
  Define WData.TWindowData

  Repeat
    Event = WaitWindowEvent()

    If Event = #PB_Event_CloseWindow  ; If the user has pressed on the close button
      Quit = #True
    EndIf
    If Quit
      CollectWindowData(0, WData)  
    EndIf
    
  Until Quit = #True
  DebugWinData(WData)
EndIf

End   ; All the opened windows are closed automatically by PureBasic

Putting all into a Module and add the load/save File functions.
If the user can't manipulate Gadgets in the runtime this should be enough.
Adapting the Gadgets is done with a Resize!

If you want so save user Inputs in Gadgets, it will be more complicated!
User avatar
Piero
Addict
Addict
Posts: 1040
Joined: Sat Apr 29, 2023 6:04 pm
Location: Italy

Re: EASY Prefs

Post by Piero »

SMaag wrote: Mon Feb 10, 2025 6:42 pmBut for saving only the Window
Read better: that thing (optionally) saved/restored the window(s) placement/size, and also ALL (or some) gadgets/rectcontrols' full State :shock:

Edit: it's a shame the old "gadget saver" module was encrypted (the author later disappeared… :( )
I bet it would be interesting for us to see how it was done, even after all this time and with another Basic…
It stopped working (only) for unicode text after it was introduced, and lots of ppl asked ME to fix it, but I couldn't :cry:
Post Reply