Attila Kovacs 629 Posted February 25, 2021 @balabuev Could you figure it out what is happening there? It's not clear for me based on that workaround. Share this post Link to post
balabuev 102 Posted February 25, 2021 (edited) Not yet. But I see that the tree view does not receive WM_DESTROY message after pressing a close button. Which is quite strange. Edited February 25, 2021 by balabuev 1 Share this post Link to post
Guest Posted February 25, 2021 (edited) On 2/23/2021 at 5:24 PM, aehimself said: Now, if the TreeView on the TabSheet has ANY items created if the application has a VCL style active, those items will not be freed up. here my tests: RAD Studio 10.3.3 Arch VCL project with "1 Frame" and "2 TreeViews" the frames is created by code on FormMain OnCreate, and destroyed on FormMain OnDestroy events, as usual! using reportmemoryleaks for tests! FormMain unit type TForm1 = class(TForm) Panel1: TPanel; spdbtn_ShowMyFrameOnPanel2: TSpeedButton; pnlFormMainClientArea: TPanel; ComboBox1: TComboBox; procedure spdbtn_ShowMyFrameOnPanel2Click(Sender: TObject); procedure ComboBox1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} uses Vcl.Themes, uFrameWithTreeViews; var myFrameWithTreeViews: TfrmeFrameWithTreeViews = nil; procedure TForm1.ComboBox1Click(Sender: TObject); begin if (ComboBox1.ItemIndex > -1) then begin TStyleManager.TrySetStyle(ComboBox1.Items[ComboBox1.ItemIndex], true); end; end; procedure TForm1.FormCreate(Sender: TObject); begin ComboBox1.Items.AddStrings(TStyleManager.StyleNames); ComboBox1.ItemIndex := ComboBox1.Items.IndexOf(TStyleManager.ActiveStyle.Name); Caption := TStyleManager.ActiveStyle.Name; // myFrameWithTreeViews := TfrmeFrameWithTreeViews.Create(nil); // if not(myFrameWithTreeViews = nil) then pnlFormMainClientArea.Caption := 'myFrameWithTreeViews was created successfully' else pnlFormMainClientArea.Caption := 'myFrameWithTreeViews WAS NOT created!'; end; procedure TForm1.FormDestroy(Sender: TObject); begin FreeAndNil(myFrameWithTreeViews); end; procedure TForm1.spdbtn_ShowMyFrameOnPanel2Click(Sender: TObject); begin spdbtn_ShowMyFrameOnPanel2.Enabled := false; // just one time! // pnlFormMainClientArea.Font.Size := 12; // for better look! // if not(myFrameWithTreeViews = nil) then begin myFrameWithTreeViews.Parent := pnlFormMainClientArea; myFrameWithTreeViews.Align := TAlign.alClient; end; end; initialization ReportMemoryLeaksOnShutdown := true; finalization end. Frame unit type TfrmeFrameWithTreeViews = class(TFrame) Splitter1: TSplitter; tvOnPanelLeft: TTreeView; pnlToPageControl: TPanel; Splitter2: TSplitter; pnlWithPageControlInto: TPanel; PageControl1: TPageControl; TabSheet1: TTabSheet; tvOnTabSheet1: TTreeView; TabSheet2: TTabSheet; pnlWithMemoInto: TPanel; Memo1: TMemo; pnlToTreeViewOnLeftOnFrame: TPanel; Panel1: TPanel; spdbtnAddNewItemsOnLeft: TSpeedButton; Panel2: TPanel; spdbtnAddNewItemsOnRight: TSpeedButton; pgctrlOnFrame: TPageControl; TabSheet3: TTabSheet; tvOnpgctrlOnFrameOnTabSheet3: TTreeView; SpeedButton1: TSpeedButton; procedure spdbtnAddNewItemsOnLeftClick(Sender: TObject); procedure spdbtnAddNewItemsOnRightClick(Sender: TObject); procedure SpeedButton1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; implementation {$R *.dfm} procedure TfrmeFrameWithTreeViews.spdbtnAddNewItemsOnLeftClick(Sender: TObject); begin tvOnPanelLeft.Items.Add(nil, Format('NewItem_%d', [tvOnPanelLeft.Items.Count + 1])); end; procedure TfrmeFrameWithTreeViews.spdbtnAddNewItemsOnRightClick(Sender: TObject); begin tvOnTabSheet1.Items.Add(nil, Format('NewItem_%d', [tvOnTabSheet1.Items.Count + 1])); end; procedure TfrmeFrameWithTreeViews.SpeedButton1Click(Sender: TObject); begin tvOnpgctrlOnFrameOnTabSheet3.Items.Add(nil, Format('NewItem_%d', [tvOnpgctrlOnFrameOnTabSheet3.Items.Count + 1])); end; end. NOTE: now add a new PageControl "on" Frame, and same logic to add new "items" and change styles on app! hug Edited February 25, 2021 by Guest Share this post Link to post
Attila Kovacs 629 Posted February 25, 2021 (edited) I'm not sure whether it's even worth further debugging. I just got an email from quality emba that they are unable to reproduce this: https://quality.embarcadero.com/browse/RSP-20010 and there is also this: https://quality.embarcadero.com/browse/RSP-15109 The whole unit is a mess. (And I don't think they fixed it. Did they? 10.4.2 anyone?) Edited February 25, 2021 by Attila Kovacs Share this post Link to post
balabuev 102 Posted February 26, 2021 I have to admit that this is one of rare cases when I cannot find the reason of issue What I've found: - Upon closing the form calls DestroyWindow in its destructor to destroy self handle. As specified in MSDN, DestroyWindow destroys all children windows (recursively) and then - the window itself. And it should send WM_DESTROY messages. - So, this is not Delphi stuff (no recursive itertation of children, etc) - all handles of all controls are destroyed with a single call to DestroyWindow. - However, WM_DESTROY is not received by the tree view. Moreover, WM_NCDESTROY message (which should be sent after WM_DESTROY) is received - and so, this is an indicator that everything is still set up at the moment (constrol exists; its handle exists and valid; its WndProc is still wired and continues to receive messages). So, I believe that something crazy happens recursively, which prevents DestroyWindow to do its work correctly. Maybe DestroyWindow or some other incompatible API is called second time from one of messages sent by the original DestroyWindow call - something like that. I've tried to Google, but was unable to find any results where people discuss mising WM_DESTROY messages. Another idea is that some hook (maybe even style hook) eats the message. But, unfortunately, tree view's style hook also does not receive WM_DESTROY. Who steal the message!!! 1 Share this post Link to post
Guest Posted February 26, 2021 maybe if he can upload the files envolved as original for test? hug Share this post Link to post
balabuev 102 Posted February 26, 2021 20 minutes ago, emailx45 said: maybe if he can upload the files envolved as original for test? Test project (was already provided in one of previous posts) 1 Share this post Link to post
Guest Posted February 26, 2021 3 hours ago, balabuev said: was already provided in one of previous posts i dont saw it, thanks hug Share this post Link to post
pyscripter 689 Posted March 7, 2021 On 2/24/2021 at 3:26 PM, balabuev said: What is interesting: removing the bottom list view will stop the bug from occurring. This is indeed weird. In fact, just turning the Visible property of the ListView to False prevents the error. Some further observations: I confirm that WMDestroy is not received by the treeview The bug is definitely related to Vcl.Styles. If you change the style to a Vcl.Style and then back to Windows, the error does not occur You can prevent the error by calling Treeview.Items.Clear in the FormCloseQuery event handler. Strangely calling RecreateWnd in the same handler also prevents the error. Share this post Link to post
Guest Posted March 7, 2021 (edited) On 2/26/2021 at 11:39 AM, balabuev said: (was already provided in one of previous posts) hi @balabuev trying just building, no executing Debug or Release: why your project try execute "Powershell later building..."? Quote [Exec Error] The command "powershell.exe Expand-Archive -Force ..\..\Cairo\Dlls\librsvg-Win32.zip .\build\ " exited with code 1. hug Edited March 7, 2021 by Guest Share this post Link to post
pyscripter 689 Posted March 7, 2021 3 minutes ago, emailx45 said: hi @balabuev trying just building, no executing Debug or Release: why your project try execute "Powershell later building..."? hug You need to remove the build event from the project options. This was stated earlier in this thread. 1 Share this post Link to post
Guest Posted March 7, 2021 (edited) my fault!! all the same... hug Edited March 7, 2021 by Guest Share this post Link to post
pyscripter 689 Posted March 7, 2021 (edited) The issue results from the TListView being recreated as a response to the CM_STYLECHANGED message (see CustomListView.WndProc). If you add the following at the top of UMainForm.pas TListView = class(Vcl.ComCtrls.TListView) protected procedure WndProc(var Message: TMessage); override; end; with the following implementation procedure TListView.WndProc(var Message: TMessage); begin if (Message.Msg = CM_STYLECHANGED) then begin if ViewStyle = vsReport then UpdateColumns; end else inherited; end; the error does not happen. There does not appear to be much point in recreating the ListView, since its handle would have already been recreated, when the form it resides gets recreated. Still it remains a mystery why the recreation of the ListView affects the TreeView! The memory leak is also prevented by calling RecreateWnd after changing the style. In the process of debugging, I discovered another Vcl bug: [RSP-33221] CM_STYLEDCHANGE is broadcast twice - Embarcadero Technologies Edited March 7, 2021 by pyscripter 2 Share this post Link to post
Guest Posted March 7, 2021 (edited) and more, "TCustomListView.WnProc ... process" calls: unit: Vcl.Controls.pas, line: 7185 (RAD 10.3.3) function TControl.Perform(Msg: Cardinal; WParam: WPARAM; LParam: LPARAM): LRESULT; ... if Self <> nil then WindowProc(Message); // call the "procedure TCustomListView.WndProc(var Message: TMessage);" line 19652, again!!! then this is 2ªx hug Edited March 7, 2021 by Guest Share this post Link to post
Gustav Schubert 25 Posted March 7, 2021 1. I have reduced the test project (in source.zip on page 1) further and have a very small observation: With only three components (RadioGroup, TreeView, ListView) the memory leak disapears. But the memory leak (after switching style at runtime) is back when TreeView and ListView are children of (the same) Panel. I needed to bring back the panel! In other words: The observation is that the parent Panel plays a role. Why is it that we need a Panel (or maybe other common parent component) to see the problem? 2. Confirmed that the TListView.WndProc override 'works' in Tokyo. 1 Share this post Link to post
Guest Posted March 7, 2021 as another container, it sould provide the "pacific end", be a TPanel, TLaiout ot TForm. of course, if you added a Item in a object, then, you should "clear" it, as do IDE on Desingtime. hug Share this post Link to post
Vincent Parrett 746 Posted March 8, 2021 8 hours ago, pyscripter said: In the process of debugging, I discovered another Vcl bug: [RSP-33221] CM_STYLEDCHANGE is broadcast twice - Embarcadero Technologies This whole saga is typical of the VCL Styles support - in short, it's a mess. My guess is they really don't have anyone inhouse that is an expert with this stuff, so various people (contractors?) tinker with individual issues without an overall picture of things and with an impact analysis. You only have to look at how double buffering is handled 15 different ways in the vcl for various controls. Then there's the overpainting that happens when controls are resized (the whole form is repainted for each control). https://quality.embarcadero.com/browse/RSP-30639 And the response to it has been laughable at best. They "fixed" the design issue by tinkering with one affected control (TMemo) but left the rest (citing the need for interface changes) - but now they expect us to enter separate issues for each affected control! I suspect that is so they can split the tasks up to different people... so we can get more of the same tinkering. Seriously, if you are not already using VCL Styles, then don't bother with it. 1 Share this post Link to post
Attila Kovacs 629 Posted March 8, 2021 I'm chanting since ages that VCL is practically abandoned by Emba. Share this post Link to post
pyscripter 689 Posted March 8, 2021 @Vincent Parrett@Attila KovacsI am afraid you are both off-topic. If you want to rant about Vcl, Vcl.Styles, Embarcadero etc. please do it in a new thread. Share this post Link to post
Vincent Parrett 746 Posted March 8, 2021 @pyscripter I'm just pointing out that this bug is not isolated, but is a symptom of an endemic issue with vcl styles in general. I'll leave it at that. Share this post Link to post
Attila Kovacs 629 Posted March 8, 2021 Not just with styles but it's the cream on the cake. Share this post Link to post
Guest Posted March 8, 2021 (edited) as @Vincent Parrett pointed, my thesis on the need for a remaster of language itself is necessary. Otherwise, the fight will be eternal and will win the bug, as it is already known. or worse, the developer will continue to pay for a commercial beta ... without complaining! hug Edited March 8, 2021 by Guest Share this post Link to post
Daniel 417 Posted March 8, 2021 I agree with @pyscripter, please come back to the topic. Share this post Link to post
Dalija Prasnikar 1393 Posted March 8, 2021 I opened new thread for more general discussion about VCL and VCL Styles 1 Share this post Link to post
balabuev 102 Posted March 8, 2021 16 hours ago, pyscripter said: The issue results from the TListView being recreated as a response to the CM_STYLECHANGED message Good observation. And its quite strange that your workaround affects the issue, because: In the demo you can switch between VCL Styles any times and, then, switch back to Windows style. Obviously, in this case CM_STYLECHANGED will be processed one or more times, but no bug will occurred an the end. CM_STYLECHANGED does not received after form's close button click. So, there should be some resulting side effect - a difference in the application's state with and without workaround. So, I've decided again to look at the child windows of the panel. The code: var s: string; function EnumProc(hwnd: HWND; lParam: LPARAM): BOOL; stdcall var c: TWinControl; begin c := FindControl(hwnd); if c = nil then s := s + 'nil' else s := s + c.ClassName; s := s + #13#10; Result := True; end; procedure TMainForm.Button1Click(Sender: TObject); begin s := ''; EnumChildWindows(ClientPanel.Handle, @EnumProc, 0); ShowMessage(s); end; With the system style: With VCL style: And with the workaround from @pyscripter: So, with workaround, we have at least different child windows order. 2 Share this post Link to post