Jump to content

dan13l

Members
  • Content Count

    3
  • Joined

  • Last visited

Community Reputation

0 Neutral
  1. @PeterBelow, thank you but my question was how to have a base data module class without a DFM. This is possible with forms, but when it comes to doing the same thing with data modules, Delphi's designer treats data module as a form when it clearly shouldn't. EDIT: I may not have been clear, so here's a small example. You can do this with forms: Say you have a form: TForm1 = class(TForm). You then want to change it to inherit from a base class, e.g. TBaseForm (say, you want to add something to all descendants, but you don't want the base class to be designable). You can simply declare TBaseForm = class(TForm) - no DFM here, and simply change the code to inherit from TBaseForm instead of TForm. This works fine. If you were to then open the designer for TForm1, it would work as normal. Doing the same thing with data modules works as in the code would compile and run without problems, but if I open the designer for such a data module (descendant data module), it shows a form and screws up the DFM (after which the code won't run :D)
  2. I am having a weird issue with Delphi which at first looked like a bug in the IDE, but now I'm thinking it's a combination with me not doing something right. The problem is as follows: - I have a bunch of TDataModules in the project and I needed to change them to descend from a base class that adds a method and some data the descendants can use. - The base class won't contain any designable items (no published elements), so I don't necessarily need a base DFM. - So I went and changed all the places that descend from TDataModule to descend from the new base class; all builds and runs fine. However, when I open the descendant data module in the designer, it opens it as a form and so adds a bunch of form related properties to the DFM, after which I will get runtime errors such "Error reading MainDataModule.ClientHeight: Property ClientHeight does not exist." For completeness, here is the PAS for the base data module: unit uBaseDataModule; interface uses System.Classes; type TBaseDataModule = class(TDataModule) private FSomeList: TList; protected procedure SomeMethod; end; implementation [...] end. And here is the PAS for the descendant data module: unit fMainDataModule; interface uses System.SysUtils, System.Classes, uBaseDataModule; type TMainDataModule = class(TBaseDataModule) private { Private declarations } public { Public declarations } end; var MainDataModule: TMainDataModule; implementation {%CLASSGROUP 'Vcl.Controls.TControl'} {$R *.dfm} end. The DFM for the descendant looks like this: object MainDataModule: TMainDataModule Left = 0 Top = 0 Height = 480 Width = 640 end If I did it "properly", the DFM above would inherit the base DFM, so the keyword object would have to be changed to inherited, as I'm sure you know. So I am aware I'm doing things in a slightly hacky way, I just figured if it works for forms, it should work for data modules, but for some reason Delphi assumes the data module is a form. This is what the descendant's DFM looks like after opening the designer and saving (notice the form related properties having been added): object MainDataModule: TMainDataModule Left = 0 Top = 0 ClientHeight = 402 ClientWidth = 608 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -12 Font.Name = 'Segoe UI' Font.Style = [] TextHeight = 15 end On the project I'm working on, there was already a base form - without a DFM - with many forms descending from it, with the designer not having any issues. I'm really curious to know how Delphi determines what is a form and what is a data module when it opens the DFM in the designer. My short term solution is to create a DFM file and change all descendant data modules to say inherited instead of object, and add the base data module to the DPR with the correct bits going into the bit inside the curly braces like so (I simply re-added the base data module unit after adding the {$R *.dfm} bit): uBaseDataModule in 'uBaseDataModule.pas' {BaseDataModule: TDataModule}; As an aside, it's weird that Delphi assumes there is a global variable named BaseDataModule. There isn't one defined. It appears to be using this name ("BaseDataModule") when going to File -> Add -> Other -> Inheritable Items. Otherwise, in there, it's just "TDataModule". Surely it should use "TBaseDataModule", not the name defined in curly braces. Similarly, I've noticed that the DFM's root object also has a name, i.e., "MainDataModule: TMainDataModule". What's the point of that? Surely it should just be the type as there may not be a MainDataModule global variable (removing it doesn't break anything; in fact, putting anything for the name works, but Delphi will correct it after saving). This is probably some really ancient Delphi stuff that isn't going to change any time soon, but I wonder if anyone has a workaround so I can avoid needlessly having a base DFM for all my data modules. All I wanted was to add a method and some data to existing data modules, so having them descend from a base data module looked like the way to go.
  3. 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.
×