New to PB - questions to clear confusion

Just starting out? Need help? Post your questions and find answers here.
JaxMusic
User
User
Posts: 20
Joined: Sun Feb 14, 2021 2:55 am
Location: Max Meadows, Virginia, USA
Contact:

New to PB - questions to clear confusion

Post by JaxMusic »

Good evening.

I'm considering switching over to PB for my business related projects. I'm experienced in VB.net as well as PHP, Python, and, years ago, C. I've dabbled in several other tools and languages but get tired of the needless complexity (and bloat) that seems to be inherent in most development environments plus I'm not a fan of OOP although I can do it. I've spent some time playing around with PB today and developed some questions that I have not found good answers.

1. Is there a particular program flow recommended? Something like how in VB you - Form -> Events-> Code?

2. When using the GUI form designer, how do you name the reference to the form in the properties (object) window? I was able to change the reference by editing the form code but it seems like this could be done in the GUI designer.

3. I created an initial form with a button and a text gadget. When I test it, the button is not visible although the form is. Is this because there are no events generated for the form?

Honestly I find the structure and code on the back quite simple from a code standpoint but the Form Designer/GUI has me a bit confused. Thanks in advance.
Desert Polar Bear
User
User
Posts: 25
Joined: Thu Feb 04, 2021 9:27 pm
Location: Nowhere Special, Arizona, USA

Re: New to PB - questions to clear confusion

Post by Desert Polar Bear »

I'm very new here as well. I found this post extremely helpful.
viewtopic.php?f=22&t=64684
Last edited by Desert Polar Bear on Wed Feb 17, 2021 4:01 am, edited 1 time in total.
"You should never judge a book by its cover."
"A picture is worth a thousand words."

Well, which...? Shuddup!
Image
- Desert Polar Bear • Nowhere Special • Arizona, USA
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: New to PB - questions to clear confusion

Post by mk-soft »

The FormDesigner of Purebasic can be used to create individual windows very well (even if it is not quite perfect). However, I would switch off the event management of the FormDesigner and change it to constants.
You can set this under Preferences -> Form
- Disable New gadgets use #PB_Any by default
- Deactivate Generate event procedure

Include the form files with IncludeFile and write the event procedures yourself.
If you want to create multiple windows, you have to be careful to assign unique constant names to the windows and gadgets.

As I am a lazy writer, I have written a tool that adapts the gadget of several windows to the constants by extending the constant of the window as a prefix and creating a common file. I was also able to automate the creation of the event procedures and the call.

To learn Purebasic and how the event management of Purebasic works, you should first learn it yourself.

But if you want to have them automated like in VB6, you can have a look at my tool EventDesigner. (see signature)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Axolotl
Enthusiast
Enthusiast
Posts: 435
Joined: Wed Dec 31, 2008 3:36 pm

Re: New to PB - questions to clear confusion

Post by Axolotl »

Hi JaxMusic,

welcome to the PureBasic Community.
Honestly I do not use the gui designer.
Because of my small tools I do the gui stuff inside the code editor.

The important thing is, that the event management is the same.

Some of my "rules" from my personal "coding guidelines"
Please bear in mind, that I do not want to start a discussion on pro and cons of guidlines
You will see that there are different "styles" on the forums codes, and that is absolutly okay with me.

My solid rule:
-> EnableExplicit ;' always the first addition even to code from the forum (but you dont have to, its up to you)

Some Syntax (usage is up to you)
I use special prefix letters for
-> E for named enums i.e. Enumeration EWindow
-> T for structures i.e. Structure TProgramData


Here is a running example with different event management behavior (please see the comments)
I skipped the multi window event management for this time (maybe you can find this on existing solutions on the forum)

Code: Select all

 
;' File : Sample.pb 

EnableExplicit 
DebugLevel 9 ;' all debug message on :-)  -- also my style 

#ProgramName$          = "Sample" 
#ProgramMajorVersion$  = "1"


Enumeration EWindow   ;' use of named enums is helpful, if you use several files 
  #WINDOW_Main 
  #WINDOW_SearchAndReplace 
EndEnumeration 

Enumeration EGadget  ;'small projects with only one window (or max three)  
  #GADGET_CloseBtn 
  #GADGET_HelpBtn   
  #GADGET_Filename  
  #GADGET_New          ;' nameing is not really useful 
  #GADGET_Open 
  #GADGET_Clear 
EndEnumeration 

;' this is possible -- thanks to the named enum you get always different IDs 
Enumeration EGadget  ;'midsize or bigger projects with more windows and many gadgets 
  #GADGET_Main_CloseBtn                 ;' use the Window name inside 
  #GADGET_Main_HelpBtn   
  ; ... 
  #GADGET_SearchAndReplace_HelpBtn    ;' second window 
EndEnumeration 

Enumeration EMenu  
  #MENU_New    ;' sample 
  #MENU_Open
  #MENU_Clear 
EndEnumeration 

;' Constants 
#MainCaption$ = #ProgramName$ + " "+#ProgramMajorVersion$ + "." + #PB_Editor_BuildCount + " (" + #PB_Editor_CompileCount + ")" 

#WindowFlags = #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget  

;' 
;' Example of BindEvent() 
;' 
Procedure OnEvent_SizeMainWindow()
  Protected WndW, WndH                          :Debug #PB_Compiler_Procedure + "() ", 9 
  
  ; Resize the gadget to fit the new window dimensions
  ;
  WndW = WindowWidth(#WINDOW_Main)
  WndH = WindowHeight(#WINDOW_Main) 
  
  ResizeGadget(#GADGET_CloseBtn, #PB_Ignore, #PB_Ignore, WndW - 16, #PB_Ignore) 
  ResizeGadget(#GADGET_Filename, #PB_Ignore, #PB_Ignore, WndW - 16, #PB_Ignore) 
EndProcedure  

;' 
;' Example of SetWindowCallback() 
;' 
Procedure MainWindowCallback(hWnd, Message, wParam, lParam)
  Protected result 

  result = #PB_ProcessPureBasicEvents

  Select Message 
    Case #WM_SIZE 
      Select WParam 
        Case #SIZE_MINIMIZED           :Debug "Window was minimized", 9 
        Case #SIZE_RESTORED            :Debug "Window was restored", 9 
        Case #SIZE_MAXIMIZED           :Debug "Window was maximized", 9  
      EndSelect 

    Case #WM_QUERYENDSESSION  :Debug "WM_QUERYENDSESSION ", 9  
      result = #True 

    Case #WM_ENDSESSION       :Debug "WM_ENDSESSION ", 9 
      If wParam = 1 
        ;' now we have a series problem :-) 
      EndIf 
    
  EndSelect 

  ProcedureReturn result 
EndProcedure 

;'
;' example for main loop based event management 
;'
Procedure OnEvent_NewFile() 
EndProcedure 

Procedure OnEvent_OpenFile() 
EndProcedure 

;­---------------------------------------------------------------------------------------------------------------------

Procedure OpenMainWindow(WndW, WndH) 
  Protected hwnd  

  hwnd = OpenWindow(#WINDOW_Main, 0, 0, WndW, WndH, #MainCaption$, #WindowFlags) 
  If hwnd <> 0 
    StickyWindow(#WINDOW_Main, 1) 
    
    ButtonGadget(#GADGET_CloseBtn, 8,  8, WndW - 16, 25, "Close", #PB_Button_Default) 
    StringGadget(#GADGET_Filename, 8, 48, WndW - 16, 20, "c:\temp\dummy.txt")   

    ;' add the gadgets, menus, etc. here 
    
    SetWindowCallback(@MainWindowCallback(), #WINDOW_Main) 
    BindEvent(#PB_Event_SizeWindow, @OnEvent_SizeMainWindow(), #WINDOW_Main)     
  EndIf  
  ProcedureReturn hwnd   
EndProcedure 

Procedure MainProgram() 
  Protected state 

  If OpenMainWindow(640, 480) 
    ;' main loop 
    Repeat
      Select WaitWindowEvent() 
        Case #PB_Event_CloseWindow 
          Select EventWindow()  ;' which window fired the event 
            Case #WINDOW_Main 
              Break  ;' escape the main loop 
            Case #WINDOW_SearchAndReplace 
              ;' do what ever you want to do 
          EndSelect 

        Case #PB_Event_Gadget 
          Select EventGadget() 
            Case #GADGET_New 
              OnEvent_NewFile() 
            Case #GADGET_Open 
              OnEvent_OpenFile() 
            ; ...  
            Case #GADGET_Clear 
            ; ...  
          EndSelect 

        Case #PB_Event_Menu  
          Select EventMenu() 
            Case #MENU_New 
              OnEvent_NewFile() 
            Case #MENU_Open 
              OnEvent_OpenFile() 
          EndSelect 

      EndSelect 
    ForEver 
  EndIf 
EndProcedure 

End MainProgram() 


happy coding and stay healthy
Mostly running PureBasic <latest stable version and current alpha/beta> (x64) on Windows 11 Home
Bitblazer
Enthusiast
Enthusiast
Posts: 733
Joined: Mon Apr 10, 2017 6:17 pm
Location: Germany
Contact:

Re: New to PB - questions to clear confusion

Post by Bitblazer »

Hi JaxMusic,
welcome to the PureBasic community. You can find many resource links on my personal website. There is a series of tutorials for beginners too. Personally i use PureVision as GUI designer and am happy with that combination for the last decades ;)

That's all i personally need, but lately sql tools are an optional help too. PureBasic/PureVision is an excellent investment to comfortably do desktop or server applications for windows/linux/Mac OS.

Check my website at http://www.bitblazer.de for a complete? collection of purebasic links with thousands of samples, tips and tricks. Click Links -> PureBasic -> Resources
webpage - discord chat links -> purebasic GPT4All
JaxMusic
User
User
Posts: 20
Joined: Sun Feb 14, 2021 2:55 am
Location: Max Meadows, Virginia, USA
Contact:

Re: New to PB - questions to clear confusion

Post by JaxMusic »

Thanks for the responses given so far. Some of the answers do address, in a way, the questions I have. But would still like clarity. Thanks.



1. Is there a particular program flow recommended? Something like how in VB you - Form -> Events-> Code?

2. When using the GUI form designer, how do you name the reference to the form in the properties (object) window? I was able to change the reference by editing the form code but it seems like this could be done in the GUI designer.

3. I created an initial form with a button and a text gadget. When I test it, the button is not visible although the form is. Is this because there are no events generated for the form?
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4747
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: New to PB - questions to clear confusion

Post by Fangbeast »

Form -> Events-> Code?
That's the way I do it, with all the visual designers I have ever tried.

Once the form is designed, you should never manually edit it unless you have some strange third-party controls you need to replace a built-in one with but even that is done without touching the form code.

Design the form, give all objects long winded names that will tell you what they are when you are coding for them, let the visual designer (Not sure if the pb one does this) create a basic loop for you such as the one below. Designers like the one I use from Reelmedia create that and the basic set of controls (Gadgets, PB parlance) and then you add your events that you want to check for and then design the code (Procedures) you want them to triggerr.

Code: Select all

  Repeat
    EventID   = WaitWindowEvent()
    MenuID    = EventMenu()
    GadgetID  = EventGadget()
    WindowID  = EventWindow()
    TimerID   = EventTimer()
    Select EventID
      Case #PB_Event_CloseWindow
        Select WindowID
          Case #Window_Mywindow
            CloseWindow(#Window_Mywindow)
        EndSelect
    EndSelect
  Until #PB_Event_CloseWindow  = #True
End
It took me 17 years (?) to get this far, with a lot of help and I am still learning. I still call myself a beginner but my current project is 53,000 lines of code (Not all of it mine you understand, I had a lot of help) and liable to be around 95,000 by the time I am finished but it all works. That's a miracle in itself for someone as old and stupid as me:):)
Amateur Radio, D-STAR/VK3HAF
User avatar
TI-994A
Addict
Addict
Posts: 2512
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: New to PB - questions to clear confusion

Post by TI-994A »

JaxMusic wrote:...But would still like clarity.
Here's a quick six-step example to illustrate the structure, functionality, and implementation of form files.

1. Open a new form (press F11).
2. Position and size an IMAGE gadget and a BUTTON gadget onto it (ensure their positions don't overlap).
3. In the CAPTION property of the button gadget, type "LOAD IMAGE" (without quotes).
4. In the EVENT PROCEDURE field of the button gadget, type "buttonEvent" (without quotes).
5. Save this form as myForm.pbf (take note of the saved location paths).

The code generated by the Form Designer should look something like this (with the GENERATE EVENTS PROCEDURE option in the Window_0 layout properties selected):

Code: Select all

;
; This code is automatically generated by the FormDesigner.
; Manual modification is possible to adjust existing commands, but anything else will be dropped when the code is compiled.
; Event procedures needs to be put in another source file.
;

Global Window_0

Global Image_0, Button_0

Declare buttonEvent(EventType)

Procedure OpenWindow_0(x = 0, y = 0, width = 480, height = 320)
  Window_0 = OpenWindow(#PB_Any, x, y, width, height, "", #PB_Window_SystemMenu)
  Image_0 = ImageGadget(#PB_Any, 16, 16, 448, 240, 0)
  Button_0 = ButtonGadget(#PB_Any, 16, 272, 448, 32, "LOAD IMAGE")
EndProcedure

Procedure Window_0_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False

    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect

    Case #PB_Event_Gadget
      Select EventGadget()
        Case Button_0
          buttonEvent(EventType())          
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure
6. Open a new code tab (press Ctrl-N), paste the following code, save it as myCode.pb, then run it.

Code: Select all

; ensure that the form file (myForm.pbf) is in the same folder as this code file
; otherwise ensure that the proper path to the form file is included - eg: C:\path\folder\myForm.pbf
XIncludeFile "myForm.pbf"

; include these image plug-ins to enable JPG and PNG image support (BMP support is built in)
UseJPEGImageDecoder()
UsePNGImageDecoder()

; create a procedure for the button event and name it according to the name given in myForm.pb (buttonEvent)
; this procedure takes the event type as a parameter and is called when the button in myForm.pb (Button_0) is clicked
Procedure buttonEvent(event_type)
  
  ; some code to select and load an image into the image gadget

  ; open a file explorer dialog for selecting an image file
  pattern.s = "Images (BMP, JPG, PNG)|*.bmp;*.jpg;*.png"
  imageFile.s = OpenFileRequester("Select an image file", "", pattern, 0)
  imageType.s = LCase(GetExtensionPart(imageFile))
  imageSize = FileSize(imageFile)
  
  ; some cursory validation on the selected image file before attempting to load it
  If imageSize > 0 And (imageType = "bmp" Or imageType = "jpg" Or imageType = "png")
    image_id = LoadImage(#PB_Any, imageFile)
    
    ; size the image to fit the image gadget
    ResizeImage(image_id, 448, 240)
    
    ; set the selected image into the image gadget in myForm.pb (Image_0)
    SetGadgetState(Image_0, ImageID(image_id))
    
  EndIf
    
EndProcedure

; this function was generated by the form designer
; call this function to display the form in myForm.pbf
OpenWindow_0()

; the main event loop
Repeat
  
  event = WaitWindowEvent()
  
  ; this function was generated by the form designer
  ; call this function and pass it the EVENT value to process the events required by myForm.pbf
  ; STATUS holds the boolean result from this function - FALSE only when the window is closed
  status = Window_0_Events(event)
  
; break the event loop and end the program when STATUS = FALSE
Until status = #False
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Joris
Addict
Addict
Posts: 885
Joined: Fri Oct 16, 2009 10:12 am
Location: BE

Re: New to PB - questions to clear confusion

Post by Joris »

Yeah I know, but keep in mind ... Leonardo da Vinci was also an autodidact.
Axolotl
Enthusiast
Enthusiast
Posts: 435
Joined: Wed Dec 31, 2008 3:36 pm

Re: New to PB - questions to clear confusion

Post by Axolotl »

Hi,

maybe my answers help you a little
1. Is there a particular program flow recommended? Something like how in VB you - Form -> Events-> Code?
IMHO there is not only one way. As you can see, there are many different possibilities. In the end, you have to choose your way.
The link between forms and code are the constants #WINDOWS_* or #GADGET_* or the WIN_ID, GDT_ID variables if #PB_Any is used in the create procedures (OpenWindow, TextGadget, ButtonGadget, and so on). A general recommendation is to separate the Forms and the Code into several files and use XIncludeFile "<filename>".
2. When using the GUI form designer, how do you name the reference to the form in the properties (object) window? I was able to change the reference by editing the form code but it seems like this could be done in the GUI designer.

Hint: Use the Menu 'Form | Switch Code/Design View' to see the result. All this is going through the compiler. It is not like C with a separate resource file.

If I would use the VD and I define my main window like

Properties - Variable: Window_0 ;' <-- default, name it to your liking

it leads to a code like this:

Code: Select all

Enumeration FormWindow  ; <-- named enums :-) 
  #Window_0
EndEnumeration

Enumeration FormGadget
  #Button_0
  #Text_0
EndEnumeration

Procedure OpenWindow_0(x = 0, y = 0, width = 600, height = 400)
  OpenWindow(#Window_0, x, y, width, height, "", #PB_Window_SystemMenu)
  ButtonGadget(#Button_0, 128, 48, 104, 32, "")
  TextGadget(#Text_0, 16, 56, 100, 25, "")
EndProcedure

Procedure Window_0_Events(event)
  Select event
    Case #PB_Event_CloseWindow
      ProcedureReturn #False

    Case #PB_Event_Menu
      Select EventMenu()                          ; <-- here you have to work on menu events 
      EndSelect

    Case #PB_Event_Gadget
      Select EventGadget()                     ; <-- here the events of the gadgets 
      EndSelect
  EndSelect
  ProcedureReturn #True
EndProcedure
3. I created an initial form with a button and a text gadget. When I test it, the button is not visible although the form is. Is this because there are no events generated for the form?

If you have only created the form, then you are still missing the start and the (as i call it) mainloop.
This additional code should not be stored in the form file, the form should be included via xincludefile instead.

see help for WaitWindowEvent() and the article about window management

Minimum additional code to the above VD created Form and Event you need is this:

Code: Select all

Define Event 

;' call this first to create the window 
OpenWindow_0() ; <- can be empty because of (x = 0, y = 0, width = 600, height = 400)

;' main loop 
Repeat
  Event = WaitWindowEvent() 
  If Window_0_Events(Event) = 0 
    Break 
  EndIf 
ForEver 
IMHO this is not the best implementation because of lack on error handling and so on, but that is a different story.
Mostly running PureBasic <latest stable version and current alpha/beta> (x64) on Windows 11 Home
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: New to PB - questions to clear confusion

Post by mk-soft »

I like my method with constants and virtual tables on the event procedures. Then connect with BindEvent and that's it. See EventDesigner.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Tenaja
Addict
Addict
Posts: 1948
Joined: Tue Nov 09, 2010 10:15 pm

Re: New to PB - questions to clear confusion

Post by Tenaja »

I learned the old school way from Petzold (in C), so I still do it that way. It's all manual, but when I started pb I didn't want to add a new process to the new language learning curve.
Form -> Events-> Code?
I might for the next project... But I keep saying that.
JaxMusic
User
User
Posts: 20
Joined: Sun Feb 14, 2021 2:55 am
Location: Max Meadows, Virginia, USA
Contact:

Re: New to PB - questions to clear confusion

Post by JaxMusic »

Thanks everyone.
JaxMusic
User
User
Posts: 20
Joined: Sun Feb 14, 2021 2:55 am
Location: Max Meadows, Virginia, USA
Contact:

Re: New to PB - questions to clear confusion

Post by JaxMusic »

Thanks for the information. I was able to get the code working. It did have a bug in it but I don't know if it was system generated. This code in the form:

Declare buttonEvent(EventType)

versus the procedure

Procedure buttonEvent(event_type)

I changed the procedure reference to match. I am guessing that EventType is a system variable, so the procedure would have to match it?

Questions:
How does the compiler know where to start? There is no void main() like in C. Does it just start at code that it first encounters that is not in a procedure?
TI-994A wrote: Save this form as myForm.pbf (take note of the saved location paths).
What do you mean by take note of the paths? Is there an organizational issue here that I should be cognizant of? In this case I just put all the files in the same test directory I'm using.
TI-994A wrote: ; Event procedures needs to be put in another source file.
I assume this is because the form is exclusive to form procedures?
TI-994A wrote:
Case #PB_Event_CloseWindow
ProcedureReturn #False
Are these "#PB_Event" constants always generated in a form?



Thanks. Jack/Jax
User avatar
Tenaja
Addict
Addict
Posts: 1948
Joined: Tue Nov 09, 2010 10:15 pm

Re: New to PB - questions to clear confusion

Post by Tenaja »

This book will likely answer your questions.
viewtopic.php?f=14&t=37059&p=563379&hil ... ad#p563379

All of the gadget events have constants assigned, and described in the pb manual. (Not referring to the aforementioned book.)

The code starts at the first statement, although procedures are "jumped over" meaning they are actually placed last in asm, iirc. Therefore, you don't need a "main" like C, although many of us start with a main-like proc so the only code not encapsulated in a proc is a call to that proc. For short & simple code, I might skip that main and put the loop out in free code space.

As for paths, you can use form files as includes or as a project, and either way, you want to know which directory they are in.
Post Reply