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.
Related
I've a question about High-DPI application in Delphi.
Surfing on the Internet I've found a series of articles published by Žarko Gajić. these articles speaks about create Delphi application ready for High-DPI.
The method describes works fine but, the author use it inside every single application; for example speaking about TSpeedButtons.
My question is this: there is a way to implement this kind of behaviour also into components? For example I'm realising a simple component that works like the Embarcadero TSpeedButton but using Transparent PNG images.
The images inside the component are loaded at design-time from some PNG images. I've a TObjectDictionary in which I register the buttons states: enabled, disabled and so on.It is declared in this way:
FGlyphs: TObjectDictionary<TGlyphState, TPicture>
In the application that use this component I load PNG images from the files that are 24 x 24 pixel. When I execute the application on a 4K monitor this images become very small.
If I apply the Žarko method all works well but in this way every application the use my component need to implement this solution.
How to implement it directly inside the component? I thought to implement it inside the SetGlyph procedure, that is like the following code, but I don't know if this is the right place.
procedure TNCRSpeedButton.SetGlyphs(Index: TGlyphState; Value: TPicture);
begin
FGlyphs.Items[Index].Assign(Value);
end;
TGlyphState is defined in this way:
TGlyphState = (gtEnabled, gtDisabled, gtDown, gtOver);
Eros
1) First of all you should enable option Enable High-Dpi in Project Option -> Application -> your target platform -> Manifest file. This option is available since Delphi 10 (Seattle).
2) if in W10 OS you have different Scale, you could calculate and run TWinControl.ScaleBy (available for Forms) for adjust window and all elements on one specific window.
See demo on https://github.com/KohrAhr/DelphiDemoPPI
Demo contain TToolButtons controls.
I am using Delphi XE. I have come across a memory leak problem using Delphi Soap. It turns out to be due to a missing .Free call in TWSDLLookup.Destroy, as described in QC 91160
The problem that I have is the described work-around, which is simply to add FLookup.Free to the TWSDLLookup.Destroy method.
I don't want to change the Delphi source, so I tried copying the unit to my project folder, making the change and recompiling, as described here in Tom's answer. The problem with this technique is that it apparently only works if you also recompile all the dependent units. I have tried copying just WSDLLookup.pas to my project directory and I get a Stackoverflow error. I'm not familiar with Web Services / SOAP so I don't know what other units I should copy over if I do use this technique.
Rob Kennedy's answer on the same page describes a different technique involving code hooking - but it doesn't seem to apply to object methods. I have done as he suggests and downloaded the free code for the TNT Unicode controls and located the relevant procedures, but I have been unable to find info on how to hook an object's methods - if indeed this is possible. If I could do this, I would then hook TWSDLLookup.Destroy and add the FLookup.Free call.
Any ideas for how to fix this will be much appreciated. I'm a bit of a newbie programmer so I'm hoping that I've missed something obvious?
What you are trying to do does in fact work fine. I tested it out myself. Here's the project file I used:
program WSDLLookupTest;
{$APPTYPE CONSOLE}
uses
WSDLLookup in 'WSDLLookup.pas';
var
intf: IInterface;
begin
intf := GetWSDLLookup as IInterface;
end.
I made a copy of the WSDLLookup.pas file and placed it in the same directory as the .dpr file. Then, in the copy rather than the original, I modified TWSDLLookup.Destroy.
destructor TWSDLLookup.Destroy;
begin
Beep;
ClearWSDLLookup;
FLookup.Free;
inherited;
end;
I added the Beep to prove to myself that this code was indeed being executed.
In your position I would definitely use this solution instead of attempting code hooks. And of course the other simple solution is to upgrade to a later Delphi version.
One thing to be careful of is to remember to remove the modified unit when you do upgrade. The leak was fixed in XE2.
After years of Delphi development I now have hundreds of forms shared throughout our Applications. Compilation ranges from Delphi 7 through to XE, thus one form might be opened in any IDE. The well-known Explicitxxx property addition after Delphi 7 has solutions to avoid a form accidentally acquiring properties that earlier compilers can't process (e.g Andreas's DDevExtensions) but I'd like a more positive 'switch' that prevented Delphi from making or saving any form modifications at all. Period.
Of course you could use the read-only flag, and a version control system provides additional means particulay of seeing that such a modification has occured. What I'd really like though is a {$LockDFM} switch that I could put in the form's unit, or a context menu option when viewing the form layout.
Can anyone think of a neat way of achieving this?
Thanks
The only thing I can think of (other than the read-only/VCS options you mentioned) is the Edit menu's Lock Controls option. This sets a flag that prevents controls from being moved around. I'm not sure how much good it would actually do, as I've never tried it; I just know it's there.
Helo
I am pretty sure that Delphi has no such a thing. I have been searching for a solution to this problem as well.
But, theres one thing you can do: You can write your own Delphi addon using OTA (Open Tools API). I know that there are a few classes which are able to notify you when something are about to be saved. You can intercept this event and decide if you wanna save it (in your case, if it is a DFM).
BTW, if you have plans to do such component, tell me. :)
EDIT:
I have found a piece of code that may help you. Extracted from http://www.gexperts.org/otafaq.html
TMyFormNotifier = class(TNotifierObject, IOTANotifier, IOTAFormNotifier)
protected
procedure FormActivated;
procedure FormSaving;
procedure ComponentRenamed(ComponentHandle: TOTAHandle; const OldName, NewName: string);
end;
In design time there is Edit->Lock Control.
LE: this is only for resizing/repositioning the controls on the forms. Concerning the ObjectInspector I don't know if there is anything that can 'lock' the values set there(so the developer can not change them).
Basically, no. Aside from the f'ing (pardon my french) explicit size and position properties which IMO never should have been in the .dfm, there are some third party components will change stuff just by you viewing the form. F.x. TMS components will update a version number even if you didn't change a thing since the previous version of their components.
I'm looking for a simple, transparent checkbox component that properly supports XP/Vista/7 theming.
It should also work with Delphi 7.
I've found a component on Torry's that's not working properly, and I know that Raize components has a transparent checkbox - but I'm obviously not going to pay $300 for the entire package just to get this single component.
I've also found many other solutions, but none of them support theming.
The main problem is that TCustomCheckBox is a TWinControl descendant, and in order to implement transparency, you need to make a new TGraphic descendant control from ground up.
Any ideas?
LMD-Tools SE is free, works great on Delphi 7 and has a checkbox component that has a transparency property. I've recently used TLMDCheckbox with its transparency property enabled with Delphi 7.
http://www.lmdinnovative.com/download/index.php#LMD
Download file: setupse10d7.zip. Sorry, I can't post the whole path (url) since I don't have enough juice yet.
This should fix you up :).
ShawnH.
Raize Components is overkill for just this component, but much more capable and supports transparency in a whole load more components. Once you have it, you'll appreciate the other items greatly. I'd say it is the solution you are looking for.
If you can accept an alternative control there is JvXPCheckCtrls.pas with its TJvXPCheckbox component in the JVCL library. http://jvcl.delphi-jedi.org
I think (if I remember correct) it is transparent when themes are used.
It's quite a large package which will add to vcl with the installation of Jvcl. And it doesn't cost you a cent.
But remember, the TJvXPCheckbox component is part of their XP-controls package and you cannot simply lift out the component as a standalone. You will need the installation of Jedi and to get the core code and necessary theme handling to use it.
- Its Mozilla Public Licence ("MPL") version 1.1.
I use AlphaControls for some of my programs - all of their components are skinnable and have reasonably powerful graphics handling options. A lot of the components also have more features than their corresponding Delphi standard components - some I just use for those functions alone. There's a free Lite version available at www.alphaskins.com - it may just be what you're after. It's not Vista/7 theme-aware, mind you. We use Delphi 2010 and vista/7 theme awareness is built into the standard VCL there, although that's probably not the solution you were hoping for.
Not sure if this will help, but I ran into what I think is the same problem when working with the TMSSmooth controls: the label of a checkbox place on a form looked terrible because it was not transparent.
Their demo/example programs had nice looking checkboxes so I took a look at their sample code.
Turns out they reduced the width of the checkbox component to 13 so that only the box itself and no caption shows. Then they added a TLabel for the caption.
Seemed like a clever workaround to me.
Hope this helps.
How can I reduce resources inside my application?
I have tried a number of tricks
I have reduce and rewritten code, reduce line number,
Reduce comments,
Compressed the final EXE, but this is not the way I want to go,
Improve the variable type cast,
Remove ICONs,BMP,JPG, from inside the application
I need my applications to be as small as possible on the final EXE and in general resource consumption.
Any more ideas, any good articles on this subject
Thanks
What about switching debug information off in the project options:
no debug info
no runtime checks
reduce number of external units uses if possible.
But debug info kan be a major killer.
I would not spend any time removing comments the compiler strips them out anyway
You could reference your images from an external service(eg Amazon S3)
Put any images that the program uses more than once into image lists or TGraphic components, and put those into a data module. Link all your components using these glyphs to the image lists. If you use the Object Inspector to add the same glyph to several components you will end up with multiple copies of it, increasing both your loading time and your executable and working set size.
A nice trick to reduce executable size (actually, PE-image size, as this applies to DLL's too), when relocation is not an issue :
Leave the relocation-info out!
In Delphi, you could do it like this :
// Remove relocation table (generates smaller executables) :
// (See http://hallvards.blogspot.com/2006/09/hack12-create-smaller-exe-files.html)
{$SetPEFlags 1} // 1 = Windows.IMAGE_FILE_RELOCS_STRIPPED
Cheers!
Drop the VCL and use KOL and MCK: http://kolmck.net/
This is radical and very big change, but will get the exe size down.
Do not create all forms automatically, even though Delphi gives you the option now, and did this unconditionally for new forms in earlier versions. Only create the main form, and use the following (pseudo) code for the showing of modal dialogs:
procedure TMainForm.OptionDialog(Sender: TObject);
var
Dlg: TOptionDialog;
begin
Dlg := TOptionDialog.Create(nil);
try
// prepare dialog
if Dlg.ShowModal = mrOK then begin
// apply changed settings
end;
finally
Dlg.Free;
end;
end;
This will shorten application loading time and reduce your overall resource usage, especially for complex dialogs with many controls.
Measure first, THEN optimise. How big is your application, and how big would you like it to be?
Are you concerned about...
The size of the application .EXE file on disk? Then...
Build with runtime packages on. You'll get a tiny .EXE, but will need to distribute .bpls as well.
The RAM memory used by the application? Then...
Build with runtime packages off - the linker will omit most unused parts of packages.
The size of the application installer? Then...
Build with runtime packages off
Use Inno Setup
Most of the suggestions above?
The size of the application PLUS PACKAGES/DLLS after installation? Then...
Build with runtime packages off, and use UPX
Project -> Options -> Compiler:
===============================
Optimization ON
Debug Information OFF
Local Symbols OFF
Reference Info OFF
Use debug DCUs OFF
Project -> Options -> Packages:
===============================
Build with runtime packages ON (but you will have to distribute your BPLs!)
Note to non-delphi folks:
a BPL is just a DLL, but with magic Delphi dust to make it easier to use.
This article may be useful to you.
Is it really worth all this trouble? We are not living in 640 KB memory times anymore.
If you want youre EXE to be smaller then use dynamic linking of packages and libraries. That gives most of the boost. Also put all your resources (images,sounds) into separate DLL. You won't save anything by deleting comments and writing all your code in one long line.
Typically speaking if you want a smaller EXE size then go with an earlier version of Delphi.
I always use UPX to compress exe files. It works perfectly, often resulting in a factor 2 compression. And, of course, disable all the debug info will help reduce file size.
Use a memory profiler like the one from Red Gate to get a real time view into the run-time memory usage.
UPX and ASPack will create a lot of trouble because antivirus false positive alarms. Kaspersky does that a lot!