Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3664382
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 19, 20262026-05-19T01:38:24+00:00 2026-05-19T01:38:24+00:00

Mike Lischke’s TThemeServices subclasses Application.Handle , so that it can receive broadcast notifications from

  • 0

Mike Lischke’s TThemeServices subclasses Application.Handle, so that it can receive broadcast notifications from Windows (i.e. WM_THEMECHANGED) when theming changes.

It subclasses the Application object’s window:

FWindowHandle := Application.Handle;
if FWindowHandle <> 0 then
begin
 // If a window handle is given then subclass the window to get notified about theme changes.
 {$ifdef COMPILER_6_UP}
    FObjectInstance := Classes.MakeObjectInstance(WindowProc);
 {$else}
    FObjectInstance := MakeObjectInstance(WindowProc);
 {$endif COMPILER_6_UP}
 FDefWindowProc := Pointer(GetWindowLong(FWindowHandle, GWL_WNDPROC));
 SetWindowLong(FWindowHandle, GWL_WNDPROC, Integer(FObjectInstance));
end;

The subclassed window procdure then does, as it’s supposed to, WM_DESTROY message, remove it’s subclass, and then pass the WM_DESTROY message on:

procedure TThemeServices.WindowProc(var Message: TMessage);
begin
  case Message.Msg of
     WM_THEMECHANGED:
        begin
               [...snip...]
        end;
     WM_DESTROY:
        begin
          // If we are connected to a window then we have to listen to its destruction.
          SetWindowLong(FWindowHandle, GWL_WNDPROC, Integer(FDefWindowProc));
          {$ifdef COMPILER_6_UP}
             Classes.FreeObjectInstance(FObjectInstance);
          {$else}
             FreeObjectInstance(FObjectInstance);
          {$endif COMPILER_6_UP}
          FObjectInstance := nil;
        end;
  end;

  with Message do
     Result := CallWindowProc(FDefWindowProc, FWindowHandle, Msg, WParam, LParam);
end;

The TThemeServices object is a singleton, destroyed during unit finalization:

initialization
finalization
  InternalThemeServices.Free;
end.

And that all works well – as long as TThemeServices is the only guy who ever subclasses the Application’s handle.

i have a similar singleton library, that also wants to hook Application.Handle so i can receive broadcasts:

procedure TDesktopWindowManager.WindowProc(var Message: TMessage);
begin
case Message.Msg of
WM_DWMCOLORIZATIONCOLORCHANGED: ...
WM_DWMCOMPOSITIONCHANGED: ...
WM_DWMNCRENDERINGCHANGED: ...
WM_DESTROY:
    begin
        // If we are connected to a window then we have to listen to its destruction.
        SetWindowLong(FWindowHandle, GWL_WNDPROC, Integer(FDefWindowProc));
        {$ifdef COMPILER_6_UP}
        Classes.FreeObjectInstance(FObjectInstance);
        {$else}
        FreeObjectInstance(FObjectInstance);
        {$endif COMPILER_6_UP}
        FObjectInstance := nil;
    end;
end;

with Message do
    Result := CallWindowProc(FDefWindowProc, FWindowHandle, Msg, WParam, LParam);

And my singleton is similarly removed when the unit finalizes:

initialization
   ...
finalization
    InternalDwmServices.Free;
end.

Now we come to the problem. i can’t guarantee the order in which someone might choose to access ThemeServices or DWM, each of which apply their subclass. Nor can i know the order in which Delphi will finalize units.

The subclasses are being removed in the wrong order, and there is a crash on application close.

How to fix? How can i ensure that i keep my subclassing method around long enough until the other guy is done after me is done? (i don’t want to leak memory, after all)

See also

  • Raymond Chen: Safer Subclassing
  • MSDN: Using Window Procedures
  • Raymond Chen: When the normal window destruction messages are thrown for a loop

Update: i see Delphi 7 solves the bug by rewriting TApplication. ><

procedure TApplication.WndProc(var Message: TMessage);
...
begin
   ...
   with Message do
      case Msg of
      ...
      WM_THEMECHANGED:
          if ThemeServices.ThemesEnabled then
              ThemeServices.ApplyThemeChange;
      ...
   end;
   ...
end;

Grrrr

In other words: trying to subclass TApplication was a bug, that Borland fixed when they adopted Mike’s TThemeManager.

That very well may mean that there is no way to remove subclasses on TApplication in reverse order. Someone put that in the form of an answer, and i’ll accept it.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-19T01:38:24+00:00Added an answer on May 19, 2026 at 1:38 am

    Change your code to call SetWindowSubclass, as the article you linked to advises. But that only works if everyone uses the same API, so patch Theme Manager to use the same technique. The API was introduced in Windows XP, so there’s no danger that it’s not available on the systems where it would be needed.

    There should be no problem with patching Theme Manager. It’s designed to support Windows XP, which Microsoft doesn’t support anymore, and to support Delphi 4 through 6, which Borland doesn’t support anymore. Since development has ceased on all relevant products, it is safe for you to fork the Theme Manager project without risk of falling behind due to future updates.

    You’re not really introducing a dependency. Rather, you’re fixing a bug that’s only present when both window-appearance libraries are in use at the same time. Users of your library don’t need to have Theme Manager for yours to work, but if they wish to use both, they need to use Theme Manager with your patches applied. There should be little objection to that since they already have the base version, so it’s not like they’d be installing an entirely new library. They’d just be applying a patch and recompiling.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to get rid of everything before the filename ex: /home/mike/whatever/test_1.txt leaving only
var name = 'Mike'; var person = { name: 'John', welcome: function(){ var name
I am using Mike Bluestein's article, http://mikebluestein.wordpress.com/2009/09/27/using-monotouch-with-the-net-library-for-the-google-data-api/ , to build an application that communicates
val name = mike val xml = <name>{name}</name> xml will be <name>mike</name> But what
val name = mike val str = Hi, {name}! println(str) I want it output
I have the following code: [Thank you Mike Rosenblum!] using System; using Microsoft.Office.Interop.Excel; using
I am trying to apply Mike Chen's answer here , using SDK 3.0. In
I came accross this on the Mike Ash Care and feeding of singletons and
Take this enum for example: public enum PersonName : short { Mike = 1,
I have a string like this: $a = Mike , Tree ; I want

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.