-
Content Count
2771 -
Joined
-
Last visited
-
Days Won
147
Everything posted by Anders Melander
-
That's pretty easy: RecreateWnd is part of the documented public API. CM_RECREATEWND is undocumented. The VCL core is the implementation of the API so there's no surprise there. No I am not. I said "it seems" so I'm talking about appearances. I have no idea about why you do what you do so I can only guess. Calm down. I'm free to state what I think he means since it seems you misunderstood what he said. There is no conspiracy here and we're not all out to get you. We just disagree with you.
-
I think the point is that you are violating the API contract; You are supposed to call the API but instead you are circumventing the API and calling the implementation directly - for no good reason. Sometimes there are good reasons to do so but this isn't one of them so it seems you are doing so just because you can, because you don't know better or because you are stubborn. There are multiple definitions of perverse. In this case I think David meant obstinate in opposing what is right, reasonable, or accepted (from Merriam-Webster).
-
The OP asked for design time functionality. I replied with a design time solution and stated that there's no need for a run time package, so I don't understand what you are arguing about; You are the only one mentioning run-time executables. Here's a complete solution in a single design-time package: The component unit: unit amAwesome; interface uses Classes; type TMyAwesomeComponent = class(TComponent) // You awesome code here end; implementation end. The design time unit: unit amAwesomeDesign; interface procedure Register; implementation uses Classes, VCL.Dialogs, DesignIntf, DesignEditors, amAwesome; type TMyAwesomeComponentEditor = class(TComponentEditor) public function GetVerb(Index: Integer): string; override; function GetVerbCount: Integer; override; procedure ExecuteVerb(Index: Integer); override; end; procedure Register; begin RegisterComponents('Awesome', [TMyAwesomeComponent]); RegisterComponentEditor(TMyAwesomeComponent, TMyAwesomeComponentEditor); end; procedure TMyAwesomeComponentEditor.ExecuteVerb(Index: Integer); begin var LocalIndex := Index - inherited GetVerbCount; case (LocalIndex) of 0: ShowMessage('TMyAwesomeComponent 1.0'); else inherited ExecuteVerb(Index); end; end; function TMyAwesomeComponentEditor.GetVerb(Index: Integer): string; begin var LocalIndex := Index - inherited GetVerbCount; case (LocalIndex) of 0: Result := 'About...'; else Result := inherited GetVerb(Index); end; end; function TMyAwesomeComponentEditor.GetVerbCount: Integer; begin Result := inherited GetVerbCount + 1; end; end. The design time package source: package AwesomeSuite; {$R *.res} {yada yada yada lots of options here...} {$DESIGNONLY} requires rtl, designide; contains amAwesome in 'amAwesome.pas', amAwesomeDesign in 'amAwesomeDesign.pas'; end.
-
There's no requirement for both run- and design-time packages. A design time package alone is enough. Assuming you mean component editor the purpose is to separate run- and design-time functionality. The end-user doesn't need to know that the application uses TAwesomeComponent version x.y.z and there's no need to include the about form in the compiled application.
-
Yes of course and it does but ShowHint controls if the control supplies hint text when the mouse hovers over the control. If it doesn't then it will try to get the hint from the parent control, etc. The help is pretty clear on how it works.
-
Okay. What you need is a component editor. With this you can specify what happens when the user double clicks your component (at design time) and you can add menu items to the context menu. For example a "About My Awesome Component..." menu item. The help is a bit sparse on how to implement a component editor for VCL (there's a good example for FireMonkey though) but there's plenty of examples available on the net: https://www.google.com/search?q=delphi+component+editor There might also be an example installed with Delphi.
-
Don't do that. You're trying to eliminate the symptoms of a problem somewhere else in your application. Hint/ShowHint works just fine. If you manage to "hide" the problem by setting ShowHint=False then you will just have removed the only lead you currently have to the underlying problem. By the way, ShowHint does more than controlling if the control displays hints. It also controls if the child controls display hints - if Child.ParentShowHint=True. You usually set ShowHint=True on the form and then ParentShowHint=True on all child controls. Setting ParentShowHint=True just means that the parent ShowHint value propagates down to the child control. Anyway, what I would do is install MadExcept and configure it to "Instantly crash on buffer overrun". I'm guessing you have a stale pointer or a memory overwrite somewhere.
-
I think you need to explain a little bit better what you are trying to do. Start with an example of how you would like to use your component. Once we understand that we can better help you with how to implement it.
-
Should Delphi have native interfaces?
Anders Melander replied to Koru's topic in RTL and Delphi Object Pascal
Sorry to continue this but I simply don't get it; Your example works exactly as I would expect. You're telling the compiler to use two different implementations for IBar.Foo and IFoo.Foo. Even though interface B inherits from A and we have an object that implements both A and B, their shared methods (the ones from A) need not be the same (but they can be if you choose that). In fact COM explicitly states that it's the API that is inherited, not the implementation. Your example more or less corresponds to: type IFoo = interface ['{1E77F313-1C93-4A59-957B-751FB23EC63F}'] end; IBar = interface(IFoo) ['{49FC3BDA-7A09-4596-A80C-5EBEF73BA201}'] end; TFooBar = class(TInterfacedObject, IFoo, IBar) private FFoo: IFoo; FBar: IBar; public property Foo: IFoo read IFoo implements IFoo; property Bar: IBar read FBar implements IBar; end; That's a secondary source. I'm looking for a primary one or at least a more reputable one. -
Should Delphi have native interfaces?
Anders Melander replied to Koru's topic in RTL and Delphi Object Pascal
Do you have any sources for this bug in COM or can you explain what bug is? Edit: Never mind. You just did. -
Should Delphi have native interfaces?
Anders Melander replied to Koru's topic in RTL and Delphi Object Pascal
Thank you! This is in line with my understanding of the rules of COM. It seems that, unlike Kaster (it's a bug, it's a bug), Chuck (it's by design) actually read the books. -
Should Delphi have native interfaces?
Anders Melander replied to Koru's topic in RTL and Delphi Object Pascal
Why would you need a GUID if this is supposed to be "COM free"? -
Should Delphi have native interfaces?
Anders Melander replied to Koru's topic in RTL and Delphi Object Pascal
You are correct: type IBar = interface ['{570FBD40-8ECF-4B4B-9898-EF3F4146FFF9}'] end; IFooBar = interface(IBar) ['{F99BAE4A-6612-4714-96B4-237763239C7F}'] end; type TFooBar = class(TInterfacedObject, IFooBar) end; procedure test; begin var FooBar: IFooBar := TFooBar.Create; var Bar: IBar := FooBar; end; ...but as we already know... var FooBar: IFooBar := TFooBar.Create; Assert(Supports(FooBar, IBar)); ...will fail, so there's a bug somewhere - or at least a really bad inconsistency. Supports just does a IUnknown.QueryInterface which ends up in TObject.GetInterface. The assignment on the other hand just copies the pointer and calls _AddRef. From my understanding on what interface inheritance is in Delphi, Supports() is correct and the compiler is wrong but there are obviously different interpretations of this. -
Should Delphi have native interfaces?
Anders Melander replied to Koru's topic in RTL and Delphi Object Pascal
But it isn't true. The IFooBar interface inherits the methods of IBar - at compile time. The implementing object doesn't inherit the contract that it must implement the IBar interface. I'm not convinced that John Kaster knew what he was talking about when he wrote that. I mostly included the link because it seems to be the earliest mention of the feature. The limitation as-is matches my recollection of "the rules of COM" but I could be mistaken. I'm not up to reading the COM bible again just to find out. It was hard enough the first time(s). -
Should Delphi have native interfaces?
Anders Melander replied to Koru's topic in RTL and Delphi Object Pascal
I agree. Interface inheritance is just syntactic sugar. http://edn.embarcadero.com/article/29779 (warning this links contain references to The Version That Must Not Be Mentioned: Delphi 8) -
Should Delphi have native interfaces?
Anders Melander replied to Koru's topic in RTL and Delphi Object Pascal
I think I have encountered this problem on rare occasions but I can't remember the circumstances. Did you mean interface inheritance? For example the following works fine: type IFoo = interface ['{F99BAE4A-6612-4714-96B4-237763239C7F}'] end; IBar = interface ['{570FBD40-8ECF-4B4B-9898-EF3F4146FFF9}'] end; type TFoo = class(TInterfacedObject, IFoo) end; TBar = class(TFoo, IBar) end; type TFooObject = class(TComponent, IFoo) end; TBarObject = class(TFooObject, IBar) end; procedure Test; begin // Supports(interface) var FooBar := TBar.Create as IUnknown; Assert(Supports(FooBar, IFoo)); Assert(Supports(FooBar, IBar)); // Supports(instance) var FooBarObject := TBarObject.Create(nil); Assert(Supports(FooBarObject, IFoo)); Assert(Supports(FooBarObject, IBar)); end; -
It sounds like you fell into the premature optimization trap; "Optimized" something because it looked inefficient without actually measuring if it would matter.
-
Pfft. That is up to the customer to decide. [edit: before I start a sh*t storm let me rephrase that] It should be up to the customer to decide. Not you, not Embarcadero and not Microsoft. If the customer wants to run on Windows 7, which I perfectly understand in many cases, then I will support it. They are paying for that privilege. We are here to serve their needs, not the other way around. Windows 7 has a market share around 20%. Slightly higher than OS X... Works for me. It complained to install but I haven't encountered any issues that I can pin on Windows 7.
-
@Kazantsev Alexey Yes now I understand. Thanks.
-
Converting project from Delphi 2006 to Delphi 10.2
Anders Melander replied to RTollison's topic in General Help
Yes. Like I implied. Or just use the code I used: In the OP's example it doesn't matter much but a real StrLPas would be more efficient as it would avoid the reallocation (like your example). -
Converting project from Delphi 2006 to Delphi 10.2
Anders Melander replied to RTollison's topic in General Help
Okay, so do we agree that it's not equivalent to StrLPas? -
Um... Aren't you responsible for initializing the record yourself if you have declared an initializer for the record?
-
Converting project from Delphi 2006 to Delphi 10.2
Anders Melander replied to RTollison's topic in General Help
In my example there's already room for 65 characters in the destination since Delphi strings have an implicit null terminator. -
Converting project from Delphi 2006 to Delphi 10.2
Anders Melander replied to RTollison's topic in General Help
I can't tell from the documentation if SetString copies up to Length characters or always Length characters and it seems to be an intrinsic function so I can't check the source. -
Converting project from Delphi 2006 to Delphi 10.2
Anders Melander replied to RTollison's topic in General Help
You need to use StrLCopy instead of StrPas since there's no guarantee that the source string is null terminated. You actually need a StrLPas function but fo some reason they've never implemented that variant. Also remember that the buffer is a static array[] of Char[0..63] so you need to iterate the outer array somehow. var Buffer: PChar; GetMem(Buffer, PaperCount*SizeOf(Char)); try var p := Buffer; for i := 0 to PaperCount-1 do begin var PaperName: string; SetLength(PaperName, 64); StrLCopy(PChar(PaperName), p, 64); PaperName := PChar(PaperName); // or SetLength(PaperName, StrLen(PChar(PaperName))) ... Inc(p, 64); end; finally FreeMem(Buffer); end;