Page 1 of 2

Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 1:12 pm
by Blue Steel
Hi,

This is REALLY my first PureBasic Program . Its being Written while READING and LEARNING all about this language
I have used other Coding languages before (as you can hopefully tell .. and for the better I hope)

Its a combination of what i've learned so far from reading the book , manual , and here on the forums

I hope i havn't made any totally noob errors or coding fopa's

Let me know what you think

Code: Select all

;{ How To open a window,ADD menus,some gadgets And use window events then close everything.
; Also lets you press ENTER key IN string Gadget And respond the same As pressing the button.

; Original examples taken from
; "PureBasic - A Beginners Guide To Computer Programming";
; The PureBasic help file and the PureBasic Forums

; Code merged , fixed (Depreciated commands replaced or removed) , modified
; To work on PureBasic 4.40 by Cameron Arnott AKA Blue Steel
; Extra advive Given at the PureBasic forums to better structure my program

; This program is my First PureBasic Program,
; Written in about 12 hours from totaly knowing nothing about PureBasic,
; while reading and searching all of the above
; If I can do it so can anyone ;)
; PS: Expect this to Grow as time goes on to include Different things
; as I experiment and learn

;} The {} after the start and end remarks make them into a foldable block

;Compiler Directives
EnableExplicit ; make sure all variables are explicitly defined before use

; Declare Procedures
Declare UPDATE_LIST_VIEW_GADGET() ; ; and reset the String Gadget back to defaults

; Setup the About box content
Define About.s = "How To open a window,ADD menus,some gadgets And use window events then close everything."
About + "  Also lets you press ENTER key IN string Gadget And respond the same As pressing the button."

;Setup vairables the window
Define Event.l ; Set to = WaitWindowEvent() later on in event loop
Define Title.s = "My Window"
Define WindowHeight.i = 200
Define WindowLength.i = 300
; Setup window type Flags 
#FLAGS = #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_ScreenCentered

; Setup global variables
Global Quit.i = #False 
Global Taunt.s = "Go on I dare you"

; Setup constants for Purebasic Libraries using enumerate
; starting at 0 in each block

Enumeration ; Windows
  #WIN_MAIN         
EndEnumeration

Enumeration ; Gadgets
  #TEXT_INPUT
  #STRING_INPUT
  #LIST_INPUT   
  #BUTTON_INTERACT
  #BUTTON_CLOSE   
EndEnumeration 

Enumeration ; Menus
  #MENU_MAIN       
  #MENU_QUIT       
  #MENU_ABOUT     
  #MENU_CHILD1 
  #RETURN_KEY ; Dummy menu item to process Enter key in string gadget
EndEnumeration     

;Try to open a window if it can't fail and quit out
If OpenWindow(#WIN_MAIN, 0, 0, WindowLength, WindowHeight + MenuHeight(), Title, #FLAGS) 
;                              ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
;                                Internal Size of Window Not External
;              Still need ^  ^ even if Window is going to be centered

; Set up menu, NOTE: the &Q and &A are only underlined if accessed by the F10 Key and arrows
  If CreateMenu(#MENU_MAIN, WindowID(#WIN_MAIN)) 

    MenuTitle("File")
      OpenSubMenu("Parent Menu Item")
        MenuItem(#MENU_CHILD1, " Sub Menu Item")
      CloseSubMenu()
      MenuBar()  
      MenuItem(#MENU_QUIT, "&Quit" + #TAB$ + "Ctrl+Q") 

    MenuTitle("Help") 
      MenuItem(#MENU_ABOUT, "&About..." + #TAB$ + "Ctrl+A")

; Add shortcut keys to menu's
    AddKeyboardShortcut(#WIN_MAIN,#PB_Shortcut_Control|#PB_Shortcut_Q,#MENU_QUIT)
    AddKeyboardShortcut(#WIN_MAIN,#PB_Shortcut_Control|#PB_Shortcut_A,#MENU_ABOUT) 
  EndIf

; Setup Gadgets
  ButtonGadget(#BUTTON_CLOSE, 190, 170, 100, 20, "Close window") 
  ButtonGadget(#BUTTON_INTERACT, 10, 170, 120, 20, "Enter text") 

  ListViewGadget(#LIST_INPUT, 10, 60, 280, 100) 

  StringGadget(#STRING_INPUT, 10, 30, 280, 20, Taunt) 

  TextGadget(#TEXT_INPUT, 10, 10, 280, 20, "Enter text here:") 

; ADD some colour To the gadgets IN form $BBGGRR Or even using RGB(Red,Green,Blue)
  SetGadgetColor(#LIST_INPUT, #PB_Gadget_BackColor, $A40000)
  SetGadgetColor(#LIST_INPUT, #PB_Gadget_FrontColor, RGB(0, 255, 255))

  SetGadgetColor(#STRING_INPUT, #PB_Gadget_BackColor, $004B85)
  SetGadgetColor(#STRING_INPUT, #PB_Gadget_FrontColor, RGB(255, 255, 0))

; Set Active Gadget
  SetActiveGadget(#STRING_INPUT) 

; Start of main Program LOOP
  Repeat

; Check if something has happened in the window    
    Event = WaitWindowEvent() 
    Select Event 

; Check to see if any menu items have been accessed
      Case #PB_Event_Menu 
        Select EventMenu() 
          Case #MENU_ABOUT 
            MessageRequester("About", About) 
          Case #MENU_CHILD1
            AddGadgetItem(#LIST_INPUT, -1, "You selected the Sub Memnu Item") 
          Case #MENU_QUIT 
            Quit = #True 
          Case #RETURN_KEY
; I used a procedure here so that I wouldn't have to double up my code
            UPDATE_LIST_VIEW_GADGET()
        EndSelect 

; Check to see if any gadgets have been accessed           
      Case #PB_Event_Gadget 
        Select EventGadget() 
          Case #BUTTON_CLOSE 
            Quit = #True 
          Case #BUTTON_INTERACT 
; I used a procedure here so that I wouldn't have to double up my code
            UPDATE_LIST_VIEW_GADGET()
          Case #STRING_INPUT
            Select EventType()
              Case #PB_EventType_Focus
; Keyboard Shortcuts are only linked to the Menu's so this ads shortcut to a dummy menu item
; Add Enter key shortcut only if the String Gadget is in focus
                AddKeyboardShortcut(0,#PB_Shortcut_Return, #RETURN_KEY)
; If its not in focus then Remove the Enter key shortcut
              Case #PB_EventType_LostFocus
                RemoveKeyboardShortcut(0,#PB_Shortcut_Return)
            EndSelect
        EndSelect 
    EndSelect 
  Until Event = #PB_Event_CloseWindow Or Quit = #True 
EndIf 
End

Procedure UPDATE_LIST_VIEW_GADGET() ; and reset the String Gadget back to defaults
; copy the text in the string Gadget into the list gadget
  AddGadgetItem(#LIST_INPUT, -1, GetGadgetText(#STRING_INPUT)) 
; Reset the Message displayed in the string gedget
  SetGadgetText(#STRING_INPUT, Taunt) 
; make sure that the string gadget has the focus again
  SetActiveGadget(#STRING_INPUT) 
EndProcedure

Edited , Tweaked with all suggestions i've had so far. and even re-organised and added a little more

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 1:43 pm
by ts-soft
Looks great!

Some Tips:
Use EnableExplicit and declare all variables!

Code: Select all

Global Quit.b = #False
Better use Integer. Integer is the native type and is faster.
Byte and so on make only sense in structures or for some API. We are programming not
a 8-Bit Homecomputer :wink:

greetings
Thomas

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 2:31 pm
by UserOfPure
ts-soft wrote:We are programming not a 8-Bit Homecomputer
But we should code as if we are, to avoid bloatware. ;)

What's wrong with using a byte for the quit flag? Makes perfect sense to me, and only uses 1 byte of memory. You think it's better to use an integer and 8 bytes of memory to do the same job? Why waste 7 bytes? Sure, everyone has 2 GB of RAM these days but that's no reason to throw things away unnecessarily. Speed is not a factor here either because it's just a flag to indicate a state.

To summarise: always use a data type of the size of data needed. For a quit flag, a byte type is perfect.

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 2:39 pm
by Kaeru Gaman
sorry, this is simply wrong.

simple variables are way more efficient when 32bit-aligned.
Windows reserves memory for it's tasks in large chunks.

so, you can use a byte for a single flag ragister until the pacific runs dry, windows will still reserve the same amount of memory, your exe will still be of the same size,
only your performance is worse, because the CPU has to CUT the register the value was computed in, because you used a byte instead of a register size.

only when you have complex structures in large arrays, the bytes will really be spared, like ts said:
Byte and so on make only sense in structures or for some API

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 3:32 pm
by ts-soft
UserOfPure wrote: To summarise: always use a data type of the size of data needed. For a quit flag, a byte type is perfect.
Kaeru is right :!:

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 3:44 pm
by Fluid Byte
To summarise: always use a data type of the size of data needed. For a quit flag, a byte type is perfect.
To summarise, indeed. To summarise what is bad programing style.

As for the argument of saving memory: It's not 1980. Go spend some bytes and use native types. Your program will thank you.

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 3:50 pm
by Blue Steel
I just ran some tests.. all i did was change the Global Quit.b = #False to Global Quit.i = #False
I don't know if this proves anything though but to me it looks like on average the INT uses more memory
and as for CPU usage i couldn't decern any difference

measured with windows 7 performance meter

Strange how windows uses its memory ..
one would think that a program would use the same amount every time you run the same program with absolutly no changes

ran 5 times with it set as byte
Image PID Hard Faults/sec Commit (KB) Working Set (KB) Shareable (KB) Private (KB)
PureBasic_Compilation1.exe 3936 0 19,008 4,872 3,884 988
PureBasic_Compilation1.exe 4016 2 19,004 4,796 3,812 984
PureBasic_Compilation1.exe 5604 0 19,016 4,848 3,852 996
PureBasic_Compilation1.exe 4116 0 19,004 4,868 3,888 980
PureBasic_Compilation1.exe 2208 0 19,004 4,864 3,884 980
------------------------------------------------------------
Commit Working Share Private
Averages 19,007.2 4,849.6 3,864.0 985.6

ran 5 times with it set as int
Image PID Hard Faults/sec Commit (KB) Working Set (KB) Shareable (KB) Private (KB)
PureBasic_Compilation1.exe 5884 0 19,004 4,936 3,956 980
PureBasic_Compilation1.exe 2092 0 19,008 4,996 4,012 984
PureBasic_Compilation1.exe 5268 2 19,008 4,932 3,940 992
PureBasic_Compilation1.exe 1820 0 19,008 4,944 3,964 980
PureBasic_Compilation1.exe 484 0 19,004 4,928 3,936 992
-------------------------------------------------------------

Commit Working Share Private
Averages 19,006.4 4,947.2 3,961.6 985.6



summary
Averages Int Commit 19,006.4, Working 4,947.2, Share 3,961.6, Private 985.6
Averages byte Commit 19,007.2, Working 4,849.6, Share 3,864.0, Private 985.6
---------------------------------------------------------------------------------
Diff 194.4 Commit -0.8, Working 97.6, Share 97.6, Private 0.0

and with no noticable CPU usage Differences it looks to me like the Bytes have it won

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 4:04 pm
by Kaeru Gaman
as you see, the amount of memory used differs for other reasons, may simon know why, and not for the use of .i or .b
you cannot take a conclusion out of five tests, you would have to run five billion, to make a statistic statement.

for the performance difference I was talking about, it's a theorhetical difference, it may also differ from CPU type to CPU type,
maybe some archtectures simply ignore you used a byte and use a register and just ignore the upper seven bytes when presenting the result.

to tell something definitely about this, you'll need to construct a complicated loop aligned measuring code, an doing a test operation a hundret billion times, and run it under many different circumstances.


only reasonable conclusion so far:

there is no meaningful and earnest reason to use another type than register size for a single integer variable.

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 4:27 pm
by Blue Steel
I am really confused now...

why have bytes if better to use ints..

I was always taught the right tool for the right job.. or package things in as smaller boxes as you need..
and the example (out of the Coding book "PureBasic - A Beginners Guide To Computer Programming" ) used .b so I followed
I was also taught that it was bad programming practice to just use ints for everything (ie: not use the other types that were smaller) just because it was that languages default.

Maybe Fred can explain the different memory usages that i'm seeing. and what is better to use when .. ie: byte or int..

to me it makes sence to only use a byte if thats all you need.

I really didn't want to start a discussion about use of bytes or ints . mearly to show what all i'd learned in a short space of time.
but now that this discussion has come up i'd like to know the Best methods of memory usage.

I do understand that in speed criticle curcomstances it would be better to use the fastest and to hang the memory. and when you don't need the speed then go for best memory usage.

I could never get my head around Bit maths though.. to get the absolute max out of memory

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 4:51 pm
by Kaeru Gaman
in old times it WAS good style.

when we had 640KB of Memory avaliable to create a big game, DOS on a 286, it sure was important to use bytes instead of words whenever possible.
when you created something like a Map, with structured tiles, for something like Civilization or so,
it sure was helpful, to create the structure as tight as possible, to have space for as many tiles as possible.
in C-versions of that time it was even possible to create fields in a structure with a size of single bits!

nowadays it maybe helpful to use byte inside of structures,
e.g. when you want to create a big pseudo neuronal network with billions of cells to simulate ... whatever.
when you have billions of cells, it still is important to spare some byte in a single cell's structure.

but not when it's about a single variable with a unique name.

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 4:56 pm
by Demivec
@Blue Steel: What is best is determined by what you need. You summed it up well as memory vs. speed, and that does a relatively good job of it.

Another important point mentioned by Kaeru, ts-soft, and others is that even though you specify a byte sized variable you may end up with an integer sized variable. This is done because of the operating system, CPU, or compiler. I'm honestly not sure which, probably all three. Because this may use memory you thought you were saving it makes sense to just select the larger size variable when there isn't a reason not to. The integer sized variable is the 'ideal' size for a given processor and is accessed faster by the CPU. This is due to things like the size of the CPU's registers and some related things such as the need to align memory accesses to certain boundaries that are related to the register size.

If you are simply writing experimental test code, which works well by the way :wink:, it seems the wrong thing to be focusing on. It is something to keep in mind as you gain experience with PureBasic and the code becomes more involved. It's true that you don't have to sweat about every byte a program may be using (usually) because of the progress made with computers but it is helpful to keep a program's memory needs within some bounds so as to not bog down a multi-tasking system that is running other programs and processes at the same time.

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 5:00 pm
by srod

Code: Select all

a = -1
b = a
Translates to 3 lines of ASM whilst the following :

Code: Select all

a.b = -1
b = a
translates to 4 lines because of the need to sign extend the byte value to fill a 32-bit integer.

Because of this kind of thing I always reserve bytes for use with pointers (when trawling memory buffers for example) or with structures as mentioned previously and instead use integer variables (which match the underlying register size) wherever possible.

**EDIT : actually, thinking about it, I don't understand why PB uses 4 ASM statements with the second snippet above when 3 will do the job - unless it something to do with the ASM flags? Oh well, never mind. :) One thing is clear, the sign extension required above certainly uses more clock cycles.

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 5:50 pm
by freak
Arguing speed over size in this situation is really a bit ridiculous. Yes, there are less instructions involved when dealing with register sized values as srod explains, but then we are also talking memory access here. So you have multiple levels of caches involved in the reading of that value. This is going to cost you way more than a simple sign extending operation. So in the end, unless you run a really tight loop with millions of accesses to the same variable you won't get a significant difference. The size argument is also out of the window because more often than not the variables will be aligned to larger boundaries anyway by the compiler (by adding space after them). So really the differences are insignificant.

I see the difference more from a practical side: If you just use the default type for normal variables, you (generally) won't have to worry about whether it will fit all your values in the future. Variable overflows can be a bitch to track down, so why create more trouble when you don't have to? In the case here its just a yes/no situation so you won't run into that, but consider something like this:

Code: Select all

Define.b i
For i = 0 to 100  ; still fits into a byte variable
  ; ...
Next i
This is dangerous, especially when the definition and use are further apart. 6 Months in the future you may decide that your loop should go 0-200, and if you don't remember that you used a byte and change that you will get an overflow (byte ranges from -128 to +127).

So really its about writing code that is easier to maintain and less likely to introduce bugs. I generally only use three types in my programs (except for really large data structures): Integer, String and Double. The less types used the less things i have to worry about :)

Blue Steel wrote:I am really confused now...

why have bytes if better to use ints..

I was always taught the right tool for the right job.. or package things in as smaller boxes as you need..
and the example (out of the Coding book "PureBasic - A Beginners Guide To Computer Programming" ) used .b so I followed
I was also taught that it was bad programming practice to just use ints for everything (ie: not use the other types that were smaller) just because it was that languages default.
Its usually the language default for good reason. Usually its because the compiler will make the types larger anyway to fit other requirements. In the end its about what works best for you. As explained above i tend to go the route that is less likely to introduce errors in my programs, but thats just me.

Anyway, your code looks good to me. Good luck in your further journey into PureBasic :)

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 6:12 pm
by Fred
Just a remark about your use of enumeration:

Code: Select all

Enumeration  ; automatically assign Contstants incrementing Values
  #WIN_MAIN         ;1
  #TEXT_INPUT       ;2
  #STRING_INPUT     ;3
  #LIST_INPUT       ;4
  #BUTTON_INTERACT  ;5
  #BUTTON_CLOSE     ;6
  #MENU_MAIN        ;7
  #MENU_QUIT        ;8
  #MENU_ABOUT       ;9
  #MENU_CHILD1      ;10
  #RETURN_KEY       ;11 .. dummy menu item to make return key work in string gadget
EndEnumeration  
You put evety different object in the same enumeration. While it does work, on a big program it can be unefficient. Better use an enum per object type (one for Menu, Gadget, Window etc.). Each PB library has it's own object range. Also an enumeration starts from index '0', unless told otherwise. I would so write it like this:

Code: Select all

Enumeration ; Windows
  #WIN_MAIN         
EndEnumeration

Enumeration ; Gadgets
  #TEXT_INPUT
  #STRING_INPUT
  #LIST_INPUT    
  #BUTTON_INTERACT
  #BUTTON_CLOSE   
EndEnumeration  

Enumeration ; Menu items
  #MENU_MAIN        
  #MENU_QUIT        
  #MENU_ABOUT      
  #MENU_CHILD1  
  #RETURN_KEY
EndEnumeration

Re: Here is my First PureBasic Program - Window, Menu and Gadget

Posted: Sat Jan 09, 2010 6:53 pm
by Blue Steel
Cool thanks Fred ;)
I'll change that and try to remember it in future.

so far Changes being implimnented are

1. Use EnableExplicit and declare all variables!
2. Use and int as opposed top a byte in my Quit variable
3. Seperate Enumerations as to PB library instead of all in one and that they actually start from 0

anything else ??

Question: is the way i'm getting the return key press the best way..
I was trying to get it to activate the button "Enter Text" so that i wouldn't need a procedure nor double up on code
I tried for hours myself then went looking on the forum and i found the way I ended up doing it (well the basic's of it) in there