I'm rewriting an old application using Delphi 2010 and I'd like to put placeholders in my code for when I port it over to XE2. Just curious if FireMonkey has an equivilent to GetSystemMetrics. I'm specifically interested in:
GetSystemMetrics(SM_CXSCREEN)
GetSystemMetrics(SM_CYSCREEN)
If you just need the main monitor size, and not the desktop size (n monitors sum), you can use this:
uses ..., FMX.Platform;
var
p: TPointF;
begin
p := Platform.GetScreenSize;
ShowMessage(Format('X: %f' + LineFeed + 'Y: %f', [p.X, p.Y]));
In fact SM_CXSCREEN and SM_CYSCREEN should probably not be used at all. That just tells you the dimensions of the primary monitor. In these days of multiple monitors, that's not terribly useful. In VCL code you should be using Screen.Monitors[] and related properties to obtain information about your monitors.
As for FMX, there is no multi-monitor support and no platform independent way to find out screen size metrics. In your shoes I would simply use Screen.Monitors[] and deal with the FMX port when you get to it. You are going to have to re-write all your GUI code anyway when you port to FMX and this particular issue is the least of your worries.
Finally, when you say
I'd like to put placeholders in my code for when I port it over to XE2
I trust you are aware that porting to FMX is not compulsory. The VCL is still supported and available in XE2 and I can't see it being removed for a long time to come. You can port to XE2 without having anything to do with FMX.
Related
I'm trying to create an Android (multi-device) application with Delphi 10.2 that uses TWebBrowser. I load a URL and I want to parse its contents for fields, but I don't know how do it.
I read this excellent guide: http://www.cryer.co.uk/brian/delphi/twebbrowser/twebbrowser_oleobject.htm#OleObject.Document, but the property WebBrowser.OleObject.Document doesn't exist.
Can somebody help me, please?
The TWebBrowser for FMX is completely different from TWebBrowser for VCL. The VCL one makes use (for access to the Document, etc) of interfaces provided by Internet Explorer, or rather the DLLs on which it is based. IE only runs on Windows, so you shouldn't be surprised to learn that the interfaces it provides are not available on FMX.
The FMX TWebBrowser is a completely different and far more limited beast. It is not automatable in the same way TWebBrowser for VCL/Windows is, and some would say that is a good thing.
Considering the grief we've been having with VCL styles in Delphi 10.2 Tokyo around its use in dynamic link libraries and how it affects the built-in help viewer, as well as a number of negative comments from the community about VCL styles in general, is there another way that we can colour the application windows as in the examples below:
This feature has been part of the application since it's inception in 2001 and it vital for a number of our largest clients, as they actually maintain separate accounts for their subsidiaries and use the colours as an indication of which company they are working with.
Here are the third party skinning products I found so far:
TMS Skin Factory. This has been discontinued.
VCL Styles Utils. This extends VCL Styles and the issues with 10.2
Tokyo remain.
VCLSkin. This has not been updated since XE6.
Almediadev. Just like with DevExpress, we would need to replace all the standard controls with their specific versions in order to apply their skins.
I will update my answer as I find more.
Unfortunately, any answer where we have to replace the components offered by Vcl.StdCtrls or Vcl.ComCtrls with versions specific to the third party package is not going to work. We have 2500 TButtons alone across all the programs in the suite.
EDIT: In the end, we found an answer, or workaround, to the System Exception problem that had us looking at alternatives to VCL Styles in the first place:
Using VCL Styles in a DLL causes System Exception in 10.2 Tokyo
In VCL, I could load a font from resource and without saving it I could use it from memory.
Here is the code I use and it works in VCL:
procedure TForm1.Button1Click(Sender: TObject);
var
ResStream : tResourceStream;
FontsCount : DWORD;
begin
ResStream := tResourceStream.Create(hInstance, 'MyResourceName', RT_RCDATA);
winapi.windows.AddFontMemResourceEx(ResStream.Memory, ResStream.Size, nil, #FontsCount);
ResStream.Free();
button1.Font.name := 'MySavedFontNameInResource';
end;
In Firemonkey I just changed button1.Font.name to button1.Font.family but unfortunately the font didn't change. So I think this code is not compatible with firemonkey.
So in Firemonkey, how can I load a font from resource and save it temporary to memory and use it directly from there?
Update:
I saw these pages: Install font in firemonkey, How to use external fonts?
According to Mr Ed 's answer, it seems that there is no solution for this problem in FMX. But maybe we could load the font if we install it before running the app. I tried almost everything but I still can't load the the font.
There is also StylesSettings.ssFamily : Boolean property in New Delphi and must be set to False to have custom font family working. The same with Size, Style and FontColor.
This may or may not help.
Disclaimer
This requires extra researching that I have not gotten around to yet, but I believe this to be a good starting point.
Link for the MSDN page :- Custom Font Collections
You need to use the WinAPI.D2D1 unit (you may need FMX.TextLayout and FMX.Canvas.D2D as well) to gain access to the DirectWrite API. You can use this to get at the DirectWrite factories which will allow you to define and load a font from disk.
Once you have the font loaded AFAIK it should then be available to the entire application and hopefully all of the firemonkey controls. Its entirely possible that firemonkey only enumerates fonts at application load though, so this may all be for naught.
As I said, this requires research that I have not gotten to yet, so may only work if you are also custom painting your control (which I will be) and might not be suitable as a result.
I think I have an answer, which was only possible because of a LOT of help by Roy Nelson of Embarcadero's support staff who pointed me in the right direction.
I have verified that this works with Berlin 10.1 (without the Anniversary Patch applied) on Windows 10, 64 bit but I don't guarantee that will will work on all compiler versions/Windows versions and any insight other people have to offer would be very interesting to hear.
First off, I think the (currently) insurmountable issue starts with trying to use AddFontMemResourceEx as that produces fonts that are not enumerable and for Firemonkey to convert an installed TrueType Font to a graphically rendered D2D font--which is what it actually uses--it has to first be able to find it.
Replacing AddFontMemResourceEx with AddFontResource with a temp font file you write from the resource solves that problem, but it's not enough. After it's installed you need to force the TextLayout rendering engine to rebuild its font list which you can do with calling two lines from the FMX.Canvas.D2D.pas unit.
UnregisterCanvasClasses; //this tells it to forget everything it knows
RegisterCanvasClasses; //this tells it to learn it again based on the current state of this system, which now includes our dynamically loaded font.
I've posted a test project on GitHub at https://github.com/TheOriginalBytePlayer/FireMonkey-Fonts for anyone who wants to try it out.
Basically you create a resource file with your fonts in it -- numbered from 0 to whatever -- replace the {$R assimilate.res} line in the FMXFontInstaller.pas, with the one you jut created, add this file to your project source and you theoretically should be good to go.
I need to open a webpage with safari in my iOS application.
With XE2 there was iphoneall unit, which exposed UIApplication. XE4 doesn't use FPC anymore, so I can't use that.
Embarcadero documentation
says I can use SDKs only with C++ or using delphi interfaces (and still, macapi is for OSX only, not iOS). So, it seems that there is no interface for UIKit framework?!
Another solution I tried was:
_system('open http://www.google.com');
But that had no affect at all!
Is there any other ways to open urls or am I out of luck to accomplish it?
I know there is TWebBrowser component for ios, but I wouldn't want to take that road just to display a webpage.
By chance, someone at Embarcadero posted a code snippet to do exactly this two days ago.
If you are using XE4, look in the Samples, and you can find one (sorry, not sure of the name) where the final code is:
OpenURL('http://www.embarcadero.com');
This uses the XE4 FireMonkey framework and a class helper written by David Clegg, available in the sample.
If you are using an older version of FireMonkey, you can use the rather more cumbersome code:
function SharedApplication: UIApplication;
begin
Result := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication);
end;
procedure TForm2.Button1Click(Sender: TObject);
begin
SharedApplication.openURL(TNSURL.Wrap(TNSURL.OCClass.URLWithString(NSSTR(PChar(String('http://www.embarcadero.com'))))));
end;
(Attribution: Code snippets all copied from the linked blog post.)
There is also a very old forum post from the early days of FireMonkey showing how to tackle these problems in general (basically, string <-> NSString <-> NSURL), and while it's a bit out of date - as you can see by the above code, FireMonkey has matured greatly - it may give some insight into the underlying reason for the code.
These days, any decent Windows desktop application must perform well and look good under the following conditions:
XP and Vista and Windows 7.
32 bit and 64 bit.
With and without Themes.
With and without Aero.
At 96 and 120 and perhaps custom DPIs.
One or more monitors (screens).
Each OS has its own preferred font.
Oh my! What is a lowly little Windows desktop application developer to do? :(
I'm hoping to get a thread started with suggestions on how to deal with this GUI dilemma.
First off, I'm on Delphi 7.
a) Does Delphi 2010 bring anything new to the table to help with this situation?
b) Should we pick an aftermarket component suite and rely on them to solve all these problems?
c) Should we go with an aftermarket skinning engine?
d) Perhaps a more HTML-type GUI is the way to go. Can we make a relatively complex GUI app with HTML that doesn't require using a browser? (prefer to keep it form based)
e) Should we just knuckle down and code through each one of these scenarios and quit bitching about it?
f) And finally, how in the world are we supposed to test all these conditions?
For the moment I would like to answer only one question:
f) Use virtual machines and (if possible) automated tests. I know it is a big job to set this up but you will never regret.
I, too, am a lowly Windows developer (D7) - much more interested in solving my vertical market application user's problems than coping with M$ foibles.
I cobbled up up a component to deal with all with these issues, plus some more.
As far as I know, all the pieces were in the public domain, and I have credited them where possible.
These are some of the properties:
type
TAppEnvironment = class(TComponent)
private
{ Private declarations }
// environment management
FEnvError : TEnvError; // environment error code
FEnvErrorMsg : string; // environment error message
FEnvLocalComputerName : string; // name of the client computer
FEnvCurrentUserName : string; // logged-on user
FEnvCurrentUserAdmin : Boolean; // is logged-on user Admin?
FEnvProduct : string; // windows edition
FEnvProductFlavour : string; // windows flavour (Home/Pro)
FEnvBuildNumber : string; // windows build number
FEnvServicePack : string; // windows service pack
FEnvThemeActive : Boolean; // Windows Theme active
// calc using product & theme
FEnvTitleHeight : integer; // window title height
FEnvMenuHeight : integer; // window menu height
FEnvStatusHeight : integer; // window status bar height
FEnvBorderHeight : integer; // window border height
FEnvMainHeight : integer; // main menu window height
FEnvMainWidth : integer; // main menu window width
FEnvHeightAdjust : integer; // window height adjust
FEnvWidthAdjust : integer; // window width adjust
FEnvLocalPath : string; // App exe home folder
FEnvAppFolderName : string; // application name less extension
FEnvAppFileVersionStr : string; // like 6.0.0.4567
FEnvAppFileVersion : TFileVersion; // HiVersion, LoVersion, etc.
And some utilities:
function EnvironmentReady : TEnvError;
function GetLocalComputerName : string; // network needs this
function GetAppFolderName : string;
function BuildNumber : Integer;
procedure GetFileInfo(const AFileName: string; var RFileInfo: TFileInfo);
function GetLocalPath : string;
procedure getEnvWindowAdjust(bar : TStatusBar);
function setAppFileVersionStr : string;
function GetFileTime(const FileName: string): LongInt;
function initEnvironment : Boolean;
function exitEnvironment : Boolean;
function AlreadyRunning : Boolean;
function specialBuild : Boolean;
I have a function to size each form correctly, using FEnvTitleHeight, etc.
All the dumb user paths are also generated, depending on Windows version.
I have no clue as to how to manage the process, but if people want, I will toss the whole thing into the pot - so that the masters can work it over.
Excellent question.
I've been developing my application for over 10 years, starting with Delphi 2, 3 and then 4 and then staying there and waiting many years to upgrade to Delphi 2009 because Unicode was a must. I'll upgrade again when the 64 bit version comes out.
So I've run the gamut of Operating Systems: Windows 98, Windows 2000, XP, Vista and now 7. Each breaks your UI somewhat, but Delphi has been pretty good about it. At some point in time, you have to decide you cannot support the older OS's anymore, and moving to Unicode finally cut out Windows 98 from my supported list.
Generally, I've found that core Delphi gives you the best UI support. Some third party packages may appear to provide more, but their inconsistencies are worse problems than their benefits might be. Minimize other packages where you can.
The one UI goal I've had is to go for the Windows Vista Logo Program, and more recently the Windows 7 program, and Microsoft does provide a lot of information on what the standards should be that relate the your conditions 1 to 7 in your question. But getting a Delphi program to use a manifest and go through Microsoft's hoops was in the end, not worth the hassle and cost to me, especially since my non-compliant program worked just fine on Vista and 7.
Keeping my program running and keeping the UI looking the same on Windows XP, Vista and 7 when I am developing on a 64-bit Vista machine means I use Microsoft Virtual Machine when I need to. I have been told my program also works on Wine, so that's another test machine.
Now answering your questions:
a) Does Delphi 2010 bring anything new to the table to help with this situation?
Yes. Every version adds new VCL components that have been added to the new OS's. e.g. Windows 7's new UI's have been added.
b) Should we pick an aftermarket component suite and rely on them to solve all these problems?, and c) Should we go with an aftermarket skinning engine?
As I said above, I think its better to do it in Delphi itself than in a 3rd party package.
d) Perhaps a more html type gui is the way to go. Can we make a relatively complex gui app with html that doesn't require using a browser? (prefer to keep it form based)
My application is like a Word Processor with Rich Text. I've looked at HTML-based editor suites and there are a few, but I don't think its the way to go for a desktop application. If you want a web-based application, you would be better off with .NET and Prism.
e) Should we just knuckle down and code through each one of these scenarios and quit bitching about it?
Upgrade to Delphi 2010 first. You'll find Delphi itself will handle most of those situations for you.
f) And finally, how in the world are we supposed to test all these conditions?
Doing it yourself is a big task, even with virtual machines. What you've got to do is have an open Beta and get as many different users in different environments to test your program for you. Then you'll handle all the environments that are most important to your users.
Now, if you think getting user interface compatibility in different Windows environments is tough, just wait until Embarcadero comes up with their version of Delphi that will compile for the Mac. Your current UI worries will seem trivial by comparison to what it will then become.
For te scaling of your forms on multiple resolutions / DPI sizes: we use DevExpress LayoutControl for that. It makes sure that the controls on your form always align to use the available space, no matter what. And it does a lot more. Have a look at their site.
Delphi 2010 brings native Unicode support.
Delphi 2010 brings Windows Vista/Seven controls.
There is no 64 bit Delphi compiler for the moment beeing.
You should'nt have any problem to handle dpi and monitor count questions with Delphi 7
Delphi makes that fairly easy, but in the end you'll have run your software on all Windows versions and visually check that everything looks fine. Automated test are great to test the functionality, but the cosmetics can be checked visually only.
Delphi 2009 brought in support for theming (it is an application level setting). When you run a Delphi 2009 or above application in Vista / Windows 7, it changes the message boxes to TaskDialogs, so you get some UI improvements for free.
We had a bit of a struggle porting to Delphi 2009, and Unicode, but that was a 'technical debt' that we had to pay at some point.
Hope this helps.