Jump to content

balabuev

Members
  • Content Count

    241
  • Joined

  • Last visited

  • Days Won

    2

Everything posted by balabuev

  1. balabuev

    TTreeNode leak when VCL styles are active

    I've replaced the treeview with a frame to remove the mess with the second pair of unneeded scrollbar windows. I've simulated some resource allocation on WM_CREATE in a frame, which is then freed on WM_DESTROY, similar to tree view. Run the demo. Switch to any VCL Style. Press "Bring to front" button. Close the form Source.zip
  2. balabuev

    TTreeNode leak when VCL styles are active

    I think, csDestroying flag cannot be used also, because it is set in any situation: Form as a whole is destroyed Or, the control only is destroyed by the user.
  3. balabuev

    TTreeNode leak when VCL styles are active

    I need some time to modify our demo to show this in one simple step. The problem is that we have currently four scrollbar windows, from which only two belong to list view (other two belong to tree view). This hides the bug, when they are not in the needed specific order relative to each other.
  4. balabuev

    TTreeNode leak when VCL styles are active

    Yes, exactly.
  5. balabuev

    TTreeNode leak when VCL styles are active

    Not necessary. During the runtime of the application you can just create and destory as many ListViews dynamically as you want. I can create and destroy 1000 ListViews in a loop. All on the same parent panel. Anyway, this is up to application. We cannot predict this.
  6. balabuev

    TTreeNode leak when VCL styles are active

    When some ListView is destroyed, all associated resources, like style hooks and scrollbar windows should be also destroyed as soon as possible. Such stuff should not live until the application end.
  7. balabuev

    TTreeNode leak when VCL styles are active

    We have actually two parts in each TScrollWindow: Real window represented by window handle Delphi object of TScrollWindow class. First one will be deleted by window manager, but the second - not. However, even the first one will be deleted only when the parent panel will be destroyed. Which is not acceptable as a good quality fix. I'm actually have somewhat similar idea: we should work on a slightly lower layer. Let's style hooks be destroyed like they are destroyed now. But, TScrollingStyleHook.Destroy should not destroy its owned TScrollWindow objects immediatelly. Instead it should hide them (make non-visible) and collect in some global list for later asynchronous destrution.
  8. balabuev

    TTreeNode leak when VCL styles are active

    You cannot use this condition, because this effectively leaves the corresponding style hook in the FControls dictionary forever. So, you'll have a leak of style hooks. Yes, but look at TScrollingStyleHook.Destroy method. It destroys FVertScrollWnd and FHorzScrollWnd owned objects, which are of TScrollWindow class.
  9. balabuev

    TTreeNode leak when VCL styles are active

    Did you checked it somehow? I think, this will not change anything, because we still destroy control's style hook. Which will internally destroy its own parts, like scrollbar windows.
  10. balabuev

    TTreeNode leak when VCL styles are active

    @pyscripter, forget about handles recreation in CM_STYLECHANGED. First, because it may happen by some other reason; recreation of handles is a part of VCL - nothing to do with that. Second, because this anyway does not fix the bug, since the user can change Z-order explicitly using ListView.BringToFront, for example. I can reproduce the bug even with this your workaround: procedure TListView.WndProc(var Message: TMessage); begin if (Message.Msg = CM_STYLECHANGED) then begin if ViewStyle = vsReport then UpdateColumns; end else inherited; end;
  11. balabuev

    TTreeNode leak when VCL styles are active

    I can imagine a linked list iteration inside DestroyWindow function, like: cur := FirstChild; while cur <> nil do begin nxt := cur.Next; ProcessNode(cur); cur := nxt; end; If ProcessNode will (as in our case) recursively delete the next node from the list - the function will fail, because it already fetched the pointer to the next node into its local variable. However, if ProcessNode will delete the next next node (the node after next) - nothing bad will happen. I think it's not necessary. For example, when scrollbars are hidden these controls may stay untouched. On the other hand this may be the simplest fix.
  12. balabuev

    TTreeNode leak when VCL styles are active

    Part 2: The demo with simple three buttons on a panel. RunTestClick destroys the panel handle using DestroyWindow function. Button1 is the first in Z-order, and thats why it will first receive WM_DESTROY message. In the message handler it will destroy Button2 recursively. And the test shows, that in this case Button3 will not receive WM_DESTROY. ButtonsTest.zip
  13. balabuev

    TTreeNode leak when VCL styles are active

    I've solved this puzzle In short - this is not about handles recreation, this is about handles destruction. And the order of destruction plays essential role here. First, I want to recall again, that the process starts in form's destructor, which calls DestroyWindow function. And as specified in MSDN, DestroyWindow will actually destory all children window handles recursively, and each of destorying window should receive WM_DESTROY message. It vital to understand that the destruction of a handle does not imply the destruction of the corresponding control. Control can exist without its handle. Opposite is not possible - each control destroys its own handle during the control destruction. So, from this viewpoint, form destruction is a two stage process: A single call to DestroyWindow in a form destructor deallocates all handles of all child controls on the form. And only after that, child controls are destroyed recursively. So, what is happening in the demo. Given the following panel child order: List view is the first child control of the panel, which will receive the WM_DESTROY message due to form's DestroyWindow call. List view's TWinControl.WMDestroy message handler will eventually call the following: TStyleManager.Notification(snControlDestroyed, Self); The above notification will force the style hook to destroy two owned TScrollWindow controls, which at this time have its handles allocated, and so, each of the TScrollWindow control, will call DestroyWindow recursively. So, this recursive calls of the DestroyWindow (where the nested function call destroys the window, which was already enqueued for destruction in outer function call) is the cause of the bug. This may be either: illegal usage of DestroyWindow function by Delphi or Windows bug. I don't know. Part two is comming, in which I'll reproduce this strange behavior with a simple three buttons placed on a panel (no relation to VCL Styles at all).
  14. balabuev

    TTreeNode leak when VCL styles are active

    I see this in TScrollingStyleHook.TScrollWindow.CreateParams: Params.Style := Params.Style or WS_CHILDWINDOW ...
  15. balabuev

    TTreeNode leak when VCL styles are active

    Just a note: HWND_TOPMOST only applies to top level windows, not child windows. So, it's not clear, what SetWindowPos really do in this case.
  16. balabuev

    TTreeNode leak when VCL styles are active

    Yet another evidence: It's sufficient simply to reorder children in Z-order for bug to disappear. And Z-order is the order in which EnumChildWindows function reports child windows. And so, it's most probably the order in which DestroyWindow function processes child windows. function MoveScrollWindows(hwnd: HWND; lParam: LPARAM): BOOL; stdcall; var c: TWinControl; begin c := FindControl(hwnd); if c is TScrollingStyleHook.TScrollWindow then SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE + SWP_NOSIZE); Result := True; end; procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction); begin EnumChildWindows(ClientPanel.Handle, @MoveScrollWindows, 0); end;
  17. balabuev

    TTreeNode leak when VCL styles are active

    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.
  18. balabuev

    Delphi 10.4.2 first impressions

    This is VCLEditors.pas standard unit used in a package project (package compiles ok)
  19. balabuev

    Delphi 10.4.2 first impressions

    Same behavior in older IDEs (I've checked with XE2).
  20. balabuev

    Delphi 10.4.2 first impressions

    Btw, the question: given the red error insight line in code editor, how can I show error message using keyboard only?
  21. balabuev

    Annoying IDE behavior changes in 10.4.2

    I've looked for it several days and yet not found anything. @Uwe Raabe may be you switched to Classic Code Insight mode?
  22. balabuev

    Annoying IDE behavior changes in 10.4.2

    Please vote: https://quality.embarcadero.com/browse/RSP-33156 https://quality.embarcadero.com/browse/RSP-33157
  23. balabuev

    Annoying IDE behavior changes in 10.4.2

    I can confirm all above issues. The first one is especially annoing thing for me. And the third also.
  24. balabuev

    Possible D10.4.2 issue..

    Yes. You right. But the original code was: with TLogInForm.Create(nil) do try Result := ShowModal = mrOk; finally Free; end;
  25. balabuev

    Possible D10.4.2 issue..

    By Windows I guess. If some window becomes destroyed, all its pending messages are removed from the queue. No. Unless you explicitly call Application.ProcessMessages [potentially] in a loop.
×