Jump to content

Leaderboard


Popular Content

Showing content with the highest reputation on 02/12/19 in all areas

  1. Remy Lebeau

    First!

    I'm here!
  2. Hi, I've had lots of enquiries recently about when Bookmarks and Navigator will have a version available for 10.3 - they've been updated and new features added for every release until now. I'm please to say they will be available with the upcoming version of RAD Studio (10.3.1) which is coming out soon. The reason for for being included, and for the lack of news about a 10.3-compatible release in the past month, is that the plugins have been acquired by Embarcadero and so will now ship with the IDE itself. This is great news. I wrote the plugins originally to add features I wanted to the IDE, and hundreds (thousands, actually!) of developers have given great feedback. It's great to know the features will be available to everyone. In addition, due to the pressures of work, I haven't had much time to maintain or extend them recently, and so having them under Embarcadero's wing means they'll live on and be developed as part of Delphi and C++Builder itself. More info in the linked post! - David
  3. I just hope this nice plugins will not be killed slowly by Embarcadero after integration in the IDE like they did with Castalia.
  4. Remy Lebeau

    TIdMessageBuilderHtml add background color

    That has nothing to do with Indy, and everything to do with your particular HTML/CSS, and whether the receiver supports what you are trying (for instance, not all email readers support background images - see The Ultimate Guide to Background Images in Email ). Indy does not care about the particular content of your HTML, it gets sent as-is (other than to encode it for transmission purposes only). I will say this, though: - in your 1st case, 'url("back,png")' is wrong for an embedded image, you need to use 'url("cid:back.png")' instead since "back.png" is the Content-ID you assigned to the attachment. - in your 2nd case, the 3rd call to Html.Add() appears to be broken.
  5. Primož Gabrijelčič

    Generating one-to-many on the fly with Live Bindings

    Nice additions, Andrea 🙂 Whether for the good or bad, who can tell 😉 My initial approach was trying to get too much from LiveBindings anyway (intentionally). Your changes are definitely in direction of making my messy code more maintainable so they make it better. They, however, introduce more code, so from my original viewpoint they make it worse. 😉
  6. Andrea Magni

    Generating one-to-many on the fly with Live Bindings

    Another (small) addition (on the same path): 1) change SanitizeStr to this: function TForm1.SanitizeStr(const AString: string; const ADelimiter: string): string; begin Result := AString .Replace(' ' + ADelimiter, ADelimiter, [rfReplaceAll]) .Replace(ADelimiter + ' ', ADelimiter, [rfReplaceAll]); end; 2) change the SourceExpression to 'Owner.SanitizeStr(Text, Owner.ListBox1.Items.Delimiter)' And you can avoid setting the Items.Delimiter for your listbox. "It's a small step for man but..." :-)
  7. Andrea Magni

    Generating one-to-many on the fly with Live Bindings

    Not that I think that this would be a significant improvement with respect to your approach, but you can avoid the OnAssigningValue event-handler by introducing this public function to your form: function TForm1.SanitizeStr(const AString: string): string; begin Result := AString.Replace(' ,', ',', [rfReplaceAll]).Replace(', ', ',', [rfReplaceAll]); end; Then use as SourceExpression of your TBindExpression this value: 'Owner.SanitizeStr(Text)'. AFAIK "Owner" here stands for the owner of the BindingList and the LB expression engine is capable of calling a method on the underlying object (your form instance). Same lines of pascal code but one line left out from the XFM file (the one defining the event handler for OnAssigningValue event) and you can declare your function at your will (no prototype to match for the event handler). Does this match your definition of Better = writing less code? :-) Sincerely
  8. joachimd

    How to get data from class to TVirtualStringTree?

    For such purposes I've written my own component, derived from TWinControl. It contains a TVirtualStringTree and implements all methods required to run it. For the outside world, I've implemented my own methods and properties. Within the implementation part of that unit, I've defined a Node record being used for all data handling. This record contains an implementation of a an interface: interface type TAppListViewer = class(TWinControl) //... implementation type PSuperNode = ^TSuperNode; TSuperNode = record obj: IAppListItem; end; //... IAppListItem iss defined in another unit: IAppListItem=interface ['{CA2770B8-8A4B-4F52-AE6F-5F55E45C6014}'] procedure SetID(const aValue: TIDType); function GetID(): TIDType; property ID:TIDType read GetID write SetID; procedure SetCaption(const aValue: string); function GetCaption(): string; property Caption:string read GetCaption write SetCaption; procedure SetParent(const aValue: IAppListItem); function GetParent(): IAppListItem; property Parent:IAppListItem read GetParent write SetParent; function GetChildren(): TAppList; property Children:TAppList read GetChildren; procedure AddChild(aChild: IAppListItem); procedure RemoveChild(aChild: IAppListItem); //... end; My component has a property getting one such an item (the root) and all children of it. Setting it will cause a rebuilt of the tree. property AppList:IAppListItem read FAppList write SetAppList; HTH Joachim
  9. dummzeuch

    Two GExperts bugs fixed, 14 to go

    I just fixed two (newly reported) bugs in GExperts: The Set Tab Order dialog no longer worked in Delphi 6, 7 and 2005. This was due to me adding AlignWithMargins (and the associated Margins property) to the dfm file. This property apparently was introduced in Delphi 2006. Again, this underlines what I mentioned several times: I do not use Delphi < 2007 for anything but testing and fixing bugs GExperts. That’s why glitches like this tend to slip by unnoticed. That’s why I would like people to volunteer for testing the various versions. But apparently nobody can be bothered. Fine by me, but you will have to live with the consequences. I don’t have a QA department. The extensions to the Uses Clause Manager caused several thousand (small) files to be created in the GExperts configuration directory. This directory is located under AppData\roaming\GExperts which means it will be copied when roaming profiles are enabledin a Windows domain. I didn’t know that anybody still uses roaming profiles since they are usually not worth the trouble, but apparently they are still being used. So I now moved that cache to AppData\local and also added a config option to disable caching altogether. https://blog.dummzeuch.de/2019/02/09/two-gexperts-bugs-fixed-14-to-go/
  10. timfrost

    Two GExperts bugs fixed, 14 to go

    And perhaps one more (though tiny): The very useful Warn Directive tool misses at least one warning. I found that COMBINING_SIGNED_UNSIGNED64 (1073) is absent. It might also be useful to have an option in the dialog to show the warning numbers (and perhaps sort on this value). I find that some numbered warnings have a descriptions which does not match the the name, making them hard to find in the list. For example the compiler reports "W1036 Variable 'x' might not have been initialized", but needs USED_BEFORE_DEF to suppress this.
  11. What about that : type TRecord1 = record private var FTypeInfo: Pointer; // this must be the first field and all record must implement it. public var FField1: Integer; // Record fields. class function Create: TRecord1; static; end; TRecord2 = record private var FTypeInfo: Pointer; public var FField1: Integer; FField2: string; class function Create: TRecord2; static; end; procedure DoSomething(const Rec); type TRecordHack = record FTypeInfo: Pointer; // since FTypeInfo is the first field in all records, we can hack it ! end; PRecordHack = ^TRecordHack; var PHack: PRecordHack; TypeInfo: Pointer; LCntx: TRttiContext; LType: TRttiType; begin PHack := PRecordHack(@Rec); TypeInfo := PHack^.FTypeInfo; // RTTI: LCntx := TRttiContext.Create(); try LType := LCntx.GetType(TypeInfo); ShowMessage(LType.Name); finally LCntx.Free(); end; end; procedure TForm1.Button1Click(Sender: TObject); var a: TRecord1; b: TRecord2; begin a := TRecord1.Create(); DoSomething(a); b := TRecord2.Create(); DoSomething(b); end; { TRecord1 } class function TRecord1.Create: TRecord1; begin Result.FTypeInfo := TypeInfo(TRecord1); end; { TRecord2 } class function TRecord2.Create: TRecord2; begin Result.FTypeInfo := TypeInfo(TRecord2); end;
×