[Home]
[Edit this page]
[Recent Changes]
[Special Pages]
[Help]
Bus » startpage » IBasic » JavaScript » BASIC » Jims Page
Jims Page
introduction
general
Delphi GUI
program start
byValbyRef
public/private
conversions
files
API calls
PChar
TStrings
Strings
End blocks
classes
static
enumerations, arrays and sets
conditional compiling
graphics
TFrames
tools
=== introduction === [i]"learn to swim, learn to drown"[/i] Kevin Coyne
Introduction:
Last months I did switch from VB6 to Delphi.
overhere I wrote down some problems that I ran into.
I think the best way to learn Delphi is just start writing code. So just write a few Delphi applications of programs that you ever wrote in VB6, so you will have a good understanding what you are doing.
Do not look for code snippets, Just write all the code you need yourself.
Take your time:
First three week I felt like: 'Why do I start to learn this impossible language' and I thought I would be writing code with a book on my lap always, but eventually I learnt and by now I'm coding in Delphi the way I did in VB6.
Even more: Delphi is a much more smarter language. But your VB6 experiendce will give some advantage over every Pascal coder.
My main Delphi project lately was a codepediaparser/convertor, So I can write this page unplugged and test the result using my codepediaparser. This is why I think programming fun.
Actually this page right now is just a testrun of my parser. So if some style errors occur this is due to my parser.Seems alright though!!:)
Its about six months since I started to learn Delphi.
I forgot a lot on VB6 by now, so I will not add a lot to this page. If you also migrate from VB6 to Delphi, I hope this page will give you a hand.
If you want to write down your ideas on migrating from VB6 to Delphi, best you make a page of your own, instead of messing this one up. Thank you. Crazy Jim
VisualBasic6...Delphi
=== general ===
'''Delphi GUI'''
linking an event to a method:
In VB6 I often wrote code like
In Delphi you can link an event direct to the procedure Just enter the name of the procedure you wish to the event in the ObjectInspector. Next you can easily link the same procedure to several events. However, parameters have to match the event
Actually the linking to the code is still similar as in VB6 but it is handled in the *.dfm form file that comes along with the unit.
Still the VB6 setsize routine can be an advantage at times
notmenu:File>>Open
butmenu:Project>>addToProject
next: menu:File>>Use unit
=== program start === VB6: sub formload() or sub main(); Delphi: initialization it's sort of reserved word, and you put it just befor the final '''end.'''
=== byVal byRef === VB6: ByRev ByVal
Delphi: default is By Value.
ByRef=Var
If you put var in front of a parameter the parameter itself will be passed, so the caller will also change:
str2 and int 2 will be changed.
=== public/private === I had a lot of trouble to find out what way to write a private procedure or function, the way you write a private sub or function in a VB6 module (*.bas file). Actually its most simple:
Whatever you declare in the interface part of a *.pas file is public.
Whatever you declare in the implementation of a *.pas file is private.
Or, in human language: All what you declare under the line is private.
=== conversions ===
=== files === I do not yet know a lot on files as I just use TString until now.
(ts.loadfromfile; ts.writetofile)
fileNameroutines all start with "extract"; e.g. ExtractFileDir, etcetera
If you ever wrote a recursive routine, you will think Delphi most easy to scan folders and subfolders using
findfirst
findnext
findclose
=== API calls === Declares . . .
Uses windows;uses shellApi, uses ???
I figure in sort of way an api call is very similar in both VB6 and Delphi. The files Window.pas and shellApi.pas are just a listing of declarations.
Note: I had a real hard time to writecode for shellExecute, as it's just not around in this windows.dcu I needed import shellApiinstead! Discovered this by try and error myself and did take some time.(eg weeks) I do not know where to find more info on the windowsApi in delphi.
Shell
I still didn't figure out:
=== PChar === PChar is a pointer to a nullterminated string.
delphiHelp tells very little on PChar, so you might search the internet for more information. A PChar has a lot of functionality and you can use code like PChar+1
=== TStrings === string arrays...TStrings I think TStrings a very good tool to handle text. (until now I do all the fileHandling with a TStrings) However it took some time to find out what way to create a TStrings.Actualy you should not create a TStrings but a TStringList[/b]
=== Strings === until now I just use:
There are a lot of functions around, it seems you should use the functions that start with Ansi... other functions are obsolete. (an Ansi string also handles the letters with all this funny little symbols on top or underneath.)
=== End blocks ===
=== classes ===
so you can name the procedure and function just the way you want, all other part is similar to VB6;
=== static === static...const If you use constant within a procedure it will be similatr to vb6 style static. e.g.
'''TStrings'''
string arrays...TStrings I think TStrings a very good tool to handle text. (until now I do all the fileHandling with a TStrings) However I spent a lot of time to find out what way to create a TStrings. Actualy you should create a TStringList[/b]
=== enumerations, arrays and sets ===
similar is also a function to write function TypeNumberToString(num:number); Select case... or Case Type num of; cow: TypeNumberToString:='1'; pig: TypeNumberToString:='2'; dog: TypeNumberToString:='3';
1. to resize an array to a smaller array is not possible: you have to create a copy : newArr:=(copy(arr,start, length)
2. You cannot just pass a dynamical array as a parameter!
Acoording to delphi.hlp you have to create a Type TArray array of ... e.g.
I figure when using an array of string you best use a TStrings
=== sets === a set is not an enumeration. I figure a set is sort of unordered list.
thisOrThat:set of ....
NOTE:when you pass a set element as a parameter, you have to pass it inbetween hooks, for instance:
type TShiftState =set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble); in OnKeyDown:
not if Shift:=ssShift etc...
but if Shift:=[ssShift] etc...
same with the buttons in a messagebox, etc :
=== conditional compiling === VB6: #IF<string>
Delphi: {$IFDEF<string>} In VB6 I used a routine to see if the program was running from the IDE, so I could show some testbuttons etcetera, if it was. I figure I cann't see if a program is running from within the IDE, but I can use conditional statements, all similar to VB6;
== delphi graphics ==
In Delphi, whenever you draw a line you use a pencil, whenever you fill a plane you use a brush. If you ever tried to use some graphical API's this all should be clear.
You need a canvas to draw on. Every window object has one, but I quess you can only draw on a TImage.canvas. The better way is to draw on an invisible TBitmap, this wil also resolve all resizing problems See below.
=== cls === To clear a screen you have to overdraw the screen.
=== RGB === Notation of delphi TColor is very similar to HTML. $00FF0000 is blue, $0000FF00 is green, $000000FF is red. $00000000 is black $00FFFFFF is white.
=== scale === The easy way to draw a line is the Quickbasic way. Core in this all is scale(..,..)-(..,..).
In Delphi you have to write a renormalize function yourself. Core is next code:
I think the best way to handle the rescaling is to write a class of your own. It would be a good and rewarding exercise. Then you just store the translations and factors in class_memory, and only if the TImage is resized the XFactor and YFactor have to be recalculated.(check TImage.ClientWidth and ClientHeigth to see if TImage is resized) [actually I used a TFrame instead to handle this all, runs fine!]
=== resizing === When I draw on a Image.canvas I have a problem when I resize the Image. I found one solution: I draw on a (invisible) TBitmap.canvas instead, next I copy the bitmap.canvas to the image.canvas. The secret line to make the copy event work is from the magic book of sorcery: image1.Picture.Graphic := Bitmap;
According to delphi.hlp
== TFrames == Best way to make a template is with a TFrame.
Still it took some time to figure out what way.
1. Create a project, now you can add a TFrame to the project you can add some code and design, but when you run it you cann't show the TFrame. (however doubleclick)Standard>Frames in the component palet and the list of frames apear so you can add a Tframe it to a Form)
2. Add the TFrame to the component page. (popupmenu and topmost it tells 'Add to Palette')(best also create a 16*16 bitmap as icon with Irfan View ) (I think a component page is sort of package.)
3. Create a new project, now add the component to the form. Do not edit this component, as it is just an instance of the TFrame and not the TFrame itself. But you can also open the TFrame itself: View >> Project Manager >> etcetera. The TFrame is both the visual frame and a *.pas file. You can edit this Tframe to make it do what you want to do. You can add any code to the unit and any components to the TFrame. And you have all the events around for free
, nothing dificult like a COM-project.
Beside you can also overwrite all the code in the TForm if you feel need to. [/b]
(example: instead of a cls to handle the scaling I did create a TFrame to handle scaling, and I can add all the code I like to it, like drawgrid; cls;bouncing ball or whatever I12 )
I think this TFrame is about the best feature in Delphi. In VB6 I had my library of *.bas and *.cls files that I did add to my projects, but I think it's best to create a library of TFrames in Delphi instead. No need to create classes and inheritance, but just create TFrames instead. Next Delphi will take care of all the hassle. You may even create 'invissible' TFrames, that you can add to your project, similar to a 'timer' etcetera. Of course this is somewhat superfluous.
=== tools === A good plugin to Delphi is gexpert
[Edit this page] [Page history] [What links here] [Discuss this topic] [Printer Friendly]
Bus » startpage » IBasic » JavaScript » BASIC » Jims Page
Jims Page
Jim's Page
Migrating from VB6 to Delphi8
contentsintroduction
general
Delphi GUI
program start
byValbyRef
public/private
conversions
files
API calls
PChar
TStrings
Strings
End blocks
classes
static
enumerations, arrays and sets
conditional compiling
graphics
TFrames
tools
=== introduction === [i]"learn to swim, learn to drown"[/i] Kevin Coyne
Introduction:
Last months I did switch from VB6 to Delphi.
overhere I wrote down some problems that I ran into.
I think the best way to learn Delphi is just start writing code. So just write a few Delphi applications of programs that you ever wrote in VB6, so you will have a good understanding what you are doing.
Do not look for code snippets, Just write all the code you need yourself.
Take your time:
First three week I felt like: 'Why do I start to learn this impossible language' and I thought I would be writing code with a book on my lap always, but eventually I learnt and by now I'm coding in Delphi the way I did in VB6.
Even more: Delphi is a much more smarter language. But your VB6 experiendce will give some advantage over every Pascal coder.
My main Delphi project lately was a codepediaparser/convertor, So I can write this page unplugged and test the result using my codepediaparser. This is why I think programming fun.
Actually this page right now is just a testrun of my parser. So if some style errors occur this is due to my parser.Seems alright though!!:)
Its about six months since I started to learn Delphi.
I forgot a lot on VB6 by now, so I will not add a lot to this page. If you also migrate from VB6 to Delphi, I hope this page will give you a hand.
If you want to write down your ideas on migrating from VB6 to Delphi, best you make a page of your own, instead of messing this one up. Thank you. Crazy Jim
VisualBasic6...Delphi
=== general ===
- DoEvents...Application.ProcessMessages;
- sub QueryUnload(...)...procedure TForm1.FormCloseQuery(...)
- Exit Sub; Exit function...Exit;
- Exit Do; Exit For...Break;
- Lines end with linefeed...Lines end with ";"
- CurDir...GetDir
- easy fileName routines start all with 'extract'..
'''Delphi GUI'''
linking an event to a method:
In VB6 I often wrote code like
sub buttonClick()
dosomething
end sub
sub menuClick()
dosomething
end sub
sub dosomething
msgbox "dosomething"
end sub
In Delphi you can link an event direct to the procedure Just enter the name of the procedure you wish to the event in the ObjectInspector. Next you can easily link the same procedure to several events. However, parameters have to match the event
Actually the linking to the code is still similar as in VB6 but it is handled in the *.dfm form file that comes along with the unit.
forms
- In VB6 the code to Form is in one file, In Depphi in two. A *.pas file and a *.dfm file. You can easyly view the code of a *.dfm file when you leftclick on a form [i]>>popupmenu>>view as Text.[/i]
- in VB6 it's real fun to write your 'setSize' code and eventually you may feel real proud when you succeed to create your SplitterBars.
Still the VB6 setsize routine can be an advantage at times
uses
in VB6 I did edit most by hand, but if you want to add an unit of your own to a unit, you should do this using the menubuttons:notmenu:File>>Open
butmenu:Project>>addToProject
next: menu:File>>Use unit
=== program start === VB6: sub formload() or sub main(); Delphi: initialization it's sort of reserved word, and you put it just befor the final '''end.'''
initialization
showmessage('all code overhere when the unit is initialised');
finalization
showmessage('code overhere is similar to unit.unload,'#10'msgbox won't show however');
end.
If you have a form in a unit you can also use TForm.OnCreate and TForm.OnQueryUnload, etc. === byVal byRef === VB6: ByRev ByVal
Delphi: default is By Value.
ByRef=Var
If you put var in front of a parameter the parameter itself will be passed, so the caller will also change:
Procedure PassParams(str1:string;var str2 : String;
int1:integer Var int2 : Integer)
str1 and int1 will not be changed in the calling procedurestr2 and int 2 will be changed.
=== public/private === I had a lot of trouble to find out what way to write a private procedure or function, the way you write a private sub or function in a VB6 module (*.bas file). Actually its most simple:
Whatever you declare in the interface part of a *.pas file is public.
Whatever you declare in the implementation of a *.pas file is private.
Or, in human language: All what you declare under the line is private.
=== conversions ===
- SeeAlso:Typecasts and Floating point conversion routines in Delphi help. I was overwhelmed by all the different types, but actually some types are same in size and it should be easy convert them,
- \ (int division)...DIV
- cint(double, etc)[/b] ...TRUNC(real)
- String to Char; a string is just an array of Char so if you have to pass a char as a variable and you have a string you use char:=string[int]. int mis the position of the char in the string.
- RGB(r,g,b)... RGB:=r*$1000+g*$100+b;''(returns TColor)''
=== files === I do not yet know a lot on files as I just use TString until now.
(ts.loadfromfile; ts.writetofile)
fileNameroutines all start with "extract"; e.g. ExtractFileDir, etcetera
If you ever wrote a recursive routine, you will think Delphi most easy to scan folders and subfolders using
findfirst
findnext
findclose
=== API calls === Declares . . .
Uses windows;uses shellApi, uses ???
I figure in sort of way an api call is very similar in both VB6 and Delphi. The files Window.pas and shellApi.pas are just a listing of declarations.
Note: I had a real hard time to writecode for shellExecute, as it's just not around in this windows.dcu I needed import shellApiinstead! Discovered this by try and error myself and did take some time.(eg weeks) I do not know where to find more info on the windowsApi in delphi.
Shell
uses shellapi;
. . .
function openFileOrFolder(path:string):Integer ;
var shellResult:Integer;
const
SW_SHOWNORMAL=1;
SW_SHOW=5;
begin
shellResult:=ShellExecute(application.Handle, 'open', PChar(path), nil,PChar(''), SW_SHOW )
end;
I still didn't figure out:
- isDisc(char,var diskType)
- deleteToWastebasket(filename)
=== PChar === PChar is a pointer to a nullterminated string.
//eg CopyFile
uses windows;
var filePathFrom,filePathTo:string;
...
{we use :
copyFile(lpFilenamefrom:PAnsiString;
lpFilenameTo:PAnsiString;
bFailIfExists:LongBool);
}
copyFile(filePathFrom, filePathFrom, true); //Error!
//we need a Pointer to a nullterminated string instead;
//actually it is most simple to create
copyFile(PChar(filePathFrom),PChar(filePathFrom), true);
delphiHelp tells very little on PChar, so you might search the internet for more information. A PChar has a lot of functionality and you can use code like PChar+1
=== TStrings === string arrays...TStrings I think TStrings a very good tool to handle text. (until now I do all the fileHandling with a TStrings) However it took some time to find out what way to create a TStrings.Actualy you should not create a TStrings but a TStringList[/b]
procedure TForm1.Button1Click(Sender: TObject);
var TempList: TStringList; { declare the list }
begin
TempList :=TStringList.Create; { construct the list
object }
try { use the string list }
finally TempList.Free; { destroy the list object }
end;
end;
(delphi.hlp;Working with string lists)=== Strings === until now I just use:
- midstr(string,start,length) (=VB6 MID)
- posex(find, string, pos) (=VB6 INSTR)
- ord() e.g. ord('a') returns 97
- chr() e.g. chr(97) returns 'a'
There are a lot of functions around, it seems you should use the functions that start with Ansi... other functions are obsolete. (an Ansi string also handles the letters with all this funny little symbols on top or underneath.)
=== End blocks ===
- the VisualBasic End Sub; End Function; End If; is not similar to Delphi'sEnd;End is the conclusion of a block: begin ... end; and this begin/end construction is unknown to VB6
- Exceptions:
=== classes ===
- [blueVB6: ]myObj=new myClass[/blue]
- property
type TClass =class
private
var
function somefunction()integer;
procedure someprocedure(n:integer);
public
{now you just declare a property, instead of a variable}
property myInteger: read somefunction write someprocedure;
so you can name the procedure and function just the way you want, all other part is similar to VB6;
=== static === static...const If you use constant within a procedure it will be similatr to vb6 style static. e.g.
procedure constIsStatic const counter:integer; begin counter:=counter+1 showmessage(inttostr(counter)); end;should run fine
'''TStrings'''
string arrays...TStrings I think TStrings a very good tool to handle text. (until now I do all the fileHandling with a TStrings) However I spent a lot of time to find out what way to create a TStrings. Actualy you should create a TStringList[/b]
procedure TForm1.Button1Click(Sender: TObject);
var TempList: TStringList; { declare the list }
begin
TempList :=TStringList.Create; { construct the list object }
try { use the string list }
finally TempList.Free; { destroy the list object }
end;
end;
(delphi.hlp;Working with string lists)=== enumerations, arrays and sets ===
- enum...type
type number(cow, pig, dog); var myNumber:=number;cow will be 1, pig=2, dog=3
similar is also a function to write function TypeNumberToString(num:number); Select case... or Case Type num of; cow: TypeNumberToString:='1'; pig: TypeNumberToString:='2'; dog: TypeNumberToString:='3';
arrays
Dynamic arrays are symple except:1. to resize an array to a smaller array is not possible: you have to create a copy : newArr:=(copy(arr,start, length)
2. You cannot just pass a dynamical array as a parameter!
procedure foo(arr array of integer) begin setlength(arr,...size...); end;causes an error!
Acoording to delphi.hlp you have to create a Type TArray array of ... e.g.
Type TArray array of integer; var arr=TArray; procedure foo(arr: TArray); begin setlength(arr,...size...); end;runs fine!
I figure when using an array of string you best use a TStrings
=== sets === a set is not an enumeration. I figure a set is sort of unordered list.
thisOrThat:set of ....
NOTE:when you pass a set element as a parameter, you have to pass it inbetween hooks, for instance:
type TShiftState =set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble); in OnKeyDown:
not if Shift:=ssShift etc...
but if Shift:=[ssShift] etc...
same with the buttons in a messagebox, etc :
MessageBox('example', 'caption', [smbOK]); etcetera=== conditional compiling === VB6: #IF<string>
Delphi: {$IFDEF<string>} In VB6 I used a routine to see if the program was running from the IDE, so I could show some testbuttons etcetera, if it was. I figure I cann't see if a program is running from within the IDE, but I can use conditional statements, all similar to VB6;
'VB6msgbox "all kind of testing code overhere"
- Const rawversion
- IF rawversion
- ENDIF
//Delphi style
{$DEFINE rawversion}
{$IFDEF rawversion}
showmessage('all kind oif testing code overhere');
{$ENDIF rawversion}
== delphi graphics ==
In Delphi, whenever you draw a line you use a pencil, whenever you fill a plane you use a brush. If you ever tried to use some graphical API's this all should be clear.
You need a canvas to draw on. Every window object has one, but I quess you can only draw on a TImage.canvas. The better way is to draw on an invisible TBitmap, this wil also resolve all resizing problems See below.
=== cls === To clear a screen you have to overdraw the screen.
procedure clear(pict:TImage;backColor:TColor);
var rect:TRect;
var brushColor:TColor;{to reset the Brush.Color}
begin
brushColor:=pict.Canvas.Brush.Color;
pict.Canvas.Brush.Color:=backColor;
pict.Canvas.FillRect(pict.ClientRect);
pict.Canvas.Brush.Color:=brushColor;
end;
=== RGB === Notation of delphi TColor is very similar to HTML. $00FF0000 is blue, $0000FF00 is green, $000000FF is red. $00000000 is black $00FFFFFF is white.
function RGB(r: integer; g: integer; b: integer):TColor;
begin
RGB:=r*$1000+g*$100+b;
end;
=== scale === The easy way to draw a line is the Quickbasic way. Core in this all is scale(..,..)-(..,..).
In Delphi you have to write a renormalize function yourself. Core is next code:
function reScale(point:TPoint;scale:TRect;pict:TImage):TPoint;
var
newPoint:TPoint;//result
oldWidth, oldHeight, newWidth, newHeight:integer;
Factor,yFactor:double;
begin
{First you translate the plane so the the left top = (0,0),
next you refactor the plane. Wrote it all with try and error.
Code can be shorter, some is added for readability.}
oldWidth:= scale.Left -scale.Right;
oldHeight:= scale.Top-scale.Bottom;
newWidth:=pict.ClientWidth;
newHeight:=pict.ClientHeight;
xFactor:=newWidth/oldWidth;
yFactor:=newHeight/ oldHeight;
newpoint.X:=-trunc(xFactor*(point.X-scale.Left ));
newpoint.Y:=-trunc(yFactor*(point.Y-scale.Top ));
result:= newpoint;
end;
I think the best way to handle the rescaling is to write a class of your own. It would be a good and rewarding exercise. Then you just store the translations and factors in class_memory, and only if the TImage is resized the XFactor and YFactor have to be recalculated.(check TImage.ClientWidth and ClientHeigth to see if TImage is resized) [actually I used a TFrame instead to handle this all, runs fine!]
=== resizing === When I draw on a Image.canvas I have a problem when I resize the Image. I found one solution: I draw on a (invisible) TBitmap.canvas instead, next I copy the bitmap.canvas to the image.canvas. The secret line to make the copy event work is from the magic book of sorcery: image1.Picture.Graphic := Bitmap;
{I do it this way}
procedure drawSomethingOnFormImage( . . . );{call onresize}
{FormImage is just an TImage that you did put on the form}
var bitmap:TBitmap;
begin
bitmap:=TBitmap.create;
bitmap.Width:=FormImage.Width-FormImage.Left;
bitmap.Height:=FormImage.Height-FormImage.Top;
{now all drawing to the bitmap
. . . lines,circles or whatever u12
{end drawing }
FormImage.Picture.Graphic := Bitmap;
end;
According to delphi.hlp
image1.Canvas.StretchDraw(image1.ClientRect,bitmap);should also run fine, but the canvas just isn't resized along with the image the way it should.
== TFrames == Best way to make a template is with a TFrame.
Still it took some time to figure out what way.
1. Create a project, now you can add a TFrame to the project you can add some code and design, but when you run it you cann't show the TFrame. (however doubleclick)Standard>Frames in the component palet and the list of frames apear so you can add a Tframe it to a Form)
2. Add the TFrame to the component page. (popupmenu and topmost it tells 'Add to Palette')(best also create a 16*16 bitmap as icon with Irfan View ) (I think a component page is sort of package.)
3. Create a new project, now add the component to the form. Do not edit this component, as it is just an instance of the TFrame and not the TFrame itself. But you can also open the TFrame itself: View >> Project Manager >> etcetera. The TFrame is both the visual frame and a *.pas file. You can edit this Tframe to make it do what you want to do. You can add any code to the unit and any components to the TFrame. And you have all the events around for free
(example: instead of a cls to handle the scaling I did create a TFrame to handle scaling, and I can add all the code I like to it, like drawgrid; cls;bouncing ball or whatever I12 )
I think this TFrame is about the best feature in Delphi. In VB6 I had my library of *.bas and *.cls files that I did add to my projects, but I think it's best to create a library of TFrames in Delphi instead. No need to create classes and inheritance, but just create TFrames instead. Next Delphi will take care of all the hassle. You may even create 'invissible' TFrames, that you can add to your project, similar to a 'timer' etcetera. Of course this is somewhat superfluous.
=== tools === A good plugin to Delphi is gexpert
[Edit this page] [Page history] [What links here] [Discuss this topic] [Printer Friendly]
