SRL Archive - OSR Help

Forms in Simba


Flight

2011-05-26 00:39:24

So I read MasterKill's tutorial on Forms, but if I'm not mistaken, that's for Scar, yes? I followed the tutorial and made my own form just as an experiment. Everything was working fine, no compiling errors, the form was displayed fine, but very shortly after closing the form Simba stopped responding for me and I had to close it out through the command prompt.

So I'm curious, is there something we should be calling / freeing when we close a form?

Also, here's the tutorial if you can't find it:
http://villavu.com/forum/showthread.php?p=520210

BraK

2011-05-26 02:38:40

Here's the Player form I created a while back for my herblore script. It works with simba, but not with scar. I'm sure you'll be able to find the little changes that are needed.

{Player Form}
{Loads of Help from Daniel, Masterkill and dgby714}
type
TFormPlayer = record
Name, Pass, Nick, Pin, STAT_ID, STAT_PASS, Bank :String;
Herb, Second, Task, World :Integer;
Debug :Boolean;
end;

{Main Form Globals}
var
PharmForm :TFORM;
PharmPlayer :TFormPlayer;
PButton :array [0..3] of Tbutton;
PLabel :array [0..11] of TLABEL;
PEdit :Array [0..6] of TEDIT;
PCombo, PCombo1, PCombo2, PCombo3, PCombo4 :TCOMBOBOX;
PImage :Array[0..2] of TIMAGE;
PGroup :array[0..4] of TGROUPBOX;
PStart :boolean;
ComboText, ComboText1, ComboText2 :TStringArray;

procedure FormKill(Const S :String);
begin
ShowMessage(S);
TerminateScript;
end;

procedure LeftClick(Sender: TObject);
var
I :integer;
begin
case sender of
PButton[0]:
begin

for I := 0 to 13 do
if PCombo.TEXT = ComboText[i] then
PharmPlayer.Herb := i;

for I := 0 to 15 do
if Pcombo2.TEXT = ComboText2[i] then
PharmPlayer.Second := i;

for i := 0 to 2 do
if PCombo1.TEXT = ComboText1[i] then
PharmPlayer.Task := i;

if not (PEdit[0].TEXT = '') then
PharmPlayer.Name := PEdit[0].TEXT
else
FormKill('No Username Specified');

if not (PEdit[1].TEXT = '') then
PharmPlayer.Pass := PEdit[1].TEXT
else
FormKill('No Password Specified');

if not (PEdit[2].TEXT = '') then
PharmPlayer.Nick := PEdit[2].TEXT;

if not (PEdit[3].TEXT = '') then
PharmPlayer.Pin := PEdit[3].TEXT;

if not (PEdit[4].TEXT = '') then
PharmPlayer.STAT_ID := PEdit[4].TEXT;

if not (PEdit[5].TEXT = '') then
PharmPlayer.STAT_PASS := PEdit[5].TEXT;

PharmPlayer.World := StrToInt(PEdit[6].TEXT);
PharmPlayer.Debug := StrToBool(PCombo3.TEXT);
PharmPlayer.Bank := PCombo4.TEXT;
PStart := True;
PharmForm.ModalResult:= mrOk;
end;
PButton[1]: begin PharmForm.MODALRESULT:= mrOk; end;
PButton[2]:
begin
WriteINI('Player', 'Name', PEdit[0].TEXT, 'Player_Data');
WriteINI('Player', 'Pass', PEdit[1].TEXT, 'Player_Data');
WriteINI('Player', 'Nick', PEdit[2].TEXT, 'Player_Data');
WriteINI('Player', 'Pin', PEdit[3].TEXT, 'Player_Data');
WriteINI('Stats', 'User', PEdit[4].TEXT, 'Player_Data');
WriteINI('Stats', 'Pass', PEdit[5].TEXT, 'Player_Data');
WriteINI('Player', 'Herb', PCombo.TEXT, 'Player_Data');
WriteINI('Player', 'Task', PCombo1.TEXT, 'Player_Data');
WriteINI('Player', 'Second', PCombo2.TEXT, 'Player_Data');
WriteINI('Script', 'Debug', PCombo3.TEXT, 'Player_Data');
WriteINI('Script', 'World', PEdit[6].TEXT, 'Player_Data');
WriteINI('Script', 'Bank', PCombo4.TEXT, 'Player_Data');
end;
PButton[3]:
begin
PEdit[0].TEXT := ReadINI('Player', 'Name', 'Player_Data');
PEdit[1].TEXT := ReadINI('Player', 'Pass', 'Player_Data');
PEdit[2].TEXT := ReadINI('Player', 'Nick', 'Player_Data');
PEdit[3].TEXT := ReadINI('Player', 'Pin', 'Player_Data');
PEdit[4].TEXT := ReadINI('Stats', 'User', 'Player_Data');
PEdit[5].TEXT := ReadINI('Stats', 'Pass', 'Player_Data');
PCombo.TEXT := ReadINI('Player', 'Herb', 'Player_Data');
PCombo1.TEXT := ReadINI('Player', 'Task', 'Player_Data');
PCombo2.TEXT := ReadINI('Player', 'Second', 'Player_Data');
PCombo3.Text := ReadINI('Script', 'Debug', 'Player_Data');
PEdit[6].TEXT := ReadINI('Script', 'World', 'Player_Data');
PCombo4.TEXT := ReadINI('Script', 'Bank', 'Player_Data');
end;
end;
end;

procedure InitPForm;
var
I, B, W, H :integer;
LCap, BLoc, PGC, BCap :Tstringarray;
PGH, PGW, PGT, PGl, TIW, TIT, TIL, TIH :TIntegerArray;

begin
Lcap := ['Player Name', 'Player Pass', 'Player Nick', 'Player Pin', 'Stats User',
'Stats Pass', 'Player Task', 'Which Herb', 'Secondary', 'Bank', 'World', 'Debug On'];
ComboText := ['Guam', 'Marrentill', 'Tarromin', 'Harralander', 'Ranarr',
'Toadflax', 'Irit', 'Wergali', 'Avantoe', 'Kwuarm', 'Snapdragon',
'Cadantine', 'Lantadyne', 'Dwarf Weed', 'Torsol'];
ComboText1 := ['Clean Only', 'Unfinished', 'Potions'];
ComboText2 := ['Eye of Newt','Ground Unicorn Horn','Limpwurt Root',
'Red Spider egg','Choclate Dust','White Berries','Toad Legs',
'Snape Grass','Mort Myre Fungi','Kebbit Teeth Dust',
'Wimpy Feather','Blue Dragon Scale','Wine of Zamorak',
'Potato Cactus','Jangerberries','Crushed Bird Nest', 'Ashes'];
BLoc := ['BGND.jpg', 'BANNER.jpg', 'CAPE.jpg'];
TIW := [600, 500, 47];
TIL := [0, 50, 505];
TIT := [0, 10, 242];
TIH := [335, 100, 84];
PGC := ['Player Data', 'Script Setup', 'SRL Stats Setup'];
PGL := [15, 230, 230];
PGT := [115, 115, 246];
PGH := [130, 130, 70];
PGW := [200, 356, 230];

PharmForm := Tform.Create(nil);
with PharmForm do
begin
Left := 100;
Top := 100;
Width := 600;
Height := 335;
COLOR := 4144959;
BORDERSTYLE := bsNone;
end;
{=============================== BackGround Images ============================}
for i := 0 to 2 do
begin
PImage[i] := TIMAGE.Create(PharmForm);
with Pimage[i] do
begin
Parent := PharmForm;
Top := TIT[i];
Left := TIL[i];
Height := TIH[i];
Width := TIW[i];
end;
B := LoadBitmap(ScriptPath + BLoc[i]);
GetBitmapSize(B, W, H);
DrawBitmap(B,PImage[i].CANVAS,0,0);
FreeBitmap(b);
end;

{================================ Group Boxes =================================}

for i := 0 to 2 do
begin
PGroup[i] := TGROUPBOX.Create(PharmForm);
with PGroup[i] do
begin
Parent := PharmForm;
Top := PGT[i];
left := PGL[i];
Height := PGH[i];
Width := PGW[i];
CAPTION := PGC[i];
FONT.Style := [FSBOLD];
FONT.Size := 10;
end;
end;

{================================== LABELS ====================================}
for i := 0 to 11 do
begin
if InIntArray([0, 1, 2, 3], i) then
Plabel[i] := TLABEL.Create(PGroup[0]);
if InIntArray([4, 5], i) then
Plabel[i] := TLABEL.Create(PGroup[2])
else
Plabel[i] := TLABEL.Create(PGroup[1]);

with PLabel[i] do
begin
Height := 20;
Width := 50;
FONT.Style := [FSBOLD];
FONT.Color := clRed;
{========================= Label 0..3 (Player Setup) ==========================}
if InIntArray([0, 1, 2, 3], i) then
begin
Parent := PGroup[0];
top := 0 + (i * 30);
Left := 5;
end;
{========================== Label 4 & 5(Stats Setup) ==========================}
if InIntArray([4, 5], i) then
begin
Parent := PGroup[2];
top := 5;
left := 30 + ((i - 4) * 110);
end;
{========================== Label 6..8(Herb & Make) ===========================}
if InIntArray([6, 7, 8], i) then
begin
Parent := PGroup[1];
top := 5 + ((i - 6) * 30);
Left := 5;
end;

{===================== Label 9.. 11(Bank, World & Debug) ======================}
if InIntArray([9, 10, 11], i) then
begin
Parent := PGroup[1];
top := 5 + ((i - 9) * 30);
Left := 190;
end;
Caption := Lcap[i];
end;
end;

{=============================== TEdit Boxes ==================================}
for i := 0 to 6 do // TEdit Key
begin // [0] Name
PEdit[i] := TEDIT.Create(PharmForm); // [1] Pass
with PEdit[i] do // [2] Nick
begin // [3] Pin
Parent := PharmForm; // [4] Stats User
Height := 20; // [5] Stats Pass
Width := 100; // [6] World
top := 128 + (i * 30);
Left := 110;

if InIntArray([4, 5], i) then
begin
Parent := PGroup[2];
Top := 20;
left := 8 + ((i - 4) * 110);
end;

if i = 6 then
begin
Parent := PGroup[1];
Width := 90;
Top := 30;
Left := 260;
Caption := '53';
end;

if InIntArray([1, 3, 5], i) then
PASSWORDCHAR := '*';

if InIntArray([2, 3], i) then
MAXLENGTH := 4;
end;
end;
{================================== TButton ===================================}
BCAP := ['Start', 'Stop', 'Save', 'Load'];
for i := 0 to 3 do
begin
PButton[i] := TBUTTON.Create(PharmForm);
with PButton[i] do
begin
Parent := PharmForm;
Height := 20;
Width := 70;
Left := 30 + (i * 90);
Top := 290;
CAPTION := BCap[i];
ONCLICK := @LeftClick;
if InIntArray([2, 3], i) then
begin
Top := 260;
Left := 30 + ((i - 2) * 90);
end;
end;
end;

{================================= PComboxes ==================================}
PCombo := TComboBox.Create(PharmForm);
{=============================== Herb ComboBox ================================}
with PCombo do
begin
Parent := PGroup[1];
Top := 30;
Left := 80;
Width := 100;
Height := 20;
for i := 0 to 14 do
ITEMS.Add(ComboText[i]);
end;

{=============================== Task ComboBox ================================}
PCombo1 := TComboBox.Create(PharmForm);
with PCombo1 do
begin
Parent := PGroup[1];
Top := 0;
Left := 80;
Width := 100;
for i := 0 to 2 do
ITEMS.Add(ComboText1[i]);
end;
{============================= Secondary ComboBox =============================}
PCombo2 := TComboBox.Create(PharmForm);
with PCombo2 do
begin
Parent := PGroup[1];
Top := 60;
Left := 80;
Width := 100;
Height := 20;
for i := 0 to 16 do
ITEMS.Add(ComboText2[i]);
end;
{=============================== Debug ComboBox ===============================}
PCombo3 := TCOMBOBOX.Create(PGroup[1]);
with PCombo3 do
begin
Parent := PGroup[1];
Top := 60;
Left := 260;
Width := 90;
Height := 20;
ITEMS.Add('True');
ITEMS.Add('False');
Caption := 'False';
end;
{=============================== Debug ComboBox ===============================}
PCombo4 := TCOMBOBOX.Create(PGroup[1]);
with PCombo4 do
begin
Parent := PGroup[1];
Top := 0;
Left := 260;
Width := 90;
Height := 20;
ITEMS.Add('feb');
ITEMS.Add('fwb');
ITEMS.Add('veb');
ITEMS.Add('vwb');
ITEMS.Add('db');
ITEMS.Add('akb');
ITEMS.Add('ctb');
ITEMS.Add('clt');
ITEMS.Add('nab');
ITEMS.Add('sab');
ITEMS.Add('ynb');
ITEMS.Add('ngb');
ITEMS.Add('sgb');
ITEMS.Add('fgb');
ITEMS.Add('ge');
Caption := 'ge';
end;

end;

procedure SafeInitPForm;
var
v: TVariantArray;
begin
setarraylength(V, 0);
ThreadSafeCall('InitPForm', v);
end;

procedure ShowPFormModal;
begin
PharmForm.ShowModal;
end;

procedure SafeShowPFormModal;
var
v: TVariantArray;
begin
setarraylength(V, 0);
ThreadSafeCall('ShowPFormModal', v);
end;

~BraK

E: uploaded the file for easy use.

E2: That's also still a great tutorial.

Flight

2011-05-26 02:59:42

Ah thanks a million, BraK, I'll take a look at yours and see what I'm missing. Hopefully nothing too major.

Edit:
Well I still don't see where I'm going wrong. I mean your form has content, while mine doesn't, but I still use the exact same procedures for calling and displaying the form.

procedure SafeInitForm;
var
v: TVariantArray;
begin
setarraylength(V, 0);
ThreadSafeCall('InitForm', v);
end;

procedure ShowFormModal;
begin
frmDesign.ShowModal;
end;

procedure SafeShowFormModal;
var
v: TVariantArray;
begin
setarraylength(V, 0);
ThreadSafeCall('ShowFormModal', v);
end;

I have these ran in the script to display the form:
SafeInitForm;
SafeShowFormModal;

Did you run Smart while you were running the form?

Flight

2011-05-26 04:29:58

Does this mean anything to you?


Maybe I should pass this along to Wizzup?

BraK

2011-05-26 04:50:47

Means nothing to me. I'd have to check out your code. Wizzup? is looking at it now :)

~BraK

E:


Wizzup?

2011-05-26 04:51:37

Simba debug version would be of more help in this case. :)

Flight

2011-05-26 05:31:11

Ok I have the debug version, I'll run it and see what I get.

Edit:
It completely crashed the debug version of Simba. I didn't even have a chance to see the command prompt. I'll try running the debug version through Windows Command and see what happens.

Coh3n

2011-05-26 12:03:07

Try using this template. I had the same setup as you and my Simba almost always crashed (debug never showed anything, though). Once I switched to this setup the crashing seemed to stop.

http://paste.villavu.com/show/TgNgTamdC1ZpOjzddmfC/

Flight

2011-05-26 20:23:02

Thanks Coh3n, I'll do some experimenting with that. :)

sm0k3

2011-05-26 20:58:24

heres the form for my hiker script.
and i dare say its never yet crashed on me.. :)

procedure LocFormBG;
begin
DrawBitmap(FormBG,TFBG.canvas, 0, 0);
end;

procedure SetupLocForm;
Begin
// Begin BackGround Image
TFBG := TImage.Create(LocForm);
TFBG.Parent := Locform;
TFBG.SetBounds(0, 0, 184, 224);
// End BackGround Image

// Begin Location ListBox
List := TListBox.Create(LocForm);
List.Parent := LocForm;
List.SetBounds(184, 0, 184, 224);
List.ONCLICK := @Go;
// End Location ListBox

// Begin Ok Button
Ok := TButton.Create(LocForm); //Every Object must be created before using it.
Ok.Parent := LocForm; //every object must have a parent (except for TForm) usually its the same as the owner
Ok.SetBounds(80,225, 75, 25); //Adds the Width, Height, Left, and Top in one line.
Ok.Caption := 'Ok';
Ok.ONCLICK := @Go;
// End Ok Button

// Begin Quit Button
CLSQb := TButton.Create(LocForm); //Every Object must be created before using it.
CLSQb.Parent := LocForm; //every object must have a parent (except for TForm) usually its the same as the owner
CLSQb.SetBounds(200,225, 75, 25); //Adds the Width, Height, Left, and Top in one line.
CLSQb.Caption := 'Quit Script';
CLSQB.ONCLICK := @Closeb;
// End Quit Button
End;

function CLocForm(): Boolean;
var
i, h: Integer;
v : TVariantArray;
begin;
Locform := TForm.Create(nil);//creates the form
Locform.Position := poDesktopCenter;
Locform.Width := 184*2;
Locform.Height := 250;
Locform.Caption := 'Hiker - Sm0k3 V'+SVER;
Locform.Color := clBlack;
Locform.BorderStyle := bsSingle;
SetupLocForm;
LocFormBG;
LoadNodes('WorldM');
Locform.ShowModal;//shows the form
ActivateClient;
LocForm.BringToFront
Locform.Free;//frees the object so it doesn't rape your memory
end;


Function StartForm(): Boolean;
var
v : TVariantArray;
begin
ThreadSafeCall('ClocForm', v);
end;

Flight

2011-05-26 21:17:34

Well your template works just fine, Coh3n, but it seems like it waits until you close out the form before doing anything else within the script. For most people this is fine, but I'm using it for different purposes. I'll continue to experiment.

Dgby714

2011-05-26 21:47:46

Heres a example but remember if you do it this way you need to handle closing the form correctly.

program _;

var
Form: TForm;
oLabel: TLabel;
Button: TButton;
Timer: TTimer;

procedure form_update(sender: TObject);
begin
if (Form <> nil) then
Form.Refresh;
end;

procedure Click(sender: TObject);
begin
if (oLabel <> nil) then
oLabel.Caption := 'Clicks: ' + IntToStr(StrToInt(ExtractFromStr(oLabel.Caption, Numbers)) + 1)
end;

procedure form_init();
begin
Form := TForm.Create(nil);
with Form do
begin
Width := 500;
Height := 500;
end;

oLabel := TLabel.Create(Form);
with oLabel do
begin
Parent := Form;
Caption := 'Clicks: 0';
Top := 10;
Left := 10;
end;

Button := TButton.Create(Form);
with Button do
begin
Parent := Form;
Caption := 'Inc';
Top := 100;
Left := 100;
OnClick := @Click;
end;

Timer := TTimer.Create(Form);
with Timer do
begin
Interval := 100;
OnTimer := @form_update;
Enabled := True;
end;

Form.Show;
end;

procedure form_free();
begin
if (Timer <> nil) then
Timer.Free;

if (Form <> nil) then
Form.Free;
end;

procedure callsafe(proc: string);
var
V: TVariantArray;
begin
ThreadSafeCall(Proc, V);
end;

var
I: Integer;

begin
try
callsafe('form_init');
except
WriteLn(ExceptionToString(ExceptionType, ExceptionParam));
end;

for I := 0 to 10 do
begin
WriteLn(oLabel.Caption);
Wait(1000);
end;

callsafe('form_free');
end.

Coh3n

2011-05-26 21:56:45

From: Flight
Well your template works just fine, Coh3n, but it seems like it waits until you close out the form before doing anything else within the script. For most people this is fine, but I'm using it for different purposes. I'll continue to experiment.

I'm confused. Anything that you want done after the form (i.e. code after the form code in the mainloop) you have to wait for it to be closed no matter what.

Dgby714

2011-05-26 21:58:37

From: Coh3n
I'm confused. Anything that you want done after the form (i.e. code after the form code in the mainloop) you have to wait for it to be closed no matter what.


He may want a form that shows debug info? While a script runs?

Coh3n

2011-05-26 22:51:39

From: Dgby714
He may want a form that shows debug info? While a script runs?

I guess, but that's what the debug box is for. Tabbed debugging would be nice. Have a method in mml like SetScriptProps that adds a debug tab to simba. Something like:

var
msiTab: integer;
begin
msiTab := addTab('MSI');
debug(msiTab, 'I''m writing in the MSI tab');
end;
I think that would be cool. How difficult would it be to implement? I've wanted to contribute to Simba for a while and I like working with GUIs. Sorry I got off-topic. :p

Flight

2011-05-27 00:42:14

More or less I suppose. I was wanting to do a separate form with a streaming progress report. I can get it to work with how I had my original form but as soon as I close out Simba will crash on me. Is there some way we check if a form has been closed? Something like…

if Form.destroy then
Form.Free;

Tis wrong… but you get my point.

Coh3n

2011-05-27 01:21:51

Couldn't you call your mainloop in the form init() procedure? Or if you're not using the form for player setup (or it's separate) you may be able to create the "Report Form" and set Form.Visible := False; then when the script starts up, set visible to true.

Not sure if those would work but it's worth a shot.

Flight

2011-05-27 04:47:36

Ok I might try running the script loop through the form, I didn't think about that. I'll try it later, don't want to stop running my Astralz because I testing V1.3 and at the moment I just hit 6 hours running strong. :)

masterBB

2011-05-27 06:49:49

I had an idea an it worked:
program formTemplate;

var
Form: TForm;
StartButton: TButton;
CloseButton: TButton;
Timer: TTimer;

procedure StartLoop(Sender:TObject);
begin
Timer.ENABLED := True;
end;

procedure DoLoop(Sender:TObject);
begin
//DoStuff
writeln('doing all kind of stuff');
end;

procedure DoOtherLoop;
begin
repeat
wait(100);
//DoStuff
writeln('doing all kind of other stuff');
until(False);
end;

procedure CloseForm(Sender:TObject);
begin
Timer.ENABLED := False;
Form.Visible := False;
wait(300);
DoOtherLoop;
end;

procedure Form_Init;
begin
Form := TForm.Create(nil);
with Form do
begin
Caption := 'Form Template';
SetBounds(100, 100, 500, 300);
end;


StartButton := TButton.Create(Form);
StartButton.Parent := Form;
StartButton.ONCLICK := @StartLoop;
StartButton.setBounds(150,150,100,100);
StartButton.CAPTION := 'Start';

CloseButton := TButton.Create(Form);
CloseButton.Parent := Form;
CloseButton.ONCLICK := @CloseForm;
CloseButton.setBounds(300,150,100,100);
CloseButton.CAPTION := 'Close';

Timer := TTimer.Create(Form);
Timer.INTERVAL := 70;
Timer.OnTimer := @DoLoop;
Timer.enabled := false;

Form.ShowModal;
end;

procedure Form_SafeCall(Proc: string);
var
v: TVariantArray;
begin
SetLength(v, 0);
ThreadSafeCall(Proc, v);
end;

procedure Form_Free();
begin
Form.Free();
end;

begin
ClearDebug();

try
Form_SafeCall('Form_Init');
except
Writeln(ExceptionToString(ExceptionType, ExceptionParam));
finally
Form_SafeCall('Form_Free');
end;
end.

Dgby714

2011-05-27 08:43:46

Did no one look at mine? It works exactly how you want….

o and its
if (Form <> nil) then
Form.Free;

Flight

2011-05-27 08:48:30

From: Dgby714
Did no one look at mine? It works exactly how you want….

o and its
if (Form <> nil) then
Form.Free;


That makes sense. I'll test it soon. :)

Home

2011-05-27 09:38:15

Guys. All your templated what i tested in this thread occurs these:

Simba will totally close.
Simba will become not responding state / crash. :(

~Home

masterBB

2011-05-27 09:49:17

From: Home
Guys. All your templated what i tested in this thread occurs these:

Simba will totally close.
Simba will become not responding state / crash. :(

~Home


Mine doesn't… just don't use the close button in the top right corner of the screen but big ass self made one.

Flight

2011-05-27 20:20:28

From: masterBB
Mine doesn't… just don't use the close button in the top right corner of the screen but big ass self made one.


If this is true then it would be a problem with Simba closing forms rather than everyone's templates.

masterBB

2011-05-27 20:40:11

The point is this, if you still got a certain procedure running, and you run a second one. The pascal script is going to crash. Using a timer, like in my form will work, but only hides the form. Cause you can't destroy the form when there is still a procedure from it running.

Yago

2011-05-27 21:04:11

Maybe MSI has the same problem?