Control LCD back light - c++

I'd like to control LCD back light.
First, I use the code as below:
// Turn off monitor
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 2);
// Turn on monitor
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) -1);
// Low power monitor
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 1);
But program will hang on SendMessage()
I found the disscuss topic to solve hanging problem (Use: SendMessageTimeout function)
// Turn on monitor
SendMessageTimeout(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) -1, SMTO_ABORTIFHUNG, 100, NULL);
// Turn off monitor
SendMessageTimeout(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 2, SMTO_ABORTIFHUNG, 100, NULL);
// Low power monitor
SendMessageTimeout(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 1, SMTO_ABORTIFHUNG, 100, NULL);
My problem is the program can not turn on monitor.
My process is: turn off monitor -> wait 10 seconds -> turn on monitor.
Monitor can be turned off, can not turn on monitor again after 10 seconds,
But I can see the monitor is on for a very short time after 10 seconds.
Can anyone tell me what's wrong? Thanks!

I found on Windows 8 platform, Can send a key to system to turn on LCD after turn off LCD via
SendMessageTimeout(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM) 2, SMTO_ABORTIFHUNG, 100, NULL);
I don't know why, but it actually work well...
INPUT in[1];
KEYBDINPUT kb;
kb.wVk = VK_CONTROL;
in[0].type = INPUT_KEYBOARD;
in[0].ki = kb;
SendInput(1, in, sizeof(in));

Related

Setting a child window under Progman window to show video ender desktop icon

I'm trying to make a function similar to the wallpaper engine, by adding a child window to the Progman window. The function did allow me to add the video, however, the window size is fixed, which made me unable to fit the video to the entire desktop.
I tried to change the window size, but neither MoveWindow nor SetWindowPos worked. The Progman's hwnd Rect is just screen size (1920x1080), so it's not a boundary issue. The video window size is 640x480. I'm able to change the location of the window, meaning no permission issue, just can't change the size of it.
Here is the code.
LPCWSTR lpParam = L" videoTest2.mp4 -noborder -fs -loop 0";
STARTUPINFO si{ 0 };
PROCESS_INFORMATION pi{ 0 };
if (CreateProcess(L"ffplay.exe", (LPWSTR)lpParam, 0, 0, 0, 0, 0, 0, &si, &pi)) {
Sleep(200);
HWND hProgram = FindWindow(_T("Progman"), _T("Program Manager"));
HWND hFfplay = FindWindow(L"SDL_app", 0);
SetParent(hFfplay, hProgram);
// MoveWindow(hFfplay, 0, 0, 3840, 1080, true);
SetWindowPos(hFfplay, NULL, 0, 0, 3840, 1080, SWP_NOZORDER);
ShowWindow(hFfplay, SW_MAXIMIZE);
EnumWindows(EnumWindowProc, (LPARAM)SW_HIDE);
Sleep(1000);
EnumWindows(EnumWindowProc, (LPARAM)SW_SHOW);
}
else {
std::cout << GetLastError() << std::endl;
}
EnumWindowProc is just for showing and hiding system background images.

PostMessage / SendMessage without interference from modifier keys

I'm trying to post/send a message to some hwnd without the interference from modifier keys (ctrl, alt, shift).
Basically i want to send F1 message (without ctrl) to hwnd while im pressing ctrl (like Example 2) but with SendMessage\PostMessage.
I tried use SendInput to set up the CTRL key, post the message and set down the CTRL key back, but it fails 50% of time.
Example 1: Code with SendMessageA:
HWND hwnd = FindWindowA(0, "Notepad");
if (GetKeyState(VK_CONTROL) < -1) // if CTRL is pressed
{
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); // up the CTRL key
SendMessageA(hwnd, WM_KEYDOWN, VK_F1, 0); // send F1 keydown
keybd_event(VK_CONTROL, 0, 0, 0); // down the CTRL key
}
else
{
SendMessageA(hwnd, WM_KEYDOWN, VK_F1, 0); // send F1 keydown
}
Theoretically this code would solve the problem, but it sometimes sends the message with the CTRL pressed and sometimes not.
Example 2: Same code with SendInput (but these works fine)
HWND hwnd = FindWindowA(0, "Notepad");
if (GetKeyState(VK_CONTROL) < -1) // if CTRL is pressed
{
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); // up the CTRL key
keybd_event(VK_F1, 0, 0, 0); // send F1 keydown
keybd_event(VK_CONTROL, 0, 0, 0); // down the CTRL key back
}
else
{
keybd_event(VK_F1, 0, 0, 0); // send F1 keydown
}

Send "button pressed" message to UnityWndClass

I have 3D game and i need to press buttons in this game from another application. Spy++ says that window of the game is UnityWndClass. When i pressing buttons in game, window recives only mouse messages like WM_SETCURSOR, WM_LBUTTONDOWN etc, but when i try to send WM_LBUTTONDOWN and WM_LBUTTONUP with coordinates of the button from another window nothing happend. Why? Any ideas how to press buttons?
WM_SETCURSOR is for changing the cursor image of your own window. WM_LBUTTONDOWN and WM_LBUTTONUP are notification messages sent after mouse click. WM_LBUTTONXXX messages are probably not handled by the main Window procedure.
To fake mouse input, you can use mouse_event or SendInput. For example, this moves cursor to x=10 / y=10 and and clicks left mouse.
int x = 10 * 65536 / GetSystemMetrics(SM_CXSCREEN);
int y = 10 * 65536 / GetSystemMetrics(SM_CYSCREEN);
mouse_event(MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE, x, y, 0, 0);
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
Or use SendInput for multiple calls (see comments)
INPUT input[3];
for (int i = 0; i < 3; i++)
{
memset(&input[i], 0, sizeof(INPUT));
input[i].type = INPUT_MOUSE;
}
input[0].mi.dx = x;
input[0].mi.dy = y;
input[0].mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
input[1].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
input[2].mi.dwFlags = MOUSEEVENTF_LEFTUP;
SendInput(3, input, sizeof(INPUT));
Window should be at least visible and preferably be active. You can use SetForegroundWindow. See this example to make sure window is visible and active.
Other alternatives:
Use Spy++ to get information about the button which you want to press.
For example, if this was Windows Calculator, you can spy on calculator's buttons, it shows calculator button 2 has ID set to 0x84. You can send WM_COMMAND with WPARAM set to 0x84 to simulate button press.
HWND hwnd = FindWindow(0, L"Calculator");
if (IsWindow(hwnd))
{
//this should put "234" in to calculator's edit box
SendMessage(hwnd, WM_COMMAND, 0x84, 0);
SendMessage(hwnd, WM_COMMAND, 0x85, 0);
SendMessage(hwnd, WM_COMMAND, 0x86, 0);
}

C++ sends virtual key with WM_KEYDOWN on keybd_event()

I would like my program to send this third party virtual key VK_ALOGIN or 0xf7 with WM_KEYDOWN.
So I try the following:
keybd_event(0xf7, 0, 0, 0);
But the program that receives this keyboard message, it receives only VK_ALOGIN, and not with WM_KEYDOWN. So is it possible that I can send 0xf7 with WM_KEYDOWN?
Please note that VK_ALOGIN is not Microsoft Virtual Key.
Receiver might be looking for keydown, as well as key up. Try sending both.
keybd_event( VK_ALOGIN, 0, 0, 0 );
keybd_event( VK_ALOGIN, 0, KEYEVENTF_KEYUP, 0 );
or
keybd_event( VK_ALOGIN, 0, KEYEVENTF_EXTENDEDKEY, 0 );
keybd_event( VK_ALOGIN, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0 );
Edit: I deleted reference to SendInput because now I think it has nothing to do with the question, and I am not sure if I got SendInput right.

Why Am I getting extra messages when sending keystroke to an application?

I am sending CTRL+A and CTRL+C to an application ( in order to copy the content obviously ).
For this I wrote some C++ code which seems to be ok.
Indeed I see on spy++ that the messages produced and sent to the application by my code are exactly the same ( expect frepeat value ) than the messages received by the application when CTRL+A and CTRL+C are inputed ,manually on the keyboard... except that with my code, the application receive at the end two extra WM_CHAR messages for 'A' and 'B'.
since I do not send these WM_CHAR messages but only WM_KEYDOWN and WM_KEYUP I am slightly puzzled. Incidentally nothing is selected and nothing is copied ( even if selected before )
here is my C++ code:
HWND hTargetWindow=(HWND) 0x280908;
LPARAM lparam1 = 0x00000001 | (LPARAM)(0x1D << 16);
LPARAM lparam2 = 0x00000001 | (LPARAM)(0x1E << 16);
LPARAM lparam3 = 0x00000001 | (LPARAM)(0x2E << 16);
LPARAM lparam1_ = lparam1 | (LPARAM)(0x1 << 31);
LPARAM lparam2_ = lparam2 | (LPARAM)(0x1 << 31);
LPARAM lparam3_ = lparam3 | (LPARAM)(0x1 << 31);
PostMessage(hTargetWindow, WM_KEYDOWN, VK_CONTROL, lparam1);
PostMessage(hTargetWindow, WM_KEYDOWN, VK_A, lparam2);
PostMessage(hTargetWindow, WM_KEYUP, VK_CONTROL, lparam1_);
PostMessage(hTargetWindow, WM_KEYUP, VK_A, lparam2_);
PostMessage(hTargetWindow, WM_KEYDOWN, VK_CONTROL, lparam1);
PostMessage(hTargetWindow, WM_KEYDOWN, VK_C, lparam3);
PostMessage(hTargetWindow, WM_KEYUP, VK_C, lparam3_);
PostMessage(hTargetWindow, WM_KEYUP, VK_CONTROL, lparam1_);
and here respectively
a) the messages received when CTRL+A CTRL+C are inputed manually
b) here the messages received when when CTRL+A CTRL+C are sent by my C+ code
I will put frepeat to 1 for KEYUP events but I doubt this will change anything so I post the question anyway.
so why are these two extra messages sent by my code ?
thanks in advance for any hint.
added 7:09:05 p.m.(GMT + 2:00):
the KEYUP and KEYDOWN for CTRL+A are reversed ( CTRL+C sequence is the same ) but this is because I have also tried this to solve the problem. I have also tried many times the right combination.
this is spy++ when the keydown and keyup dequence is exactly the same , that does not change anything:
You're doing things in the wrong order, doing the WM_KEYUP on VK_A before you do the WM_KEYUP on VK_CONTROL. Same for the C. Reverse those and it should be fine.
// Send [CTRL-A] to select the entire text in a Notepad window, even if Notepad is out of focus,
// without bringing the Notepad window into focus.
// Works with Notepad, but not with Command Prompt window.
BYTE gucKeybStateCur [256] = {'\0'};
// hwN = Find Notepad HWND
AttachThreadInput (GetWindowThreadProcessId (hwN, NULL), GetCurrentThreadId (), TRUE);
GetKeyboardState ((PBYTE) &gucKeybStateCur);
gucKeybStateCur [VK_CONTROL] |= 0x80;
SetKeyboardState ((LPBYTE) &gucKeybStateCur);
PostMessage (hwN, WM_KEYDOWN, (WPARAM) 0x00000041, (LPARAM) 0x001E0001);
PostMessage (hwN, WM_KEYUP, (WPARAM) 0x00000041, (LPARAM) 0xC01E0001);
GetKeyboardState ((PBYTE) &gucKeybStateCur);
gucKeybStateCur [VK_CONTROL] &= 0x0F;
SetKeyboardState ((LPBYTE) &gucKeybStateCur);
AttachThreadInput (GetWindowThreadProcessId (hwN, NULL), GetCurrentThreadId (), FALSE);
// Send [CTRL-C] to interrupt a batch file running in a Command Prompt window, even if the Command Prompt window is not visible,
// without bringing the Command Prompt window into focus.
// [CTRL-C] will have an effect on the batch file, but not on the Command Prompt window itself -- in other words,
// [CTRL-C] will not have the same visible effect on a Command Prompt window that isn't running a batch file at the moment
// as bringing a Command Prompt window that isn't running a batch file into focus and pressing [CTRL-C] on the keyboard.
ulong ulProcessId = 0UL;
// hwC = Find Command Prompt window HWND
GetWindowThreadProcessId (hwC, (LPDWORD) &ulProcessId);
AttachConsole ((DWORD) ulProcessId);
SetConsoleCtrlHandler (NULL, TRUE);
GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0UL);
SetConsoleCtrlHandler (NULL, FALSE);
FreeConsole ();