Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have a problem about Delphi source code.
Please help me explain it.
Detail problem as below:
I have two Delphi applications. They are two .dll files (it call App1 and App2).
App1 has a method as below:
procedure SetImage( objControl : Object; img: Pointer);
begin
objControl.Picture.Bitmap := img;
end;
In App2, I call above method of App1 as below to display image on report.
SetImage( objPreImgs, tempJPEG );
With objPreImgs is correct object and temJPEG is TJPEGImage object.
If I compile App1 and App2 with Delphi 7, there is not any problem.
If I compile App1 with Delphi 7 and App2 with Delphi 6, there is one problem (cannot display image on report).
I have not known root cause of above problem yet.
If you know, please explain for me.
p/s: App1 cannot compile with Delphi 6.
Despite the fact that both "apps" share a common memory area, each of them:
uses its own memory manager,
have their own VMT (virtual method table)
and the object model.
Thus, when you pass a pointer to an object in another "application", it considers its own and is looking for methods in own VMT. Naturally, D6 VMT differs from D7, which leads to AV, stack overflow and other errors.
So, you can`t pass objects and classes via dll | apps.
Returning to the task: you need to pass the contents of an image in a way that does not require the use of objects, for example - using iStream or SharedMemory. Also you can pass a handle to the image, because the handle is "global" value for both dll in the unified address space of the application. But...the first procedure (SetImage) is not necessary - this action must be performed in app2.
It cant compile because it's not the correct syntax
First of all objControl : Object should be objControl : TImage
img: Pointer should be img: TBitmap
objControl.Picture.Bitmap := img; shoud be objControl.Picture.Bitmap.Assign(img);
I belive you need a beginners book
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I know dynamic objects are objects created during run time. I have to make use of dynamic objects for a project, but not quite sure what to do. I'm not too sure what dynamic objects actually are except for the definition and for example once a button is clicked a panel is created, but this isn't exactly what is wanted from me. It is supposed to be more complex and meaningful.
What are other examples of dynamic objects and when or why would you use it?
Any instance of a class created at runtime in your code, and freed when you no longer need them. This happens all the time for classes that aren't visual components and can't just be dropped on a form.
Basic examples are things like TStringList for working with strings or text files, TStream descendants like TFileStream or TResourceStream, threads using TThread, generic lists such as TList<T>, and many other classes.
For instance, to work with a text file, an example of a dynamically created TStringList could be as follows:
var
SL: TStringList;
begin
SL := TStringList.Create;
try
SL.LoadFromFile('C:\Temp\MyFile.txt');
SL[0] := 'I changed this line.';
SL.SaveToFile('C:\Temp\MyFile.txt');
finally
SL.Free;
end;
end;
This sounds like a class project, and you don't seem to understand some of the terminology involved.
Just to generalize on this a little bit, in Delphi, instances of ANY class you define need to be created dynamically. This contrasts with records, which can be declared statically as variables as well as allocated dynamically.
In both cases (classes and records), when you create an instance dynamically, the memory for them is allocated from the heap, rather than the stack (where local vars are created). But the syntax is different in each case.
In Delphi, this contrasts sharply with C++, because C++ classes are basically structs (like Delphi records) with some embellishments, meaning that you can declare instances of classes in C++ as member variables where their memory is allocated on the stack in the same way you can declare instances of structs, as well as records in Pascal.
But this doesn't work in Delphi, even though the syntax looks the same. That's because in Delphi, the variables referring to classes are really pointers, like in C++, but they're automatically dereferenced, so they look syntactically as if they're just instances rather than a pointer-to-an-instance.
In Delphi, if you're working with a class, you MUST create it dynamically (by calling TMyObj.Create(...)). Thus, every class has a constructor associated with it; if you don't define one, the default TObject.Create constructor is called. (This is again different than in C++ where a default constructor will be created for you by the compiler for any class that needs one and it's not defined.)
I'll repeat this again so you're clear about it. Anything defined like THIS in Delphi:
type
Twhatever = class
is equivalent to this:
type
Twhatever = class( TObject )
and absolutely MUST be created dynamically in your code like this:
var
xyz : Twhatever; // xyz is really a pointer here! It's NOT an "instance"
begin
xyz := Twhatever.Create(); // you need to create an instance using the Create() method
try
// do some stuff
finally
xyz.Free;
end;
You cannot NOT use xyz without first creating an instance of it via it's .Create method.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I was looking at all the examples shipped with RAD Studio xe6 when I came across the custom listbox example located at
Object Pascal > FireMonkey Desktop > CustomListBox
Trying to play with it and see what modifications I could do, I decided that it I wanted to create a for loop that would get the visible or not property for each object. The thing though is that I can't understand what the following line actually means.
107| Item.StylesData['visible.OnChange'] := TValue.From<TNotifyEvent>(DoVisibleChange); // set OnChange value
It adds an onChange event, but how exactly? What is TNotifyEvent, is that how we tell the compiler to create a new event?
Thanks.
The FireMonkey styles framework has been designed to be flexible and extensible. It is introduced at the root of the styled control hierarchy, TStyledControl. This article gives a brief introduction and explanation of the philosophy behind the design.
Because the styling framework is designed to support many different types of controls, there is a clear need for flexibility and extensibility. So you see code like this:
StylesData['visible.OnChange'] := ...
The StylesData property is an array property, indexed with a string. It is declared like this:
property StylesData[const Index: string]: TValue;
The TValue type is the modern variant type that is used throughout the RTL. So, we gain flexibility by allowing StylesData to hold any kind of object, by means of using a variant type, TValue. And we have extensibility by allowing named indices.
So, the control that you are referring to allows you to customise its behaviour when its visibility changes. It does so by checking for a style named visible.OnChange that is expected to be of type TNotifyEvent. We cannot supply the TNotifyEvent directly, we have to wrap it in a TValue. And hence the call to TValue<TNotifyEvent>.From().
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I created an empty unit to store my public procedures and functions but I get access violation in the first line of a procedure, but this for the first time only I call this procedure, later calls work normally !!
The unit code:
unit myFunc;
interface
uses
Windows, Messages, SysUtils, System.UITypes, Variants, Classes, Graphics, Controls, Forms;
Procedure GSet(grid_form: TForm; app, operation: string);
implementation
Procedure GSet(grid_form: TForm; app, operation: string);
var
grd_idx: integer;
begin
if operation = 'save' then begin // Access violation in this line
if (grid_form.components[grd_idx] is TMyComponent) then
(grid_form.components[grd_idx] as TMyComponent).Storedata('c:\'+app);
end;
end;
Update:
I call this procedure from form create event like this
GridSettings(myform, 'cost', 'save');
From the code in the question, the most obvious mistake is that the variable grd_idx is not initialised. You must initialise variables before using them.
On top of that it is possible that you are passing an invalid object reference in the first parameter. We cannot tell from here. However, it is possible that you are passing a global variable that has not been initialised. It looks awfully like you should be passing Self rather than that global variable.
GridSettings(Self, 'cost', 'save');
Of course, I am assuming here that Self is what you intend to pass here. Since you did not supply very much code, we can only guess as to the details of your code.
You ask how to make the OnCreate event fire after all controls are created. Well, that is already the case. The OnCreate method is fired after the controls are created and their properties streamed in.
I would also comment that using strings to select discrete options is not a good idea. Use enumerated types for that.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
In our Delphi 2007 application we are using a lot of the following constructs
FdmBasic:=TdmBasicData(FindOwnerClass(AOwner,TdmBasicData));
The FindOwnerClass travels the Owner hierarchy of the current component upwards to find a specific class (in the example TdmBasicData). The resulting object is stored in the Field variable FdmBasic. We use this primarily to pass datamodules along.
Example:
When generating a report, the resulting data is compressed and stored in a Blob field of a table accessed through a datamodule TdmReportBaseData. In a separate module of our application, there is functionality to show the data from the report in a Paged form using ReportBuilder. The main code of this module (TdmRBReport), uses a class TRBTempdatabase to convert the compressed blob data into different tables that are usable in the Reportbuilder runtime reportdesigner.
TdmRBReport has access to TdmReportBaseData for all kinds of report-related data (type of report, report calculationsettings, etc). TRBTempDatabase is constructed in TdmRBReport but has to have access to TdmReportBasedata. So this is now done using the construction above:
constructor TRBTempDatabase.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
FdmReportBaseData := TdmRBReport(FindOwnerClass(Owner, TdmRBReport)).dmReportBaseData;
end;{- .Create }
My feeling is that this means that TRBTempDatabase knows a lot of its owner, and I was wondering if this is some sort of code smell or Anti-pattern.
What are your thoughts about this? Is this a code smell? If so, what is a better way?
On the description presented here I regard this as mildly smelly. However, it seems easy to fix.
I'd be inclined to pass the dmReportBaseData object into the constructor of any component that needs it. This makes the contract clear at compile time rather than enforcing it at runtime as you currently do.
As it currently stands, the contract you enforce is stronger than it needs to be. Although TRBTempDatabase only requires a dmReportBaseData instance, it will only function if it can get that instance from a TdmRBReport report object.
Making this change would also allow TRBTempDatabase and TdmRBReport to have a divorce and still function successfully. And as #Lieven points out in the comments, this would likely make testing easier.
If all you're doing in a base class is maintaining a reference to a parent object then no, it's not code-smell, it's a perfectly legitimate use. You can explicitly design a base class to carry information about "something that might come later."
If the base class is relying on some characteristic of the derived class that isn't present in itself (i.e. the generalized class relies on a specialization of one of its children) then yeah, that might be a bit funky.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
It happens to me quite often that I call a function Foo and want to know what exceptions this function might throw. In order to find out I then look into the implementation of Foo, but that is not enough. Foo might indeed call a function Bar that raises an exception.
Sometimes I even miss Java's checked exception handling.
So it is obivous to me that it is necessary to document the exceptions each function can throw: the question is: how? Are there any best practices on how to document exceptions? How do you handle this problem?
I think this covers some part of the problem you became aware of
Cleaner, more elegant and wrong
Cleaner, more elegant and harder to recognize
Most Delphi applications are VCL applications. They do not require a checked exception, because the main message loop has a try/except block catching everything.
It can be good practice to document which exceptions can be explicitly raised by your code though.
I'd use XMLDoc for that (there are various questions on XMLDoc her on SO, and here is some documentation from Embarcadero).
Note however that underlying code can also raise exceptions. Depending on the influence you have on libraries, you can or cannot assure those are always the same. A different thing is the OS: depending on where you run, you can get different exceptions.
--jeroen
We use Javadoc style comments for documentation. We extract the info and generate the output with some simple text scripts. We have used DelphiCodeToDoc, too.
Documenting exceptions, we have mandated to use the #throws tag.
this is looking great for documenting code - Documentation Insight from DevJet.net
I use XMLDoc comments. It's basically adding a specialized type of comment to your code in the interface section, just above the property or method declarations. Here's a nonsensical (of course) example. If you add similar style comments in your code, they'll pop up in Code Insight when you invoke it while writing code, just like the VCL's documentation does.
type
{$REGION 'TMyClass description'}
/// <summary>TMyClass is a descendent of TComponent
/// which performs some function.</summary>
{$ENDREGION}
TMyClass=class(TComponent)
private
// your private stuff
FSomeProp: Boolean;
procedure SetSomeProp(Value: Boolean);
protected
// your protected stuff
public
{$REGION 'TMyClass constructor'}
/// <summary> TMyClass constructor.</summary>
/// <remarks>Creates an instance of TMyClass.</remarks>
/// <param>Owner: TObject. The owner of the instance of TMyClass</param>
/// <exception>Raises EMyObjectFailedAlloc if the constructor dies
/// </exception>
{$ENDREGION}
constructor Create(Owner: TObject); override;
published
{$REGION 'TMyClass.Someprop'}
/// <summary>Someprop property</summary>
/// <remarks>Someprop is a Boolean property. When True, the
/// thingamajig automatically frobs the widget. Changing this
/// property also affects the behavior of SomeOtherProp.</remarks>
{$ENDREGION}
property Someprop: Boolean read FSomeProp write SetSomeProp;
end;
I prefer to wrap these XMLDoc comments in regions, so they can be collapsed out of the way unless I want to edit them. I've done so above; if you don't like them, remove the lines with {$REGION } and {$ENDREGION}
I use PasDoc for documenting almost all of my Delphi projects. It includes a "raises" tag which does what you seem to be asking for.
Regards
- turino