Replace Sleep until Window on desktop opened - c++

When, I open some of the software applications I have to wait 2-3 seconds until window will show on desktop. I have to use Sleep(2000); and then call method set always on top. I'm trying to replace Sleep in my code. I would like to get signal from opened window and after this, call a method, which allows opened window be always on top.
Here's my code:
BOOL CALLBACK EnumWindowsProc(HWND windowHandle, LPARAM lParam)
{
DWORD searchedProcessId = (DWORD)lParam;
DWORD windowProcessId = 0;
GetWindowThreadProcessId(windowHandle, &windowProcessId);
cout << "Process id: " << windowProcessId << endl;
if(searchedProcessId == windowProcessId) {
HWND hwnd = windowHandle;
Sleep(2000);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
cout << "Process ID found!" << endl;
return TRUE;
}
return TRUE;
}
void AlwaysOnTop(int processId)
{
EnumWindows(&EnumWindowsProc, (LPARAM)processId);
}
void AlwaysOnTop(char *name)
{
cout << "String: " << name << endl;
Sleep(2000);
HWND h = FindWindow(NULL, (LPCSTR) name);
SetActiveWindow(h);
SetForegroundWindow(h);
SetWindowPos(h, HWND_TOPMOST, 0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
}
int main()
{
char s[] = {"Application"};
AlwaysOnTop(s);
//AlwaysOnTop(2307);
system("PAUSE");
return 0;
}

Probably the best you can do is to call WaitForInputIdle:
Waits until the specified process has finished processing its initial input and is waiting for user input with no input pending, or until the time-out interval has elapsed.
This is the closest you can get to a general way to wait until a process is showing its UI. It won't always do what you want, but it's the best there is.

Related

In c++'s SetWindowsHookEx function

I'm Korean student.
Now this is my first question after signing up.
DWORD getProcessId() {
PROCESSENTRY32 process_infor;
process_infor.dwSize = sizeof(PROCESSENTRY32);
HANDLE snap_handle = CreateToolhelp32Snapshot(
TH32CS_SNAPALL, //스냅 단계
NULL //스냅할 pid
);
if (snap_handle != INVALID_HANDLE_VALUE) {
Process32First(snap_handle, &process_infor);
do {
wchar_t* temp = process_infor.szExeFile;
wstring ws(temp);
string name(ws.begin(), ws.end());
if (name == "notepad.exe") {
cout << name << " : " << process_infor.th32ProcessID << endl;
return process_infor.th32ProcessID;
}
} while (Process32Next(snap_handle, &process_infor));
}
CloseHandle(snap_handle);
return FALSE;
}
BOOL inject() {
HMODULE dll_handle;
HOOKPROC func;
HHOOK process_hook;
dll_handle = LoadLibrary(L"hello.dll");
func = (HOOKPROC) GetProcAddress(dll_handle, "injectSuccess");
cout << "handle : " << dll_handle << endl;
cout << "pid : " << getProcessId() << endl;
process_hook = SetWindowsHookEx(
WH_KEYBOARD,
func,
dll_handle,
getProcessId()
);
cout << "pook : " << process_hook << endl;
cout << "err : " << GetLastError() << endl;
FreeLibrary(dll_handle);
return FALSE;
}
There seems to be a problem with SetWindowsHookEx of the inject function in this case. The dll file loads well, and the injectSuccess function inside is well fetched. (I tried running it, but it worked)
And I wondered if the argument values ​​of SetWindowsHookEx were entered incorrectly, so I compared them and checked them continuously, but I couldn't find any difference. So, I tried GetLastError() with the return value of SetWindowsHookEx below, but the return value is 0 and the error code is 87 ("the parameter is incorrect").
So I searched, but I can't speak English well and I'm a beginner, so I'm not sure.
According to the SetWindowsHookExW:
dwThreadId
A handle to the DLL containing the hook procedure pointed to by the lpfn parameter. The hMod parameter must be set to NULL if the dwThreadId parameter specifies a thread created by the current process and if the hook procedure is within the code associated with the current process.
So what SetWindowsHookExW needs is the thread ID, and you pass in the process ID of notepad.exe, so the parameter is wrong.
I creat a sample and test the following code:
BOOL inject() {
HMODULE dll_handle;
HOOKPROC func;
HHOOK process_hook;
dll_handle = LoadLibrary(L"hello.dll");
if (dll_handle) func = (HOOKPROC)GetProcAddress(dll_handle, "injectSuccess");
else return FALSE;
cout << "handle : " << dll_handle << endl;
cout << "pid : " << getProcessId() << endl;
HWND h = FindWindow(L"notepad", NULL);
DWORD pid;
threadID = GetWindowThreadProcessId(h, NULL);
cout << "threadID = " << threadID << endl;
process_hook = SetWindowsHookEx(
WH_KEYBOARD,
func,
dll_handle,
threadID
);
cout << "pook : " << process_hook << endl;
cout << "err : " << GetLastError() << endl;
if(dll_handle) FreeLibrary(dll_handle);
return FALSE;
}
This example worked for me, and you can see the difference between pid and threadID:
Edit
According to the document:
An application installs the hook procedure by specifying the
WH_KEYBOARD hook type and a pointer to the hook procedure in a call to
the SetWindowsHookEx function. This hook may be called in the context
of the thread that installed it. The call is made by sending a message
to the thread that installed the hook. Therefore, the thread that
installed the hook must have a message loop. So if you want to run
this func, you need to add a message loop.
You can refer to the following code:
int main()
{
inject();
MSG msg;
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
When you press the button, the message box will pop up:
Because there are two messages for each key press and release, func is triggered twice each time.If you only want to trigger every time a button is pressed, you can modify the following code:
if ((0x80000000 & lParam) == 0)//This means that when the key is pressed
{
MessageBox(NULL, L"Success (dll injection)", L"Window", MB_OK);
}
You can refer to KeyboardProc to view the messages for each value in lParam.

Cannot receive WM_CLIPBOARDUPDATE messages

I am trying to use Clipboard Format Listener for my C++ Console Application. The goal is to monitor every change in the clipboard. I create MessageOnly window, successfully call AddClipboardFormatListener in WM_CREATE, but never get WM_CLIPBOARDUPDATE message in WindowProc function.
#include <iostream>
#include "windows.h"
using namespace std;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE:
if (AddClipboardFormatListener(hwnd))
cout << " Listener started" << endl;
else
cout << " Start listener failed" << endl;
break;
case WM_DESTROY:
if (RemoveClipboardFormatListener(hwnd))
cout << " Listener stopped" << endl;
else
cout << " Stop listener failed" << endl;
break;
case WM_CLIPBOARDUPDATE:
// Clipboard content has changed
cout << " Clipboard updated" << endl;
break;
default:
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int main(int argc, char* argv[])
{
HWND hWindow = nullptr;
static const wchar_t* className = L"ClipboardListener";
WNDCLASSEX wx = {};
wx.cbSize = sizeof(WNDCLASSEX);
wx.lpfnWndProc = WindowProc;
wx.hInstance = GetModuleHandle(NULL);
wx.lpszClassName = className;
if (!RegisterClassEx(&wx)) {
cout << "Cannot register class" << endl;
}
else
{
hWindow = CreateWindowEx(
0,
className,
L"ClipboardListener",
0, 0, 0, 0, 0,
HWND_MESSAGE,
NULL, NULL, NULL);
}
if (!hWindow)
{
cout << "Cannot create window" << endl;
}
else
{
while (true)
{
// Peek for a WM_CLIPBOARDUPDATE message
MSG message = { 0 };
PeekMessage(&message, hWindow, WM_CLIPBOARDUPDATE, WM_CLIPBOARDUPDATE, PM_REMOVE);
if (message.message == WM_CLIPBOARDUPDATE)
{
cout << "Sample window received WM_CLIPBOARDUPDATE message" << endl;
}
}
}
cin.get();
DestroyWindow(hWindow);
return 0;
}
PeekMessage works well, but I don't want to use loop to receive messages.
If I delete PeekMessage or replace PM_REMOVE with PM_NOREMOVE, nothing changes.
Your message loop is wrong.
CreateWindowEx() sends a WM_CREATE message before exiting, which is why your WindowProc() receives that message.
However, PeekMessage() does not dispatch messages to windows, which is why your WindowProc() does not receive the WM_CLIPBOARDUPDATE messages. Your message loop needs to call DispatchMessage() for that. You should also be using GetMessage() instead of PeekMessage(), so that the loop makes the calling thread sleep when there are no messages to process.
A standard message loop looks more like this:
MSG message;
while (GetMessage(&message, NULL, 0, 0))
{
TranslateMessage(&message);
DispatchMessage(&message);
}

list of programs with interface and processes with enumwindows

I need to find all the open Window with graphic interfaces and their processes and I don't really know how to do it. I've written some code but I just succeeded in finding open windows:
HWND hwnd = GetForegroundWindow(); // get handle of currently active window
GetWindowText(hwnd, wnd_title, sizeof(wnd_title));
cout << "Window with focus: " << wnd_title << endl << endl;
EnumWindows(EnumWindowsProc, 0);
EnumWindowsProc is defined like this:
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
char class_name[80];
char title[80];
if (IsWindowVisible(hwnd)) {
GetClassName(hwnd, class_name, sizeof(class_name));
GetWindowText(hwnd, title, sizeof(title));
cout << "Window title: " << title << endl;
cout << "Class name: " << class_name << endl << endl;
}
return TRUE;
}
Someone can help me?
I would recommend you not to check if IsWindowVisible because of
If the specified window, its parent window, its parent's parent window, and so forth, have the WS_VISIBLE style, the return value is nonzero. Otherwise, the return value is zero.
Because the return value specifies whether the window has the WS_VISIBLE style, it may be nonzero even if the window is totally obscured by other windows.
While enumerating windows you can use DWORD WINAPI GetWindowThreadProcessId(_In_ HWND hWnd, _Out_opt_ LPDWORD lpdwProcessId); to retrieve process id correlated with that particular HWND.
example :
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
char class_name[80];
char title[80];
DWORD dwProcessId;
GetClassName(hwnd,class_name, sizeof(class_name));
GetWindowText(hwnd,title,sizeof(title));
// get process id based on hwnd
GetWindowThreadProcessId(hwnd, &dwProcessId);
std::cout << "Window title: "<< title << std::endl;
std::cout << "Class name: "<< class_name << std::endl
// display process id based on hwnd
std::cout << "Process Id: " << dwProcessId << std::endl;
return TRUE;
}

Separate window message pumps and receiving WM_QUIT

I'm trying to create independent window wrapper classes for my project. It's mostly working but cannot figure out how to get WM_QUIT in my main message pump. In the interest of learning Windows, I don't want to use other libraries for this.
This is a quick example of whats happening.
#include <iostream>
#include <Windows.h>
void TestPump()
{
MSG msg = { 0 };
PostQuitMessage(0);
std::cout << "Posted WM_QUIT" << std::endl;
while (true)
{
BOOL result = PeekMessage(&msg, (HWND) -1, 0, 0, PM_REMOVE);
std::cout << "PeekMessage returned " << result << std::endl;
if (result == 0)
break;
if (WM_QUIT == msg.message)
std::cout << "got WM_QUIT" << std::endl;
}
}
void MakeWindow()
{
auto hwnd = CreateWindowEx(0, "Button", "dummy", 0, 0, 0, 32, 32, NULL, NULL, NULL, NULL);
std::cout << std::endl << "Created Window" << std::endl << std::endl;
}
int main()
{
TestPump();
MakeWindow();
TestPump();
std::cin.get();
return EXIT_SUCCESS;
}
The PeekMessage documentation is here: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644943(v=vs.85).aspx
I haven't been able to find any examples of using a -1 HWND filter, but MSDN says that it'll receive thread messages where the HWND is NULL (I've checked that this is true for WM_QUIT), which I believe PostQuitMessage does with WM_QUIT.
The problem only occurs if I create a Window.
Is there anything I'm doing wrong, or are there better methods?
This seems to be an interesting case so I've created a mcve, though I'm struggling to explain this behavior:
#include <Windows.h>
#include <CommCtrl.h>
#include <iostream>
#include <cassert>
void
Create_ThreadMessagePump(void)
{
::MSG msg;
::PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
::std::wcout << L"initialized thread message pump" << ::std::endl;
}
void
Create_Window(void)
{
auto const hwnd{::CreateWindowExW(0, WC_STATICW, L"dummy window", 0, 0, 0, 32, 32, NULL, NULL, NULL, NULL)};
(void) hwnd; // not used
assert(NULL != hwnd);
::std::wcout << L"created window" << ::std::endl;
}
void
Test_QuitMessageExtraction(void)
{
::PostQuitMessage(0);
::std::wcout << L"posted WM_QUIT" << ::std::endl;
for(;;)
{
::MSG msg;
auto const result{::PeekMessageW(&msg, (HWND) -1, 0, 0, PM_REMOVE)};
::std::wcout << L"PeekMessageW returned " << result << ::std::endl;
if(0 == result)
{
::std::wcout << L"no more messages to peek" << ::std::endl;
break;
}
if(WM_QUIT == msg.message)
{
::std::wcout << L"got WM_QUIT" << ::std::endl;
}
}
}
int
main()
{
//Create_ThreadMessagePump(); // does not change anything
Test_QuitMessageExtraction();
Create_Window();
Test_QuitMessageExtraction();
system("pause");
return(0);
}
output:
posted WM_QUIT
PeekMessageW returned 1
got WM_QUIT
PeekMessageW returned 0
no more messages to peek
created window
posted WM_QUIT
PeekMessageW returned 0
no more messages to peek
The problem appears to be with the way WM_QUIT and PostQuitMessage() operates. You can find information here:
Why is there a special PostQuitMessage function?.
In short, the WM_QUIT message will not be received while the queue is non-empty. Even if you filter out other messages by using a -1 HWND, the queue is still non-empty, and thus WM_QUIT is not returned. Creating of a window results in multiple HWNDs being created.

Non-Blocking Timer C++

I'm trying to create a simple non-blocking timer in C++ that can be reset. I've google searched for a while to find some code examples but everything I find is either too complicated to understand or does not compile without extra non example code.
I have a program that logs a key press to a file, but I want this file to be written over one seconds after the key has been pressed unless another key has been pressed before the second is up.
I believe I should use Win32 timers, (I am using windows) however I can't find a simple compilable example of their use.
for example this method taken from the info page:
SetTimer(hwnd, // handle to main window
IDT_TIMER1, // timer identifier
1000, // 1-second interval
(TIMERPROC) MyTimerProc); // no timer callback
VOID CALLBACK MyTimerProc(
HWND hwnd, // handle to window for timer messages
UINT message, // WM_TIMER message
UINT idTimer, // timer identifier
DWORD dwTime) // current system time
{
// my proceedure code
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen("LOG.TXT", "w");
fprintf(OUTPUT_FILE, "%s", "");
fclose(OUTPUT_FILE);
// writes a blank text file.
KillTimer(hwnd, IDT_TIMER1); // stop timer after one call
}
doesn't compile because the IDT_TIMER1 hasnt' been defined I think.
Also, I'm not sure if this would be reset by calling it twice or would just start two separate calls 1 second apart.
Any help greatly appreciated.
Just use the Hardware Performance Timer, which can be quickly found via google, or if you want something more cross platform use the timegettime method, which can also be found via google, neither need a Win32 message loop.
You are responsible for giving ID_TIMER1 a value. I believe you (99%) also have to have a windows message loop for it to work.
Here are a couple of minimal, compilable examples.
The following console program works. It sets a timer using SetTimer
then loops in a message loop. The message loop receives and processes WM_TIMER messages
and the timer callback also is called for each time interval. And it does not block.
#define STRICT 1
#include <windows.h>
#include <iostream.h>
VOID CALLBACK TimerProc(HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime)
{
cout << "Time: " << dwTime << '\n';
cout.flush();
}
int main(int argc, char *argv[], char *envp[])
{
int Counter=0;
MSG Msg;
UINT TimerId = SetTimer(NULL, 0, 500, &TimerProc); //SetTimer
cout << "TimerId: " << TimerId << '\n';
if (!TimerId)
return 16;
while (GetMessage(&Msg, NULL, 0, 0))
{
++Counter;
if (Msg.message == WM_TIMER)
cout << "Counter: " << Counter << "; timer message\n";
else
cout << "Counter: " << Counter << "; message: " << Msg.message << '\n';
DispatchMessage(&Msg);
}
KillTimer(NULL, TimerId);
return 0;
}
You don't need a window or even an event loop. Look at the WaitForSingleObject function.
Here is some code
HANDLE hStdin;
hStdin = GetStdHandle(STD_INPUT_HANDLE);
FILE *OUTPUT_FILE;
OUTPUT_FILE = fopen("LOG.TXT", "w");
bool previous_input_written = TRUE;
switch (WaitForSingleObject(hStdin, 1000) {
case WAIT_OBJECT_0:
// input happened on hStdin
if (!previous_input_written) {
// the previous input was not saved to file
fprintf(OUTPUT_FILE, ...
previous_input_written= TRUE;
}
ReadConsoleInput(hStdin, ...
previous_input_written = FALSE;
case WAIT_TIMEOUT:
// the 1000ms delay timed out, write to file
fprintf(OUTPUT_FILE, ...
previous_input_written= TRUE;
}
fclose(OUTPUT_FILE);