How to show WIndows Start Menu - winapi

I need to activate Windows start menu on mouse location.
I know I can send CTRL + ESC or Win keys to the specific window, and move the window afterwards, but it still shows menu on original location for a short period of time (unless I install hook, and that is overkill for the task).
I recall there is some way to do this, using some dll call or sending some message to the shell or something.
Ty

Do you get the same behaviour if you "press" the button more programmatically?
// Find the Start button
HANDLE hScreenDC = GetDC(0);
DWORD height = GetDeviceCaps(hScreenDC, VERTRES);
ReleaseDC(0, hScreenDC);
hTaskBarWnd = FindWindow("Shell_TrayWnd", 0);
hStartButtonWnd = GetWindow(hTaskBarWnd, GW_CHILD);
// Now simulate a press on the Start button
SendMessage(hButtonWnd, WM_LBUTTONDOWN,
MK_LBUTTON, LOWORD(5) + HIWORD(height - 20));
Otherwise you might explore the "Shell_TrayWnd" window using WinSpy++ or by using a similar utility, perhaps the Start menu is a child window of the tray window.

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow (string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool ShowWindow (IntPtr hWnd, ShowWindowCommand nCmdShow);
int ShowCmd = 5;
int HideCmd = 0;
ShowWindow(FindWindow("DV2ControlHost", "Start menu"), ShowCmd);
Should do the trick in windows 7 at least. Use "HideCmd" instead of "ShowCmd" to hide again.

Related

Minimize all open windows?

I need to perform the same task as WindowsKey + M through code, ie. minimize all open windows. This must be done through the Win32 API, not .Net.
I tried the following in FreeBasic, but nothing happens:
Dim hWndConsole As HWND
'Shell_TrayWnd = class name of taskbar
Dim WindowName as String = "Shell_TrayWnd"
hWndConsole = FindWindow(0, strptr(WindowName))
ShowWindow(hWndConsole, SW_MINIMIZE) 'outta my sight
Does someone know how to do this?
Thank you.
Edit: Here's the working solution:
#include "Windows.bi"
Dim hWndConsole As HWND
'Shell_TrayWnd = class name of taskbar
Dim WindowName as String = "Shell_TrayWnd"
Dim res as LRESULT
CONST minall = 419
hWndConsole = FindWindow( "Shell_TrayWnd",null)
res = postMessage(hWndConsole, WM_COMMAND, minall, null )
This seems like a bit of a hack to me, but the following does seem to accomplish what you are looking for (in C):
HANDLE hwnd = FindWindow( "Shell_TrayWnd", NULL );
LRESULT res = SendMessage( hwnd, WM_COMMAND, (WPARAM)419, 0 );
When you have the handle of a window, you can make it minimize with the WM_SYSCOMMAND message. E.g.:
SendMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
So all you would need to do is enumerate the top-level windows (with the EnumWindows command) and send that command to the windows you want to minimize (which wouldn't be all top-level windows - probably only visible, overlapped windows without the WS_EX_TOOLWINDOW extended style should be minimized like this).
Putting this out as an option, not a recommendation - simulating the keyboard events for Win-M:
keybd_event(VK_LWIN, 0, 0, 0);
keybd_event('M', 0, 0, 0);
keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0);

SendMessage WM_LBUTTONDOWN/UP works on buttons but not window

I am trying to send some simple mouse down/up messages to Windows Calculator using SendMessage. I have been able to press the buttons by sending the messages to the buttons directly. However, I have not been able to successfully send the same messages to the main calculator window handle. Given that hWnd is the window handle to calculator, this is my code.
IntPtr fiveKey = FindWindowEx(hWnd, IntPtr.Zero, "Button", "5");
int x = 5; // X coordinate of the click
int y = 5; // Y coordinate of the click
IntPtr lParam = (IntPtr)((y << 16) | x); // The coordinates
IntPtr wParam = IntPtr.Zero; // Additional parameters for the click (e.g. Ctrl)
const uint downCode = 0x201; // Left click down code
const uint upCode = 0x202; // Left click up code
SendMessage(fiveKey, downCode, wParam, lParam); // Mouse button down
SendMessage(fiveKey, upCode, wParam, lParam); // Mouse button up
Can anyone explain to me why sending the messages to hWnd instead of fiveKey with the x/y offsets changed to the position of the "5" key does not work? I would like to eventually use this code to simulate mouse clicks on a different application that doesn't have buttons like calculator.
I'm not sure I follow you. Are you trying to send WM_LBUTTONDOWN to the main window with the coordinates of where the 5 button is, with the hopes that the 5 button will get "clicked"? If so, that's just not going to work. WM_LBUTTONDOWN is only ever sent to the window under the mouse cursor. In theory the main window could handle WM_LBUTTONDOWN and see if any of its child windows are at that location, but nobody does that because that's not how WM_LBUTTONDOWN is designed to work.

Win32: full-screen and hiding taskbar

I have a window, which I SetWindowPos(window, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);
It covers the whole screen, ok, but it takes a while (0.5 sec) to cover the taskbar as well.
Is there a way to come over the taskbar immediately? I found that setting HWND_TOPMOST does it immediately, but it stays above all the other windows, even if I switch the app - this is something I don't want. Also, if I first hide the window and then show it, it somehow forces the window to redraw and covers the taskbar immediately, but it flickers (because of the hiding). Is there another way?
Edit 2. There is even a better way for doing fullscreen, the chromium way, source taken from here:
http://src.chromium.org/viewvc/chrome/trunk/src/ui/views/win/fullscreen_handler.cc?revision=HEAD&view=markup
void FullscreenHandler::SetFullscreenImpl(bool fullscreen, bool for_metro) {
ScopedFullscreenVisibility visibility(hwnd_);
// Save current window state if not already fullscreen.
if (!fullscreen_) {
// Save current window information. We force the window into restored mode
// before going fullscreen because Windows doesn't seem to hide the
// taskbar if the window is in the maximized state.
saved_window_info_.maximized = !!::IsZoomed(hwnd_);
if (saved_window_info_.maximized)
::SendMessage(hwnd_, WM_SYSCOMMAND, SC_RESTORE, 0);
saved_window_info_.style = GetWindowLong(hwnd_, GWL_STYLE);
saved_window_info_.ex_style = GetWindowLong(hwnd_, GWL_EXSTYLE);
GetWindowRect(hwnd_, &saved_window_info_.window_rect);
}
fullscreen_ = fullscreen;
if (fullscreen_) {
// Set new window style and size.
SetWindowLong(hwnd_, GWL_STYLE,
saved_window_info_.style & ~(WS_CAPTION | WS_THICKFRAME));
SetWindowLong(hwnd_, GWL_EXSTYLE,
saved_window_info_.ex_style & ~(WS_EX_DLGMODALFRAME |
WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
// On expand, if we're given a window_rect, grow to it, otherwise do
// not resize.
if (!for_metro) {
MONITORINFO monitor_info;
monitor_info.cbSize = sizeof(monitor_info);
GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST),
&monitor_info);
gfx::Rect window_rect(monitor_info.rcMonitor);
SetWindowPos(hwnd_, NULL, window_rect.x(), window_rect.y(),
window_rect.width(), window_rect.height(),
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
} else {
// Reset original window style and size. The multiple window size/moves
// here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be
// repainted. Better-looking methods welcome.
SetWindowLong(hwnd_, GWL_STYLE, saved_window_info_.style);
SetWindowLong(hwnd_, GWL_EXSTYLE, saved_window_info_.ex_style);
if (!for_metro) {
// On restore, resize to the previous saved rect size.
gfx::Rect new_rect(saved_window_info_.window_rect);
SetWindowPos(hwnd_, NULL, new_rect.x(), new_rect.y(),
new_rect.width(), new_rect.height(),
SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
if (saved_window_info_.maximized)
::SendMessage(hwnd_, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
}
}
Edit.
It is probably better to create a fullscreen window as BrendanMcK pointed it out in a comment to this answer, see this link: http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx ("How do I cover the taskbar with a fullscreen window?")
The new code using the link above would be:
HWND CreateFullscreenWindow(HWND hwnd)
{
HMONITOR hmon = MonitorFromWindow(hwnd,
MONITOR_DEFAULTTONEAREST);
MONITORINFO mi = { sizeof(mi) };
if (!GetMonitorInfo(hmon, &mi)) return NULL;
return CreateWindow(TEXT("static"),
TEXT("something interesting might go here"),
WS_POPUP | WS_VISIBLE,
mi.rcMonitor.left,
mi.rcMonitor.top,
mi.rcMonitor.right - mi.rcMonitor.left,
mi.rcMonitor.bottom - mi.rcMonitor.top,
hwnd, NULL, g_hinst, 0);
}
Old answer below - do not use it, stays only for the record on how NOT to do this.
You have to hide taskbar and menubar to see fullscreen immediately.
Here is the code (uses WTL), call SetFullScreen(true) to go into full screen mode:
template <class T, bool t_bHasSip = true>
class CFullScreenFrame
{
public:
bool m_fullscreen;
LONG m_windowstyles;
WINDOWPLACEMENT m_windowplacement;
CFullScreenFrame()
:
m_fullscreen(false),
m_windowstyles(0)
{ }
void SetFullScreen(bool fullscreen)
{
ShowTaskBar(!fullscreen);
T* pT = static_cast<T*>(this);
if (fullscreen) {
if (!m_fullscreen) {
m_windowstyles = pT->GetWindowLongW(GWL_STYLE);
pT->GetWindowPlacement(&m_windowplacement);
}
}
// SM_CXSCREEN gives primary monitor, for multiple monitors use SM_CXVIRTUALSCREEN.
RECT fullrect = { 0 };
SetRect(&fullrect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
WINDOWPLACEMENT newplacement = m_windowplacement;
newplacement.showCmd = SW_SHOWNORMAL;
newplacement.rcNormalPosition = fullrect;
if (fullscreen) {
pT->SetWindowPlacement(&newplacement);
pT->SetWindowLongW(GWL_STYLE, WS_VISIBLE);
pT->UpdateWindow();
} else {
if (m_fullscreen) {
pT->SetWindowPlacement(&m_windowplacement);
pT->SetWindowLongW(GWL_STYLE, m_windowstyles);
pT->UpdateWindow();
}
}
m_fullscreen = fullscreen;
}
void ShowTaskBar(bool show)
{
HWND taskbar = FindWindow(_T("Shell_TrayWnd"), NULL);
HWND start = FindWindow(_T("Button"), NULL);
if (taskbar != NULL) {
ShowWindow(taskbar, show ? SW_SHOW : SW_HIDE);
UpdateWindow(taskbar);
}
if (start != NULL) {
// Vista
ShowWindow(start, show ? SW_SHOW : SW_HIDE);
UpdateWindow(start);
}
}
};
You also have to add some code to WM_CLOSE message:
case WM_CLOSE:
ShowTaskBar(true);
There is one caveat with this solution, if your application crashes or is killed through task manager, then user losses taskbar on his system permanently! (unless he runs your application again, goes into fullscreen and exits, then he will see the taskbar again).
Earlier in my answer I pointed to "atlwince.h" but that function worked only on Windows CE, the one I pasted above works fine with XP, Vista and 7.
Yup, HWND_TOPMOST does it for me.
Here is a section of code that makes full-screen work well (and quick) for me:
bool enterFullscreen(HWND hwnd, int fullscreenWidth, int fullscreenHeight, int colourBits, int refreshRate) {
DEVMODE fullscreenSettings;
bool isChangeSuccessful;
RECT windowBoundary;
EnumDisplaySettings(NULL, 0, &fullscreenSettings);
fullscreenSettings.dmPelsWidth = fullscreenWidth;
fullscreenSettings.dmPelsHeight = fullscreenHeight;
fullscreenSettings.dmBitsPerPel = colourBits;
fullscreenSettings.dmDisplayFrequency = refreshRate;
fullscreenSettings.dmFields = DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_BITSPERPEL |
DM_DISPLAYFREQUENCY;
SetWindowLongPtr(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_TOPMOST);
SetWindowLongPtr(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fullscreenWidth, fullscreenHeight, SWP_SHOWWINDOW);
isChangeSuccessful = ChangeDisplaySettings(&fullscreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL;
ShowWindow(hwnd, SW_MAXIMIZE);
return isChangeSuccessful;
}
Note that this will change the resolution if you tell it the wrong settings. This is what I usually want, but if you don't like that, you can find out your resolution by using (where mainWindow is returned from something like CreateWindow() or CreateWindowEx()):
windowHDC = GetDC(mainWindow);
fullscreenWidth = GetDeviceCaps(windowHDC, DESKTOPHORZRES);
fullscreenHeight = GetDeviceCaps(windowHDC, DESKTOPVERTRES);
colourBits = GetDeviceCaps(windowHDC, BITSPIXEL);
refreshRate = GetDeviceCaps(windowHDC, VREFRESH);
When you want to get out of full-screen you do something like this:
bool exitFullscreen(HWND hwnd, int windowX, int windowY, int windowedWidth, int windowedHeight, int windowedPaddingX, int windowedPaddingY) {
bool isChangeSuccessful;
SetWindowLongPtr(hwnd, GWL_EXSTYLE, WS_EX_LEFT);
SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
isChangeSuccessful = ChangeDisplaySettings(NULL, CDS_RESET) == DISP_CHANGE_SUCCESSFUL;
SetWindowPos(hwnd, HWND_NOTOPMOST, windowX, windowY, windowedWidth + windowedPaddingX, windowedHeight + windowedPaddingY, SWP_SHOWWINDOW);
ShowWindow(hwnd, SW_RESTORE);
return isChangeSuccessful;
}
I set my code to change between full-screen and windowed mode using a hotkey, and I keep the windowed mode variables as global, so that when changing to windowed mode, it stays put.
This code also has the advantage of running in the equivalent of "exclusive mode" (I'm using XP, and haven't tried it on the newer versions of windows), which means it'll be much, much faster. Let me know if I've made any mistakes from condensing the code (from my much bigger code).
Raymond Chen describes the "correct" way to do this at his blog:
https://devblogs.microsoft.com/oldnewthing/20100412-00/?p=14353
Fiddling with the task bar window explicitly is not recommended behaviour.
Here's the latest unbroken link to Raymond Chen answer.
Since MSDN/Microsoft keeps breaking links I'll paste below for posterity:
For some reason, people think too hard. If you want to create a fullscreen window that covers the taskbar, just create a fullscreen window and the taskbar will automatically get out of the way. Don't go around hunting for the taskbar and poking it; let it do its thing.
As always, start with the scratch program and add the following:
HWND CreateFullscreenWindow(HWND hwnd)
{
HMONITOR hmon = MonitorFromWindow(hwnd,
MONITOR_DEFAULTTONEAREST);
MONITORINFO mi = { sizeof(mi) };
if (!GetMonitorInfo(hmon, &mi)) return NULL;
return CreateWindow(TEXT("static"),
TEXT("something interesting might go here"),
WS_POPUP | WS_VISIBLE,
mi.rcMonitor.left,
mi.rcMonitor.top,
mi.rcMonitor.right - mi.rcMonitor.left,
mi.rcMonitor.bottom - mi.rcMonitor.top,
hwnd, NULL, g_hinst, 0);
}
void OnChar(HWND hwnd, TCHAR ch, int cRepeat)
{
if (ch == TEXT(' ')) {
CreateFullscreenWindow(hwnd);
}
}
HANDLE_MSG(hwnd, WM_CHAR, OnChar);
Note that this sample program doesn't worry about destroying that fullscreen window or preventing the user from creating more than one. It's just a sample. The point is seeing how the CreateFullScreenWindow function is written.
We use the MonitorFromWindow function to figure out which monitor we should go fullscreen to. Note that in a multiple monitor system, this might not be the same monitor that the taskbar is on. Fortunately, we don't have to worry about that; the taskbar figures it out.
I've seen people hunt for the taskbar window and then do a ShowWindow(hwndTaskbar, SW_HIDE) on it. This is nuts for many reasons.
First is a mental exercise you should always use when evaluating tricks like this: "What if two programs tried this trick?" Now you have two programs both of which think they are in charge of hiding and showing the taskbar, neither of which is coordinating with the other. The result is a mess. One program hides the taskbar, then the other does, then the first decides it's finished so it unhides the taskbar, but the second program wasn't finished yet and gets a visible taskbar when it thought it should be hidden. Things only go downhill from there.
Second, what if your program crashes before it gets a chance to unhide the taskbar? The taskbar is now permanently hidden and the user has to log off and back on to get their taskbar back. That's not very nice.
Third, what if there is no taskbar at all? It is common in Terminal Server scenarios to run programs by themselves without Explorer (archived). In this configuration, there is no Explorer, no taskbar. Or maybe you're running on a future version of Windows that doesn't have a taskbar, it having been replaced by some other mechanism. What will your program do now?
Don't do any of this messing with the taskbar. Just create your fullscreen window and let the taskbar do its thing automatically.
I believe the taskbar will get out of the way when its shell hook tells it about a "rude app", this might take a little while.
What if you start out with the window HWND_TOPMOST and make it not top most after 1 second?
Right click on the taskbar
choose Properties
uncheck the checkbox that says "Keep the taskbar on top of other windows".
The taskbar belongs to the user, It's up to them to care about having it take 1/2 second to auto-hide when you app goes full screen. If they want to change that behavior then they can change it.
If you are working in an embedded system, then you may have a legitimate reason to hide the taskbar. But in that case, there's no reason not to simply configure the taskbar to not always be on top. You could also have a look at SystemParametersInfo if you want to change some of these settings in your code.

Programmatically prevent Windows screensaver from starting

Is there a recommended way to prevent the Windows screensaver from starting? The closest thing I've found is this article, but what I would really like to do is just tell Windows that the computer isn't idle rather than fooling with the currently set screensaver values.
For testing, I set the screensaver to 1 minute and required a password.
I tried capturing SC_SCREENSAVE and returning -1 in VB .Net. As commented, it works when there is no screensaver password but fails if the screensaver password is active. (I tried it in Windows XP). I also put this into a Timer's tick event, every 1000 milliseconds:
Static dir As Integer = 4
Cursor.Position = Cursor.Position + New Size(dir, dir)
dir = -dir
It doesn't work. The cursor jiggles back and forth and after 1 minute the screensaver flashes on for a short instance and then turns off. The screensaver turns on for only a moment, not long enough to require a password. But still, the flash is ugly.
Then I tried using user32.dll's SetCursorPos and GetCursorPos. You can look them up at pinvoke. Same result as above.
Then I peeked at the code of "JiggleMouse" mentioned elsewhere in this question. JiggleMouse uses SendInput. SendInput works! No flash of the screensaver. I put a call to SendInput inside of a Timer that triggers every 50 seconds (just less than the minimum screensaver timeout of 60 seconds). It's sufficient to move the mouse by a delta of 0,0, no real movement. That does work. The code to put in the Tick event:
Dim i(0) As INPUT
i(0).dwType = INPUT.InputType.INPUT_MOUSE
i(0).mkhi = New MOUSEKEYBDHARDWAREINPUT
i(0).mkhi.mi = New MOUSEINPUT
i(0).mkhi.mi.dx = 0
i(0).mkhi.mi.dy = 0
i(0).mkhi.mi.mouseData = 0
i(0).mkhi.mi.dwFlags = MOUSEINPUT.MouseEventFlags.MOUSEEVENTF_MOVE
i(0).mkhi.mi.time = 0
i(0).mkhi.mi.dwExtraInfo = IntPtr.Zero
SendInput(1, i(0), Marshal.SizeOf(i(0)))
This comes from pinvoke.com:
Public Declare Function SendInput Lib "user32" (ByVal nInputs As Integer, ByRef pInputs As INPUT, ByVal cbSize As Integer) As Integer
Public Structure INPUT
Enum InputType As Integer
INPUT_MOUSE = 0
INPUT_KEYBOARD = 1
INPUT_HARDWARE = 2
End Enum
Dim dwType As InputType
Dim mkhi As MOUSEKEYBDHARDWAREINPUT
End Structure
Public Structure MOUSEINPUT
Enum MouseEventFlags As Integer
MOUSEEVENTF_MOVE = &H1
MOUSEEVENTF_LEFTDOWN = &H2
MOUSEEVENTF_LEFTUP = &H4
MOUSEEVENTF_RIGHTDOWN = &H8
MOUSEEVENTF_RIGHTUP = &H10
MOUSEEVENTF_MIDDLEDOWN = &H20
MOUSEEVENTF_MIDDLEUP = &H40
MOUSEEVENTF_XDOWN = &H80
MOUSEEVENTF_XUP = &H100
MOUSEEVENTF_WHEEL = &H800
MOUSEEVENTF_VIRTUALDESK = &H4000
MOUSEEVENTF_ABSOLUTE = &H8000
End Enum
Dim dx As Integer
Dim dy As Integer
Dim mouseData As Integer
Dim dwFlags As MouseEventFlags
Dim time As Integer
Dim dwExtraInfo As IntPtr
End Structure
Public Structure KEYBDINPUT
Public wVk As Short
Public wScan As Short
Public dwFlags As Integer
Public time As Integer
Public dwExtraInfo As IntPtr
End Structure
Public Structure HARDWAREINPUT
Public uMsg As Integer
Public wParamL As Short
Public wParamH As Short
End Structure
Const KEYEVENTF_EXTENDEDKEY As UInt32 = &H1
Const KEYEVENTF_KEYUP As UInt32 = &H2
Const KEYEVENTF_UNICODE As UInt32 = &H4
Const KEYEVENTF_SCANCODE As UInt32 = &H8
Const XBUTTON1 As UInt32 = &H1
Const XBUTTON2 As UInt32 = &H2
<StructLayout(LayoutKind.Explicit)> Public Structure MOUSEKEYBDHARDWAREINPUT
<FieldOffset(0)> Public mi As MOUSEINPUT
<FieldOffset(0)> Public ki As KEYBDINPUT
<FieldOffset(0)> Public hi As HARDWAREINPUT
End Structure
Subtle. The official way to tell Windows that the system is not idle is SetThreadExecutionState. This resets the idle timer, (or turns it off, if you pass ES_CONTINUOUS ). However, even though SetThreadExecutionState resets the idle timer, it does not stop the screensaver!
SystemParametersInfo
Specifically, the SPI_SETSCREENSAVEACTIVE parameter.
Does this not work? I was surprised that I did not see it here. Note that SetThreadExecutionState will not affect the screen saver at all, just the sleeping of the display.
I use Mouse Jiggler to reset the idle state. This gets around a Group Policy that tends to start my screensaver (and lock the machine) at inopportune times: when I'm reading a long document, studying a complex chunk of code, or talking/listening/not-constantly-typing during a meeting.
As it can be slightly annoying to have the mouse jump 1px diagonally every second, I intend to use AutoHotKey to write a script that does basically the same thing, but only after a configured keyboard/mouse idle timeout, and maybe use the Shift key (or Scroll Lock) instead of a mouse move.
From MSDN:
Windows does not start the screen saver if any of the following conditions exist:
The active application is not a Windows-based application.
A CBT window is present.
The active application receives the WM_SYSCOMMAND message with the wParam parameter set to the SC_SCREENSAVE value, but it does not pass the message to the DefWindowProc function.
There's a caveat though:
Windows Vista and later: If password protection is enabled by policy, the screen saver is started regardless of what an application does with the SC_SCREENSAVE notification.
That seems to apply even if you use the SetThreadExecutionState with ES_CONTINUOUS.
So, if it weren't for the caveat, your choices would be:
SetThreadExecutionState with ES_CONTINUOUS (as described in other answers).
Put up a computer-based training window (which requires hooks).
Don't let the WM_SYSCOMMAND with SC_SCREENSAVE be passed onto DefWindowProc. (Assuming you care only when your application is the active application.)
Install a dongle that simulates mouse jiggle.
The last option is nice in that it works even with the password protection policy.
In Windows 7+, use the Power Management API's PowerSetRequest() with PowerRequestDisplayRequired
https://msdn.microsoft.com/en-us/library/windows/desktop/dd405534(v=vs.85).aspx
In previous versions of windows, intercept the WM_SYSCOMMAND - SC_SCREENSAVE message as detailed in Eddie Parker's answer.
This blog post details what you need to do in C++.
The actual code snippet from the website:
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SYSCOMMAND:
{
switch (wParam)
{
case SC_SCREENSAVE:
return 0;
case SC_MONITORPOWER:
return 0;
}
break;
}
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
Can't believe no one has pointed out the easy and obvious solution:
#include <windows.h>
void main()
{
while(1){
INPUT input;
input.type = INPUT_MOUSE;
input.mi.dx = 1;
input.mi.dy = 1;
input.mi.mouseData = 0;
input.mi.dwFlags = MOUSEEVENTF_MOVE;
input.mi.time = 0;
input.mi.dwExtraInfo = 0;
SendInput( 1, &input, sizeof(input) );
sleep(60000);
}
}
As Adrian McCarthy mentioned from MSDN that :
If password protection is enabled by policy, the screen saver is started regardless of what an application does with the SC_SCREENSAVE notification.
So catch the event from WM_SYSCOMMAND using UINT SC_SCREENSAVE and discarded it by returning 0 or by creating a fake mouse move ("mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, 0)") will not work properly if the user enabled password-protected screen saver option.
Use SetThreadExecutionState winAPI to tell the operating system that the thread is in use, even if the user is not interacting with the computer. These will prevent to appear screen saver and stop the machine from being suspended automatically.
There are series of flags to specify a new state for the current thread:
ES_AWAYMODE_REQUIRED (0x00000040) : Enables away mode.
ES_DISPLAY_REQUIRED (0x00000002) : Forces the display to be on by
resetting the display idle timer.
ES_SYSTEM_REQUIRED (0x00000001) : Forces the system to be in the
working state by resetting the system idle timer.
ES_CONTINUOUS (0x80000000) : Informs the system that the state being
set should remain in effect until the next call that uses
ES_CONTINUOUS and one of the other state flags are cleared.
As it's a winAPI, you can call this directly in win32 or mfc application
//To stop/start screen saver and monitor power off event
void SetKeepScreenOn(BOOL isKeepScreenOn)
{
if (isKeepScreenOn == TRUE)
{
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED /*| ES_AWAYMODE_REQUIRED*/);
}
else
{
SetThreadExecutionState(ES_CONTINUOUS);
}
}
If someone wants to use this in C#, must have to PInvoke this :
[DllImport("kernel32.dll", CharSet = CharSet.Auto,SetLastError = true)]
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
User-Defined Types:
[FlagsAttribute]
public enum EXECUTION_STATE :uint
{
ES_AWAYMODE_REQUIRED = 0x00000040,
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
}
Here below is the calling procedure:
void SetKeepScreenOn(bool isKeepScreenOn)
{
if (isKeepScreenOn == true)
{
//You can combine several flags and specify multiple behaviors with a single call
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED /*| EXECUTION_STATE.ES_AWAYMODE_REQUIRED*/);
}
else
{
//To reset or allow those event again you have to call this API with only ES_CONTINUOUS
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
}
}
According to MSDN this API is safe also to use.
The system maintains a count of applications that have called SetThreadExecutionState. The system tracks each thread that calls SetThreadExecutionState and adjusts the counter accordingly. If this counter reaches zero and there has not been any user input, the system enters sleep.
If the Application crashed before resetting flag, the System will adjust and will reset automatically.
You can use SystemParametersInfo
to get the SCREENSAVETIMEOUT and then immediately set the timeout back to the same value. Do this periodically on a timer for as long as you want to prevent the screensaver from going on.
This has the effect of resetting the current countdown timer without actually changing the system setting.
You probably also want to call SetThreadExecutionState to affect the power as other answers mention.
Just reset the timeout counter with
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, 1, nil, SPIF_SENDWININICHANGE);
From JD Design Freeware - Flipss.exe (download 12kb) is a command line utility that will set SPI_SETSCREENSAVEACTIVE for you.
"FlipSS.exe -h" to see the current state.
"FlipSS.exe /on" to set the screensaver on.
"FlipSS.exe /off" to set the screensaver off.
AutoHotkey can set SystemParametersInfo(SPI_SETSCREENSAVEACTIVE) with a 1-liner DllCall in script to easily accomplish this with a .ahk script.
AutoHotkey code to disable Screensaver:
DllCall("SystemParametersInfo", Int, 17, Int, 0, UInt, NULL, Int, 2)
AutoHotkey code to enable screensaver:
DllCall("SystemParametersInfo", Int, 17, Int, 1, UInt, NULL, Int, 2)
Reference Forum Threads:
F13Key - Toggling Screen Saver with SystemParametersInfo
SKAN - How to Disable Screen Saver Temporarily
I realize this is an old thread, but I'm faced with this issue for the first time (work machine is totally locked down, as far as changing super short sleep time, screensaver, etc. - I can't even change my desktop background). I've looked around at solutions, some seemingly way overcomplicated and some...not so much.
Some of my colleagues are using Caffeine. But that is surely some kind of spyware, etc., as it refuses to run if there is not an open internet connection.
So I found this (and modified it slightly), which is exactly what Caffeine does (except Caffeine does it every 59 seconds), without all the...at best, bloatware.
In PowerShell, execute the following 2 command lines:
$WShell = New-Object -Com "Wscript.Shell"
while(1) {$WShell.SendKeys("{F15}"); sleep 200}
Or you can make it a one-liner if you like:
while(1) {(New-Object -Com "Wscript.Shell").SendKeys("{F15}"); sleep 200}
(the latter of which seems like it would leak memory, but it does not seem to at all)
Once you run either of those, your screen will NOT lock, until you do ctrl-c, or close the Powershell window (in the latter version only, it seems, the ctrl-c may not happen until the sleep interval elapses).
Note that there is no F15 key, at least on any keyboard I've ever seen (but it's a legit windows keystroke), so there are no side effects. Now, if you your IT dept. is exceptionally paranoid, they may flag an F15 keystroke (mine is super paranoid, but they haven't noticed anything for months). If so, use something like scroll-lock instead.
Both of these 100% work on my win10 machine. Simple is good!

How to make the taskbar blink my application like Messenger does when a new message arrive?

Is there an API call in .NET or a native DLL that I can use to create similar behaviour as Windows Live Messenger when a response comes from someone I chat with?
FlashWindowEx is the way to go. See here for MSDN documentation
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
[StructLayout(LayoutKind.Sequential)]
public struct FLASHWINFO
{
public UInt32 cbSize;
public IntPtr hwnd;
public UInt32 dwFlags;
public UInt32 uCount;
public UInt32 dwTimeout;
}
public const UInt32 FLASHW_ALL = 3;
Calling the Function:
FLASHWINFO fInfo = new FLASHWINFO();
fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
fInfo.hwnd = hWnd;
fInfo.dwFlags = FLASHW_ALL;
fInfo.uCount = UInt32.MaxValue;
fInfo.dwTimeout = 0;
FlashWindowEx(ref fInfo);
This was shamelessly plugged from Pinvoke.net
HWND hHandle = FindWindow(NULL,"YourApplicationName");
FLASHWINFO pf;
pf.cbSize = sizeof(FLASHWINFO);
pf.hwnd = hHandle;
pf.dwFlags = FLASHW_TIMER|FLASHW_TRAY; // (or FLASHW_ALL to flash and if it is not minimized)
pf.uCount = 8;
pf.dwTimeout = 75;
FlashWindowEx(&pf);
Stolen from experts-exchange member gtokas.
FlashWindowEx.
From a Raymond Chen blog entry:
How do I flash my window caption and taskbar button manually?
How do I flash my window caption and
taskbar button manually? Commenter
Jonathan Scheepers wonders about those
programs that flash their taskbar
button indefinitely, overriding the
default flash count set by
SysteParametersInfo(SPI_SETFOREGROUNDFLASHCOUNT).
The FlashWindowEx function and its
simpler precursor FlashWindow let a
program flash its window caption and
taskbar button manually. The window
manager flashes the caption
automatically (and Explorer follows
the caption by flashing the taskbar
button) if a program calls
SetForegroundWindow when it doesn't
have permission to take foreground,
and it is that automatic flashing that
the SPI_SETFOREGROUNDFLASHCOUNT
setting controls.
For illustration purposes, I'll
demonstrate flashing the caption
manually. This is generally speaking
not recommended, but since you asked,
I'll show you how. And then promise
you won't do it.
Start with the scratch program and
make this simple change:
void
OnSize(HWND hwnd, UINT state, int cx, int cy)
{
if (state == SIZE_MINIMIZED) {
FLASHWINFO fwi = { sizeof(fwi), hwnd,
FLASHW_TIMERNOFG | FLASHW_ALL };
FlashWindowEx(&fwi);
}
}
Compile and run this program, then
minimize it. When you do, its taskbar
button flashes indefinitely until you
click on it. The program responds to
being minimzed by calling the
FlashWindowEx function asking for
everything possible (currently the
caption and taskbar button) to be
flashed until the window comes to the
foreground.
Other members of the FLASHWINFO
structure let you customize the
flashing behavior further, such as
controlling the flash frequency and
the number of flashes. and if you
really want to take control, you can
use FLASHW_ALL and FLASHW_STOP to turn
your caption and taskbar button on and
off exactly the way you want it. (Who
knows, maybe you want to send a
message in Morse code.)
Published Monday, May 12, 2008 7:00 AM
by oldnewthing Filed under: Code
The FlashWindowEx Win32 API is the call used to do this. The documentation for it is at:
http://msdn.microsoft.com/en-us/library/ms679347(VS.85).aspx
I believe you're looking for SetForegroundWindow.

Resources