Checking form's existence doesn't work - forms

I have a Form for which I coded my own constructor:
constructor Create(AOwner: TComponent; AParent: TWinControl; ASender: TMyClass;
ATab: String); reintroduce; overload;
To create such a form I use the following:
try
MyForm := TMyClassForm.Create(nil, Self.Parent, Self as TMyClass, 'FirstTab');
MyForm.ShowModal;
finally
MyForm.Free;
end;
Somewhere else, before starting a procedure, I need to check whether this form is opened or not, so I check its existence with:
if (Assigned(MyForm)) and (MyForm.Active) and (MyForm.Showing) then
// Don't do the procedure
else
// Do the procedure
Now, if I open the form and close it, and I check this conditional statement, everytime I get true, but the Form is not opened and not showing anymore, because I freed it after creating.
Any idea of what could be the problem?

You called Free on the MyForm global method, but you did not modify the reference. So, MyForm still refers to the now destroyed form. And so Assigned(MyForm) evaluates as True, and then the other two tests operate on the stale object reference. Anything could happen when you operate on a stale object reference. In the situations that you have tried, it seems that the operations both return True. But another time you might get an access violation.
You'll want to set the MyForm variable to nil after call Free. At the risk of re-starting the great religious Delphi war of our times, you might contemplate using FreeAndNil(MyForm) in place of MyForm.Free.
You might find my answer here to be instructive: Why should I not use "if Assigned()" before using or freeing things?

Init:
MyForm := nil;
User FreeAndNil(MyForm)
if (Assigned(MyForm)) then
DON'T DO THE PROCEDURE
else
DO THE PROCEDURE

Related

Cannot create class in AHK after destruction

I'm trying to wrap my head around classes in AHK. I'm C++ dev, so would like to make use of RAII (__New, __Delete), but it looks like I miss some concepts since things look very contra-intuitive for me.
After some tries I came up with this simple example:
class Scenario
{
__New()
{
MsgBox, NEW
}
__Delete()
{
MsgBox, DELETE
}
}
scenario := new Scenario
scenario := new Scenario
scenario := 1
scenario := {}
scenario := new Scenario
Return
As a result I get the following messages:
NEW
NEW
DELETE
DELETE
Questions:
Why doesn't the object get destroyed during the second assignment? I'd assume the number of refs going to 0, no?
How come I get 2 destructions in a row? Where was that object stored meanwhile? How could scenario variable hold both references?
Why was not the third construction called?
Why doesn't the object get destroyed during the second assignment?
Garbage collection had not been triggered yet
I'd assume the number of refs going to 0, no?
References going to 0 does not necessarily trigger GC
How come I get 2 destructions in a row?
Garbage collection cleaned both references at the same time
Where was that object stored meanwhile?
The heap
How could scenario variable hold both references?
scenario does not hold both references
Why was not the third construction called?
Only two Scenario objects are constructed. The variable scenario is a dynamic variable and is not always an instance of the class Scenario. The last assignment scenario := {} just creates an empty object.
Ok, found out what was missing. Two things:
AHK script is case-insensitive.
Since class is an object by itself in AHK it's possible to override the class by another object.
Here is a piece of the documentation:
Because the class is referenced via a variable, the class name cannot be used to both reference the class and create a separate variable (such as to hold an instance of the class) in the same context. For example, box := new Box would replace the class object in Box with an instance of itself. [v1.1.27+]: #Warn ClassOverwrite enables a warning to be shown at load time for each attempt to overwrite a class.
This explains what happened in the code above: variable name scenario is effectively the same as a class name Scenario, so I just quietly overrode my class with an empty object.
Also, since the new instance of the class is created before assignment, I got two 'NEW' in a row, only than 'DELETE'.

Does every Class we create in Delphi need to have destructor?

When I create my custom Class in Delphi Application I use standard procedure:
TCustomClass = Class
private
var1,var2 : integer/string/Real/Boolean...
procedure P1...
function F1...
public
constructor Create;
end;
...
CustomClass := TCustomClass.create;
I want to know do I always have to also create Destructor procedure or are resources automatically free when application closes?
I always use Application as owner, rarely Self or Nil and I don't remember I saw anyone declaring Destructor on classes I saw on Internet, except for one when someone used pointers.
Is the logic behind destructor same in Delphi as in C++ as described in this question:
Should every class have a virtual destructor?
Thanks in advance.
EDIT1:
As Free Consulting mentioned I forgot to say that one of the variables might be TBitmap type
It only needs to have a destructor if you need to clean up something, like allocated memory. For example, if you have used TClassname.Create(...) in the constructor, you need to free in the destructor method.
Of course there can be many different reasons to need a destructor (all the way up to informing the user that his data is about to get wiped), but this is the most common one.

Create Form // Tabsheet // access Methods on Form

I am writing an application like this:
There is a main form with a PageControl on it,
In the Page Control I create Tabsheets,
In the Tabsheets, forms are placed.
This helps because the user can create one type of form more than once, like a standard pdf viewer opened in more than one tab, but displaying different data, in essence its the same form.
This works very well and is very useful! Unfortunately something important isn't working, this is the problem:
This code will work fine:
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption := 'Hello';
end;
The caption will change, however, if I would like to call a method instead, like this:
Procedure changeLabel(str : String);
Begin
Form1.Label1.Caption := str;
End;
procedure TForm1.Button1Click(Sender: TObject);
begin
changeLabel('Hello');
end;
I get an access violation at Form1.Label1.Caption := str; in the procedure
Here is how I created the form:
procedure TfrmPage.CDMA1Click(Sender: TObject);
var
TabSheet: TTabSheet;
frmTest : TForm;
begin
TabSheet := TTabSheet.Create(PageControl1);
TabSheet.Caption := 'kjklhhj';
TabSheet.PageControl := PageControl1;
frmTest := TForm1.Create(Nil);
frmTest.Show;
frmTest.Parent := TabSheet;
end;
I did everything as everyone said here: another stackoverflow question
My Question, how can the newly created form, pinned to the Tabsheet, access its own procedures without throwing exceptions? Another piece that might be important: When I have delphi Auto-Create the form, theres no access violation but the method does nothing to the form, so I think the procedure might be changing things on the wrong form, one thats not created yet (which gives AV), and not to the one i just created, or the application is not calling the method on my new form, but calling one somewhere where that form isn't created yet.
If I auto-create the form, calling the procedure probably changes the label on the form that was created when the application started and not the new form..
Any help would be appreciated, as I've been googling for hours now with no real help to this problem
Thanks in advance :)
If you plan to create several instances of the TForm1 class, it is correct to not auto-create Form1. In fact you should delete the Form1: TForm1 declaration altogether to reduce the risk of errors.
You probably want to keep references to the forms you create f.ex. in a TList, possibly hosted by the TfrmPage instance depending on what TfrmPage is. (See below in discussion about AV)
Access Violation
When you created an instance of TForm1 in TfrmPage.CDMAClick() you assigned the reference of the created form to a local variable frmTest and then you show it in a tabsheet. You can click Button1 and change caption of Label1. However when you call the ChangeLabel procedure you state
Form1.Label1.Caption := str;
but the Form1 variable has never been assigned, therefore is nil and the AV is triggered. Now, since you assigned the forms reference to the local frmTest variable in TfrmPage.CDMAClick() you don't really have any reference anymore to the form, and cannot access it (actually, since you parented it to the tabsheet, you can search for it in the tabsheets controls). This is why I suggested to keep references to the forms you create in a list. Then you can access the forms through that list when needed.
My Question, how can the newly created form, pinned to the Tabsheet,
access its own procedures without throwing exceptions?
You can always access an objects methods, fields and properties from the object itself without using a reference variable. In fact, you should never use the objects reference variable from within the object:
Label1.Caption := 'Whatever'; // correct from within the form
Sometimes it may be necessary to use a reference within the object and for that purpose you can use self f.ex.:
self.Label1.Caption := 'Whatever'; // self can be used if needed
From an external method/procedure/function you need to use a reference to the object
Form1.Label1.Caption := 'Whatever'; // assuming Form1 has been assigned

Xamarin Sport App - What does IsDirty do?

I am looking through the Xamarin Sport app code and trying to understand some of the cool things they are doing in it. I cannot understand what IsDirty is being used for exactly. It gets defined here and implemented here and used in many places, such as here.
I read a little about and ICommand's IsDirty property so maybe it is a way to call an entire model as being dirty, but what implications does that have?
I also see it being used here which I am assuming is why they created it in the first place.
Thanks for y'all's insight into it.
They're just using it as a clever way to handle modification detection. Consider a "Save Changes" feature; you don't actually want to enable the "Save" button until something has changed, and you can key off the IsDirty property to test that.
Technically, you could handle this yourself by having a base class hook INotifyPropertyChanged.PropertyChanged and maintaining a dirty bit of your own (possibly in a base class), but rather than require all of their classes to have an IsDirty property that they may or may not need, they've made it an optional feature that a class can implement. For example, take a look at GameResult for an example of something that can't be changed, and therefore, can't be marked as dirty.
With this approach, you've minimized the amount of code you need to write to implement this functionality. All your derived classes need to do is derive from BaseNotify, implement IDirty, and call SetPropertyChanged(...) as the setter to set the private tracking field, signal to any observers that a property has changed, and automatically set the dirty bit.
NOTE: I did just make an interesting observation: while the implementation of the SetProperty extension method does set the IsDirty flag, the BaseNotify class' IsDirty implementation doesn't call anything to bubble up a PropertyChanged event for IsDirty, which means bindings against it won't get updated when it changes. I believe the fix would be for that extension method to invoke PropertyChanged with the property name "IsDirty":
if(dirty != null) {
dirty.IsDirty = true;
handler.Invoke(sender, new PropertyChangedEventArgs("IsDirty"));
// Yes, I'm a bad person for hard-coding the name.
}
Alternately, you could defer signaling the IsDirty change until after you signal the original property has changed. I just chose to keep it with the original logic.
I think it's relatively simple and you're on the right track: the purpose of that property is to have an easy way to know whether some property has been changed, so the whole object has to be saved. It's baked in to the way property changes are propagated, so you don't have to set it by yourself whenever a property value is being set.
tl;dr: You can use it to check if you your (view)model is worth a save operation ,-).

zend_form access parent form element

I couldn't find any reference on how to use a parent form element in a subclassed form. May be because it's obvious to everyone but me. It's got me stumped. This is what I tried.
At first, within my form constructor I called
parent::__construct($options = null);
then accessed the parent elements like this
$type = parent::setName($this->type);
The problem was that ALL the parent form elements would display whether explicitly called or not. Someone said, "don't use __construct(), use the init() function instead. So I changed the constructor to init(), commented out the parent constructor, then ran the form. It bombed saying it couldn't pass an empty value for setName(). I commented out all the seName() calls and the form ran, but only displayed the elements instantiated in the subclassed form.
My question is this: If I don't use the parent constructor, how do i get and use the parent's form elements?
Solved: Since the constructor was switched to init, the call to the parent also needed to be switched. Easy for someone with php background. Not so much for one who doesn't.
Use
parent::init();
Solved: Since the constructor was switched to init, the call to the parent also needed to be switched. Easy for someone with php background. Not so much for one who doesn't.
Use
parent::init();
You should learn OOP principles first. Obviously you have no understanding of it whatsoever. You need to call parent::init() in you Form_Class::init() method as you wrote, but why? Because otherwise the parent method is not called and is overriden by the From_Class method.
Other thing is that when you have a parent class "SuperForm" with input and submit, then your "SuperForm_Subclass" would have the same elements assigned. There is no need to use "parent::*" to access element (only exception would be if you used static SuperForm variable to store them - which makes no sense).
You can easily use $this->inputElement and $this->submitElement inside your SuperForm_Subclass like you would in the SuperForm class.
In your example you could used the __contruct() as good, but with the same condition of calling the parent constructor. You would be able to access elements generated there too...