Pascal for Visual Basic users: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: Pascal for Visual Basic users
| Old | New | Line | |
|---|---|---|---|
| 1 | + | ## Overview | |
| 2 | + | ||
| 3 | + | This wiki page has been created to help you if you are switching from Visual Basic to Free Pascal (the Pascal dialect and compiler used by Lazarus). It is not meant to convince you that Lazarus is better than VB (or vice versa). Although VB and Pascal have superficial similarities these two languages differ greatly. Since VB programmers beginning to use Pascal face immediate difficulties in trying to do things which in VB have nice syntax that Pascal does not provide, we focus here on those differences. | |
| 4 | + | ||
| 5 | + | ## Comparison and assignment of values | |
| 6 | + | ||
| 7 | + | Values in Pascal are compared using the = operator. | |
| 8 | + | ||
| 9 | + | Values in Pascal are assigned using the := operator (there is a : added). | |
| 10 | + | ||
| 11 | + | For example: | |
| 12 | + | ||
| 13 | + | ``` pascal | |
| 14 | + | if a = 1 then b := 2; | |
| 15 | + | ``` | |
| 16 | + | ||
| 17 | + | ## Beginning and ending statements | |
| 18 | + | ||
| 19 | + | Blocks of Pascal code have no distinguishing end statements for functions, procedures, loops, etc. Pascal needs only **begin** and **end**. You can easily add a comment manually following **end** statements to clarify which named routine corresponds to this particular **end;**. | |
| 20 | + | ||
| 21 | + | For example: | |
| 22 | + | ||
| 23 | + | ``` pascal | |
| 24 | + | for i := 0 to 100 do | |
| 25 | + | begin | |
| 26 | + | ... | |
| 27 | + | end; // for i do | |
| 28 | + | ``` | |
| 29 | + | ||
| 30 | + | ## Variables | |
| 31 | + | ||
| 32 | + | ### Declaring variables | |
| 33 | + | ||
| 34 | + | In Pascal **all** variables have to be declared before use, and you have to make the declarations in a special **var** section which must precede the code that makes use of the variable. You cannot declare a new variable in the middle of code. | |
| 35 | + | ||
| 36 | + | For example: | |
| 37 | + | ||
| 38 | + | ``` pascal | |
| 39 | + | procedure VarDecl; | |
| 40 | + | var | |
| 41 | + | MyVar1: string; | |
| 42 | + | Myvar2, MyVar3: integer; //Multiple variables can be declared on the same line. | |
| 43 | + | begin | |
| 44 | + | WriteLn('Print something'); | |
| 45 | + | var MyVar4: string = 'else'; // This declaration is not allowed here - it must be moved three lines above to the var section | |
| 46 | + | WriteLn('Print something ', MyVar2); | |
| 47 | + | end; //VarDecl | |
| 48 | + | ``` | |
| 49 | + | ||
| 50 | + | Local variables do not get initialized upon declaration. They get random value (whatever value happen to be on the stack where they landed). Global variables are initialized to zero. | |
| 51 | + | ||
| 52 | + | To initialize a local variable upon declaration the following syntax can be used in procedures and functions only. | |
| 53 | + | ||
| 54 | + | ``` pascal | |
| 55 | + | var | |
| 56 | + | MyVar1: string = ''; | |
| 57 | + | MyVar2: integer = 0; | |
| 58 | + | ``` | |
| 59 | + | ||
| 60 | + | ### Types of variables | |
| 61 | + | ||
| 62 | + | Besides the variables known in VB, Free Pascal supports unsigned integers. You should pay special attention not to mix them with signed integers. | |
| 63 | + | ||
| 64 | + | ## Loops | |
| 65 | + | ||
| 66 | + | Free Pascal has four kinds of loops. | |
| 67 | + | ||
| 68 | + | [[Basic Pascal Tutorial/Chapter 3/FOR..DO|for... do...]] | |
| 69 | + | ||
| 70 | + | [[Basic Pascal Tutorial/Chapter 3/WHILE..DO|while... do]] | |
| 71 | + | ||
| 72 | + | [[Until|repeat... until]] | |
| 73 | + | ||
| 74 | + | [[for-in loop|for.. in..]] | |
| 75 | + | ||
| 76 | + | **Note:** In FPC there is the [[Continue]] procedure to jump to the end of the loop. | |
| 77 | + | ||
| 78 | + | ### For... do... | |
| 79 | + | ||
| 80 | + | This is quite similar to the For.. Next loop in VB, but more limited in syntax. The following restrictions apply in Pascal: | |
| 81 | + | ||
| 82 | + | 1\. A for loop counter must be an integer (it cannot be a floating point type). | |
| 83 | + | ||
| 84 | + | 2\. There is no Step property. To emulate the VB Step syntax you have to introduce a second counter variable yourself. | |
| 85 | + | ||
| 86 | + | 3\. To decrement the value of the loop counter from a positive value, you use the keyword DOWNTO in place of TO. | |
| 87 | + | ||
| 88 | + | For example: | |
| 89 | + | ||
| 90 | + | ``` pascal | |
| 91 | + | procedure ForLoop; | |
| 92 | + | var | |
| 93 | + | i: integer; | |
| 94 | + | begin | |
| 95 | + | for i := 50 downto 0 do | |
| 96 | + | begin | |
| 97 | + | ... | |
| 98 | + | end; // for i | |
| 99 | + | end. // procedure ForLoop | |
| 100 | + | ``` | |
| 101 | + | ||
| 102 | + | 4\. In Lazarus it is possible to loop down when the index is a **byte**, which is **not** possible in VB6. | |
| 103 | + | ||
| 104 | + | ``` pascal | |
| 105 | + | procedure ForLoop; | |
| 106 | + | var | |
| 107 | + | i: byte; | |
| 108 | + | begin | |
| 109 | + | for i := 200 downto 195 do | |
| 110 | + | begin | |
| 111 | + | ShowMessage (IntToStr (i)); | |
| 112 | + | end; | |
| 113 | + | end; | |
| 114 | + | ``` | |
| 115 | + | ||
| 116 | + | 5\. The value of the counter (i in the example above) can**not** be changed programmatically inside the loop. Attempting to do so will throw a compiler error. Instead one could use *Continue* to skip execution of a loop: | |
| 117 | + | ||
| 118 | + | ``` pascal | |
| 119 | + | procedure ForLoop; | |
| 120 | + | var | |
| 121 | + | i: integer; | |
| 122 | + | begin | |
| 123 | + | for i := 0 to 5 do | |
| 124 | + | begin | |
| 125 | + | if i=2 then Continue; //Following part of the loop will not be executed | |
| 126 | + | ShowMessage (IntToStr (i)); | |
| 127 | + | end; // for i | |
| 128 | + | end. // procedure ForLoop | |
| 129 | + | ``` | |
| 130 | + | ||
| 131 | + | 6\. In order to interrupt execution of a loop one could use *Break*. | |
| 132 | + | ||
| 133 | + | ``` pascal | |
| 134 | + | procedure ForLoop; | |
| 135 | + | var | |
| 136 | + | i: integer; | |
| 137 | + | begin | |
| 138 | + | for i := 0 to 5 do | |
| 139 | + | begin | |
| 140 | + | if i=2 then | |
| 141 | + | begin | |
| 142 | + | ShowMessage (IntToStr (i)); | |
| 143 | + | break; | |
| 144 | + | end; //if | |
| 145 | + | end; // for i | |
| 146 | + | end. // procedure ForLoop | |
| 147 | + | ``` | |
| 148 | + | ||
| 149 | + | ## Functions and procedures | |
| 150 | + | ||
| 151 | + | Output of functions is supplied as: | |
| 152 | + | ||
| 153 | + | ``` pascal | |
| 154 | + | Result:=Value | |
| 155 | + | ``` | |
| 156 | + | ||
| 157 | + | Note that *Result:=* does **not** act as *Return*. Function will **not** exit after assigning it. | |
| 158 | + | ||
| 159 | + | One should use | |
| 160 | + | ||
| 161 | + | ``` pascal | |
| 162 | + | exit(Value) | |
| 163 | + | ``` | |
| 164 | + | ||
| 165 | + | instead. | |
| 166 | + | ||
| 167 | + | ### Visibility | |
| 168 | + | ||
| 169 | + | In FPC a function or a procedure cannot see another one, which is written **after** it. | |
| 170 | + | ||
| 171 | + | Example: | |
| 172 | + | ||
| 173 | + | ``` pascal | |
| 174 | + | procedure Proc1; | |
| 175 | + | begin | |
| 176 | + | Proc2; //This is not possible | |
| 177 | + | end; | |
| 178 | + | ||
| 179 | + | procedure Proc2; | |
| 180 | + | begin | |
| 181 | + | Proc1; //This is possible | |
| 182 | + | end; | |
| 183 | + | ``` | |
| 184 | + | ||
| 185 | + | To enable visibility, disregarding writing order, functions and procedures have to be declared. | |
| 186 | + | ||
| 187 | + | ``` pascal | |
| 188 | + | unit MyUnit; | |
| 189 | + | ... | |
| 190 | + | procedure Proc1; | |
| 191 | + | procedure Proc2; | |
| 192 | + | ... | |
| 193 | + | implementation | |
| 194 | + | ||
| 195 | + | procedure Proc1; | |
| 196 | + | begin | |
| 197 | + | Proc2; //This is possible now | |
| 198 | + | end; | |
| 199 | + | ||
| 200 | + | procedure Proc2; | |
| 201 | + | begin | |
| 202 | + | Proc1; //This is possible | |
| 203 | + | end; | |
| 204 | + | ``` | |
| 205 | + | ||
| 206 | + | ### Using default parameters in functions and procedures | |
| 207 | + | ||
| 208 | + | In Pascal functions and procedures it is possible for parameters to automatically take default values. However, in the parameter list the parameters that might take default values must be declared as a contiguous list at the end of the parameter declaration part. Also, when a routine with default parameter(s) is subsequently called in your code, you can only specify non-default values beginning at the first parameter which would otherwise take a default value. You cannot specify a non-default value for a later parameter, if there are preceding parameters you have to specify values for which have not also been specified explicitly in the function or procedure call. | |
| 209 | + | ||
| 210 | + | For example: | |
| 211 | + | ||
| 212 | + | If a procedure is declared (correctly) as follows with two default parameters: | |
| 213 | + | ||
| 214 | + | ``` pascal | |
| 215 | + | procedure SampleProc(parm1: integer; parm2: string= 'something'; parm3:Boolean= True); | |
| 216 | + | begin | |
| 217 | + | end. //proc | |
| 218 | + | ``` | |
| 219 | + | ||
| 220 | + | it is not possible to call SampleProc as in VB like this: | |
| 221 | + | ||
| 222 | + | ``` pascal | |
| 223 | + | SampleProc(5,,False); | |
| 224 | + | ``` | |
| 225 | + | ||
| 226 | + | This will produce a compiler error. | |
| 227 | + | ||
| 228 | + | When calling a procedure (or function), if you specify a parameter which has a default value, you must also specify all parameters that have a default value that are in front of it. So, in the example above if you want the third parameter to be False, then you must also specify the value of second parameter. | |
| 229 | + | ||
| 230 | + | These are valid calls: | |
| 231 | + | ||
| 232 | + | ``` pascal | |
| 233 | + | SampleProc(5,'something',False); | |
| 234 | + | ||
| 235 | + | SampleProc(5,'nothing'); | |
| 236 | + | ||
| 237 | + | SampleProc(5,''); | |
| 238 | + | ||
| 239 | + | SampleProc(5); | |
| 240 | + | ``` | |
| 241 | + | ||
| 242 | + | ## Dynamic arrays | |
| 243 | + | ||
| 244 | + | In Pascal the minimum index of a dynamic array is 0, i.e. *MyArray (1)* will return the **second** elements of an array named *MyArray*. | |
| 245 | + | ||
| 246 | + | Arrays are resized using: | |
| 247 | + | ||
| 248 | + | ``` pascal | |
| 249 | + | setlength (MyArray, NewDimension); | |
| 250 | + | ``` | |
| 251 | + | ||
| 252 | + | *SetLength* does **not** clear the array, i.e. it acts like *ReDim Preserve*, not like *ReDim*. | |
| 253 | + | ||
| 254 | + | ## Translation of some commonly sought commands | |
| 255 | + | ||
| 256 | + | DoEvents = TApplication.ProcessMessages | |
| 257 | + | ||
| 258 | + | ``` pascal | |
| 259 | + | var | |
| 260 | + | app: TApplication; | |
| 261 | + | i: integer; | |
| 262 | + | begin | |
| 263 | + | app := TApplication.Create(nil); | |
| 264 | + | ||
| 265 | + | for i := 0 to 1000000 do | |
| 266 | + | begin | |
| 267 | + | app.ProcessMessages; // Handling process messages. | |
| 268 | + | OutputDebugString(PChar(IntToStr(i))); | |
| 269 | + | end | |
| 270 | + | end; | |
| 271 | + | ``` | |
| 272 | + | ||
| 273 | + | While the *OutputDebugString* printing the number to *Event Log*, you may do any events with Form without *Freezing* except when you close the form, you must wait the loop until finished. | |
| 274 | + | ||
| 275 | + | ## VB commands, which are not present in FPC/Lazarus | |
| 276 | + | ||
| 277 | + | *Split* - Split is not a separate function in FPC. It shall be used the following way: | |
| 278 | + | ||
| 279 | + | ``` pascal | |
| 280 | + | String1D := '1;2,3;4;5,6'.Split([',',';']); | |
| 281 | + | ``` | |
| 282 | + | ||
| 283 | + | *Join* works the following way: | |
| 284 | + | ||
| 285 | + | ``` pascal | |
| 286 | + | MyString := ''.Join(';',String1D); | |
| 287 | + | ``` | |
| 288 | + | ||
| 289 | + | ## Debugging | |
| 290 | + | ||
| 291 | + | Lazarus IDE has no Instant panel. | |
| 292 | + | ||
| 293 | + | In order to debug in Windows the dos prompt windows shall be enabled the following way: *Lazarus IDE-\> Main menu -\> Project -\> Project options... -\> Compiler Options -\> Config and Target -\>* uncheck *Win32 gui application (-WG)* | |
| 294 | + | ||
| 295 | + | In Linux the console invokes itself. | |
| 296 | + | ||
| 297 | + | Then the *write* and *writeln* commands can be used to print debug messages. | |
| 298 | + | ||
| 299 | + | Compiler might give some more information if the following items are checked in the IDE main menu -\> *Project* -\> *Project Option* -\> *Compiler Option* -\> *Debugging* -\> -Ci, -Cr, -Co, -St, -Cr, -Sa. | |
| 300 | + | ||
| 301 | + | ## Substitution tables | |
| 302 | + | ||
| 303 | + | | VB | [[Pascal]] | Remark | | |
| 304 | + | |----|----|----| | |
| 305 | + | | = | := | [[Becomes]] | | |
| 306 | + | | = | = | [[Equal]] | | |
| 307 | + | | / | / | [[Slash|Float Division]] | | |
| 308 | + | | \\ | [[Div]] | | | |
| 309 | + | | & | + | String concatenation | | |
| 310 | + | | MOD | [[Mod]] | Modulo operation | | |
| 311 | + | | \<\> | \<\> | [[Not equal]] | | |
| 312 | + | | Not | [[Not]] | | | |
| 313 | + | | And | [[And]] | | | |
| 314 | + | | Or | [[Or]] | | | |
| 315 | + | | Xor | [[Xor]] | | | |
| 316 | + | | \>\> | [[Shr]] | bit **sh**ift **r**ight | | |
| 317 | + | | \<\< | [[Shl]] | bit **sh**ift **l**eft | | |
| 318 | + | | New line | ; | In Pascal lines end with the ; character not by a new line. | | |
| 319 | + | | _ | | No symbol is required for wrapping a line and new line symbols are acceptable within it. | | |
| 320 | + | | ' | // | End of line [[Comments|Comment]] (only one line comment) | | |
| 321 | + | | Exit For | Break | Interrupt execution of a loop | | |
| 322 | + | ||
| 323 | + | | VB type | [[Pascal]] [[Data type|type]] | Size (bits) | Range | Remark | | |
| 324 | + | |----|----|----|----|----| | |
| 325 | + | | SByte | [[Shortint]] | 8-bit | -128 .. 127 | | | |
| 326 | + | | Byte | [[Byte]] | 8-bit | 0 .. 255 | | | |
| 327 | + | | Short | [[Smallint|SmallInt]] | 16-bit | -32768 .. 32767 | | | |
| 328 | + | | Char | [[Word]] | 16-bit | 0 .. 65535 | | | |
| 329 | + | | Integer | [[Integer]] | 32-bit | -2147483648..2147483647 | | | |
| 330 | + | | UInteger | [[Cardinal]] | 32-bit | 0 .. 4294967295 | | | |
| 331 | + | | Single | [[Single]] | 32-bit | 1.5E-45 .. 3.4E+38 | Decimal delimiter in both languages, applied **in source code** is dot on the line. | | |
| 332 | + | | Double | [[Double]] | 64-bit | 5.0E-324 .. 1.7E+308 | | | |
| 333 | + | | Boolean | [[Boolean]] | | [[True]] [[False]] | | | |
| 334 | + | | | | | | | | |
| 335 | + | ||
| 336 | + | ### String functions | |
| 337 | + | ||
| 338 | + | | VB | [[Pascal]] | Remark | | |
| 339 | + | |----|----|----| | |
| 340 | + | | & | + | String concatenation | | |
| 341 | + | | Format(item, formatstring) | format(formatstring, items) | | | |
| 342 | + | | left(some_string,n) | leftstr(some_string, n) or copy (some_string,1,n) | | | |
| 343 | + | | Len(some_string) | length(some_string) | | | |
| 344 | + | | LCase(some_string) | lowercase(some_string) | | | |
| 345 | + | | Mid(some_string, startpos, numChars) | copy(some_string, startpos, numChars) | | | |
| 346 | + | | StrReverse(string) | See [[Palindrome]] | | | |
| 347 | + | | UCase(some_string) | uppercase(some_string) | | | |
| 348 | + | | | | | | |
| 349 | + | ||
| 350 | + | ## Component prefixes | |
| 351 | + | ||
| 352 | + | There is a [list of component prefixes](http://kodu.ut.ee/~jellen/delphi/cs.html#Components_Instance) for Delphi, which can be used in Lazarus. Using them might provide better code readability. | |
| 353 | + | ||
| 354 | + | It is also usual to start the name of a type with the capital letter *T*. | |
| 355 | + | ||
| 356 | + | ## Arrays of controls | |
| 357 | + | ||
| 358 | + | Unlike in VB6 and like in VB.NET arrays of controls cannot be created statically (trough the IDE), and they can be created only dynamically. | |
| 359 | + | ||
| 360 | + | Example, creating 6 buttons above each other: | |
| 361 | + | ||
| 362 | + | ``` pascal | |
| 363 | + | procedure TForm1.FormCreate(Sender: TObject); | |
| 364 | + | var | |
| 365 | + | i: Integer; | |
| 366 | + | btnArray: array of TButton; | |
| 367 | + | begin | |
| 368 | + | SetLength(btnArray, 6); | |
| 369 | + | for i := 0 to 5 do | |
| 370 | + | begin | |
| 371 | + | btnArray[i] := TButton.Create(Self); | |
| 372 | + | btnArray[i].Left := 0; | |
| 373 | + | btnArray[i].Top := i * 30; | |
| 374 | + | btnArray[i].Parent := Self; | |
| 375 | + | end; | |
| 376 | + | end; | |
| 377 | + | ``` | |
| 378 | + | ||
| 379 | + | ## Visual Basic to Delphi (Pascal) Converters | |
| 380 | + | ||
| 381 | + | - <https://www.marcocantu.com/tools/vb2delphi.htm> | |
| 382 | + | - <https://cc.embarcadero.com/item/17064> | |
| 383 | + | ||
| 384 | + | --- | |
| 385 | + | *From the Free Pascal wiki, page "Pascal for Visual Basic users", as it stood on 2023-01-25 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* | |
| 386 | + | Category: FPC | |
| 387 | + | Category: Rosetta Stone |
