Jump to content


Popular Content

Showing content with the highest reputation since 10/21/19 in all areas

  1. Better Translation Manager https://bitbucket.org/anders_melander/better-translation-manager The Better Translation Manager (BTM) is a replacement for the Delphi Translation Manager a.k.a. the Integrated Translation Environment (ITE) and External Translation Manager (ETM). Why is it better? Well, for one thing, it's free but more important; It actually works - unlike the ITE/ETM. Why? The standard Translation Manager that ships with Delphi today was originally an individual product known as the Borland Translation Suite. With Delphi 5 it became a part of the enterprise edition. The Borland Translation Suite showed great promise but unfortunately it never evolved from its roots as an external tool and has always been hampered by severe bugs that made it completely unusable in practice. As a result nobody uses it. This can be witnessed by the plethora of homegrown and commercial alternatives. The great benefit of the standard translation system is that it just works (this is the system itself I'm talking about, not the tools. The tools suck). Apart from the requirement that you must use resourcestrings you don't need to do anything special when writing your code. At run time you just place the compiled resource modules in the same folder as your application and the Delphi Run Time Library automatically takes care of loading and using the translations based on the current Windows user interface language. Anyway, since Embarcadero has now finally admitted that they are never going to fix the Delphi Translation Manager and instead recommend that we find alternative solutions, I decided that it was time I solved this little problem once and for all. The core functionality of the Better Translation Manager was written in two weeks during my summer vacation in Italy 2019. Amazing what you can do with a little pasta! Features Does not require any changes to the source code of the application being translated. Works with the existing standard Delphi localization system. Translates resourcestrings and all strings in forms regardless of any 3rd party components used. Works on compiled application. Source code is never used. Generates localized binary resource modules (resource DLLs). Does not use an external compiler. Can import existing translations from compiled application and resource modules or from XLIFF localization source files (dfn, rcn files). Read and save TMX and TBX translation memory files. Import Translation Memory from TMX (Translation Memory eXchange), TBX (TermBase eXchange), Microsoft Glossary and CSV. Machine Translation using Translation Memory, Microsoft Translation Service or Microsoft Terminology Service. Forms, Components, Types and Values that should be ignored can be specified in a Stop List. Translations are Spell Checked. Validation Rules to catch common translation mistakes. Supports Right To Left (RTL) editing based on translation language. Translation project is stored in a single XML file. Command line interface for use in automated build systems. Fast! Refreshing a large project typically takes less than a second vs. many minutes with the ITE/ETM. Supports all Unicode versions of Delphi (i.e. Delphi 9 and later). Resource modules contain the version resource of the source application. What it doesn't do There's one task that BTM, by design, doesn't attempt to solve: Localizing the placement and size of controls. Since it has been my experience that it is a far better idea to design the user interface in such a way that the layout automatically accommodates changes in font- and text size and shorter/longer texts due to translation, I decided from the start that I would not be supporting localization of size and position of controls. This also relieved me of having to create a run time form designer, supporting 3rd party controls visually (something that nobody so far has managed to find a foolproof solution to) and deciding what individual properties constitutes size/position values. Instead I just localize all string values - and only string values. But wait... There's More! Yup, you not only get this little wonder for free. You get the full source code too. Grab it at the repository linked at top. More details at the repository. Enjoy / Anders Melander
  2. In case this of use to anyone: Quite often you find a bug in Delphi RTL and you come up with a fix. Patching involves replacing the RTL procedure with a new patched one. To do that you can use your favorite patching routine or library (I use Detours), but you need the address of the original function/method. a) Patching a non-virtual public method This is quite straight-forward: type TMethodType = procedure ... of object function GetAddress: Pointer; var MethodPtr : TMethodType; begin MethodPtr := TRTLClass(nil).PublicMethod; Result := TMethod(MethodPtr).Code; end; Note the type cast TRTLClass(nil). b) Patching a virtual public method If for example PublicMethod is virtual the above type cast TRTLClass(nil) with result in access violation, since to resolve the virtual method you need to access Self which is nil. You could create a class instance and use that instead of TRTLClass(nil), but apart from not being elegant, in some cases this has side-effects (for example it may require a valid windows handle). The trick is described in this Stackoverflow question. function GetAddress: Pointer; var VMT : NativeInt; MethodPtr: TMethodType; begin VMT := NativeInt(TRTLClass); MethodPtr := TRTLClass(@VMT).PublicMethod; Result := TMethod(MethodPtr).Code; end; This is based on two facts. A class is a pointer to the Virtual Method table (VMT) and an Object structure has as the first field a pointer to the VMT of its class. c) Patching a private virtual method The trick this time involves using a class helper to access the private method of the TRTLClass type TPrivateMethodType = procedure ... of object; TRTLClassHookFix = class helper for TRTLCLass function GetPriveMethodAddr: Pointer; end; function TRTLClassHookFix.GetPriveMethodAddr: Pointer; var VMT : NativeInt; MethodPtr: TPrivateMethodType; begin // Adjust Self to point to the VMT VMT := NativeInt(TRTLCLass); Self := TRTLCLass(@VMT); with Self do MethodPtr := PrivateMethod; Result := TMethod(MethodPtr).Code; end; That's it.
  3. David Heffernan

    Delphi 2007 to 10.3 and Windows 10 taskbar issue

    Destroy the form when you close it. It's as simple as that. If you want to preserve some state between invocations, put that in a separate object. Forms should just present views anyway, and not be part of your apps business logic.
  4. http://rvelthuis.de/articles/articles-pointers.html
  5. Edit: I rewrote this on my blog: https://larsfosdal.blog/2019/10/31/demystifying-pointers-in-delphi/ Having a general understanding of how memory and addressing works, helps a bit for pointers. Learning assembler gives you that knowledge, but there are simpler ways to think about it. A pointer is a memory location that contains the address to the actual data you want Think of a street with houses. Make a list of the houses and their addresses. This is a list of pointers. Each pointer leads to the actual house it refers to. As you move through the list and follow each pointer, you can visit each house. Street of houses (i.e. your blocks of data, 1Kb each) 10k 11k 12k 13k 14K +------------+------------+------------+------------+------------+ |Apple |Pear | |Banana |Orange | | H1 | H2 | | H3 | H4 | | | | | | | +------------+------------+------------+------------+------------+ Your list of addresses (aka 4 byte pointers) is stored at memory address 100k var ptrlist: array[0..3] of pointer; assuming the list has been initialized with the correct addresses ptrlist[0] 100k contains 10k ptrlist[1] 100k+4 contains 11k ptrlist[2] 100k+8 contains 13k ptrlist[3] 100k+12 contains 14k for var ix := 0 to Length(ptrlist) - 1 do begin here, ptrlist[ix] = 10k,11k,13k,14k, and ptrlist[ix]^ = whatever value that is stored in the respective house the pointer addresses f.x. ptrlist[1] contains 11k (and that value is stored at 100k+4, and ptrlist[1]^ points to 'Pear', i.e. whatever is stored from address 11k Why the empty house? To exemplify that your list of pointers may be a consecutive array or linked list, but the data each pointer points to does not necessarily need to be consecutive. Now, if you address ptrlist[4] - you are out of bounds on the pointer list, and if you are so "lucky" that the address @ptrlist[4] (which is 100k+16) is not inaccesible, then ptrlist[4]^ will point you to whatever random value that pointer contains,, and most likely give you an access violation, or for sure - point you to data you are not meant to visit.
  6. Good news about iOS crashes! I owe Embarcadero and all of you to show the updated crash report graph. The problem was an internal hard limit in librtlhelper.a on the number of OC wrappers that could be created. As my app uses the TMC iCL native components, and is a large and comprehensive app, it wraps thousands of OC objects. Each new Delphi version used more and more OC wrappers on its own, leaving less for use in the app. That's seen clearly on the previous graph I showed. Marco sent an updated version of librtlhelper.a to me with a higher internal limit, and the result is seen clearly on the graph below. There are still some crashes though, which might indicate that a some of our users still reach the limit, <irony>since I can't imagine that there can be other errors in our software</irony>.
  7. Dany Marmur

    Deal - breaker: Registration Limit Increase

    You got that 100% right at least 🙂 I will dearly hold on to all my VMs with regged installations.
  8. Dmitry Arefiev

    InterBase or Firebird?

    1) DB admin features - PostgreSQL 2) DB developer features - PostgreSQL / FireBird 3) Encryption, and ... speed - InterBase. On many tests IB outperforms FB, at least. 4) Mobile platforms - InterBase 5) Change Views is unique InterBase feature If to put SQLite into this list, then if you does not need multi-user access, scalability, DB is relatively small, then SQLite is the right way. If something from this list is not true, or may become false in future, then not SQLite. In order of descending preferences - SQLite, IbToGo / Firebird embedded, PostgreSQL
  9. I have implemented a few improvements in the Uses Clause Manager Identifier Search: 1. The number of Identifier Search filter results is now displayed. 2. Previously the search term was searched only at the start of the identifier names. Now you can choose between "Match anywhere" and "Match at start". If you change the match type then the filter results are updated automatically. Here are the sources, so you can build GExperts with these new features yourself: GX_UsesExpert5.zip Fixed a small bug just now; if you have already downloaded GX_UsesExpert3.zip or GX_UsesExpert4.zip then re-download this archive. Here are a few Uses Clause Manager features planned for the future: • Export the list of Project Units additional option: Preformatted as uses clause. • Identifier search: Fuzzy-Search option • Identifier search: Optimize filter performance with TParallel.For • Identifier search (or all tabs?): Multiple search terms (like in RFindUnit) • Identifier search: Search the selected Identifier result in custom help files • All Tabs: Button/Combobox on the bottom panel to Copy the selected List item(s) to the clipboard, or to copy the selected unit path(s) to the clipboard, or to copy the selected unit FILES to the clipboard • SearchPath: Add a custom list of user paths • Add a Statusbar to the UCM window which displays the file-path of a single selected unit; then a Ctrl-click on the statusbar opens Windows Explorer at the location of the selected unit and selects the unit file in Windows Explorer.
  10. Anders Melander

    How to use Open Street Maps with Delphi - cross platform?

    Amen! https://killedbygoogle.com/
  11. You may need a license to use Google Maps, while Open Street Map is free, you can even host your own map server. Also, I would rather trust in OSM than Google that they keep their service available and the APIs mostly unchanged. (Just remember why this forum exists. G+ anybody?)
  12. Alexander Elagin

    How to get Linux installed?

    Yes, PAServer is needed to pull the necessary tools and libs from the target Linux machine. After this stage it is needed for deployment/debugging (but the Linux debugging in Delphi is a joke, simple WriteLn's in code can do better...) The best documentation I've seen so far is here: http://docwiki.embarcadero.com/RADStudio/Rio/en/Linux_Application_Development and here: https://chapmanworld.com/2016/12/29/configure-delphi-and-redhat-or-ubuntu-for-linux-development/
  13. The Delphi world contains a lot of database-solutions. One school of them are the TDataSet-based libraries, components and classes. If you are using TDataSet-based cached Lookups in a more "modern Delphi" you can easily speed up lookup handling. I'm posting this because when i googled in order to fix a couple of thing in my current project, i did not find much, almost nothing on this. This can save HUGE amounts of processor cycles if: You use "VCL Lookups" (they are not strictly VCL, but that is the term for example in DevExpress* forums) and have a lot of value-rows and a lot of lookup values. You use a component that cannot use lookup values and therefore need to "expand" the lookup values with their actual looked up "listfield" value. * I use the DevExpress PivotGrid a lot. The "QuantumGrid" has a "SortByDisplayText" property for sorting on lookup values. But the PivotGrid does not. So for the data fed to a PivotGrid i see to it to use "VCLLookups" so that the PivotGrid handles looked-up values rather than their IDs... as if they where text. This is the only way to get columns/rows sorted the way the users want. In a scenario with 100K rows and 80K lookup values having a character length of 256, this decreased the time needed to load the PivotGrid with data (for each fetch the lookup values is "expanded"). In some scenarios (like the one i describe above) the time needed for the operation (and that is the time the user has to wait) decreased from 120 to 6,5 seconds. The reason being the "LookupCache" in Data.DB uses an O(1) algo on a Variant. Let's change that like so: 1. The treading "lightly" approach is to override you TDataSet-based class, mine is called TkbmMemTable: ... interface ... // Faster lookups TDictionaryLookupList = class(TLookupList) private FDict: TDictionary<Variant, Variant>; public constructor Create; override; destructor Destroy; override; procedure Add(const AKey, AValue: Variant); override; procedure Clear; override; function ValueOfKey(const AKey: Variant): Variant; override; end; TkbmMemTableEx = class(TkbmMemTable) protected function GetLookupListClass(Field: TField): TLookupListClass; override; end; ... implementation ... function TkbmMemTable.GetLookupListClass(Field: TField): TLookupListClass; begin Result := TDictionaryLookupList; end; ... { TDictionaryLookupList } procedure TDictionaryLookupList.Add(const AKey, AValue: Variant); begin if not VarIsNull(AKey) then FDict.Add(AKey, AValue); end; procedure TDictionaryLookupList.Clear; begin FDict.Clear; end; constructor TDictionaryLookupList.Create; begin inherited; FDict := TDictionary<Variant, Variant>.Create; end; destructor TDictionaryLookupList.Destroy; begin if FDict <> nil then Clear; FDict.Free; end; function TDictionaryLookupList.ValueOfKey(const AKey: Variant): Variant; begin if (not VarIsNull(AKey)) and (not FDict.TryGetValue(AKey, Result)) then Result := Null; end; I am NOT "indexing" on Variant here. The TDictionary<Variant, ....> will convert variants to strings because the Dictionarys keys are hashed. I do not think that any database solution will yield a value when the key is null. But please comment if you are aware of such a scenario. 2. The "One Dict to rule them all" approach: Instead of having each flavour of TDataSet kick in the new LookupList you can substitute the vanilla one for our dictionary based one for the entire application: .... initialization DefaultLookupListClass := TDictionaryLookupList; This will see to it that any TDataSet that does not have it's own lookuplist will use the dictionary one. This approach can be tested in almost any application in under an hour. It would be interesting to receive a comment or two if it affected the performance of your application. Please note: This is only useful for lookup fields that have the "LookupCache" flag set. HTH, /Dany Disclaimer one: I did not look at lookups on segmented indices. Disclaimer two: All coding is done under the responsibility of the coder, not the author of this article.
  14. Stefan Glienke

    RttiContext Create and Free

    You only ever have to worry about dropping the TRttiContext when you unload modules such as dll and bpl during your application livetime from whom you needed rtti because then the type information from those modules is not removed and might still hang around possibly causing some issues.
  15. ByteJuggler

    Extremely slow Link phase

    Orthogonally to the suggestions from Pawel, I'd suggest also trying to analyse what the step is actually doing while it's "being slow", with ProcessMonitor. Even the built in Windows 10 Resource Monitor, which you can get to from the Task Manager in Windows, can be fairly useful as it allows you to isolate and drill into individual processes to monitor their behaviour as well, including handles/files opened/loaded etc etc. Understanding what it's actually doing and working out why this step is being slow might give you ideas on how to avoid it.
  16. Fr0sT.Brutal

    Uses Clause Manager in Tree in r2809

    @PeterPanettone man you really mixing forum and WhatsApp.
  17. David Schwartz

    Any update on the v10.3.3 release?

    I use a VM. Installing a new Delphi update is just as much of a PITA on a VM as on a host machine.
  18. David Heffernan

    ShellExecute and passing of password

    You probably need to decide what you want to be secure from. As it stands it's probably impossible to give you specific advice.
  19. Silver Black

    How best to update from 10.3.1 to 10.3.2?

    Totally agree with you.
  20. Dany Marmur

    InterBase or Firebird?

    Firebird has been working so well for me since version 1 that i have not been very interested in alternatives. IB/FB would probably be a more "political" choice. IB is proprietary and FB is OS. From what i gather PostgreSQL is a capable RDBMS functionality-wise too and it is OS too, even though a bit more commercial IMHO. Q: Why do you need a full-blown RDBMS for a one-platform application? Perhaps Johns suggestion is better, depends on a lot of factors... perhaps some more info for better recommendations?
  21. John Kouraklis

    InterBase or Firebird?

    For projects with local database, I would go for sqlite as it doesn't require a DB server.
  22. Serge_G

    Right To Left Components

    Hi, I don't write nor read RTL languages, I wrote a function to detect if the text starts with a RTL char function checkRtl (S : string; Exceptions : String = '' ) : TTextAlign; var carray : array of WideChar; i : int64; ws : String; begin for I := 0 to 9 do S:=StringReplace(S,i.ToString,'',[rfReplaceAll]); // supprime autres caractères spéciaux S:=StringReplace(S,'(','',[rfReplaceAll]); S:=StringReplace(S,')','',[rfReplaceAll]); S:=StringReplace(S,'"','',[rfReplaceAll]); S:=StringReplace(S,'''','',[rfReplaceAll]); S:=StringReplace(S,'-','',[rfReplaceAll]); if not E.IsEmpty then begin for I := 1 to Length(Exceptions) do S:=StringReplace(S,Exceptions[i],'',[rfReplaceAll]); end; S:=Trim(S); // arabic + hebrew SetLength(carray,$6ff-$590); for I := $590 to $6ff do carray[i-$590]:=Char(I); // there are some farsi char to be added result:=TTextAlign.Trailing; if S.IsEmpty then exit; if inOpArray(S[1],carray) then result:=TTextAlign.Leading; end; And, with Nabil's Help I test my ideas in a grid. You can find (french) discussion here and my tutorial https://serge-girard.developpez.com/tutoriels/Delphi/Livebindings/Grilles/#LVII-C-1 I did not test for TEdit and TLabel though but my guess it is possible
  23. David Heffernan

    Delphi 2007 to 10.3 and Windows 10 taskbar issue

    You don't want to make the application window the popup parent. Then your dialog can appear behind the main form. You want the main form to be the popup parent. Which you can do in CreateParams, or by setting PopupParent. It's important that you understand what popup parent aka Window owner in Windows terminology means. At the moment you seem to be trying stuff without understanding it. I think I already explained that destroying the window is the key to getting the behaviour you want. I gave you two options for doing that.
  24. WPTools is a complete WYSIWYG word processing control which does not add a huge overhead to your program. It loads and saves RTF, HTML, text and its own native format. DocX import and export functionality is available as an add-on and, for PDF export, use our wPDF component. WPTools reliably supports editable headers and footers in its page layout mode. Zooming, splitscreen, tables - including the possibility of page breaks inside table rows - and a powerful concept with a CSS-like paragraph style are supported by the modern architecture. Optional support for footnotes, columns and text boxes is availabe in the Premium Edition. Please see our website and the WPTools 9 word processing EXE demo. WPTools 9 includes the improved component WPImagelist which holds the icons for the TWPToolbar. If you add the unit WPIcons to your project (i.e. in one uses clause) all TWPToolbars will automatically use the new, nicer icons. The color icons can now display the current color. You can use the WPImageList with the TWPToolButtons to create a modern GUI easily. The WPImageList can also populate a standard TImageList. WPTools 9 creates PropertyGrids To display an inspector like grid, you can use the new API AppendPropertyGrid and AppendPropertyRow. Support for inplace checkbox controls The check boxes can be automatically created within property grids. But they can also be added in code to any cell or text object. Internally they are based on a "InplaceEditor" architecture which will be subsequently extended and improved. Now it is possible to have round and square check boxes, also with radio button functionality. It is also possible to use an event to paint the appearance, i.e. by using gylphs from the TWPImageList. The extended properties used by the inplace editors can be saved in WPT format. Dynamic Tables (TableProducer component - included in WPTools "Bundle") Do you need to present the user the result of a database query and also print it? With WPTools' dynamic tables the user can not only browse the result of the query, but also change the appearance of the table and the data cells and print it in WYSIWYG manner. In contrast to "data-grid" solutions, it is also possible to copy part of the created tables and paste them directly into a word processor program, such as MS Word or, of course, TWPRichText. Improved, more intuitive API Many low level TParagraph methods return a reference of the used paragraph. This makes compact and easy to understand coding possible. There is now also a simplified variant of TableAdd() which works with an anonymous procedure as callback New possibility to automatically direct all character attribute changes to the attributes of the paragraph If axtivated, a change of the font of a paragraph will not change the current writing mode or the selected text but the paragraph(!) attributes directly. The effect is, that the complete paragraph will change. Also the character attributes will automatically cleared. We uses this feature in our TableProducer demo. Here the user can change the attributes of the lines with the field names and later this attribute will be used to update the table. So the user can directly change the background color or use a bold or italic font style. Support for the Windows Emoji Font. Symbol objects can now be rendered using Direct2D (on a temporary bitmap, for compatibility). This enables the colors in certain fonts, such as the Segoe UI Emoji font. The special rendering can be enabled using ViewOptionsEx2 and is also activated in the Insert-Symbol dialog for the font with the name in the variable WPDrawD2DTextForFont and can also be selected per object. Regards, Julian Ziersch WPCubed GmbH - www.wpcubed.com
  25. dummzeuch

    Improvements in Uses Clause Manager Identifier Search

    Delphi 6 (and Delphi 2007) does not have any enhanced threading library, so TParallelFor is out. I hope the rest of your changes hasn't broken too many places. (Mind you, I'm not complaining, I'm glad that somebody shows so much enthusiasm and contributes to GExperts, but as long as it can be done without too much hassle, I want to continue supporting Delphi 6 and 7. And Delphi 2007 is a must as long as I'm stuck with it.)