Date: | June 13, 2006 / year-entry #197 |
Tags: | other |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20060613-05/?p=30893 |
Comments: | 68 |
Summary: | I don't mean to pick on this series of entries, but it illustrates an interesting pattern of stumbling across the wrong "solution". The series begins by attempting to trigger the system's monitor blank timeout by posting a message to the desktop window. As we saw earlier, the desktop window is a very special window and... |
I don't mean to pick on this series of entries, but it illustrates an interesting pattern of stumbling across the wrong "solution".
The series begins
by attempting to trigger the system's monitor blank timeout
by posting a message to the desktop window.
As we saw earlier,
the desktop window is a very special window
and as a rule
should be avoided, since it won't behave like windows created
by applications.
In particular, the author tried to post a message to the desktop
window.
This used to work in the
historically open world of the window manager,
but security and robustness concerns have come to take
priority over compatibility.
In Windows XP SP2, the desktop window resists being disabled
because programs were doing it inadvertently,
and
it appears that the desktop also resists having messages posted to it.
My guess is that this was done as a way to strengthen protection against
shatter attacks.
This did improve robustness and stability,
but
it also broke the article's dubious
Enter round three,
wherein the author fumbled around for other windows the
monitor blank timeout message could be posted to,
and eventually
the author found that
posting the message to the mysterious window
I knew in the back of my mind that people developed software this way, but the hopeful part of my brain continued to wish that it was merely taking place in a fantasy world. Making up intentionally invalid parameters and seeing what happens falls into the category of malicious goofing around, not in the realm of software engineering and design. Even if you find something that seems to work, you certainly wouldn't design a product around it!
(Similarly, I've seen people ask questions like
"What does message 49251 mean?"
This is the reverse case: Seeing a made-up number and
attempting to assign meaning to it.
Message numbers starting at
If you look more carefully at what the author stumbled
across, you'll see that the "solution" is actually another bug.
It so happens that the numerical value
#define HWND_BROADCAST ((HWND)0xffff)
It so happens that internally, the window manager
supports
For example, a presentation program might want to suppress monitor power-off when it is the foreground window by trapping the message and turning the monitor back on. If such a program happens to be running, broadcasting the power-off message to all top-level windows would turn off the monitor for all the windows that deferred to system default behavior, but when that presentation program received the message, it would turn the monitor back on. Now you're at the mercy of the order in which the windows process that broadcast message. When the presentation program processes the message, the monitor will turn back on, and if that program happens to be the last one to process the message (say, it got paged out and was slow to page back in), then the monitor will merely blink off and back on. The correct solution is not to post messages to random windows. If you want the message to go through window message default processing, create a window and process it yourself. Don't try to trick some other window (or in this case, hundreds of other windows simultaneously) into doing it for you. |
Comments (68)
Comments are closed. |
Re HWND_TOPMOST vs. HWND_BROADCAST issue… I searched MSDN for HWND_TOPMOST and found a handful of items where it’s described as a valid (or even required) target to send/post messages to:
About Messages and Message Queues
http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/windowing/messagesandmessagequeues/aboutmessagesandmessagequeues.asp
"If the window handle is HWND_TOPMOST, DispatchMessage sends the message to the window procedures of all top-level windows in the system."
Using Messages and Message Queues
http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/windowing/messagesandmessagequeues/usingmessagesandmessagequeues.asp
"If the handle is HWND_TOPMOST, the system posts the message to the thread message queues of all top-level windows."
WM_TIMECHANGE
http://msdn.microsoft.com/library/en-us/sysinfo/base/wm_timechange.asp
"Windows Me/98/95: An application should send this message to all top-level windows after changing the system time using the SendMessageTimeout function with HWND_TOPMOST. Do not send this message by calling SendMessage with HWND_BROADCAST."
I only ever used it with SetWindowPos to make a window topmost…
Don’t leave us hanging…what is the correct method of powering down the monitor? A quick search on MSDN reveals ‘SetActivePwrScheme’ as a good start anyways.
Another dangerous habit I noticed looking at the examples is misusing special parameters such as HWND_BROADCAST and HWND_TOPMOST. These values are only valid in certain functions, PostMessage/SendMessage and SetWindowPos in this case. You cannot expect any function that takes an HWND to properly handle these values. It seems obvious but its one of those mistakes I made when starting Windows programming.
So, what is the correct way of turning off the monitor?
Ok now I think I may have badly interpreted your last paragraph, and that sending a message is not the correct solution! (And I am reassured!)
Still, why does the posted solution work? Is it because of the defwndproc or is a window intercepting the notification and doing the correct API call? (That would still leave me wondering why)
Your article started by saying the user was trying to “trigger the
system’s monitor blank timeout”. He said he was trying to power
off the monitor. Are those the same things?
"Making up intentionally invalid parameters and seeing what happens falls into the category of malicious goofing around, not in the realm of software engineering and design."
Some would describe it as hacking, which isn’t always malicious, or goofing around. We owe a good many of the world’s inventions to people who were just "seeing what happens."
The correct way is to make your own window and once it’s up and running to SendMessage or PostMessage to it. If your window procedure is correctly written, the messages which are not handled by your code will be handled by the system, and that’s what you want.
From the MSDN articles Aaron dug up I see there’s even a little internal confusion between HWND_TOPMOST and HWND_BROADCAST. Perhaps this is partly the reason why the window manager accepts an alternate value of -1 for HWND_BROADCAST.
Another thing I’m wondering about, hasn’t HWND always been an unsigned value? If so, isn’t
#define HWND_TOPMOST ((HWND)-1)
a bad idea?
If Windows was open source we wouldn’t have to “fumble around in the
dark”. Us poor non-Microsoft developers often have to reverse
engineer Windows to get our job done; please don’t demean us because of
it. We don’t really want to use Windows — its just forced on us
by the marketplace.
I’m going to be ruthless and defend the developers actions. Power management in windows is pretty minimally documented except in the driver pages, and support in .NET is particularly sparse. And of course, there is no source code for all of us to look at.
Raymond: you have the advantages of (a) the source and (b) the ability to email someone who will know someone who knows the answer. The rest of us have to make do with experiments. Just be glad this isnt shipping software that you have to support in future.
Please tell us:
1. How to power off the monitor in the right way and
2. How to prevent the monitor from turning off, if you are writing eg. a presentation program.
Are these two things even possible?
So, is the correct method to power-off a monitor to:
hwnd = CreateWindow(WC_MYCLASS, WS_POPUP..);
PostMessage(hwnd, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_OFF);
[pump messages]
Where WC_MYCLASS has a WndProc like:
LRESULT MyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Close after processing?
if (message == WM_DESTROY) PostQuitMessage(0);
return DefWindowProc(hWnd, message, wParam, lParam);
}
As an aside, is there a built-in Windows class that has a virtually-empty procedure body, save calling DefWindowProc and handles WM_DESTROY by calling PostQuitMessage? Or, is it easier to create a top-level hidden STATIC window (or something similiar) to perform that processing?
Huh, I didn’t think it would work but indeed posting a SC_MONITORPOWER message to an existing window does in fact turn the monitor off. For example, from a MFC application:
::PostMessage(SomeCWnd.m_hWnd, WM_SYSCOMMAND, SC_MONITORPOWER, 2);
I’m still wondering how you’d do it if you don’t have a window handle, such as a console application, without creating a temporary window.
“With the source code, people would be more likely to break the rules, because they can see which rules they can get away with breaking.” –Raymond
If I have neither the source code nor reliable documentation, I can only find (by experiment) what works right now. I can’t even determine if I am really breaking any rules. With either source code access or correct documentation, I can discover the correct thing to do, and then decide whether to take chances.
I posit that I am much more likely to track changes in released source code or in reliable documentation than I am to repeat my entire series of experiments whenever I suspect that something may have changed.
-Wang-Lo.
Exactly! To power off the monitor you just
SendMessage(MyhWnd, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_OFF)
where MyhWnd is the handle to a window you created yourself. The message is then passed to DefWindowProc which does the dirty deed for you.
To put Raymond’s comments re open source another way – having the source code will make developers MORE likely to rely on the side effects of internal implementation details than they already do. That’s fine as long as the internal implementation details NEVER change, but that is rarely true of any product that lives beyond version 1.0. Believe me, I feel your pain – I live with it too. But open source is the wrong medicine for that pain.
Well, yes and no. They’re rhetorical in that the answer is obvious. They’re not rhetorical in that they still deserve an answer.
MSDNWiki covers "Visual Studio 2005 and .NET Framework 2.0." Yes, .NET is great and all, but an awfully large percentage of software isn’t written in it, and an awfully large percentage of software probably never will be. You’re not going to see any drop in questions about Win32 until you have the documentation about it posted there and available for edit and discussion.
Sean, your claim was that a Wiki would generate correct and complete documentation.
Raymond’s effectively using the VS 2005 and CLR V2 Wiki as a test harness. If, after 6 months the CLR V2 Wiki has better documentation than MSDN, clearly you were right. If, on the other hand, it doesn’t, then a wiki isn’t the right solution.
I must disagree with your (Raymond’s) argument that open source APIs are more prone to misuse. Your argument boils down to “people can see the guts of the thing, so they’re more likely to rely on implementation choices; when the implementation changes, their app will be broken.”
APIs are contracts; the API promises to provide such-and-such functionality if called in such-and-such fashion.
If the correct calling procedure is documented in an easy-to-find way, there is no excuse for the developer to break the contract by calling it in a way other-than-specified.
So much is true of both open and closed source software.
The problem is that documentation tends to quickly fall out of sync.
Open source has the advantage that the contract can be specified right in the code. This obviates (to a certain extent) the need to consult and maintain outside documentation.
So open source has the advantage when it comes to maintaining and exploring APIs (for any given development team.)
So Raymond, who pissed in your cornflakes today? Seriously, either the documentation needs to be improved or you should stop bitching about how we try to call the under documented items. Actually noting how to call the function (or answering any of the 4 or 5 comments asking may have helped as well).
http://msdnwiki.microsoft.com/ –>
“We are not able to support editing in Firefox for this release. Check back soon for an updated release that will provide better Firefox support.”
Will this be fixed in 6 month?
I would’ve thought that by now people would’ve stopped requesting "the right way" to stop the monitor from turning off.
The "right way" is to get the user to go into his power settings and choose presentation mode or always on or something to that effect.
To understand why he’s responded to a few other posts and not to the ones requesting this information, perhaps you should read this: http://blogs.msdn.com/oldnewthing/archive/2005/06/07/426294.aspx
which is his post entitled "What if two programs did this?" and think about what would happen if one program tried to turn the monitor off while another tried to keep it on.
Hmm… Raymond, do you mean that in order to put the monitor into blank timeout, one has to post a message to ITS window?
How is that logical?
And besides, I hope the message in question is not the one tried in the linked blog, because he is sending (WM_SYSCOMMAND, SC_MONITORPOWER), which is described as a notification (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardaccelerators/keyboardacceleratorreference/keyboardacceleratormessages/wm_syscommand.asp)
and not as being able to result as an order to the ‘system’! I am not a GUI programmer, so maybe I don’t understand the windowing "model", but I would expect that this WM_SYSCOMMAND notification only have an impact on the defwndproc for the maximize&co notifications, the monitor&screensavers being simple "notifications" on which the window/app shall not have any influence (other than saying "hey i’m using the display, please don’t do that") and certainly I wouldn’t expect *my* defwndproc to handle the screensaver start by itself.
I can see why many people thought that the desktop window was "responsible" for the screensaver and monitor shutdown, but granted they should have checked in the doc! :)
I have often wanted my 2 monitors (on separate computers) to come *out* of power-save mode (power off mode?) at about 8:00 AM each weekday, just before I arrive at work.
Not crucial in the scheme of things, but one can always hope…
How man!
My previous MSDN link says (in the remarks) that the defwndproc, when passed the WM_SYSCOMMAND, *does* the action corresponding to the notification. Well as I said before, I can understand for the maximize, close & co but not for the screensaver & monitor power…
This GUI stuff is confusing for me…
Guillaume: so the right way to put the monitor in standby is to pop a message box asking the user to make it ‘always-on’? ;-)
Maybe you meant "pop-up a message box to ask the user to shut down his monitor" ;)
The "what if two programs did this" doesn’t apply here, what if two programs wanted to shut down the monitor? Hmm I don’t know… maybe… shut down the monitor!!
Anyway, I guess the correct solution is the defwndproc one. Still, I don’t understand what is the idea behind it…
Guillaume:
So you’re seriously saying that the user should toggle the power settings himself every time he wants to watch a DVD? Blech.
Nektar:
Add a handler for WM_SYSCOMMAND. If wParam is SC_MONITORPOWER and lParam is 1 or 2, return 0. All other wParam and lParam values, if not already handled by your code, should be forwarded to DefWindowProc. A similar approach exists for SC_SCREENSAVE.
To turn the power off, I have used this
#include “stdafx.h”
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
SendMessage(GetForegroundWindow(),WM_SYSCOMMAND, SC_MONITORPOWER, 1);
return 0;
}
and it seems to work.
Of course, that doesnt account for if there is a foreground window that actually processes SC_MONITORPOWER instead of passing it to DefWindowProc.
Monitor Blank vs Power Off
At first I was thinking along the lines of the vertical blank on CRT devices – which iirc was the period of time it took for the CRT guns to reset from the end of the final line on the display to the beginning of the first line.
Terminology exists for a reason – mixing up terms, even if the context seems to make it obvious what is meant. In this case I can’t even see a reason for having changed the terminology at all.
The “screensaver defense” is a little disingenuous.
Screensaver = screensaver = screensaver.
But blanking the monitor doesn’t necessarily involve turning it off, and the term “blank” has other, very precise meanings for display devices.
Also I find it a little odd to criticise a consumer of an API for naively making a call that the API itself seems to be mis-interpreting – for whatever reason – and then lambasting the consumer code for the API’s idiosynchracies.
This blog is usually interesting, often informative, but every now and again it seems to miss the point a little.
Had the tone of the piece been different it wound’t have mattered, but it seemed to be just a little condescending and critical, rather than a factual critique of an innocent mistake.
<shrug>
Keep it up though.
:)
Is it justifiable to break the law because you can’t find any legal alternative to what you’re trying to do? -Raymond
Yes, depending on what you want to do. Of course, that’s a philosophy debate.
So if open source is the wrong medicine for the pain of underdocumentation, then what is the right medicine — given that the average developer cannot contact people inside Microsoft to ask them either (A) how it’s supposed to work or (B) to fix the documentation?
Microsoft, for years, has had a very opaque corporate structure to the outside world; I’ll place bets the majority of readers of this blog (myself included) don’t even know which team *Raymond* is on, much less how to contact members of the right team. That dearth of information has started to change over the last few years, but the net effect is that Microsoft has gone from an opaque wall to an opaque wall with a few pinholes of knowledge poked through it — far from transparent.
Here’s a proposal: Convert a large portion of the Windows API documentation over to a Wiki, so that anybody can post, comment, and edit, with a suitable history log and rollbacks in case of abuse. My guess is that less than six months after converting it, the complaints about the confusing parts of the API would vanish almost entirely. Of course, this would mean embracing open communication, and I get the feeling there are a lot of folks inside Microsoft who really don’t want to do that.
So you’re seriously saying that the user should toggle the power settings himself every time he wants to watch a DVD? Blech. – Bob
Any program that went and automatically changed the power scheme or monitor setting goes straight into the recycle bin on my machine. Keep your filthy mits off my personal user settings!
http://msdnwiki.microsoft.com/wikiedit/search.aspx?query=createwindow
> MSDN Wiki
>
> CreateWindow [Search]
>
> There are no search results to display.
Um, exactly what is this site supposed to be documenting, anyway? It seems a little lacking on Win32, which is where most of the Windows-related questions seem to be. I’d say the six months starts when the content is actually *posted* the first time around, and it sure doesn’t seem to be yet.
*sigh* Wish it didn’t take upwards of 30 seconds to load a single page there, either. Traceroute gets as far as a few servers on msn.net before reaching ungodly ping times. :-(
Win32 API documentation is poor. Until the documentation is as good as
i want it to be, my life would be easier if i had the source code.
Let’s pull out a random example, since AJAX is the new cool thing: IXMLHttpRequest.Send()
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/52aaf5ff-e302-4490-821a-cb3a085fe5ee.asp
If i do a synchronous request, will OnReadyStateChange get called? If so, how many times?
i already know the answer, i’m not asking for technical support.
i’m pointing out one example were the “contract” between the API
writers and the developers is not fully spelled out.
Yes, there is a contract that we want to adhere to, but you have to tell us what the contract is.
> Is it justifiable to break the law because you can’t find any legal alternative to what you’re trying to do?
It depends on:
* the consequences of breaking the law (why the law is there)
* the consequences of not being able to do what you’re trying to do
* how hard you tried to find a legal alternative
* what else is on your list of things to do
Finding a "correct" way of doing things is a halting problem… it’s hard to tell if the answer is just one more search away, or doesn’t exist.
Dear god, (some)people! If it’s not documented, it’s logical to assume absolutely nothing about it. Doc writers will never think to write down every way to NOT use something — only the proper ways *to* use it (think about how long the documentation would be for SendMessage!) and perhaps some common mistakes. I’m shocked people think this is some new revelation — this is simply the way documentation has always worked for every toolkit ever made.
> First you said that some documentation to the effect of "Implementation detail, subject to change" is needed
Yes… *in the source code.* That comment fell under the scope of your "if you got the source code to hundreds of undocumented APIs" scenario.
To save copy/paste time, it would suffice to have a rule that "everything in source code is subject to change unless it specifically says otherwise," and then just tag certain chunks of code as /* public */
> now you say it’s implicit…
In a /library of external documentation/ it’s implicit.
*poor-man’s bold*
/poor-man’s italic/
/* just a comment */
Larry says, “Raymond’s effectively using the VS 2005 and CLR V2 Wiki as a test harness. If, after 6 months the CLR V2 Wiki has better documentation than MSDN, clearly you were right. If, on the other hand, it doesn’t, then a wiki isn’t the right solution.”
I understand that. The principle behind a Wiki is that you should get the best results with the most eyeballs. Lots of folks are interested in .NET, sure, but not anywhere near as many as are interested in accurate documentation of Win32. So wouldn’t it make sense to populate the Wiki initially with the most desired information, which in this case would be the Win32 API?
Raymond says, “My point was ‘I can’t believe people actually develop software this way – randomly doing stuff to see what happens instead of thinking about what they are actually doing.’ But from the feedback it appears that it’s unfair of me to suggest that people try to understand what they’re doing.”
Ray, I think you’re right on both counts. It’s pretty insane that people try to develop that way, and I doubt anybody here would disagree with that. To quote MST3K: “Randomly blowing up things is not a good battle strategy in a spaceship.”
But, that said, the only reason folks resort to the software equivalent of guerrila warfare is because the known documentation is either misleading, hard to find, or just plain wrong. It’s fair to suggest people know what they’re doing, but unfair to *require* it. You and I may have degrees in computer science or software engineering, but the majority of people coding for Windows don’t, so it behooves you to provide the best documentation for them that you can. I would think that by this point, having heard a thousand people complaining that the Win32 documentation has significant problems and almost nobody claiming it’s good the way it is, and that with thousands of people getting the API calls wrong, that you’d at least consider that maybe, just maybe, there’s a problem with it. This poor guy sounds to me like an exasperated programmer who tried everything he could to do it right and finally just gave up and tried anything he could think of until he found something that worked (and yes, we’ve all been at the “just work already!” stage; don’t claim you haven’t!). Had the docs been more precise and easier to find, he might never have resorted to the crazy solutions.
This does suggest that perhaps a Win32 API Wiki might be appropriate. Then all these people suggesting API doc improvements could, well, improve the API docs.
Bloody hell. There IS an msdn wiki. Who knew? Not I for certain. I sense a certain .NET focus however.
"I’m still wondering how you’d do it if you don’t have a window handle, such as a console application, without creating a temporary window."
Lookup GetConsoleWindow()
So, how do we avoid fumbling around in the dark in the first place? For instance, I’d like to emulate the effect of pressing Alt+Esc. (I do know you can’t use WM_SYSCOMMAND in this case because it starts a modal event loop looking for the release of the Alt key).
It is possible to just do this without creating a temporary window:
DefWindowProc(0, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_OFF);
paul2: Any program that went and automatically changed the power scheme or monitor setting goes straight into the recycle bin on my machine. Keep your filthy mits off my personal user settings!
—
The approach given DOES keep its mitts off your profile. Do you complain that games change your "personal user settings" when they open a fullscreen window?
[How could the SendMessage documentation have been improved to solve this problem? "When sending a message to a window, make sure it’s really a window"? -Raymond]
There’s nothing wrong with the SendMessage documentation. the problem is with the WM_SYSCOMMAND documentation. For reference:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/userinput/keyboardaccelerators/keyboardacceleratorreference/keyboardacceleratormessages/wm_syscommand.asp
First of all, the title of the page is "WM_SYSCOMMAND Notification" which implies that the message is a *notification* and not something you’d generate yourself.
Then, the first paragraph says:
"A window receives this message when the user chooses a command from the Window menu (formerly known as the system or control menu) or when the user chooses the maximize button, minimize button, restore button, or close button."
Which is totally wrong in this case. Now further down the page it says this:
"An application can carry out any system command at any time by passing a WM_SYSCOMMAND message to DefWindowProc."
Which is probably what the original person was wanting. This suggests that the functionality of WM_SYSCOMMAND has probably evolved over time, while the documentation has not evolved as well.
I’ll not suggest that what the original person did was right, and thinking about what is written in the documentation should have come up with the "correct" solution. But you can’t deny the documentation for WM_SYSCOMMAND probably needs some work.
Should I post a comment on the documentation page asking them to clarify it? Probably. But I’m a busy person, and if I wanted to submit corrections every time I spotted them, I’d be using open source software :p~
<quote>But if you were going to fill in the gaps, would you really consider intentionally passing invalid parameters as part of the missing documentation?</quote>
i would have thought so, yes. But when i actually read the guys posts for myself, i see that he wasn’t randomly passing garbage and hoping it would work. He did what we all do, read through differect sections of the SDK documentation, trying to cobble together the idea of how it’s supposed to work. The fact that code iteration #1 and #2 didn’t work obviously means that the documentation wasn’t clear enough and he did something wrong. So we keep trying things that are along the same line until it does work. The fact that it works by accident isn’t something that we’re supposed to just divine.
If you look at the documentation for SC_MONITORPOWER there is no indication that you are allowed to send the message anywhere. If fact, looking at the documentation for WM_SYSCOMMAND there is no indication that you’re supposed to be allowed to send any WM_SYSCOMMAND messages anywhere. The contract doesn’t specify it being allowed, so it must be forbidden – and therefore "hacking." Yet i find no shortage of people sending fake SC_MINIMIZE and SC_CLOSE messages.
So maybe it’s not so bad after all – just poorly documented.
Next, i receive a SC_MONITORPOWER notification when the monitor is powering down. It is a chance for me to know this is happening, and i can react accordinly (e.g. make my program do less graphical stuff.) Windows will know i’ve seen the message when i call DefWindowProc. Fair enough. But now someone is suggesting that if i simply generate a SC_MONITORPOWER notification message, and pass it to the DefWindowProc, and that will magically shut down the monitor is crazy. That is not only counter-intuitiave, but not mentioned in the documentation (even taking into account the line "The DefWindowProc function carries out the window menu request for the predefined actions specified in the previous table."). And as we’ve seen before
http://blogs.msdn.com/oldnewthing/archive/2006/05/12/596113.aspx
simply mimicing the thing doesn’t make it so. Just because you decide to generate a SC_MONITORPOWER message doesn’t mean that the monitor was in the process of turning off, or that the process will suddenly startup – at least the documentation provides no indication of that. And yet other people used to do it and it worked. So either it was a bug in Windows that it didn’t react as documentation, or it was an undocumented feature – subject to change in future versions of Windows, or it was a poorly documented feature. Yet i find no shortage of people sending fake SC_MONITORPOWER messages.
So maybe it’s not so bad after all – just poorly documented
Finally, he didn’t broadcast a message, he sent a message to WM_TOPMOST. Apparently if i fake the symptoms of a monitor in the process of shutting down, then it shuts down. So one gets the idea that if i send a SC_MONITORPOWER message, the monitor will start to power down. Well obviously i can’t send it to myself, because i have no ability to initiate a monitor shutdown. i need to send it to some central "windows" authority who will then initiate the monitor shutdown procedure, and in turn broadcast a message to every window on the system, letting them know the monitor is about to turn off, as part of the normal preparation for monitor shutdown. Sounds perfectly reasonable and logical. But how shall we tell Windows the monitor should be shut off? Well, who starts the process in the first place? Windows of course. What is our way in to talk to "the sytem"?
SendMessage(0, …
SendMessage(-1, …
SendMessage(GetDesktopWindow(), …
One of those outta work. No? Dammit, wish this stuff was documented. Any other Windowsy hWnd’s we can find?
SendMessage(HWND_TOPMOST, …
Documentation doesn’t say to can send WM_SYSCOMMANDS, but you can. Documentation doesn’t say you can initiate a monitor shutdown by calling yourself, but you can.
If i generate a WM_POWER message and pass it to DefWindowProc will the computer turn off? Documentation doesn’t really say. It says "Notifies applications that the system is about to enter a suspended mode." Still ambigious.
So, in the absense of documentation as good as i want it to be, couse code please. Perhaps you could just redo windows in CLR, so we would decompile it ourselves into readable source code.
I agree that the guy with the crazy solution is wrong. But I can’t help to sympathize.
As Sean W mentioned: How many times when you want to do something and you don’t know how? Documentations doesn’t help. You can spend hours on MSDN unless you have the right keywords. So you google it or ask your friends how – but this likely leads to a buggy solution from the last guy who experienced the same problem.
And this is mainly the fault of Microsoft for being so big. When you have millions of developers, you’re bound to get many wrong solutions for the same problem – especially when the "right" solution isn’t obvious.
The only way to improve this situation is for Microsoft to address the needs for all these developers. Have a database for how-to-do-stuff that’s easy to find. **Advertise it**. 3rd parties websites have already done it (only with possibly buggy solutions).
Either this, or put up with sketchy code and compatibility problems from now until windows become obsolete.
@OldNewThing,
As the author of the ‘offending’ articles, it seems only logical to respond to this. Let me state that this is oooold code and medio 2004 it was a pain in the ass to find code or a hint about powering down a monitor.
First of all, some background. I needed the monitor power off/on functionality for a TFT monitor in a painting frame on the wall at home. This monitor displays photos I shoot during holidays, cats etc, but also serves another role. The monitor is touch enabled and shows me a TV guide, photo browsing, movies at the local movie theatre and – important – trafic jam info (as I live near Amsterdam).
The monitor power off occurs at 11:30PM and the monitor is switched on again at 6:30AM. At least the living room is not lit up anymore during the night.
As soon as I published the code, Raymond Chen (you!?) notified me that this was not the ‘best’ way to do this. Unfortunately, Chen’s comments on my blog did not survive upgrade to Community Server…
<EDIT>
Googling for Raymond Chen leads me to OldNewThing, so you HAVE been helping me in 2004! <large grin>
</EDIT>
Enfin, on Chen’s comments, I modified the code to NOT use HWND_TOPMOST anymore, but just post the message to the handle of the .NET form, as Chen indicated. Unfortunately, I did not conclude the article series with the proper version (because it was already in the comments) and thus serves a happy bashing session two years later.
This is the code I use after Chen’s suggestion:
PostMessage((int)this.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, MONITOR_OFF);
The ‘this.Handle’ is the handle of the WinForm showing the photos and has been working splendidly for two years. And this is also what you and others are suggesting.
Actual code is (after refactor sessions):
User32.NativeMethods.PostMessage((int)this.Handle, User32.Constants.WM_SYSCOMMAND, User32.Constants.SC_MONITORPOWER, User32.Constants.MONITOR_OFF);
And yes, I was ‘fumbling’ to find a solution. Documentation about the messages was not usable, no code existed on blogs or article sites like Codeproject. And thus you experiment until a ‘solution’ appears and publish your findings. By publishing, Chen educated me and helped me refine the solution. The more eyes look at code, the better.
My published search for a better impersonation (in SharePoint) also yielded better versions of de solution.
The least you could have done in this blog post, is provide some code of a correct solution, instead of letting the readers guess for it. This also helps any other developer in finding the best solution for powering down a monitor.
I hope you will be as helpful as in 2004 next time I have a hardcore windows problem. ;-)
"Making up intentionally invalid parameters and seeing what happens falls into the category of malicious goofing around, not in the realm of software engineering and design."
I’d argue that this *is* part of software engineering. It’s reverse engineering and
you’ve touched on it before (http://blogs.msdn.com/oldnewthing/archive/2006/03/31/565878.aspx and other compatibility posts).
Someone must have said this before, but if not, I claim it: "Reverse engineering, the 2nd oldest [software] profession".
[BTW I like the inline comments better than replies to your own posts. I wonder sometimes why you persevere, though. I hope the good outweighs the bad].
@Victor — the correct solution was posted in the last paragraph of the post. Granted, it’s not code, but it also shouldn’t be hard to translate "make a window and post the message there" into workable code.
Re: [Picky, picky.]
Raymond, I was honsetly asking if those were the same things. I didn’t know. (I thought maybe the monitor would BLANK instead of power off. I *know* that blanking a screen and powering it off aren’t the same.)
Now that you have yelled at me, I now know. Sorry for questioning it, because it’s not obvious that those are the same things.
So passing intentionally invalid parameters is a form of civil
disobedience. Remember that another cornerstone of civil disobedience
is the expectation of being arrested. Do you expect Windows to block
your program when you do these things? -Raymond
Yes. In fact, that would have stopped the original code you
complain about. If Windows would have thrown a BadParam exception, the
original user would never have posted it. The first test run would have
made it clear it was illegal.
I’m not sure if this would require a special developers build of
XP, but even if, Microsoft could also sell that as a ‘hardened’ version
just like Sun created hardened Solaris.
Just wanted to point out that code IS documentatoin (code by contract anyone? http://www.artima.com/cppsource/deepspace3.html)
so yes, in this way open source is better (a little promo: ReactOS
0.3.0 RC1 just came out, so try it out if you want an open source
windows :) ).
Also when you are complaining about people adressing you questions
which are not your responsibility: Microsoft is for us a big
opaque thing, it’s not like on the bottom of every page there is a
link: if you want to provide feedback, click here! For example you say
that we should address our complaints regarding the blog software to
the “makers of the software”. But who are they? In every open source
forum / blog software you would have found the link to the author at
the bottom of the page, but not here. IMHO a more suitable response
would be: it’s not my responsability / area of expertise, contact X
(with a mail address or a link to the contact page) for it. Remember,
you are not just yourself, you represent the entire company, like it or
not.
(Just in a sidedone, although I’m sure I’ll start a flame war: if
open source isn’t better, how is it possible that in 4 years we have
built a browser which is more secure, and the IE team still couldn’t
plug all the holes and almost every month they come out with a remote
code execution attack? I know that rewriting software from scratch is
bad, but this is embarrasing)
Regarding IE:
> Can you open your My Computer folder from your favorite non-IE browser?
No, but on the other hand, I don’t see the point of being able to
do this, either. That’s what Windows Explorer is for. (No
matter how much Microsoft marketing wanted us to believe that the
Internet was no different from the local machine 5 years ago, it wasn’t
true then, and it’s even less true now. The local machine can be
trusted much more than the Internet can be.)
(Note that I can do it (or its equivalent, view the root directory)
in Konqueror. It’s just that Konqueror isn’t my *favorite* non-IE
browser.)
> How about an FTP site in icon mode so you can drag/drop files to upload/download?
What’s the point of this? It makes it slightly easier for new
users, or something? If you have a browser, why would you expect
to be able to drag-and-drop to download a file? Wouldn’t users
expect to click a file to download it, just like when you’re browsing
via HTTP? Except, oh, that’s right, marketing says that the
Internet is no different from the local filesystem again.
OTOH, most third-party FTP programs have a drag-and-drop mode (and
it’s possible that some of them will accept drops from Windows Explorer
too, I don’t know). Not sure how many of them are free, though.
And when you’re using a different program for FTP, it’s a little
more obvious that a different action may be required to download a
file, so the interface “cost” of going fully DnD isn’t as high.
(Actually, Konqueror may be able to do this also, but I’ve never
tried it so I don’t know for sure. Certainly the infrastructure
is there; someone would just need to write an FTP kioslave.)
> Or view a PDF file inside the browser window instead of using an external plug-in?
“External plug-in” like the one from Adobe that’s required for IE
too (at least IE6SP1)? No, I can’t view PDFs without that.
But with it, I can view them “inside the browser window”.
(But I doubt that Adobe has a plug-in for Konqueror. However,
KDE does have a PDF viewer (named, appropriately enough, kpdf), and
it’s possible that kpdf can be invoked inside the Konqueror window.
Never tried that either, though, so I don’t know for sure.)
Originally posted by Raymond:
[Or view a PDF file inside the browser window instead of using an external plug-in?]
That reminds me of an interesting thing my PC does…
I have several toolbars set up as a sidebar on the desktop, including a "My Computer" bar which lets me browse my filesystem via drop-down menus. One interesting side-effect of this method is that when I open a PDF from this menu, it opens in IE!
I’m guessing this is because the ability to make toolbars out of folders came with IE4, which was the first version of IE to be integrated into Windows, and that somehow they’re treated as being part of the "IE side" of Explorer, which naturally opens PDFs inline?
… Will this be bugfixed in Vista? ;)
BryanK — Yes, that’s the toolbar. (I was quite gratified when they started making it one of the default toolbars, since I’ve been using this particular feature since Win98.)
I’m running XP Pro SP2, and IE is not my default browser either. In fact, I told Windows never to use it – yeah, I know, like that ever made a difference…
Specifically, my PC is opening PDFs with the Acrobat plugin in an IE window. If I open then via a normal Explorer window, my application preferences are honoured.
Just out of interest: was your "My Computer" toolbar part of the taskbar when you tested, or part of a separate toolbar? If it was part of the taskbar, you might want to give it a go as part of a sidebar and see what happens. You’ll need another (blank or otherwise) toolbar on the same screen edge to make it use the menu function.
Oh, you’re right, it was part of the taskbar. But I put it on the right side of the screen (well, I put the Address toolbar on the right side of the screen, then added My Computer to it), and it didn’t open up IE, just Acrobat. I also tried a file located on a mapped network drive (so it’s from a different zone), and that didn’t seem to make any difference.
What happens if you open the PDF from the Start->Run box? (Are ShellExecute and ShellExecuteEx working, in other words?)
I wish to duplicate this followup in this thread because it follows up to this thread and there’s no way to do newsgroup-style crossposts.
> It so happens that the numerical value -1
> for a window handle is suspiciously close to
> the value of HWND_BROADCAST:
> #define HWND_BROADCAST ((HWND)0xffff)
> It so happens that internally, the window
> manager supports (HWND)-1 as an alternative
> value for HWND_BROADCAST. (I leave you to
> speculate why.)
We can leave it to MSDN to say why.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/dataexchange/dynamicdataexchange/usingdynamicdataexchange.asp
* Usually, the client broadcasts this message
* by calling SendMessage, with –1 as the
* first parameter.
The reason why -1 still can be used as a substute for 0xFFFF is because, in 16-bit Windows, -1 = 0xFFFF because the message value was 16-bit. It no longer equals 0xFFFF because the message value is increased to 32-bit in Win32.
PingBack from http://www.anti-tgtsoft.com/?p=35
PingBack from http://withinwindows.com/?p=29
PingBack from http://blog.malcom.pl/2008/07/30/wygaszanie-ekranu/