Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

New to Delphi & Stuck !! 1

Status
Not open for further replies.

vertsyeux

Programmer
Dec 19, 2003
3
US
Hi Guys/Gals...

I've been programming procedural languages (including Pascal) for over 22 years. I'm attempting to teach myself Delphi 7 (with Borland's free 30-day demo) as an introduction to OOP techniques and I've run into a problem.

I'm trying to write a program which shows all the drives on my system as buttons on a horizontal bar. Each button will display the drive letter, a gauge (showing percentage utilisation) and a text field displaying the actual space remaining - eg. "2.3Gb".. Pressing a button will open an explorer view of that drive (if I ever get that far)...

I've created a form containing a single frame into which I've placed my two text fields and gauge and successfully produced code in the CreateForm method to populate an array of records corresponding to the available hard-drives with fields for DriveLetter, TotalCapacity, UnusedSpace etc.

The Problem is that I now want to replicate my "button" for each entry of my DiskParameters array and I can't figure out how to do this. I've studied Borland's documentation, messed around with constructor etc. but to no avail. If the Form is an object, containing the frame (an object) which itself contains my labels and gauge, surely I can create another frame object (with labels & gauge) for each array element "inheriting" the attributes of the existing one, reposition it and save a pointer to the new object in the array..

Any help would be gratefully appreciated..

Thanx
Gordon


 
We've only got 30 days to solve this so we had better get cracking.

I am not sure that I really understand your problem but here goes...

I'm assuming that you have created a frame called 'TDFrame' and you want to dynamically create a row of DFrames in your Form1.

You need to give each created DFrame a unique name. I'm going to call them DFrame1, DFrame2 and so on. I'll keep track of the number in DFrameN.

Also you need to place them on the form at a particular x position. I'll keep track of the x position in DFrameX. I'm assuming that each DFrame will be 100 pixels to the right of the previous one.

I'm going to keep a list of pointers to the created DFrames in DFrameList.

So you are going to have the following global variables - it might be sensible to put these into a class:
Code:
var
  DFrameList: TList;
  DFrameN: integer = 0;
  DFrameX: integer = 0;
I'm assuming that you create DFrameList at some suitable place such as in TForm1.FormCreate.

Now when you come to create a DFrame at run time your code should look something like this:
Code:
  DFrameList.Add ( TDFrame.Create ( Form1 ) );
  with TDFrame ( DFrameList[DFrameN] ) do begin
    inc ( DFrameX, 100 );
    Left := DFrameX;
    inc ( DFrameN );
    Name := 'DFrame' + IntToStr ( DFrameN );
    Parent := Form1;  
  end;
Note that Form1 is the owner of the created DFrames and will automatically destroy them when Form1 is destroyed.

This should give you some idea how to create frames at run time.

Andrew
 
Hi Andrew,

Thanks for your interest in my problem. I tried out your suggestions, but I'm still having problems - I've included the contents of my code-window for you to look at. In your example, you refer to TDFrame - I presume that's the class of DFrame (I call mine ButtonFrame). I didn't have one of those and it wouldn't compile so I created one underneath the class definition for Form1 tho I'm not sure that'll work since the definition of my ButtonFrame already seems to be embedded in the definition of Form1. Also, although the object-viewer shows the objects I created inside ButtonFrame as child records of ButtonFrame, they seem to be part of the definition of Form1 in the code, not ButtonFrame as I would have expected - obviously, when I create a ButtonFrame, I want it to create the bits inside (gauge & 2 labels) as well.

Now, having created a class definition for TButtonFrame, it compiles. However, it won't run as the run-time system reports object ButtonFrame already exists - which makes sense as I'm creating it before I change its name. It seems that objects added to forms get created automatically when the program runs. I'm sure I'm missing something obvious here - Is there any way to design an object in the IDE and then create one or more instances at run-time?

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Grids, StdCtrls, ActnMan, ActnColorMaps, CustomizeDlg, ToolWin,
ActnCtrls, Gauges, ExtCtrls;

type
//These lines were put here by the form designer

TForm1 = class(TForm)
ButtonFrame: TGroupBox;
Letter: TLabel;
Free: TLabel;
Gauge: TGauge;
procedure FormCreate(Sender: TObject);
end;

//I had to add the next 2 lines to get it to compile

TButtonFrame = class(TGroupBox)
end;

DriveDef = record
DriveLetter : char;
FreeGB : Extended;
Percent : Integer;
end;

var
Form1 : TForm1;
ButtonFrame : TGroupBox;
Count : Byte;
DriveTable : Array [1..25] of DriveDef;

ButtonList : TList;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

var
Letter : Char;
Size : Int64;
Free : Int64;
J : integer;

begin

//Hide From Taskbar..

ShowWindow(Application.Handle, SW_HIDE) ;
SetWindowLong(Application.Handle, GWL_EXSTYLE,
getWindowLong(Application.Handle, GWL_EXSTYLE)
or WS_EX_TOOLWINDOW) ;
ShowWindow(Application.Handle, SW_SHOW) ;

Form1.AutoSize := True;

//Determine Which drives have an MFA directory and Populate
//Array with Drive Details. Count points to highest drive number..

for Letter := 'C' to 'Z' do
begin
if FileExists(Letter + ':\MFA\TERMLIST.CFG') then
begin
Count := Count + 1;
DriveTable[Count].DriveLetter := Letter;
Size := DiskSize(ord(Letter)-64);
Free := DiskFree(ord(Letter)-64);
DriveTable[Count].Percent := Integer(100 * (Size - Free) div Size);
DriveTable[Count].FreeGB := Free / 1.074e9;
end;
end;

{
if Count >= 1 then
begin
Letter.Caption := DriveTable[1].DriveLetter + ':';
Gauge.Progress := DriveTable[1].Percent;
Free1.Caption := FloatToStrF (DriveTable[1].FreeGB, ffFixed, 5, 1) + 'Gb';
end
else
ButtonFrame1.visible := False;
}

for J := 1 to 4 do
begin
ButtonList.Add ( ButtonFrame.Create ( Form1 ) );
with TButtonFrame ( ButtonList [J] ) do begin
top := 100;
Left := 100 * J;
Name := 'DFrame' + IntToStr ( J );
Parent := Form1;
end;
end;

end;
end.

Thanx for your help..
Gordon
 
Your TButtonFrame should be descended from TFrame.

The proper (and easiest) way to make a Frame is to click on

File | New | Frame

in the IDE.

This will then create a unit and a 'form' for your frame onto which you can drop controls such as buttons.

If you do this and follow the code snippets I gave previously you should find it will work (I hope). You don't have to call your frames 'DFrame'. 'ButtonFrame' might be better for your code. It could be 'HappyChristmas' if you want - perhaps not helpful but seasonal.

Andrew
 
Hi Andrew,

Thanx for your help.. I think I'm beginning to get the hang of Delphi.. My "DriveBar" is almost complete, it now displays a button for each drive that contains one or more copies of my lagacy software complete with capacity gauge. Clicking opens a seperate form with a ListView and scans that drive for folders containing different types of company information which it displays using specific icons. Now I have to figure out how to invoke my DOS application by double-clicking one of the icons... I have 236 days left. Thank-you again for your help..

Gordon
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top