Jump to content

dan13l

Members
  • Content Count

    1
  • Joined

  • Last visited

Community Reputation

0 Neutral
  1. Hello, can someone elucidate me on the following phenomenon in Delphi which presently I consider to be a bug (I have reported it but am hoping someone here could answer me sooner): I am working on a project with many (100s) forms that inherit from a base form. Ever since migrating to Delphi 12 (from Delphi 7) I have been encountering these annoying changes in the IDE whereby inheriting forms have certain properties that are written out but I believe they shouldn't be. For example, take this base form DFM file: object BaseForm: TBaseForm Left = 0 Top = 0 Caption = 'My Form' ClientHeight = 441 ClientWidth = 624 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -12 Font.Name = 'Segoe UI' Font.Style = [] TextHeight = 15 object BitBtn1: TBitBtn Left = 280 Top = 232 Width = 75 Height = 25 Caption = 'BitBtn1' TabOrder = 0 end end It is the default that the IDE generates when creating a new form, except that I've changed the Name, Caption and dropped a TBitBtn on it. When creating a new form and inheriting from the above form, the DFM looks like this: inherited MainForm: TMainForm StyleElements = [seFont, seClient, seBorder] TextHeight = 15 inherited BitBtn1: TBitBtn DoubleBuffered = True end end I don't believe any of the properties should have been written out into the inheritor's DFM. TextHeight doesn't bother me as much because it already exists in the Delphi 7 code base, and frankly I'd rather leave it. It's the new stuff added by Delphi 11 & 12 (according to posters on here) to do with the DoubleBuffered property, and earlier versions that introduced the StyleElements property. All the forms I work on and save in Delphi 12, I get this extra stuff generated that I don't agree should be generated, and I am currently holding off committing these spurious changes until I have it on good authority that those are valid changes. I have a custom tool that I use to open all project's forms in the IDE and re-save them. I have it sorting out bits like ClientWidth and ClientHeight (converting from Width/Height), and I check each change and allow for things like the removal of OldCreateOrder (it then modifies the constructor code for affected forms if they have any code after the "inherited" part - caused a lot of precedence issues otherwise) and PixelsPerInch properties, or changes in the order in which properties and their values are written out in the DFM, and other changes in the DFM as part of the migration that I am happy to commit (component versions for instance). It may seem like over the top (I often ask myself that), but it doesn't seem so now as this practice showed that it (writing a fair bit of automation code) was all worth doing. Worth noting, I run the IDE in TSRemote Desktop/RDP/RDS environment, and the application itself is primarily run via Citrix. I run Delphi 12.1 with the patch. I've done some digging into the DoubleBuffered property and the recent changes to it, and I've found that the TBitBtn's DoubleBuffered property at design time always shows as False (its default is True, and the internal property variable is set to True) - turns out the IDE detects RDP sessions and this affects the designer and what it writes into DFM for the DoubleBuffered property. I guess the IDE's TApplication has similar code for detecting TS sessions, but it doesn't seem to be the same as in Delphi 12. The reason I think this is because I can't set TBitBtn's DoubleBuffered property to True, even though the DoubleBufferedMode is set to dbmRequested. I am guessing the Delphi 12 IDE runs some former code that attempts to improve RDP performance which doesn't yet have the DoubleBufferedMode property (Delphi 11's code?). I wonder if it's possible to stop the IDE detecting RDP sessions? (EDIT2) I think because Emba combined DoubleBuffered's getter with the function CanUseDoubleBuffered, so to achieve application-wide DoubleBuffered improvements without components needing to change, it looks like a design smell because I believe the DoubleBuffered getter should be separate from the function CanUseDoubleBuffered. Moreover, because the DoubleBufferedMode is set to dbmRequested by default (not dbmDefault 😄), making the RDP optimization not on by default (i.e. DoubleBuffered is as it was before), you'd have to go through your controls and set DoubleBufferedMode to dbmDefault to enable this feature. I've read here that it was in D11 they've made changes to this and then again in D12, so maybe this explains the design change, maybe they've turned on RDP optimization by default, then backed it out due to possible issues, or maybe they've just changed DoubleBufferedMode to dbmRequested, not dbmDefault which was probably the original choice? For convenience, here's the DoubleBuffered getter and the function it calls below it: function TWinControl.GetDoubleBuffered: Boolean; begin Result := FDoubleBuffered and (CanUseDoubleBuffering or (csWriting in ComponentState)); end; function TWinControl.CanUseDoubleBuffering: Boolean; begin Result := (FDoubleBufferedMode = dbmRequested) or not (Application.InRemoteSession and Application.SingleBufferingInRemoteSessions); end; What I still don't understand, why I can't set DoubleBuffered to True on a TBitBtn and get the Object Inspector to show it as True? DoubleBufferedMode is set to dbmRequested so based on above code, I should see "True" in the Object Inspector. Could it be the BPL that contains the TBitBtn is running some old code, and not the one pasted above??? This is so weird. Have I lost my mind? 🙂 No, probably Delphi is buggy AF as usual. (END OF EDIT2) While writing this, I've found that if you set DoubleBuffered to False, even if the Object Inspector already shows it to be False, the DFM will now have that property written out with False. Then, the inheriting form doesn't have this property written out anymore (going to have to go with this unsavoury workaround for now). But if you want to leave the DoubleBuffered as the default/True, then the inheriting form will have it written out. It's as if the IDE doesn't detect that the value of a property in the inheriting form hasn't really changed from base, it's only the function in the base class that returns False due to some runtime condition (which again, in this case, is affected by IDE's detection of RDP environment). I don't understand then, why the IDE doesn't write the value into base if the getter returns False, but writes it into the inheriting form DFM if the getter for the base class property is false. Seems like a bug in the IDE to me. The bit with StyleElements is odd as well in that if I change the base form's StyleElements to [], it now appears in the base DFM (that's fine because it's no longer the default value), and when deleted from the inheriting form (or newly saved by Delphi 12 when coming from Delphi 7), it doesn't get re-added by the IDE (going to go with this, as probably won't use styles; although on one hand this seems like workaround, it's "less bad" than the one above with DoubleBuffered; on the plus side, the IDE no longer shows the forms as styled!). Logged the issue on the new Quality Portal here. Thanks P.S. I've mentioned styles here - can someone weigh in with a sentence or two and recommend or not recommend them? My superiors could be very pleased to see a different look and feel in the application after so many years of the same monotonous grey design (I've no issue with it though). But I feel that I shouldn't use styles, I also feel it may be buggy; also seeing as customers mostly use Citrix, it may be better performance to leave it all as is. One more thing, there is the option of using Developer Express's skins instead - are those any better? Sorry, I feel like I should have created a separate thread for this. EDIT: tweaking, punctuation, clarifications.
×