How do I change a VCL unit in Delphi (XE2)? - delphi

I found a workaround for a bug (QC#25702) in the Delphi VCL unit Grids.pas, so I copied that file to my project's source folder, added it to the project and changed a few lines of code. That was with Delphi 2007, and everything worked as expected.
Now, with Delphi XE2, the project no longer compiles. It complains about incompatible types "TCustomGrid" and "TdzVirtualStringGrid" (which is a descendant of TCustomGrid). It turns out that one unit refers to TCustomGrid as declared in my copy of Grids.pas, the other to TCustomGrid as declared in Vcl.Grids.pas. This happens even though both units have "Grids" in their uses clause (rather than Vcl.Grids). Any idea how I could solve this?

Your problem is that you are including the Delphi 2007 Grids unit in your XE2 project. That won't work at all. What you need to do to modify an RTL/VCL unit in this way is as follows:
Start with the source code for the unit supplied with the Delphi version that you are using. In this case start with Vcl.Grids.pas supplied with XE2.
Make a copy of that unit inside your project directory, and add that unit to your project.
Make any modifications to the implementation section of the copied unit.

Related

Error when compiling: 'Vcl.forms.dcu' not found

I worked on my school IT project from home, on a newer Delphi (RAD Studio 10 Seattle). Now when I copied my program to work on it at school (Delphi 2010), it got an error when compiling Vcl.Forms.Dcu not found.
I have looked at other StackOverflow questions and my Unit Output Library is correctly set to $(BDSCOMMONDIR)\Dcp, so I do not know what is the problem.
The VCL unit prefixing was added in XE2 to differentiate between same-named units in the VCL and (newly added) FMX frameworks. Removing the Vcl. prefix will correct the error.
Unit Scope Names were introduced in XE2, so the Vcl.Forms unit does not exist in Delphi 2010, it was still known as Forms instead.
The correct solution in this situation is to refer to the Forms unit in your code as simply Forms, not as Vcl.Forms. In your Seattle project options, make sure that Vcl is listed in the compiler's Unit scope names configuation field.
This way, when compiling the code, D2010 will look for Forms.dcu only, and Seattle will look for Vcl.Forms.dcu when it cannot find Forms.dcu.

Recompile modified VCL unit

I have to compile my project with a changed VCL unit. I use Delphi XE8. I copied Vcl.StdCtrls.pas from D:\Program Files (x86)\Embarcadero\Studio\16.0\source\vcl to my project folder where my .dpr file is localed, then I changed my copy of Vcl.StdCtrls.pas. I also added this unit to project tree. The problem is that with Delphi XE8 such method of recompiling VCL units no longer works. I put an obvious syntax error in my modified Vcl.StdCtrls.pas unit. Compiler does not report the error which means it does no even check the file. I always do a full build Shift+F9. I found a similar question How to recompile a specific unit from the VCL? but like I said, it no longer works, not for Delphi XE8.
Also, the modified unit is on my uses list in .dpr file:
uses
Vcl.StdCtrls in 'D:\Dev\MYPROJECT\Vcl.StdCtrls.pas',
...
// it does not help
This seems to be a bug. I guess you're using runtime packages. In XE7 such project will not compile - which is the correct behavior. In XE8 it compiles, apparently using the VCL runtime package and ignoring your modified unit.
Edit:
Note that even in previous Delphi versions, modifying a VCL unit while using runtime packages would still require you to repackage the modified packages and their dependencies (in this case, vcl and rtl).
In other words, you cannot simply use a modified unit while linking against a runtime package which contains another copy of that unit. Unit names must be unique within the full scope of the project, including the main executable and all linked runtime packages.
So the solution for you is to either:
not use runtime packages, or
repackage all required units into your own runtime packages, and link against them instead of Embarcadero-supplied rtl, vcl etc.

Error: F1026 File not found: 'System.Actions.dcu' switching back to Delphi XE2 from XE3

I'm moving my code to Delphi XE3 from XE2, but it should compile in both. I notice that some units get 'System.Actions' auto added to the USES clause. This then causes an error when returning to XE2 with:
F1026 File not found: 'System.Actions.dcu' (unit scope "System" indicates Win64, OSX32, Win32 only)
I've never really understood unit scope properly. Is there a correct solution to resolve this rather than wrapping stuff within compiler version {$IFDEF}'s?
Thanks
There is no Actions unit in XE2. It is new in XE3, as part of refactoring work to bring Actions support into FireMonkey. This is documented:
What's New in Delphi and C++Builder XE3:
Actions: FireMonkey now supports actions and action lists, two features that were previously supported only in VCL:
Important: Every FireMonkey or VCL application that uses actions must specify the System.Actions and System.Classes units in the uses section.
Changes in Implementation of VCL Actions
The System.Actions unit is created in the RTL package. Classes from the Vcl.ActnList unit that provide framework-independent action features are moved into this unit. Classes in System.Actions extend the most fundamental behavior of action features introduced in the TBasicAction and TBasicActionLink classes.
Important: As a result of these changes, you need to add the System.Classes and System.Actions units into the uses section.
Implementation of Actions in FireMonkey and VCL
FireMonkey (FMX)
The framework-independent implementation is common to FireMonkey and VCL:
This basic actions functionality is extended in the new System.Actions RTL unit.
VCL
Framework-independent action features that were implemented in the Vcl.ActnList unit in previous RAD Studio releases are now in the new System.Actions unit in the RTL (common to VCL and FireMonkey).
Important: As a result of these changes, you need to add the System.Actions unit to the uses section (or #includes) in your VCL applications that use actions.
You will have to either remove the reference to Actions if you are not actually using actions in your code, or else {$IFDEF} it out.
What Remy said is quite correct, but there may be an easier way to make your code work in both XE2 and XE3. Simply add a unit alias from System.Actions to Vcl.ActnList.
Add this in your project options, on the Delphi Compiler page. You need to add the following:
System.Actions=Vcl.ActnList
Note that if you need to compile in both XE2 and XE3 using the same .dproj file then you are out of luck. That unit alias setting will stop the program compiling under XE3. However, if you have have different .dproj files for XE2 and XE3, then this will allow you to use the same source in both. Or, if you only need to compile for XE2 at the command line, then you could add this unit alias there. I can't tell whether or not this will help you, but I know that the unit alias feature has helped me out of a similar spot on more than one occasion in the past.
If you have ONE project file you still can solve the problem with a "dummy" System.Actions.pas file in your project path directory:
This file will be taken under XE2.
The XE3 compiler will find his System.Actions.dcu in the IDE /lib directory.
Anyway: In normal cases you should use different project files - then the solution with the unit alias is recommended.
The dummy System.Actions.pas could look like:
unit System.Actions;
(*
XE2 compatibility unit: since XE3 unit System.Actions will be inserted into every
interface in units which use actions.
compilerswitch in [uses] is ignored by IDE - so this solution enable successful
compilation in XE2 with same project file than XE3
*)
interface
implementation
end.

Where did the unit named InvRules (formerly in the SOAP folder) go in Delphi XE2?

I am trying to port some Delphi XE code to XE2, it uses a unit called InvRules.pas, which according to the XE2 docs, has no namespace prefix.
It also isn't in the soap folder where I expect it:
C:\Program Files (x86)\Embarcadero\RAD Studio\9.0\source\soap
The simplest answer is that it's been removed (accidentally or on purpose) from XE2.
Has anyone figured out what's up? This unit contains functions like GetStackTypeSize, and RetOnStack, which are used sometimes in custom TRIOHelper type classes.
This unit is no longer used by the soap runtime so it's not being shipped anymore. In previous releases, it was part of the soaprtl runtime package. There were some significant changes made to the soap runtime for the XE2 release to make the code portable to x64 and less reliant on BASM code that was essentially duplicated in the RTTI support units. The change log entry associated with the commit states:
Refactor out InvRules, use RTTI to get type sizes.
Remove InvRules, PrivateHeap from soap package.
If you have code which relies on the helper routines in this unit you should be fine using the source from a previous release. You may also want to diff the Invoker.pas, InvokeRegistry.pas, OPToSOAPDomConv.pas and Rio.pas units between XE and XE2 to see how the code changed so it no longer relies on the InvRules.pas unit.

Upgrading to HTMLHelpViewer in DELPHI XE (Can't find HTMLHelpViewer.pas)

I am upgrading from Delphi 6 to Delphi XE. In Delphi 6 I was using HTML help files (.chm) and used the StoHtmlHelp to make it so that I could call context sensitive help like we used to call .hlp files. I'm upgrading to Delphi XE so I need to use that native HTML help support.
I know I'm supposed to add HTMLHelpViewer to the uses clause of the project, but when I do I get a compiler warning that it couldn't find the file.
Could not compile used unit 'HTMLHelpViewer.pas'
Does anyone know why Delphi isn't finding this file by default? It should be built in.
Not being able to compile a file and not finding a file arent't the same thing. If Delphi is trying to compile HTMLHelpViewer.pas you must either:
have the vcl source folder(s) on your library path (not recommended), or
another HTMLHelpViewer.pas file is somewhere on your library path, that path comes before the standard Delphi lib folder, and that HTMLHelpViewer.pas file contains something that Delphi XE is not happy about.
The first is not likely and it would be very strange indeed if Delphi could not compile one of its units (apart from system.pas).
The second seems more likely... And if that unit used to compile, the complaints from Delphi XE could well be due to differences between Delphi 6 and Delphi XE.
You don't actually need to add it the uses clause of the .dpr file – you just need to use it from some unit in your project.
Having said that, you may actually prefer to add it to your .dpr file, and if so then do it like this:
uses
Forms,
HtmlHelpViewer,
MyUnit in 'MyUnit.pas',
I'm guessing that you have something like this:
uses
Forms,
HtmlHelpViewer in 'C:\Program Files\Borland\Delphi6\Source\VCL\HtmlHelpViewer.pas',
MyUnit in 'MyUnit.pas',
This will fail because you are asking XE to compile D6 source.
For RTL/VCL units its best to omit the path to the file and let the compiler find it (it knows where to look).

Resources