So basically here is what I did:
I made a new FMHD Application and dropped a TTabControl and a Button on it. Then I designed an interface IFoo. To keep it simple, let's just pretend it only has one procedure:
type
IFoo = interface
['{D035-N07-M4773R-...}']
procedure makeTab(tc : TTabControl);
End;
I implemented this interface in a DLL. The DLL is loaded via LoadLibrary and exports a
function getFoo : IFoo;
MakeTab basically creates a TTabItem and sets tc as it's parent:
procedure TFoo.makeTab(tc : TTabControl);
var
tab
: TTabItem;
begin
tab := TTabItem.Create(tc);
tab.text := 'Hi, I am Tab';
tab.Parent := tc;
// ...
end;
If I forgot something, I am very sorry. I do not have the exact source in front of me at the moment.
This method is invoked when the Button on the form is pressed.
But nothing happens.
So I put this method into my TForm1 class. If I call it now, a tab is created.
So how can I create this tab (and several child components) from within the DLL on the application's main form?
The fundamental issue here is that you cannot share Delphi class types between modules using DLLs. The reason is that there will be multiple versions of what needs to be a single type. One version in the executable, and one version in each DLL that uses it.
This is the same well known issue that exists with the VCL and is the reason why runtime packages were developed. And that's your solution for FMX also. If you need to share Delphi class types between modules you need there to be one single definition of a type. And runtime packages are the mechanism that makes that possible.
So, stop using DLLs, move the code into a runtime package, make sure that the RTL and FMX are linked using runtime packages, and that problem will be solved.
Related
I built a wrapper around the TWebBrowser in Delphi. The wrapper aims at implementing multiple web browsers (edge chromium, chrome etc) into a single wrapper that auto detects which browser to use.
After I completed the class I turned said class into a VCL component and loaded it into a design time package. My component includes only two files, the wrapper itself and a utilities class. When I drag my component from the tools palette onto a VCL form the wrapper and the utilities class are not added automatically to the project. This means I have to manually include both the wrapper and the utility into the project.
I was hoping there was a way to automatically include these two files into the project when the wrapper is added to the form. I think I have seen this before with other third party components I have used but my memory may be failing me.
If this is a thing that can be done, my assumption is that it would be in the register section of the VCL component.
procedure Register;
begin
RegisterComponents('My Wrappers', [TWebBrowserWrapper]);
end;
As that is the code that I believe is run when in design time.
Have your design-time package implement a class that inherits from TSelectionEditor and overrides its virtual RequiresUnits() method, and then register that class for your component using RegisterSelectionEditor(). This way, whenever you place your component onto a Form/Frame/DataModule Designer at design-time, any additional units you report from RequiresUnits() will be added automatically to that unit's uses clause when the unit is saved.
For example:
uses
..., DesignIntf;
type
TWebBrowserWrapperSelectionEditor = class(TSelectionEditor)
public
procedure RequiresUnits(Proc: TGetStrProc); override;
end;
procedure TWebBrowserWrapperSelectionEditor.RequiresUnits(Proc: TGetStrProc);
begin
inherited RequiresUnits(Proc);
// call Proc() for each additional unit you want added...
Proc('MyWrapperUnit');
Proc('MyUtilityUnit');
end;
procedure Register;
begin
RegisterComponents('My Wrappers', [TWebBrowserWrapper]);
RegisterSelectionEditor(TWebBrowserWrapper, TWebBrowserWrapperSelectionEditor);
end;
I'm currently struggling with the following:
I need to create two different DLL's, which do exactly the same but are looking to a different DB. The two DB's are nothing alike.
My dll's should be handling the communication with those different DB's.
So that the main program chooses which dll he wants to use.
I want to be sure each dll has exactly the same procudes/functions/...
I was thinking of using interfaces.
But I can't figure out how to create global interfaces. the dll's belong to the same projectgroup.
I do believe you're making a "mountain out of a molehill" thinking you need 2 different DLLs. But if you choose the last of my suggested options, you should find it fairly easy to switch between a 2 DLL solution and 1 DLL solution.
Option 1
This is the most straightforward:
Create a new unit.
Add your DLL interface (the exports).
Include the unit in both projects.
unit DllExportIntf;
interface
uses
DllExportImpl;
exports DoX;
implementation
end.
Note that this unit uses DllExportImpl which will also have to be included in both projects. However, you'll need 2 different files with the same name in 2 different locations in your file system. So each DLL project will have different implementations.
Now whenever you make a change to your interface, your projects won't compile until you've updated each of the DllExportImpl units.
What I don't particularly like about this solution is the need for units with the same name but different behaviour. Since you intend having both DLLs in the same project group: I should warn you that I've experienced the IDE getting confused by duplicate unit names.
Option 2
Place the exports into a shared include file.
library DllSharedExportsImpl1;
uses
DllExportImpl1 in 'DllExportImpl1.pas';
{$I ..\Common\DllExports.inc}
The DllExports.inc file will only include your exports clauses. E.g.
exports DoX;
This has the advantage that now each DLL can use different unit names for the different implementations. And if you change your include file, neither project will compile until you've updated its implementation unit to accommodate the change.
Note that this does come with its own set of problems. The way includes work: the compiler effectively shoves the contents of the include file into the unit at compile time. So what looks like line 7 to the IDE is entirely different to the compiler. Also editing include files can be a bit of a nuisance because context can only be determined where the file is included making editor support quite impractical.
Option 3
This option is a little more work, but provides much better long-term maintainability.
You do this by implementing your interface via polymorphic objects. In this way, both DllProjects will also share the routines that are actually exported. When each DLL initialises, it sets the concrete implementation to be used.
Your DLL interface could look something like this.
unit DllExportIntf;
interface
type
TAbstractImpl = class(TObject)
public
procedure DoX; virtual; abstract;
end;
procedure AssignDllImpl(const ADllImpl: TAbstractImpl);
procedure DoX;
exports DoX;
implementation
var
GDllImpl: TAbstractImpl;
procedure AssignDllImpl(const ADllImpl: TAbstractImpl);
begin
if Assigned(GDllImpl) then
begin
GDllImpl.Free;
end;
GDllImpl := ADllImpl;
end;
procedure DoX;
begin
GDllImpl.DoX;
end;
end.
When you initialise your DLL, you can call:
AssignDllImpl(TDllImpl_1.Create);
A clear advantage of this approach is that if there is any common code between your 2 DLLs, it can be included in your base implementation. Also, if you can change an existing method DLL in such a way that it does not require a change to TAbstractImpl, you possibly will only need to recompile your DLLs.
Furthermore, if you need to change existing virtual abstract methods, you will have to update the overrides in your concrete implementations accordingly.
WARNING If you add a new virtual abstract method, your projects will still compile with warnings that you are creating objects with abstract methods. However, you should always treat warnings as errors. If you do, this caveat won't be a problem.
NOTE: As mentioned earlier, using this approach you should be able to fairly easily switch between single DLL and 2 DLL solutions. The difference basically boils down to which units are included in the project, and how you initialise the global.
It may also be worthwhile mentioning that you could even eliminate the global altogether by implementing a Handle to use with each of your DLL routines. (Similar to Windows.) Bear in mind that there are technical issues when trying to pass objects between DLL and application code. This is why instead of passing objects, you use a "handles" to objects and encapsulate the actual object instances internally.
Considering all that was said, I believe that you would be more successful if you design your solution with packages, not DLLs. A package is a DLL, but rich in symbols, so Delphi can be a better use of it. Particularly, the symbols declared inside the package will more easily be loaded by your application, with a much higher level of abstraction. It´s what the Delphi IDE uses to load components.
So, following this design, this is what you have to do:
Declare your interfaces in units existing in a package named (for instance) DBServices.dpk. Here is an example of such an unit:
unit DBService1;
interface
uses
....;
type
IService1 = interface
[....] // here goes the GUID
procedure ServiceMethod1;
procedure ServiceMethod2;
// and so on...
end;
implementation
end.
So, above you created an unit that declares an interface. Your aplication can use that interface anywhere, just reference the package in your application and use it in other units and you will have the access to the symbols declared.
Declare the implementation class for that very same interface in another unit of another package, for instance, dedicated to SQLServer (SQLServerServices.dpk):
unit SQLServerService1;
interface
uses
DBService1, ....;
type
TSQLServerService1 = class(TInterfacedObject, IService1)
protected // IService1
procedure ServiceMethod1;
procedure ServiceMethod2;
// and so on...
end;
implementation
procedure TSQLServerService.ServiceMethod1;
begin
// Specific code for SQL Server
end;
procedure TSQLServerService.ServiceMethod2;
begin
// Specific code for SQL Server
end;
...
end.
Above you declared an implementing class for the interface IService1. Now you have two packages, one declaring the interfaces and other implementing those interfaces. Both will be consumed by your application. If you have more implementations for the same interfaces, add other packages dedicated to them.
One important thing is: you have to have a factory system. A factory system is a procedure ou class that will create and return the implementations for your application from each package.
So, in terms of code, in each service package (the ones that implement the interfaces) add a unit named, for instance, xxxServiceFactories, like this:
unit SQLServerServiceFactories;
interface
uses
DBService1;
function NewService1: IService1;
implementation
uses
SQLServerService1;
function NewService1: IService1;
Result := TSQLServerService1.Create;
end;
end.
The code above declares a function that creates the SQL Server implementation and returns it as an interface. Now, if you call a method from the interface returned, you will be actually calling the specific implementation of it for SQL Server.
After loading the package, you will have to link to that function in the very same way you would do if working if a DLL. After you have the pointer for the function, you can call it and you will have the interface in your application's code:
...
var
service1: IService1;
begin
service1 := NewService1;
service1.ServiceMethod1; // here, calling your method!
end;
The model I described in this answer is the one I used in a similar scenario I had to deal with in the past. I presented general ideas that work, but you have to understand the fundamentals of packages and interfaces to really master the technique.
A comprehensive explanation on those matters would be very long for an answer here, but I guess it will be a good starting point for you!
What you want to do is create a COM component project. Define your methods on that & implementations for one DB. Then create a second COM component that uses the same interface.
On the off-chance that your question is more about the fundamentals of Delphi, I've added another answer which may be more helpful to you than the first one. My first answer focused on getting 2 DLLs to expose the same methods (as per the main body of your question). This one focuses on the last 2 sentences of your question:
But I can't figure out how to create global interfaces. The dll's belong to the same project group.
Based on this, it sounds like you're looking for an option to "mark an interface as global so that projects in the same group can use them". Delphi doesn't need a special feature to do this because it's trivially available if you understand certain fundamental principles.
When you create a new unit, it is by default added to the current project. However if you want to share the unit between multiple projects, it's a good idea to save it to a different folder so it's easy to see that it's shared. Your first DLLs project file should look something like this.
library Dll1;
uses
DllSharedIntf in '..\Common\DllSharedIntf.pas';
You can define your "global" interface in the DllSharedIntf unit. E.g.
unit DllSharedIntf;
interface
type
IDllIntf = interface
['{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}']
procedure DoX;
end;
implementation
end.
NOTE: Because the interface type is declared in the interface section of the unit, it is considered "global" because other units are able to use it. But this doesn't automatically make it available to other projects.
You now have to add the shared unit to your other project so it becomes available for use by other units in that project. To do this:
Activate Dll2
Select Project and Add to Project...
Find DllSharedIntf and add it.
Delphi will automatically update your project source file to include the unit.
library Dll2;
uses
DllSharedIntf in '..\Common\DllSharedIntf.pas';
Now in each DLL project you can add a separate implementation unit. E.g. For Dll1:
unit DllImpl1;
interface
uses
//It's very important to indicate that this unit uses the shared unit.
//Otherwise you won't be able to access the "global types" declared
//in the interface-section of that unit.
DllSharedIntf;
type
TDllImpl1 = class(TInterfacedObject,
//Any types defined in the interface-section of any units that
//this unit **uses**, can be accessed as if they were declared
//in this unit.
IDllIntf)
protected
//The fact that this class is marked as implementing the IDllIntf
//means that the compiler will insist on you implementing all
//methods defined in that interface-type.
procedure DoX;
end;
implementation
NOTE This answer only covers sharing an interface between projects. You'll still need to expose the functionality of the DLLs via appropriate exports. You'll need an approach similar to option 3 of my other answer.
Summary
We don't usually talk about "global interfaces" in Delphi. It's generally understood that anything declared in the interface section of a unit is globally accessible. (We do make more of an issue about global variables due to their dangers though; but that's an entirely different topic.)
In Delphi:
Whenever you want one unit (A) to make use of functionality defined in another unit (B), you need to add unit B to the uses clause of unit A.
Whenever you want a project to use a unit created in another project, you need to add the unit to the project. (TIP: It's a good idea to put such units in a separate folder.)
NOTE: When sharing units between projects, the project group is actually irrelevant. Projects don't need to be in the same group to share units. All you need to do is ensure the project can access the unit so that other units in your project can uses it.
I am trying to write a component which is loading 3D objects from obj files.
I am using ToolsAPI library for GetActiveProject.FileName. I added designide.dcp to Requiers part in the bpl. I registered my object and in design when I put an instance of this object on a TViewPort3D which I put before everything is OK and I can see the object from the obj file is loaded in the scene, but when I try to compile the project I get an error that says ToolsAPI.dcu not found.
The procedure that I use for loading the obj file is (Type of Model variable is TModel3D) :
procedure TMyObject.LoadModel(fileName: string);
begin
if(csDesigning in ComponentState)then
Model.LoadFromFile(IncludeTrailingPathDelimiter(ExtractFilePath(GetActiveProject.FileName))+'Obj\'+filename)
else
Model.LoadFromFile(IncludeTrailingPathDelimiter(ExtractFilePath(ParamStr(0)))+'Obj\'+filename);
end;
This procedure is used in constructor as follow (TMyObject inherited from TDummy):
constructor TMyObject.Create(AOwner:TComponent)
begin
inherited;
Model:=TModel3D.Create(Self);
Model.Parent:=Self;
LoadModel('Object1.obj');
end;
Is there anyway to prevent using the ToolsAPI library when the host project for the component is about to compile?
I just thinking about something like directives as follow.
{$IFDEF DESIGNTIME}
uses ToolsAPI;
{$ENDIF}
But is it possible to do such a thing?
It sounds as though you are trying to compile the design time code into a run time project. Either a run time package, or an executable. That's not allowed. You simply cannot compile any of the ToolsAPI units into a project that is not a design time package.
You can certainly use conditional compilation to exclude the ToolsAPI units, but you will have to define your own conditional define. There is no built-in conditional that will serve your needs.
But using conditional compilation is probably not the best solution. Typically you would separate the code that used Tools API into distinct units, and only include those units in the design time projects.
So the code for your component would be split into, say, two units. The first unit, uMyComp.pas, say, contains the bulk of the code. This unit declares the component and provides its implementation. Nothing in uMyComp.pas makes any reference to ToolsAPI. The second unit, uMyCompReg.pas say, performs the component registration and any other tasks that require the ToolsAPI. There is a dependency between these units in that uMyCompReg.pas uses uMyComp.pas. Then your design time package will include both units, and any other projects that are not design time will include only uMyComp.pas.
You could achieve the same effect using conditionals. The design time project would define a conditional to indicate that this was design time. So the project settings might include a definition of a conditional named DESIGNTIME. Then all the code for your component would reside in a unit named uMyComp.pas, say. Any code related to design time would be conditional on DESIGNTIME. And any other projects that included uMyComp.pas would not have DESIGNTIME defined and so would omit the design time only code.
Whilst this is possible it is not, in my view, the best way to solve the problem. Indeed if you look around the wealth of open source examples of component development I'd be surprised if you found any that handled the separation of design time code from run time code using conditionals.
How would you separate the ToolsAPI code into a design time unit? Here's the problem method:
procedure TMyObject.LoadModel(fileName: string);
begin
if csDesigning in ComponentState then
Model.LoadFromFile(IncludeTrailingPathDelimiter(
ExtractFilePath(GetActiveProject.FileName))+'Obj\'+filename)
else
Model.LoadFromFile(IncludeTrailingPathDelimiter(
ExtractFilePath(ParamStr(0)))+'Obj\'+filename);
end;
First of all, let's look at the commonality of this code. The first think to observe is that the outsides of the call to LoadFromFile are the same. Only in the middle, the choice of directory, is there variation. So let's write it like this:
procedure TMyObject.LoadModel(fileName: string);
var
ModelDir: string;
begin
if csDesigning in ComponentState then
ModelDir := ExtractFilePath(GetActiveProject.FileName)
else
ModelDir := ExtractFilePath(ParamStr(0));
Model.LoadFromFile(IncludeTrailingPathDelimiter(ModelDir)+'Obj\'+filename);
end;
The problem for you is how to move GetActiveProject.FileName into the design time code. You need to use dependency injection (DI) to do this. Allow some other party to supply the logic. You need to make TMyObject ignorant of this particular detail. You could use a DI framework for this, but that's perhaps a little heavyweight just for this one task. So instead let's declare a class variable that holds a function pointer:
type
TMyObject = class(...)
...
public
class var GetModelDir: TFunc<string>;
end;
This function point allows other parties, external to the class, to specify how the model directory is located. Now LoadModel becomes:
procedure TMyObject.LoadModel(fileName: string);
var
ModelDir: string;
begin
if Assigned(GetModelDir) then
ModelDir := GetModelDir()
else
ModelDir := ExtractFilePath(ParamStr(0));
Model.LoadFromFile(IncludeTrailingPathDelimiter(ModelDir)+'Obj\'+filename);
end;
At this point, your code can now be used outside of a design time package. The next step is to add code to specify GetModelDir at design time. This code goes in the design time only unit that also registers the component. The obvious place for the code is in the initialization section of that unit. It looks like this:
initialization
TMyObject.GetModelDir :=
function: string
begin
Result := GetActiveProject.FileName;
end;
I've used anonymous methods here, but you could equally use method of object, or plain old functional types, depending on your Delphi version.
Yes, but preferably not with conditional defines as this would create far more complications and restrictions than it's worth.
You need to separate your code into different units according to whether it's design-time code or run-time code.
E.g. For a single component, the bulk of the (with no ToolsAPI dependency) goes into one unit.
A second unit performs component registration and perhaps provides custom design-time editors for the component.
The second unit uses the first and you have a clean separation without conditional defines.
You then create 2 separate packages: design-time and run-time.
The design time package will have a dependency on the ToolsAPI.
Make sure that none of the run-time units use any of the design-time units.
If any design-time units use run-time units (very likely) then the design-time package will require the run-time package.
With the above package structure, your application that uses your new components should only have dependencies on the run-time units.
I'm making a mdi application with many child forms, one of which is the form to display the report.
on the report form I use dll files to display all the components on the form and look for value
in each component, I use the following code to do that.
// this code i write in dll or bpl file
procedure getReportParams(Form : Tform); stdcall;
var
i : integer;
str, cbstr : string;
b : boolean;
begin
for i:=0 to Form.ComponentCount-1 do
begin
str:=str+Form.Components[i].Name+' - '+Form.Components[i].ClassName+', ';
if (Form.Components[i] is TcxLookupComboBox) then
begin
showmessage('test 1');
// if i uncomment the code below, the program get error Einvalidcast
// cbstr:=(Form.Components[i] as TcxDBLookupComboBox).Text;
// if (Form.Components[i] as TcxDBLookUpCombobox).Parent=Form.FindComponent('pnledit') then
// showmessage((Form.Components[i] as TcxDBLookUpCombobox).Name);
end;
end;
showmessage(str);
// this showmessage work well in dll, bpl, or other unit
if b then
showmessage(cbstr+' true') else showmessage(cbstr+' false');
end;
simple question is how to write code cbstr:=(Form.Components[i] as TcxDBLookupComboBox).Text; with corecly without get EInvalidCast error?
Btw if i write this code in other unit, dll and bpl program get error but if i write that code in same unit (unit report) the code work well. thank for advance.
Your problem is that the classes in your DLL are different from the classes in your executable. You have two instances of these classes, even thought they are compiled from the same code. The compiler is accurate when it says that the object is not the class that you cast it to. You simply cannot share Delphi classes using DLLs.
The solution is either:
Compile all your code into a single executable.
Use runtime packages to share classes.
In your scenario it's not enough that you put your code in a package. The problem are the devexpresses classes. You need to link to those using runtime packages. Because you are not doing so you have multiple different versions of those classes.
You note that the results of the is operator appear to be at odds with the ClassName function. Well, that's because all the different versions of the class have the same name.
I also note that the issue you are encountering is the same as in your earlier question: How can I pass TForm to a DLL as parameter? The explanation and advice from the answer you accepted there apply equally here.
If you already used a (Foo is TSomething) type check, then you know that foo is a TSomething and you can use a static cast: TSomething(Foo)
If you are trying to link this code in another Executable or dll, you probably have not included the correct units IF IT FAILS TO COMPILE, AND IF it fails at runtime, you didn't turn the BPL link option on (Use Runtime PACKAGES, and make sure the list of package names is complete). Remember that checking "something is TSomething" you are comparing a class declaration with another live object's class. A class is not defined by the string name. It's actually type information linked into your application.
When you link a DLL (without runtime packages) you actually may have linked TSomething into your main EXE and into your DLL, and they are TWO DIFFERENT copies of the class with the same name and the name matters not one bit. When you compare for identity, there's no way to know at runtime that they were the same thing. SO they aren't.
You think about code the way you see it written on the screen. When it runs, it's been compiled into code, and the types are simply data in the exe or DLL. So TSomething-in-myexe.exe is not the same class as TSomething-in-mydll.dll.
If you want them to be the same, turn on Use Runtime Packages (BPLs) for all places where you want to compare type information between different compiled parts. In particular passing pointers or references to VCL types between non-bpl-enabled linked targets is not going to work the way you thought it would.
You should also make sure that the list of runtime packages contains the package that defines that class you're using. (TcxSomething is probably a developer express component, go find what package BPL it is defined in.)
Programming Environment: Delphi 6 and upwards
I am aware of the fact that since Delphi 6, custom components must have separate design- and run-time package. All run time features of the a component must therefore be in a separate unit and packaged separately to the component's design-time package.
My problem is the following: My component has code that needs to be run both when it is created on the form at run time and, additional code that needs to be run at design-time, when the component is placed on the form. I have managed to put the run time code into the separate run time unit, package it and deploy it successfully.
However, in the separate design-time module unit, how do I reference and add the design-time code that needs to be included into the component's create constructor during design-time, when the component gets placed onto the form?
You can separate design time behaviour from run time behaviour with
if [not] (csDesigning in ComponentState) then
But if your constructor code needs the DesignIDE design time package, e.g. from the units DesignEditors, DesignIntf, etc..., then I think you are stuck. Maybe some IOTA involvement can help. But since there does not seem to exist a notifier interface for the creation of components, that would require a custom IOTAFormEditor. Not that easy, if not impossible.
Why not use callbacks?
From your designtime package initialization code do this:
unit MyDsgnUnit;
interface
//TMyHook defined in AnImplUnit
TMyDesignHandlerObject = class
procedure MyMethod(Sender:TObject;ParentForm:TObject); { must match TMyHook }
end;
implementation
uses AnImplUnit, DesignUnitNamesHere;
procedure TMyDesignHandlerObject.MyMethod(Sender:TObject);
var
newObject:TMyComponent;
begin
newObject := TMyComponent(Sender);
DoSomethingThatneedsDesigntimeStuff(newObject);
end;
finalization
ADesignHandlerObject.Free;
initialization
ADesignHandlerObject := TMyDesignHandlerObject.Create;
AnImplUnit.AfterConstructionHook := TDesignHandlerObject.MyMethod;
and in your component do something like this:
unit AnImplUnit;
interface
type
TMyHook = procedure(Sender:TObject;ParentForm:TObject) of object;
var
AfterConstructionHook:TMyHook;
implementation
...
procedure TMyComponent.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
DOMyStuff;
if Assigned(AfterConstructionHook)
AfterConstructionHook(Sender,Parent);
end;
Update Flushed out example more. There is no reason you can't add more parameters to the AfterConstructionHook, but since your reference to Sender is already of type TMyComponent, I don't see the point, when you can access everything public or protected, in TMyComponent(Sender) from within your hook function, and if you inherit locally (known as a protected-access class), you can access the protected stuff too.
Make sure your DPK defines a symbol of your choice, for example DESIGNTIME. Then you'll be able to use something like this to only include design-time units when needed:
uses Windows, Whatever, Something
{$IFDEF DESIGNTIME}
,DesignIntf
{$ENDIF}
;
Then to the same in your constructor code:
constructor TMyClass.Create(aOwner:TComponent);override;
begin
inherited;
{$IFDEF DESIGNTIME}
// I'm at design time.
{$ENDIF}
end;
When using this technique you should either use a separate DCU directory for your pacakge and your normal executable, or do a build each time you switch from the design time package to other projects. That's because Delphi will only re-build a DCU if the PAS has changed, when in this case the PAS doesn't tell the whole story, defined symbols also matter. If you have a DCU on disk that was compiled by Delphi while you were building your design time project, you might see a ToolsApi.DCU not found when trying to compile a normal project. Rebuilding re-compiles the DCU and makes the message go away. Just as well, if you re-compile (not re-build) the design time project after you built a normal project, your DCU might be stuck in it's non-DESIGNTIME state, leaving you without your special design-time behavior.
As long as your code does not require the IDE tools, like design interface and so on, then all you need to do is check the component flag and you can use it anywhere within the component, as follows...
procedure TNewEdit.Loaded;
begin
inherited;
if (csDesigning in ComponentState) then
ShowMessage('Designing')
else
ShowMessage('Running');
end;
However without really knowing what you are attempting to do, there are several doors left open... for example, if you want to change a property value at design time, and a different value at run time, then there are streaming issues you have to deal with.