Why does SystemParametersInfo hang when I pass the SPIF_SENDCHANGE flag?

Date:March 10, 2005 / year-entry #60
Tags:code
Orig Link:https://blogs.msdn.microsoft.com/oldnewthing/20050310-00/?p=36233
Comments:    5
Summary:If you pass the SPIF_SENDCHANGE flag to the SystemParametersInfo function, it will broadcast the WM_SETTINGCHANGE message with the wParam equal to the system parameter code you passed. For example, if you call SystemParametersInfo(SPI_SETDOUBLECLICKTIME, 500, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE); then the system will broadcast the message SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETDOUBLECLICKTIME, 0); If there is a window that...

If you pass the SPIF_SENDCHANGE flag to the SystemParametersInfo function, it will broadcast the WM_SETTINGCHANGE message with the wParam equal to the system parameter code you passed. For example, if you call

SystemParametersInfo(SPI_SETDOUBLECLICKTIME,
      500, 0, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);

then the system will broadcast the message

SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE,
            SPI_SETDOUBLECLICKTIME, 0);

If there is a window that isn't responding to messages, then this broadcast will hang until that unresponsive window finally resumes responding to messages or is killed.

If you'd rather not be victimed by unresponsive windows, you have a few options, but it also may affect your program's expectations.

You could issue the SystemParametersInfo call on a background thread. Then your background thread is the one that blocks instead of your UI thread.

With this message, the background thread can notify the main thread when the broadcast finally completes, at which point your program now knows that all windows have received their notifications and are on board with the new setting.

You could issue the SystemParametersInfo call without the SPIF_SENDCHANGE flag, then manually broadcast the change via

DWORD dwResult;
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE,
            SPI_SETDOUBLECLICKTIME, 0,
            SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG,
            5000, &dwResult);

This does mean that unresponsive windows will not receive the notification that a system parameter has changed. This is acceptable if you decide that your change in settings was minor enough that a program missing the notification is no big deal. In other words, when the unresponsive program finally wakes up, it will not know that the setting has changed since it missed the notification.

You can combine the above two methods: Use a background thread and send the message with a timeout.

Perhaps the best technique is to use the SendNotifyMessage function. As we learned earlier, the SendNotifyMessage function is like SendMessage except that it doesn't wait for a response. This lets your program get back work while not messing up programs that were momentarily unresponsive when you decided to broadcast the notification.

SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE,
            SPI_SETDOUBLECLICKTIME, 0);

The downside is that you don't know when all windows have finally received and processed the notification. All you know is that someday, they will eventually find out. Usually you don't care about this aspect of the broadcast, so this lack of information is not an impediment.


Comments (5)
  1. Jack Mathews says:

    Just curious, what are the functional differences between SendNotifyMessage and PostMessage if it’s not sending to a window created by the calling thread?

    I understand that SendNotifyMessage will just call the window procedure for the local thread, does it also skip the message queue for windows in other threads?

  2. Anonymous says:

    Raymond, on that post you say "Sent messages are not queued. Obviously, I need to dedicate a future entry to explaining the difference between posting and sending messages since people appear not to grasp it."

  3. Ivo says:

    I noticed this problem with XP – If an application has a modal dialog opened (for example File/Open in Notepad) and I switch the themes from XP to Classic, the application doesn’t update. It stops responding to theme changes until it is closed and restarted. If the application starts in Classic theme, then switching to XP works fine, and all subsequent theme changes too.

    Maybe the "Display Properties" box doesn’t notify the applications correctly? Or is it a more generic problem with broadcasted messages and modal message loops?

  4. Jack Mathews says:

    Raymond: So the answer, then, is "yes." Thanks :)

Comments are closed.


*DISCLAIMER: I DO NOT OWN THIS CONTENT. If you are the owner and would like it removed, please contact me. The content herein is an archived reproduction of entries from Raymond Chen's "Old New Thing" Blog (most recent link is here). It may have slight formatting modifications for consistency and to improve readability.

WHY DID I DUPLICATE THIS CONTENT HERE? Let me first say this site has never had anything to sell and has never shown ads of any kind. I have nothing monetarily to gain by duplicating content here. Because I had made my own local copy of this content throughout the years, for ease of using tools like grep, I decided to put it online after I discovered some of the original content previously and publicly available, had disappeared approximately early to mid 2019. At the same time, I present the content in an easily accessible theme-agnostic way.

The information provided by Raymond's blog is, for all practical purposes, more authoritative on Windows Development than Microsoft's own MSDN documentation and should be considered supplemental reading to that documentation. The wealth of missing details provided by this blog that Microsoft could not or did not document about Windows over the years is vital enough, many would agree an online "backup" of these details is a necessary endeavor. Specifics include:

<-- Back to Old New Thing Archive Index