Every Delphi 7 developer knows that if he compile a application on Delphi 7, the style will be as Windows 2000 applications, but there is any method to make this better as the application can have the default theme of the Windows version, as C++ and C# applications?
Try adding the TXPManifest component to the main form of your application. located in the Win32 Tab.
The TXPManifest component has no methods or properties. All it does is include the XPMan unit in your project. This in turn causes a certain resource file to be included in your project's executable file. The resource includes a manifest - a small piece of XML that contains information about the application you are writing as well as information concerning the version of the comctl32.dll to use.
Alternatively add your own manifest resource manually - which allows you to tap into the even newer Windows 7 features, if you can be bothered to fathom out the syntax. See this link for more info but ignore the bit about enabling runtime themes as this doesn't exist in D7 (I don't think).
Related
I am supporting some legacy Delphi project. This project is divided into modules that stored in DLLs.
I need to compile one of the modules (last compiled in 2007). This module uses module DualListBox and has a variable of type TDualListBox:
uses DualListBox ....;
...
lbMasterOrders: TDualListBox;
lbChildOrders: TDualListBox;
The problem is, I don't know where to find module DualListBox. I can't find it on my machine, and I can't find it on the internet.
As far as I understand, the TDualListBox component must be something like ListBox that can Add rows at runtime.
At first, i thought that DualListBox is a part of RxLib, but RxLib's component is called DualListDialog and it's something completely else.
So maybe this is the self-written module by prev developer, that was deleted somehow.
But somehow the compiled DLL (that was comiled in 2007) is working perfectly fine. Maybe I can investigate where to find that module by decompiling that DLL?
If so, where should I look in the decompiled project? I'm using DeDe for decompiling.
The unit is called duallist and is automatically generated by Delphi 2007 (and also Delphi 10.1 and 10.2, don't know about other versions, but I would be surprised if they didn't have it) when you open a VCL project and click:
File
New
Other
Delphi Projects
Delphi Files
Dual list box
These units are usually taken from the object repository, which by default is located in the ObjRepos subdirectory of the Delphi installation.
My delphi application looks nice and pretty in the editor, but when compiled it's seemed to being using super old rendering for the buttons and stuff. I thought my compiled applications used to look pretty like the editor. What could I have screwed up for this to be happening?
One suspicion: a while back I was messing with manifests on a different app that needed to find the actual program files directory. Could I have screwed up my delphi project trying too hard for that? This project is set to use runtime themes.
The top is in the editor, the bottom is the compiled version
Your program is being rendered without themes. Possible causes for that:
Your executable has no manifest.
Your executable has a manifest, but it does not specify v6 comctl32.
Your manifest does specify v6 comctl32 but the process is using an external compatibility mode.
Your program disables visual styles in code. For example with a call to SetThemeAppProperties.
Your program uses activation contexts to activate a different manifest from that linked to the executable.
These possibilities get progressively more far-fetched. Most likely you've somehow fluffed your manifest. That's easy to check with a resource editor.
I write a lot of components and libraries for Delphi, most of which require the use of BPL Packaging so that they may be installed into the IDE.
This is simple enough and works well, right up until you want to maintain a single set of Package Project Files (in a single Project Group), but also want to compile and distribute those same packages for different Delphi versions.
Up to now I've been creating a different Package Project for each version of Delphi, and explicitly defining a Delphi Version Identifier as a suffix (e.g. Kinect_XE.bpl and Kinect_XE2.bpl).
I am aware that, in the Project Options for a Package Project, under Description, there are the fields LIB prefix and (more importantly for my needs) LIB suffix.
I am further aware that if I place a value in LIB suffix, it'll be appended to the end of the compiled BPL's filename.
My question, however, is first whether it is possible to have the IDE automatically populate the LIB suffix field with the IDE/RTL Version number, and if so... how?
I'm fairly certain this is possible, as it would appear that vcl120.bpl (and its counterparts for each respective version of Delphi) can be Referenced (as requirements) of your own packages using just vcl rather than having to type the full vcl120. It is, in fact, this same behaviour I'm hoping to achieve... where my packages can intra-reference eachother (as neccessary) without having to provide version-specific references to accommodate the suffixes.
Equally important is that resolving this will enable me to maintain a single set of Project Files in a single Project Group (with the obvious exception of XE2 where its Project Files don't necessarily behave very well with previous versions of Delphi due to the Platforms addition).
I suspect that I may need to put a value like $(VER) (or something similar) in the LIB suffix field, but this appears not to work and I've scoured Google looking for the correct solution.
Hope you can help!
UPDATE 1
I am now writing an IDE plugin to be used with (in the very least) Delphi 2007 to XE2, which gives DLL and BPL projects a new option called AutoSuffix. When toggled On, any IDE with the AutoSuffix plugin installed will immediately apply the correct IDE version suffix to the project.
The AutoSuffix plugin will be made available (freely) for everyone within the next 24 hours, and this question updated accordingly.
UPDATE 2
Okay... Delphi 2007 is being a pain! I've made AutoSuffix work with 2009 to XE2, so far, but 2007 requires a little more time (patience appreciated).
UPDATE 3
It would appear as though Embarcadero have heard our collective cry for simplier package unification between versions.
Mark is going to push this through to see if future versions of Delphi can accommodate a {$LIBSUFFIX AUTO} feature. I hope to hear back very soon whether this will be the case. If so, it certainly affects the way AutoSuffix will need to work on XE2 and older versions (as presently it doesn't provide the simple AUTO switch.. it has its own method).
My hope now is that EMB will take this request seriously, provide it as an integral feature going forward, so that it becomes a simple case of using AutoSuffix on existing versions to unify the process accross all versions!
AFAIK for Delphi up to XE2 there is no automatism for doing this.
Concerning the requires clause: when you require another package you are actually using the dcp, which doesn't inherit the LIBSUFFIX. Thus it is sufficient to require VCL.dcp during compile time, while VCL160.bpl is actually used during runtime. The DCP includes the complete BPL name to resolve that.
This makes the LIBSUFFIX approach superior to the simple "rename the package for each version of Delphi" one.
A solution like that suggested in QC83229 would make it easier to port a package to a newer Delphi version, but then you are still stuck with dproj files that are not backwards compatible.
I normally use different folders for each Delphi version, where only the project files are stored. For a new Delphi version I only have to copy a folder and change the LIBSUFFIX.
LIBSUFFIX directive is in *.dpk file, and you can edit *.dpk file manually.
You can write, for example
{$IFDEF CONDITIONALEXPRESSIONS}
{$IF CompilerVersion = 20.0}
{$LIBSUFFIX '120'}
{$IFEND}
{$IF CompilerVersion = 21.0}
{$LIBSUFFIX '140'}
{$IFEND}
{$ENDIF}
The bad thing is that IDE does not respect your manual edits of *.dpk file and deletes them then you make changes in a package. That is why some component vendors that use conditional defines in *.dpk file say in installation instruction if asked to save changes say 'NO'.
My suggestion would be to add this as a configurable option to project option sets (see QC #86491.) Rather than updating all the packages it would be sufficient to update a single option set file.
In fact, it seems the DllSuffix tag is recognized by the option set files in Delphi XE/XE2. Adding <DllSuffix>160</DllSuffix> to the <PropertyGroup> section of an option set file will cause the suffix to be appended to the package in the project manager. However, you still have to open the project options and click OK in order for it to be saved to the .dpk file.
I agree that it would be extremely useful with this feature (I would think also for the packages in the RTL.)
{$LIBSUFFIX AUTO} feature was added in Delphi 10.4.1:
In previous versions (version 10.3 and earlier) of C++Builder and
Delphi developers building packages needed to manually set their
package’s library suffix setting. The DocWiki “What’s new in version
10.4.1” mentions a new IDE projects option for setting the library suffix:
“Package AUTO libsuffix: packages can now have an automatic version
suffix, instead of manually updating and specifying the right version
suffix with each new release. (The compiler quietly supported this in
10.4, but full support for the feature in the IDE and package project settings is introduced in 10.4.1.)”
Is it good idea to put Forms that have complete functionality in dll.
And main app will invoke dll function that returns form object.
The accepted way to do this in Delphi is to use packages rather than DLLs.
Packages are essentially DLLs but with Delphi specific capabilities that allow VCL objects to be used across package boundaries.
Trying to do this with DLLs will lead to a variety of problems that packages deal with. One downside of packages is that all modules must be compiled with the same version of Delphi. But if you are wanting to share objects across module boundaries then you would face the same restriction if you used DLLs.
The Delphi documentation has extensive coverage of packages.
Having said all that, I would add that if you can put all your code into a single module (.exe or .dll) then it does make life a lot simpler.
Adding to the answers about using packages:
Packages can only be used if both, the main app and all dlls (plugins) are written in Delphi and are written using the same version of Delphi
DLLs can be written in any programming language that can create them and can be used by any program regardless of the programming language
So, using dlls rather than packages does make sense.
Regarding the actual question: Yes, it is possible to put forms into dlls and they usually work fine. Just make sure that you do not pass them around because they are only valid objects within the context of the dll. You will experience the odd problem with forms losing focus or coming up behind other forms. This can usually be fixed by passing a window handle from the main executable to the dll which is then used as the parent for the form.
Also note: TObject of your dll is different from TObject of your application. The same applies to other commonly used classes and variables like (Forms.)Application.
I have done it and it was a pain in the lower back but it was not impossible. The main program was written in Visual Basic 6, some modules were written in Delphi 6, others were written in Delphi 7 and Delphi 2007.
Conclusion: If you are sure you will never use something different than Delphi for your app and for your dlls (plugins) and are willing to always recompile everything when you switch Delphi versions, you should use packages. Otherwise it might be better to use regular dlls. (And are you sure you will always be the only person writing these dlls? Maybe at some time there will be a 3rd party developer for one of the dlls who does not own the Delphi version he needs.)
IMO this is sometimes a very good idea and the only way to go - for the reasons others have mentioned, I'm not a fan of packages, and am very comfortable with DLL's. I am currently adding functionality to an app written in Delphi 5 using Delphi XE - it was either use DLL's or write in D5 - of course I opted for the former: D5 app calls DLL's written in XE that contain all the latest and greatest features. (The first projects I did in Delphi were done via the old Borland Paradox - Paradox app invoked DLL's written in Delphi 1!)
But, I don't send the form or module from the DLL back to the main app - I just send the DLL module a structure containing what it needs to know to do its work, and when it's done and the DLL's form closes, it cleans up and then and returns a numerical code or structure back to caller indicating success, failure etc ( old fashioned but very effective).
Passing the form instance from the DLL back to your main app across the DLL threshhold can be problematic - note #dummzeuch's excellent answer above with some good tips on how to negotiate some of those problems should you decide that is your only solution.
+1 for everything that David Heffernan says.
Strategically, you really only need to implement forms (or other functionality) in external files if you're implementing a plug in system.
If you're going to allow plugins to be authored in any language, then DLL's are the only way to go.
If your plugin system will be restricted to developers with the same version of Delphi (same team perhaps?) then go with BPL's. The additional drawback of Delphi packages, from my perspective, is the need to deploy the VCL BPL's with your app, which are always more Mb than a single compiled module.
If on the other hand you want to write a modular system, you can still do that by implementing loose coupling & "plugin" techniques within your code and still compile to a single module.
If you put a form in a normal dll the form won't be able to intercept the TAB or arrow keys. I have been told that this is due to the OnKeyDown not be passed through.
if you compile a program in D2010 a manifest .res file is automatically generated. is it included in your program by default? or you have to include it yourself?if yes what level of privilage is given to you? my program modifies a registery key would it be able to do so with out any modifications to .res file?if no what modifications i need to do?
a side question: is there a component/expert(prefably free) that can generate/include .res file in my delphi 7 and delphi 2007 projects automatically just like delphi 2010?
edit: forgot to mention i do not have win7 or vista nor have i ever used them
edit2:i have included a manifest file just in case following this tutorial but the tutorial only talks about windows vista and not 7 would the .xml(manifest) file in this tutorial make my app capable of dealing with win7 UAC too
edit3 if i include my own manifest file and delphi is including it by default as well that will make 2 manifest files(1 with admin previlages and 2nd without) would this cause any problems/unpredictable behaviour
The manifest generated by delphi gives your process the lowest privileges (that is the default by the way).
You have to modify the manifest file in order for it to ASK for permission to be run under administrative rights (Called elevation).
Your application with the standard privileges should read/write to HKEY_CURRENT_USER without elevation.
Accessing %programfiles% and HKEY_LOCAL_MACHINE requires elevation. (Not so sure about the other registry hives)
This is a PDF that will help you A LOT with what you're up to.
http://pascalfonteneau.developpez.com/articles/delphi/vista/uac/VistaUACandDelphi.pdf