It is currently Wed May 27, 2020 1:05 am

All times are UTC + 1 hour




Post new topic Reply to topic  [ 120 posts ]  Go to page Previous  1, 2, 3, 4, 5 ... 8  Next
Author Message
 Post subject: Re: PureBasic Docs- Ideas/Help needed for a "We start" chapt
PostPosted: Sun Apr 03, 2011 7:21 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 6:14 pm
Posts: 1825
Location: Germany (Saxony, Deutscheinsiedel)
blueznl wrote:
Feel free to rip parts of the guide, I've said this ages ago, so I'll just repeat it once more... A little note would be nice but not even required.


Thanks blueznl.
We will see, what can be used (it still should result in a relative short introduction, which is linking to further documentation in the PB manual).

Notes in the manual for all people, which are contributing a lot of help, will be done for sure! :-)

_________________
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)


Top
 Profile  
Reply with quote  
 Post subject: Storing Data in Memory item - updated
PostPosted: Mon Apr 04, 2011 7:06 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Sep 22, 2010 1:17 pm
Posts: 327
Location: United Kingdom
This example gathers information about the files in the logged on user's home directory into a structured linked list. For now the output isn't very exciting but we will come back to this example later on and make it a bit more friendly in several different ways.

Code:
; This section describes the fields of a structure or record, mostly integers in this case,
; but notice the string for the file name and the quad for the file size.
Structure FILEITEM
  Name.S
  Attributes.I
  Size.Q
  DateCreated.I
  DateAccessed.I
  DateModified.I
EndStructure

; Now we define a new list of files using the structure previously specified
; and some other working variables we'll use later on.
NewList FilesList.FILEITEM()
Define Folder$
Define.I Result

; This function gets the home directory for the logged on user.
Folder$ = GetHomeDirectory()

; Open the directory to enumerate all its contents.
Result = ExamineDirectory(0, Folder$, "*.*")

; If this is ok, begin enumeration of entries.
If Result
 
  ; Loop through until NextDirectoryEntry(0) becomes zero - indicating that there are no more entries.
  While NextDirectoryEntry(0)
   
    ; If the directory entry is a file, not a folder.
    If DirectoryEntryType(0) = #PB_DirectoryEntry_File
     
      ; Add a new element to the linked list.
      AddElement(FilesList())
     
      ; And populate it with the properties of the file.
      FilesList()\Name = DirectoryEntryName(0)
      FilesList()\Size = DirectoryEntrySize(0)
      FilesList()\Attributes = DirectoryEntryAttributes(0)
      FilesList()\DateCreated = DirectoryEntryDate(0, #PB_Date_Created)
      FilesList()\DateAccessed = DirectoryEntryDate(0, #PB_Date_Accessed)
      FilesList()\DateModified = DirectoryEntryDate(0, #PB_Date_Modified)

    EndIf
   
  Wend
 
  ; Close the directory.
  FinishDirectory(0)
 
EndIf

; If there are some entries in the list, show the results in the debug window.
If ListSize(FilesList())
 
  ForEach FilesList()
   
    Debug "Filename = " + FilesList()\Name
    Debug "Size = " + Str(FilesList()\Size)
    Debug "Attributes = " + StrU(FilesList()\Attributes)
    Debug "Created = " + StrU(FilesList()\DateCreated)
    Debug "Accessed = " + StrU(FilesList()\DateAccessed)
    Debug "Modified = " + StrU(FilesList()\DateModified)
   
  Next FilesList()
 
EndIf


Ok, firstly, the dates in the output are just numbers - this isn't very helpful, so let's make them look a bit more familar. Replace the last three Debug statements with these:

Code:
...
Debug "Created = " + FormatDate("%dd/%mm/%yyyy", FilesList()\DateCreated)
Debug "Accessed = " + FormatDate("%dd/%mm/%yyyy", FilesList()\DateAccessed)
Debug "Modified = " + FormatDate("%dd/%mm/%yyyy", FilesList()\DateModified)


The FormatDate function takes a date in PureBasic's own numeric date format and displays it in a format that we can specify. So now things should begin to look a bit more sensible.

Finally, for now, the list isn't in any particular order, so let's sort the list before we display it. Add this line before the comment about showing the list and the ForEach loop.

Code:
...

; Sort the list into ascending alphabetical order of file name.
SortStructuredList(FilesList(), #PB_Sort_Ascending, OffsetOf(FILEITEM\Name), #PB_Sort_String)

; If there are some entries in the list, show the results in the debug window.

...


This command takes the structured list, and resorts it into ascending order (#PB_Sort_Ascending), of the Name field of the structure (OffsetOf(FILEITEM\Name)), which is a string value (#PB_Sort_String).


Last edited by spikey on Wed Aug 03, 2011 6:01 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: PureBasic Docs- Ideas/Help needed for a "We start" chapt
PostPosted: Mon Apr 04, 2011 8:00 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Sep 22, 2010 1:17 pm
Posts: 327
Location: United Kingdom
In the previous item "Input & Output" you already saw an overview about the different possibilities to output text to the user, and in the item "Storing Data in Memory", we started to build a small application to display the properties of files in a particular folder to the debug window.

Now we're going to revisit this example to improve the data output section to resolve some issues with using the debug window. Firstly, this window is only available in the PureBasic IDE which means its only useful to programmers, secondly it doesn't really give us much control over how our output looks.

PureBasic provides a text mode window, or console window, which can be used in compiled programs. So let's update our example to use it instead.

First, we will need some extra working variables to make this work properly. Amend the variable definitions like this:-
Code:
...

; Now we define a list of files using the structure previously specified.
NewList FilesList.FILEITEM()
Define Access$, Attrib$, Create$, Folder$, Modify$, Message$, Num$, Size$
Define.I Result

...


Next, remove the output section of code completely, from the comment line:-

Code:
; If there are some entries in the list, show the results in the debug window.
...


Now replace this with:-

Code:

; Open a text mode screen to show the results.
OpenConsole()

; Display a title.
; PrintN displays the string given in the console window and moves the print position to the start of the next line afterwards.
; Space(n) returns n spaces in a string.
PrintN("File list of " + Folder$ + ".")
PrintN("-------------------------------------------------------------------------------")
Message$ = "Num Name"
PrintN(Message$)
Message$ = Space(4) + "Create" + Space(5) + "Access" + Space(5) + "Modify" + Space(5) + "Attrib Size"
PrintN(Message$)

; If there are some entries in the list, show the results in the console window.
If ListSize(FilesList())
 
  ; Loop through the linked list to display the results.
  ForEach FilesList()
   
    ; Tabulate the number of the list index.
    ; ListIndex() returns the current position in the list, counting from zero.
    ; StrU converts an unsigned number into a string.
    ; RSet pads a string to a set length with the necessary number of a specified character at the front.
    ; Here we use it to make sure all the index numbers are padded to 3 characters in length.
    Num$ = RSet(StrU(ListIndex(FilesList()) + 1), 3, " ")
   
    ; Display the item number and file name.
    Message$ = Num$ + " " + FilesList()\Name
    PrintN(Message$)
   
    ; These lines convert the three date values to something more familiar.
    Create$ = FormatDate("%dd/%mm/%yyyy", FilesList()\DateCreated)
    Access$ = FormatDate("%dd/%mm/%yyyy", FilesList()\DateAccessed)
    Modify$ = FormatDate("%dd/%mm/%yyyy", FilesList()\DateModified)
   
    ; Convert the file size to a padded string the same as with the index value above,
    ; but allow space for the maximum size of a quad.
    Size$ = RSet(StrU(FilesList()\Size), 19)
   
    ; Convert the attributes to a string, for now.
    Attrib$ = RSet(StrU(FilesList()\Attributes), 6, " ")
   
    ; Display the file's properties.
    Message$= Space(4) + Create$ + " " + Access$ + " " + Modify$ + " " + Attrib$ + " " + Size$
    PrintN(Message$)
   
    ; Display a blank line.
    PrintN("")
   
  Next FilesList()
 
EndIf

; Wait for the return key to be displayed, so the results can be viewed before the screen closes.
PrintN("")
PrintN("Press return to exit")
Input()


All being well the output should appear in a console window looking something like this:-

Code:
File list of C:\Documents and Settings\user\.
-------------------------------------------------------------------------------
Num Name
    Create     Access     Modify     Attrib Size
  1 NTUSER.DAT
    03/07/2008 04/04/2011 02/04/2011     34            18874368

  2 kunzip.dll
    14/07/2008 04/04/2011 14/07/2008     32               18432

  3 ntuser.dat.LOG
    03/07/2008 04/04/2011 04/04/2011     34                1024

  4 ntuser.ini
    03/07/2008 02/04/2011 02/04/2011      6                 278

Press return to exit


This output is from a Windows XP system, later versions of Windows and Linux or Mac OSX will show different files of course.


Last edited by spikey on Wed Aug 03, 2011 6:11 pm, edited 3 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Graphical User Interface item
PostPosted: Fri Apr 08, 2011 7:44 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Sep 22, 2010 1:17 pm
Posts: 327
Location: United Kingdom
In addition to the console window, PureBasic supports the creation of graphical user interfaces (GUI) too. So let's revisit the file properties example from previous items again and turn it into a GUI application.
Note that PureBasic provides a far easier way of getting this particular job done already - the ExplorerListGadget; but, as the example is intended to introduce managing GUI elements, using that gadget would defeat this object a bit.

Code:
; The structure for file information as before.
Structure FILEITEM
  Name.S
  Attributes.I
  Size.Q
  DateCreated.I
  DateAccessed.I
  DateModified.I
EndStructure

; This is a constant to identify the window.
Enumeration
  #wdwFiles
EndEnumeration

; This is an enumeration to identify controls which will appear on the window.
Enumeration
  #txtFolder
  #lsiFiles
EndEnumeration

; Now we define a list of files using the structure previously specified.
NewList lstFiles.FILEITEM()

; And some working variables to make things happen.
Define.S strAccess, strAttrib, strCreate, strFolder, strModify, strMsg, strNum, strSize
Define.L lngResult, lngFlags

; These variables will receive details of GUI events as they occur in the program.
Define.L Event, EventWindow, EventGadget, EventType, EventMenu

; This function gets the home directory for the logged on user.
strFolder = GetHomeDirectory()

; Open the directory to enumerate its contents.
lngResult = ExamineDirectory(0, strFolder, "*.*") 

; If this is ok, begin enumeration of entries.
If lngResult
 
  ; Loop through until NextDirectoryEntry(0) becomes zero - indicating that there are no more entries.
  While NextDirectoryEntry(0)
   
    ; If the directory entry is a file, not a folder.
    If DirectoryEntryType(0) = #PB_DirectoryEntry_File
     
      ; Add a new element to the linked list.
      AddElement(lstFiles())
     
      ; And populate it with the properties of the file.
      lstFiles()\Name = DirectoryEntryName(0)
      lstFiles()\Size = DirectoryEntrySize(0)
      lstFiles()\Attributes = DirectoryEntryAttributes(0)
      lstFiles()\DateCreated = DirectoryEntryDate(0, #PB_Date_Created)
      lstFiles()\DateAccessed = DirectoryEntryDate(0, #PB_Date_Accessed)
      lstFiles()\DateModified = DirectoryEntryDate(0, #PB_Date_Modified)

    EndIf
   
  Wend
 
  ; Close the directory.
  FinishDirectory(0)
 
EndIf

; Sort the list into ascending alphabetical order of file name.
SortStructuredList(lstFiles(), #PB_Sort_Ascending, OffsetOf(FILEITEM\Name), #PB_Sort_String)

; The interesting stuff starts to happen here...

; This line defines a flag for the window attributes by OR-ing together the desired attribute constants.
lngFlags = #PB_Window_SystemMenu |#PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget | #PB_Window_TitleBar

; Open a GUI window.
Openwindow(#wdwFiles, 50, 50, 400, 400, "File Properties", lngFlags)
; A text gadget to show the name of the folder.
TextGadget(#txtFolder, 5, 40, 390, 25, strFolder)
; A list icon gadget to hold the file list and properties.
ListIconGadget(#lsiFiles, 5, 70, 390, 326, "#", 30)
; Add columns to the ListIconGadget to hold each property.
AddGadgetColumn(#lsiFiles, 1, "Name", 200)
AddGadgetColumn(#lsiFiles, 2, "Created", 90)
AddGadgetColumn(#lsiFiles, 3, "Accessed", 90)
AddGadgetColumn(#lsiFiles, 4, "Modified", 90)
AddGadgetColumn(#lsiFiles, 5, "Attributes", 150)
AddGadgetColumn(#lsiFiles, 6, "Size", 150)

; Load the files into the list view.
ForEach lstFiles()

  ; Display the item number and file name.
  strNum = StrU(ListIndex(lstFiles()) + 1)
 
  ; These lines convert the three date values to something more familiar.
  strCreate = FormatDate("%dd/%mm/%yyyy", lstFiles()\DateCreated)
  strAccess = FormatDate("%dd/%mm/%yyyy", lstFiles()\DateAccessed)
  strModify = FormatDate("%dd/%mm/%yyyy", lstFiles()\DateModified)
 
  ; Convert the file size to a padded string the same as with the index value above,
  ; but allow space for the maximum size of a quad.
  strSize = StrU(lstFiles()\Size)
 
  ; Convert the attributes to a string, for now.
  strAttrib = StrU(lstFiles()\Attributes)
 
  ; Build a row string. 
  ; The Line Feed character 'Chr(10)' tells the gadget to move to the next column.
  strMsg = strNum + Chr(10) + lstFiles()\Name + Chr(10) + strCreate + Chr(10) + strAccess + Chr(10) + strModify + Chr(10) + strAttrib + Chr(10) + strSize
 
  ; Add the row to the list view gadget.
  AddGadgetItem(#lsiFiles, -1, strMsg)
 
Next lstFiles()

; This is the event loop for the window. 
; It will deal with all the user interaction events that we wish to use.

Repeat
  ; Wait until a new window or gadget event occurs.
  Event = WaitwindowEvent()
  ; In programs with more than one form, which window did the event occur on.
  EventWindow = EventWindow()
  ; Which gadget did the event occur on.
  EventGadget = EventGadget()
  ; What sort of event occurred.
  EventType = EventType()
 
  ; Take some action.
  Select Event
     
    Case #PB_Event_Gadget
      ; A gadget event occurred.
      If EventGadget = #txtFolder
      ElseIf EventGadget = #lsiFiles
      EndIf
     
    Case #PB_Event_Closewindow
      ; The window was closed.
      If EventWindow = #wdwFiles
        Closewindow(#wdwFiles)
        Break
      EndIf
     
  EndSelect
 
  ; Go round and do it again.
  ; In practice the loop isn't infinite because it can be stopped by clicking the window's Close button.
ForEver


At this point the application already has some useful features. However, it has some problems too:-
1) You can't choose a folder to show.
2) You can't update the list contents without closing and restarting the program.
3) If you resize the window, the gadgets don't resize with it.
4) The attributes column is still not very useful.
We will revisit this program again later on to fix all these issues.


Last edited by spikey on Fri Apr 08, 2011 9:13 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Constants item
PostPosted: Fri Apr 08, 2011 8:01 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Sep 22, 2010 1:17 pm
Posts: 327
Location: United Kingdom
In addition to variables PureBasic provides a method to define constants too. In fact it provides several. We’ll have a quick look at them now.

Predefined constants - provided either by PureBasic itself, these all begin #PB_, or from the API for the operating system. The IDE’s "Structure Viewer" tool has a panel which shows all the predefined constants.

User defined constants - by defining a constant name with the prefix # you can provide your own constants to make code more readable.
Code:
#MyConstant1 = 10
#MyConstant2 = “Hello, World!”

Enumerations – PureBasic will automatically number a series of constants sequentially in an Enumeration, by default enumerations will begin from zero – but this can be altered, if desired.

Code:
Enumeration
  #MyConstantA
  #MyConstantB
  #MyConstantC
EndEnumeration

Enumeration 10 Step 5
  #MyConstantD ; will be 10
  #MyConstantE ; will be 15
  #MyConstantF ; will be 20
EndEnumeration


Last edited by spikey on Wed Apr 13, 2011 1:40 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: PureBasic Docs- Ideas/Help needed for a "We start" chapt
PostPosted: Sun Apr 10, 2011 7:02 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 6:14 pm
Posts: 1825
Location: Germany (Saxony, Deutscheinsiedel)
I've added further contributions by spikey to the first post.

I've sorted them into the existing topic structure, also 2 new topics (Constants & Building a GUI) I've added.


@spikey: Feel free to tell me, if anything is placed at the false position! Thank you very much! :D

_________________
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)


Top
 Profile  
Reply with quote  
 Post subject: Re: PureBasic Docs- Ideas/Help needed for a "We start" chapt
PostPosted: Tue Apr 12, 2011 10:06 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Mon Mar 06, 2006 3:53 pm
Posts: 562
Location: Austria
@Andre:
Feel free to copy parts from here, if you want (Tutorial is in German language). It was aimed at absolute beginners, is a little longer than just one page, but it tries build upon the previous chapter.
http://purebook.purebasic-lounge.com/in ... ic.Vorwort
It's been edited and altered over the past years, but I guess I still have the original version as ODF on my disk.

Maybe we need a little "Head First - Programming PureBasic"?

_________________
cheers,

bembulak


Top
 Profile  
Reply with quote  
 Post subject: Displaying graphics output & simple drawing item
PostPosted: Wed Apr 13, 2011 1:37 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Sep 22, 2010 1:17 pm
Posts: 327
Location: United Kingdom
This example show how to create a simple drawing. It uses the 2D drawing commands to draw two sine waves at different frequencies and shows the harmonic produced by combining the two waves. It uses procedures, which we will discuss in more detail later on, to break the drawing tasks into three self-contained tasks.
Drawing the axes - demonstrates the Line command.
Drawing the legend - demonstrates the Box and DrawText commands.
Drawing the wave forms - demonstrates the LineXY command and shows how to use color.

Code:
; Form.
Enumeration
  #wdwHarmonic
EndEnumeration

; Gadgets.
Enumeration
  #txtPlot1
  #cboPlot1
  #txtPlot2
  #cboPlot2
  #imgPlot
EndEnumeration

; Image.
Enumeration
  #drgPlot
EndEnumeration

; Event variables.
Define.L Event, EventWindow, EventGadget, EventType, EventMenu

; Implementation.
Procedure CreateWindow()
  ; Creates the window and gadgets. 

  If OpenWindow(#wdwHarmonic, 450, 200, 650, 680, "Harmonics", #PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_TitleBar)
   
    ; This is a non-visual gadget used to draw the image, later its contents will be displayed in #imgPlot.
    CreateImage(#drgPlot, 640, 640, 24)
   
    ; Label for the Plot 1 combo.
    TextGadget(#txtPlot1, 2, 5, 40, 20, "Plot 1:")
   
    ; The Plot 1 combo.
    ComboBoxGadget(#cboPlot1, 45, 5, 150, 20)
    AddGadgetItem(#cboPlot1, 0, "Sin(X)")
    AddGadgetItem(#cboPlot1, 1, "Sin(X * 2)")
    AddGadgetItem(#cboPlot1, 2, "Sin(X * 3)")
    AddGadgetItem(#cboPlot1, 3, "Sin(X * 4)")
    AddGadgetItem(#cboPlot1, 4, "Sin(X * 5)")
    AddGadgetItem(#cboPlot1, 5, "Sin(X * 6)")
   
    ; Select Sin(X)
    SetGadgetState(#cboPlot1, 0)
   
    ; Label for the Plot 1 combo.
    TextGadget(#txtPlot2, 210, 5, 40, 20, "Plot 2:")
   
    ; The Plot 1 combo.
    ComboBoxGadget(#cboPlot2, 255, 5, 150, 20)
    AddGadgetItem(#cboPlot2, 0, "Sin(X)")
    AddGadgetItem(#cboPlot2, 1, "Sin(X * 2)")
    AddGadgetItem(#cboPlot2, 2, "Sin(X * 3)")
    AddGadgetItem(#cboPlot2, 3, "Sin(X * 4)")
    AddGadgetItem(#cboPlot2, 4, "Sin(X * 5)")
    AddGadgetItem(#cboPlot2, 5, "Sin(X * 6)")
   
    ; Select Sin(X * 2), otherwise the initial display is a bit uninteresting.
    SetGadgetState(#cboPlot2, 1)
   
    ; The visual image gadget on the window.
    ImageGadget(#imgPlot, 2, 30, 646, 616, 0, #PB_Image_Border)
   
  EndIf
 
EndProcedure

Procedure PlotAxes()
  ; Draws the axes on the image #drgPlot.

  ; Send drawing commands to #drgPlot.
  StartDrawing(ImageOutput(#drgPlot))
 
  ; Draw a white background.
  Box(0, 0, ImageWidth(#drgPlot), ImageHeight(#drgPlot), #White)
 
  ; Draw the axes in black.
  Line(1, 1, 1, ImageHeight(#drgPlot) - 2, #Black)
  Line(1, (ImageHeight(#drgPlot) - 2) /2, ImageWidth(#drgPlot) -2, 1, #Black)
 
  ; Finished drawing.
  StopDrawing()
 
EndProcedure

Procedure PlotLegend(alngPlot1, alngPlot2)
  ; Draws the legend on the image #drgPlot.
 
  Protected.S strFunc1, strFunc2, strLabel1, strLabel2, strLabel3
 
  ; Set label text 1.
  If alngPlot1 = 0
    strFunc1 = "Sin(X)"
   
  Else
    strFunc1 = "Sin(X * " + StrU(alngPlot1 + 1) + ")"
   
  EndIf
 
  ; Set label text 2.
  If alngPlot2 = 0
    strFunc2 = "Sin(X)"
   
  Else
    strFunc2 = "Sin(X * " + StrU(alngPlot2 + 1) + ")"
   
  EndIf
 
  ; Set label text.
  strLabel1 = "Y = " + strFunc1
  strLabel2 = "Y = " + strFunc2
  strLabel3 = "Y = " + strFunc1 + " + " + strFunc2
 
  ; Draw legend.
  StartDrawing(ImageOutput(#drgPlot))
 
  ; Box.
  DrawingMode(#PB_2DDrawing_Outlined)
  Box(20, 10, TextWidth(strLabel3) + 85, 80, #Black)
 
  ; Label 1.
  Line(30, 30, 50, 1, #Blue)
  DrawText(95, 22, strLabel1, #Black, #White)
 
  ; Label 2.
  Line(30, 50, 50, 1, #Green)
  DrawText(95, 42, strLabel2, #Black, #White)
 
  ; Label 3.
  Line(30, 70, 50, 1, #Red)
  DrawText(95, 62, strLabel3, #Black, #White)
 
  StopDrawing()
 
EndProcedure

Procedure PlotFunction(alngPlot1, alngPlot2)
  ; Draws the waveforms on the image #drgPlot.

  Protected.L lngSX, lngEX
  Protected.F fltRad1, fltRad2, fltSY1, fltEY1, fltSY2, fltEY2, fltSY3, fltEY3
 
  StartDrawing(ImageOutput(#drgPlot))
 
  ; Set initial start points for each wave.
  lngSX = 1
  fltSY1 = ImageHeight(#drgPlot) / 2
  fltSY2 = fltSY1
  fltSY3 = fltSY1
 
  ; Plot wave forms.
  For lngEX = 1 To 720
   
    ; Sine function works in radians, so convert from degrees and calculate sine.
   
    ; Function 1
    If alngPlot1 = 0
      fltRad1 = Sin(Radian(lngEX))
     
    Else
      ; If the function should have a multiplier, account for this.
      fltRad1 = Sin(Radian(lngEX) * (alngPlot1 + 1))
     
    EndIf
   
    ; Function 2
    If alngPlot2 = 0
      fltRad2 = Sin(Radian(lngEX))
     
    Else
      fltRad2 = Sin(Radian(lngEX) * (alngPlot2 + 1))
     
    EndIf
   
    ; Plot function 1 in blue.
    ; Calculate end Y point.
    fltEY1 = (ImageHeight(#drgPlot) / 2) + (fltRad1 * 100)
    ; Draw a line from the start point to the end point.
    LineXY(lngSX, fltSY1, lngEX, fltEY1, #Blue)
    ; Update the next start Y point to be the current end Y point.
    fltSY1 = fltEY1
   
    ; Plot function 2 in green.
    fltEY2 = (ImageHeight(#drgPlot) / 2) + (fltRad2 * 100)
    LineXY(lngSX, fltSY2, lngEX, fltEY2, #Green)
    fltSY2 = fltEY2
   
    ; Plot harmonic in red.
    fltEY3 = (ImageHeight(#drgPlot) / 2) + ((fltRad1 + fltRad2) * 100)
    LineXY(lngSX, fltSY3, lngEX, fltEY3, #Red)
    fltSY3 = fltEY3
   
    ; Update the start X point to be the current end X point.
    lngSX = lngEX
   
  Next lngEX
 
  StopDrawing()
 
EndProcedure

;- Main
CreateWindow()
PlotAxes()
PlotLegend(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))
PlotFunction(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))

; Reload the image gadget now drawing is complete.
ImageGadget(#imgPlot, 2, 30, 646, 616, ImageID(#drgPlot), #PB_Image_Border)

;- Event loop
Repeat
 
  Event = WaitWindowEvent()
  EventWindow = EventWindow()
  EventGadget = EventGadget()
  EventType = EventType()
 
  Select Event
     
    Case #PB_Event_Gadget
      If EventGadget = #txtPlot1 Or EventGadget = #txtPlot2
        ; Do nothing.
       
      ElseIf EventGadget = #imgPlot
        ; Do nothing.
       
      ElseIf EventGadget = #cboPlot1 Or EventGadget = #cboPlot2
        ; If one of the combo boxes changed, redraw the image.
        PlotAxes()
        PlotLegend(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))
        PlotFunction(GetGadgetState(#cboPlot1), GetGadgetState(#cboPlot2))
        ImageGadget(#imgPlot, 2, 30, 646, 616, ImageID(#drgPlot), #PB_Image_Border)
       
      EndIf
     
    Case #PB_Event_CloseWindow
      If EventWindow = #wdwHarmonic
        CloseWindow(#wdwHarmonic)
        Break
      EndIf
     
  EndSelect
 
ForEver


Last edited by spikey on Wed Apr 13, 2011 7:01 pm, edited 2 times in total.

Top
 Profile  
Reply with quote  
 Post subject: Re: PureBasic Docs- Ideas/Help needed for a "We start" chapt
PostPosted: Wed Apr 13, 2011 1:44 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Sep 22, 2010 1:17 pm
Posts: 327
Location: United Kingdom
@Andre:
That location is fine - while writing the GUI item it occurred to me that I shouldn't start using Enumerations without introducing them properly first.

However I see that I made a couple of mistakes in that example, it won't compile as it stands! :oops: I've corrected my post now.


Top
 Profile  
Reply with quote  
 Post subject: Procedures item
PostPosted: Wed Apr 13, 2011 7:42 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Sep 22, 2010 1:17 pm
Posts: 327
Location: United Kingdom
We're going to revisit the file properties example again. This time to introduce procedures and to address some of the limitations identified in the program in previous items.

Code:
; The structure for file information as before.
Structure FILEITEM
  Name.S
  Attributes.I
  Size.Q
  DateCreated.I
  DateAccessed.I
  DateModified.I
EndStructure

; This is a constant to identify the window.
Enumeration
  #wdwFiles
EndEnumeration

; This is an enumeration to identify controls that will appear on the window.
Enumeration
  #btnFolder
  #btnUpdate
  #txtFolder
  #lsiFiles
EndEnumeration

Procedure FilesExamine(astrFolder.S, List alstFiles.FILEITEM())
  ; Obtains file properties from strFolder into lstFiles.
 
  Protected.L lngResult
 
  ; Clear current contents.
  ClearList(alstFiles())
 
  ; Open the directory to enumerate its contents.
  lngResult = ExamineDirectory(0, astrFolder, "*.*") 
 
  ; If this is ok, begin enumeration of entries.
  If lngResult
   
    ; Loop through until NextDirectoryEntry(0) becomes zero - indicating that there are no more entries.
    While NextDirectoryEntry(0)
     
      ; If the directory entry is a file, not a folder.
      If DirectoryEntryType(0) = #PB_DirectoryEntry_File
       
        ; Add a new element to the linked list.
        AddElement(alstFiles())
       
        ; And populate it with the properties of the file.
        alstFiles()\Name = DirectoryEntryName(0)
        alstFiles()\Size = DirectoryEntrySize(0)
        alstFiles()\Attributes = DirectoryEntryAttributes(0)
        alstFiles()\DateCreated = DirectoryEntryDate(0, #PB_Date_Created)
        alstFiles()\DateAccessed = DirectoryEntryDate(0, #PB_Date_Accessed)
        alstFiles()\DateModified = DirectoryEntryDate(0, #PB_Date_Modified)
       
      EndIf
     
    Wend
   
    ; Close the directory.
    FinishDirectory(0)
   
  EndIf
 
  ; Sort the list into ascending alphabetical order of file name.
  SortStructuredList(alstFiles(), #PB_Sort_Ascending, OffsetOf(FILEITEM\Name), #PB_Sort_String)
 
EndProcedure

Procedure.S FolderSelect(astrFolder.S)
  ; Displays a path requester and returns the new path, or the old one if the requester is cancelled.
 
  Protected.S strSelect
 
  strSelect = PathRequester("Choose a folder.", astrFolder)
 
  If strSelect = ""
    strSelect = astrFolder
  EndIf
 
  ProcedureReturn strSelect
 
EndProcedure

Procedure LabelUpdate(astrFolder.S)
  ; Updates the folder label.
 
  SetGadgetText(#txtFolder, astrFolder)
 
EndProcedure

Procedure ListLoad(alngListView.L, List alstFiles.FILEITEM())
  ; Load the files properties from lstFiles into the list view lngListView.
 
  Protected.S strAccess, strAttrib, strCreate, strFolder, strModify, strMsg, strNum, strSize
 
  ; Remove previous contents.
  ClearGadgetItems(alngListView)
 
  ForEach alstFiles()
   
    ; Display the item number and file name.
    strNum = StrU(ListIndex(alstFiles()) + 1)
   
    ; These lines convert the three date values to something more familiar.
    strCreate = FormatDate("%dd/%mm/%yyyy", alstFiles()\DateCreated)
    strAccess = FormatDate("%dd/%mm/%yyyy", alstFiles()\DateAccessed)
    strModify = FormatDate("%dd/%mm/%yyyy", alstFiles()\DateModified)
   
    ; Convert the file size to a padded string the same as with the index value above,
    ; but allow space for the maximum size of a quad.
    strSize = StrU(alstFiles()\Size)
   
    ; Convert the attributes to a string, for now.
    strAttrib = StrU(alstFiles()\Attributes)
   
    ; Build a row string. 
    ; The Line Feed character 'Chr(10)' tells the gadget to move to the next column.
    strMsg = strNum + Chr(10) + alstFiles()\Name + Chr(10) + strCreate + Chr(10) + strAccess + Chr(10) + strModify + Chr(10) + strAttrib + Chr(10) + strSize
   
    ; Add the row to the list view gadget.
    AddGadgetItem(#lsiFiles, -1, strMsg)
   
  Next alstFiles()
 
EndProcedure

Procedure WindowCreate()
  ; Creates the wdwFiles window.
 
  Protected.L lngFlags
 
  ; This line defines a flag for the window attributes by OR-ing together the desired attribute constants.
  lngFlags = #PB_Window_SystemMenu |#PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget| #PB_Window_TitleBar
 
  ; Open a window.
  OpenWindow(#wdwFiles, 50, 50, 400, 400, "File Properties", lngFlags)
  ; A button to choose a folder.
  ButtonGadget(#btnFolder, 5, 5, 100, 30, "Select Folder")
  ; A button to update the list.
  ButtonGadget(#btnUpdate, 105, 5, 100, 30, "Update List")
  ; A text gadget to show the name of the folder.
  TextGadget(#txtFolder, 5, 40, 390, 25, "")
  ; A list icon gadget to hold the file list and properties.
  ListIconGadget(#lsiFiles, 5, 70, 390, 326, "#", 30)
  ; Add columns to the ListIconGadget to hold each property.
  AddGadgetColumn(#lsiFiles, 1, "Name", 200)
  AddGadgetColumn(#lsiFiles, 2, "Created", 90)
  AddGadgetColumn(#lsiFiles, 3, "Accessed", 90)
  AddGadgetColumn(#lsiFiles, 4, "Modified", 90)
  AddGadgetColumn(#lsiFiles, 5, "Attributes", 150)
  AddGadgetColumn(#lsiFiles, 6, "Size", 150)
 
EndProcedure

Procedure WindowDestroy()
  ; Closes the window.
  ; If necessary, you could do other tidying up jobs here too.
 
  CloseWindow(#wdwFiles)
 
EndProcedure

Procedure WindowResize()
  ; Resizes window gadgets to match the window size.
 
  ResizeGadget(#txtFolder, #PB_Ignore, #PB_Ignore, WindowWidth(#wdwFiles) - 10, #PB_Ignore)
  ResizeGadget(#lsiFiles, #PB_Ignore, #PB_Ignore, WindowWidth(#wdwFiles) - 10, WindowHeight(#wdwFiles) - 74)
 
EndProcedure

;- Main
; Now we define a list of files using the structure previously specified.
NewList lstFiles.FILEITEM()

; And some working variables to make things happen.
Define.S strFolder
Define.L Event, EventWindow, EventGadget, EventType, EventMenu

; This function gets the home directory for the logged on user.
strFolder = GetHomeDirectory()

; Create the window and set the initial contents.
WindowCreate()
WindowResize()
LabelUpdate(strFolder)
FilesExamine(strFolder, lstFiles())
ListLoad(#lsiFiles, lstFiles())

;- Event Loop
Repeat
 
  ; Wait until a new window or gadget event occurs.
  Event = WaitWindowEvent()
  EventWindow = EventWindow()
  EventGadget = EventGadget()
  EventType = EventType()
 
  ; Take some action.
  Select Event
     
    Case #PB_Event_Gadget
      ; A gadget event occurred.
      If EventGadget = #btnFolder
        ; The folder button was clicked.
        strFolder = FolderSelect(strFolder)
        LabelUpdate(strFolder)
        FilesExamine(strFolder, lstFiles())
        ListLoad(#lsiFiles, lstFiles())
       
      ElseIf EventGadget = #btnUpdate
        ; The update button was clicked.
        FilesExamine(strFolder, lstFiles())
        ListLoad(#lsiFiles, lstFiles())
       
      ElseIf EventGadget = #txtFolder
        ; Do nothing here.
       
      ElseIf EventGadget = #lsiFiles
        ; Do nothing here.
       
      EndIf
     
    Case #PB_Event_SizeWindow
      ; The window was moved or resized.
      If EventWindow = #wdwFiles
        WindowResize() 
      EndIf
     
    Case #PB_Event_CloseWindow
      ; The window was closed.
      If EventWindow = #wdwFiles
        WindowDestroy()
        Break
       
      EndIf
     
  EndSelect
 
ForEver


Previously, we mentioned four limitations to this program. This new version uses procedures to address three of them.

1) You couldn't choose a folder to show.
The "FolderSelect" procedure shows a path requester to allow the user to select a folder. The variable "strFolder" is updated with the result of this procedure. The button also calls "LabelUpdate", "FilesExamine" and "ListLoad" to display the contents of the new folder in the window.

2) You can't update the list contents without closing and restarting the program.
Now, when the "Update List" button is clicked, "FilesExamine" and "ListLoad" are called again to update the display.

3) If you resize the window, the gadgets don't resize with it.
The "WindowResize" procedure is called in the event loop to resize the gadgets when the form is resized. Also, although this program didn't really need to, but this procedure is called after calling "WindowCreate" to make sure the gadgets are the right size initially.

Notice how several of the procedures are called more than once to perform similar but not identical functions. This improves the efficiency of the program.

We have one final limitation to overcome in a later item.


Top
 Profile  
Reply with quote  
 Post subject: Re: PureBasic Docs- Ideas/Help needed for a "We start" chapt
PostPosted: Wed Apr 13, 2011 8:25 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 6:14 pm
Posts: 1825
Location: Germany (Saxony, Deutscheinsiedel)
spikey wrote:
@Andre:
That location is fine - while writing the GUI item it occurred to me that I shouldn't start using Enumerations without introducing them properly first.

However I see that I made a couple of mistakes in that example, it won't compile as it stands! :oops: I've corrected my post now.


Thank you very much for your work, again! :D

According to your latest contributions I've updated the 'Constants' topic, and have added the content for the 'Structuring code in procedures' and 'Simple 2D Drawing...' topics.


@bembulak: thanks for your offer! Similar to the offer of bluenzl we come back to it later, if it's still needed after adding the current contributions. :)

_________________
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)


Top
 Profile  
Reply with quote  
 Post subject: Compiler Directives item
PostPosted: Thu Apr 14, 2011 8:01 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Sep 22, 2010 1:17 pm
Posts: 327
Location: United Kingdom
This will be our last visit to the File Properties program. There is one limitation discussed previously to overcome and we've left it until now because it is a special case.

So far the Attributes column on the display has simply been an integer. This is because the return values of the GetFileAttributes and DirectoryEntryAttributes instructions have a different meaning on Windows systems compared with Mac and Linux systems.

We can't allow for this difference at run-time, however we can use Compiler Directives to have the program behave differently on the three different operating systems.

Add this new procedure declaration to that section.
Code:
Declare.S AttributeString(alngAttributes.L)


Add this new procedure to the implementation section.
Code:
Procedure.S AttributeString(alngAttributes.L)
  ; Converts an integer attributes value into a string description.
  ; Supports Linux, Mac and Windows system's attributes.
 
  Protected.S strResult
 
  strResult = ""
 
  CompilerIf #PB_Compiler_OS = #PB_OS_Windows
   
    ; These are the attributes for Windows systems.
    ; A logical-and of the attribute with each constant filters out that bit and can then be used for comparison.

    If alngAttributes & #PB_FileSystem_Archive
      strResult + "A"
    Else
      strResult + " "
    EndIf
   
    If alngAttributes & #PB_FileSystem_Compressed
      strResult + "C"
    Else
      strResult + " "
    EndIf
   
    If alngAttributes & #PB_FileSystem_Hidden
      strResult + "H"
    Else
      strResult + " "
    EndIf
   
    If alngAttributes & #PB_FileSystem_ReadOnly
      strResult + "R"
    Else
      strResult + " "
    EndIf
   
    If alngAttributes & #PB_FileSystem_System
      strResult + "S"
    Else
      strResult + " "
    EndIf
   
  CompilerElse
   
    ; These are the attributes for Mac and Linux systems.
   
    If alngAttributes & #PB_FileSystem_Link
      strResult + "L "
    Else
      strResult + "  "
    EndIf
   
    ; User attributes.
    If alngAttributes & #PB_FileSystem_ReadUser
      strResult + "R"
    Else
      strResult + " "
    EndIf
   
    If alngAttributes & #PB_FileSystem_WriteUser
      strResult + "W"
    Else
      strResult + " "
    EndIf
   
    If alngAttributes & #PB_FileSystem_ExecUser
      strResult + "X "
    Else
      strResult + "  "
    EndIf
   
    ; Group attributes.
    If alngAttributes & #PB_FileSystem_ReadGroup
      strResult + "R"
    Else
      strResult + " "
    EndIf
   
    If alngAttributes & #PB_FileSystem_WriteGroup
      strResult + "W"
    Else
      strResult + " "
    EndIf
   
    If alngAttributes & #PB_FileSystem_ExecGroup
      strResult + "X "
    Else
      strResult + "  "
    EndIf
   
    ; All attributes.
    If alngAttributes & #PB_FileSystem_ReadAll
      strResult + "R"
    Else
      strResult + " "
    EndIf
   
    If alngAttributes & #PB_FileSystem_WriteAll
      strResult + "W"
    Else
      strResult + " "
    EndIf
   
    If alngAttributes & #PB_FileSystem_ExecAll
      strResult + "X"
    Else
      strResult + " "
    EndIf
   
  CompilerEndIf
 
  ; Return the result.
  ProcedureReturn strResult
 
EndProcedure


Finally, replace these two lines in the ListLoad procedure
Code:
    ; Convert the attributes to a string, for now.
    strAttrib = StrU(alstFiles()\Attributes)

with these,
Code:
    ; Call AttributeString to convert the attributes to a string representation.
    strAttrib = AttributeString(alstFiles()\Attributes)


Now when the program is executed a string display will be shown instead of the integer values.
On a Windows system it would look something like this (assuming all attributes are set):
Code:
ACHRS

and on the other two systems:
Code:
L RWX RWX RWX


The "CompilerIf" instruction works much like an "If" instruction - however it is the compiler that makes the decision at compile-time, rather than the executable at run-time. This means that we can include different code to handle the file attributes on the different operating systems.

The lines between:
Code:
CompilerIf #PB_Compiler_OS = #PB_OS_Windows

and
Code:
CompilerElse

will be compiled on Windows systems. The constant #PB_Compiler_OS is automatically defined by PureBasic to allow this kind of program logic.

The other section will be used on Mac and Linux systems - which work the same way, conveniently. If these operating systems had different attribute values too, then we could use "CompilerSelect" and "CompilerCase" to make a three-way determination.

Code:
CompilerSelect #PB_Compiler_OS
   
  CompilerCase #PB_OS_Linux
    ; Code for Linux systems.
   
  CompilerCase #PB_OS_MacOS
    ; Code for Mac systems.
   
  CompilerCase #PB_OS_Windows
    ; Code for Windows systems.
   
CompilerEndSelect


The last compiler directive that we're going to discuss here is:
Code:
EnableExplicit.


There is a good reason for using this directive. It requires that all variables must be defined explicitly before usage, in some way, (using Define, Dim, Global, Protected, Static etc.) Doing so eliminates the possibility of logic errors due to mistyped variable names being defined "on-the-fly". This type of subtle error will not affect a program's compilation but could well present as an inconvenient bug at run-time. Using this directive eliminates this kind of problem as a compiler error would occur.

For example:
Code:
EnableExplicit

Define.L lngField, lngFieldMax

; ...

If lngField < lngFeildMax
  ; If EnableExplicit is omitted this section of code may not execute when intended because lngFeildMax will be zero.
EndIf


Top
 Profile  
Reply with quote  
 Post subject: Re: PureBasic Docs- Ideas/Help needed for a "We start" chapt
PostPosted: Fri Apr 15, 2011 4:52 pm 
Offline
PureBasic Team
PureBasic Team
User avatar

Joined: Fri Apr 25, 2003 6:14 pm
Posts: 1825
Location: Germany (Saxony, Deutscheinsiedel)
@spikey: thanks, I've added your latest contribution as (new) "Compiler directives..." topic!

_________________
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)


Top
 Profile  
Reply with quote  
 Post subject: Re: PureBasic Docs- Ideas/Help needed for a "We start" chapt
PostPosted: Sat Apr 16, 2011 3:15 pm 
Offline
Always Here
Always Here

Joined: Fri Oct 23, 2009 2:33 am
Posts: 6176
Location: Wales, UK
I think the following snippet by nco2k on how to use CatchImage() belongs in the help. Though we might say it's using advanced methods, image handling is fundamental in all types of apps, something you do need to know how to handle early on:

Code:
#Win    = 1
#imGadg = 2
#Image  = 3

If OpenWindow(#Win, 0, 0, 256, 256, "Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

         If CatchImage(#Image, ?Image_Start, ?Image_End - ?Image_Start)

                  ImageGadget(#imGadg, 0, 0, ImageWidth(#Image), ImageHeight(#Image), ImageID(#Image))

                  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow

         EndIf

EndIf

DataSection
  Image_Start:
    IncludeBinary #PB_Compiler_Home + "Examples\Sources\Data\Background.bmp"
  Image_End:
EndDataSection

_________________
IdeasVacuum
If it sounds simple, you have not grasped the complexity.


Top
 Profile  
Reply with quote  
 Post subject: Re: PureBasic Docs- Ideas/Help needed for a "We start" chapt
PostPosted: Sat Apr 16, 2011 7:29 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Wed Sep 22, 2010 1:17 pm
Posts: 327
Location: United Kingdom
@Andre:
Oh OK. I was assuming that's what you meant when you put "Compiler commands" in your proposed table of contents! What did you have in mind then?


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 120 posts ]  Go to page Previous  1, 2, 3, 4, 5 ... 8  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye