How to Hook only a KeyboardFocus on Windows API - c++

I'm searching on msdn for a Hook handler about Keyboard Focus, but didn't found.
I would like the handler for the element on focus by keyboard.
Example:
When we are on Desktop and press any key that is a first letter of a program, these program is selected.
When we press the TAB key for navigation links, these element is selected.
I saw the CBTProc for hook a keyboard events, but is not helpful, because we can select the item by click of mouse.
So, I would like the handler about focus of mouse or keyboard, the element name.

I had success with this code.
// Global variable.
HWINEVENTHOOK g_hook;
//
// Callback function that handles events.
//
void CALLBACK HandleWinEvent(HWINEVENTHOOK hook, DWORD event, HWND hwnd,
LONG idObject, LONG idChild,
DWORD dwEventThread, DWORD dwmsEventTime)
{
std::cout << "Inside CB" << std::endl;
}
// Initializes COM and sets up the event hook.
void InitializeMSAA()
{
CoInitialize(NULL);
g_hook = SetWinEventHook(
EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, // Range of events (4 to 5).
NULL, // Handle to DLL.
HandleWinEvent, // The callback.
0, 0, // Process and thread IDs of interest (0 = all)
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS); // Flags.
}
// Unhooks the event and shuts down COM.
//
void ShutdownMSAA()
{
UnhookWinEvent(g_hook);
CoUninitialize();
}
int main()
{
InitializeMSAA();
MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Thanks all for yours reply

Related

How to track Application closed event in c++ winapp?

I wanted to know if any application in the foreground(except this application) is closed by clicking the cross button on the top-right or any other way like Ctrl + f4.
Here is what I have created so far:
create window event
void CALLBACK WinEventProc(
HWINEVENTHOOK hWinEventHook,
DWORD event,
HWND hwnd,
LONG idObject,
LONG idChild,
DWORD dwEventThread,
DWORD dwmsEventTime
) {
handleProcess(hwnd);
// handleProcess does other operations
}
Call the window event in wWinMain()
...
winDestructionHook = SetWinEventHook(EVENT_OBJECT_DESTROY, EVENT_OBJECT_DESTROY,
NULL, WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT);
...
The problem here is the window event is triggered without any window-closed action, but I wanted to activate it only on application closed.

Handle tab stop using DispatchMessage() without blocking the thread through message loop?

I have a function export OpenUI() in a DLL for UI view which creates the modeless main dialog and also has a modeless child dialog.
I am calling the function export OpenUI() from a separate DLL which is my controller.
How can I possibly execute more code after the function call if the message loop in OpenUI() prevents the function to return unless the dialog is closed?
I cannot remove the message loop because tab stop will not work without it.
I need the function export to return immediately after execution therefore I cannot use a modal dialog. Creating a subthread is also not an option because it caused issues in my application.
Any help is highly appreciated.
Thank you.
Pseudocode for my controller dll
typedef int(*DLL_OPENUI)();
int func()
{
HINSTANCE hinst_dll = LoadLibrary(dll_path);
DLL_OPENUI DllOpenUI = (DLL_OPENUI)GetProcAddress(hinst_dll, "OpenUI");
int ret = DllOpenUI();
//...execute more code here
return ret;
}
Pseudocode for my UI view dll
__declspec(dllexport) OpenUI()
{
hwnd_main = CreateDialog(hinst, IDD_MAIN, MainDlgProc);
ShowWindow(hwnd_main, SW_SHOW);
MSG msg;
while ((GetMessage(&msg, NULL, 0, 0) > 0))
{
if (!IsDialogMessage(hwnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
LRESULT CALLBACK MainDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_INITDIALOG:
OnInitDialog();
break;
}
}
void OnInitDialog()
{
CreateDialog(hinst, IDD_NAV_PANE, hwnd_main, NavPaneProc);
CreateDialog(hinst, IDD_NAV_TABS, hwnd_main, NavTabsProc);
CreateDialog(hinst, IDD_TAB_1, hwnd_main, TabOneProc);
CreateDialog(hinst, IDD_TAB_2, hwnd_main, TabTwoProc);
CreateDialog(hinst, IDD_TAB_3, hwnd_main, TabThreeProc);
CreateDialog(hinst, IDD_DETAILS_PANE_BG, hwnd_main, BackgroundProc);
CreateDialog(hinst, IDD_DETAILS_PANE, hwnd_main, DetailsPaneProc);
//...execute more code below
}
You have to have an active message loop, there's no way around that. One way to do it is to have one new function that would PeekMessage and execute the loop code only once. PeekMessage returns non-zero value if subsequent call to GetMessage would actually get a message and not block instead. ProcessOneMessage may look something like this:
BOOL ProcessOneMessage(HWND hwnd)
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
return TRUE;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return FALSE;
}
So, in your main code you have to call this function often (once every 10 ms should be fine). Whatever the code does it must call the function once in 10 ms. You will have a live window and run your code at the same time. But once the function returns TRUE the window was closed and you must not call the function again. For more info search for PeekMessage. The code is taken from this link: https://jeffpar.github.io/kbarchive/kb/074/Q74042/

Why doesn't my Windows API callback function run? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I've written a code that terminates egui.exe. But my callback function doesn't run after the WM_CLOSE message is processed. Why?
#include <iostream>
#include <windows.h>
#include <psapi.h>
using namespace std;
HWND ESETWindow = 0; //Variable to store a handle to the main window
// of ESET Smart Security
HWND ConfirmationWindow = 0; //Variable to store a handle to the
// confirmation dialog box that appears
// when a WM_CLOSE message is sent to
// the ESET window.
DWORD EGUIPID = 0; //Variable to store the process identifier of egui.exe
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam);
VOID SendAsyncProc(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult);
int main()
{
cout << "Terminating ESET Smart Security..." << endl;
//Obtain an array of process identifiers including the PID of egui.exe
DWORD PIDs[1024]; //The array of process identifiers
DWORD bytesReturned;
if (!EnumProcesses(PIDs, sizeof(PIDs), &bytesReturned))
{
cerr << "Unable to enumerate the processes." << endl;
return 0;
}
//Enumerate the PIDs array to find the process of egui.exe.
DWORD nProcesses = bytesReturned / sizeof(DWORD);
for (DWORD i = 0;i < nProcesses;i++)
{
//Open the process to examine its executable file name.
HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PIDs[i]);
//Create a buffer for the name of the executable file.
PSTR processName = (PSTR) VirtualAlloc((LPVOID) NULL, (DWORD) 10, MEM_COMMIT, PAGE_READWRITE);
//Get the name of the executable file name.
GetModuleBaseName(process, NULL, processName, 10);
//Check if the executable file name is egui.exe.
if (!lstrcmpi(processName, TEXT("egui.exe")))
{
EGUIPID = PIDs[i];
break;
}
VirtualFree(processName, 0, MEM_RELEASE);
CloseHandle(process);
}
//Display an error message if the process identifier of egui.exe
//could not be found.
if (!EGUIPID)
{
cerr << "Unable to find process identifier of egui.exe" << endl;
return 0;
}
//Enumerate the top-level windows to find the main window of
// ESET Smart Security and store a handle to that window in the
// ESETWindow variable.
EnumWindows(EnumWindowsProc, 0);
//Display an error message if the window could not be found.
if (!ESETWindow)
{
cerr << "Unable to find the primary window of ESET Smart Security." << endl;
return 0;
}
//Send a WM_CLOSE message to the main window of egui.exe in order
// to display a confirmation dialog box.
if (!SendMessageCallback(ESETWindow, WM_CLOSE, 0, 0, SendAsyncProc, 0))
{
cerr << "Unable to send a WM_CLOSE message to the primary window of ESET Smart Security." << endl;
return 0;
}
//Wait a second for the confirmation dialog box to appear...
Sleep(1000);
//Enumerate the windows again to find the confirmation dialog box.
EnumWindows(EnumWindowsProc, 1);
//Display an error message if the confirmation dialog box
// could not be found.
if (!ConfirmationWindow)
{
cerr << "Unable to find confirmation message." << endl;
cout << "If you have ESET NOD32, it is probably terminated successfully.";
cin.get();
}
//Find the Yes button in the confirmation dialog box and display
// an error message if failed.
HWND button = FindWindowEx(ConfirmationWindow, NULL, NULL, TEXT("&Yes"));
if (!button)
{
cerr << "Unable to find Yes button in the message box." << endl;
return 0;
}
//Activate the confirmation dialog box and simulate a mouse click
// on the Yes button.
SetActiveWindow(ConfirmationWindow);
SendMessage(button, BM_CLICK, 0, 0);
cout << "ESET Smart Security was successfully terminated!";
//Keep the program running until the user presses Enter
// in the console window.
cin.get();
return 0;
}
//If lParam is 0, the function below finds the main window of
//ESET Smart Security, otherwise, it finds the confirmation
//dialog box.
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
//Check if hwnd belongs to a window of egui.exe.
DWORD PID = 0;
GetWindowThreadProcessId(hwnd, &PID);
if (PID != EGUIPID)
return TRUE; //Exit function and continue the enumeration.
//Check if the title of the window is "ESET Smart Security"
// or "ESET Node32 Antivirus".
int len = GetWindowTextLength(hwnd);
PSTR title = (PSTR) VirtualAlloc((LPVOID) NULL, (DWORD) (len + 1), MEM_COMMIT, PAGE_READWRITE);
GetWindowText(hwnd, title, (len + 1));
if ((lstrcmp(title, TEXT("ESET Smart Security"))) && (lstrcmp(title, TEXT("ESET NOD32 Antivirus"))))
return TRUE; //Exit function and continue the enumeration.
if (lParam)
{
//If lParam is nonzero and hwnd refers to the main
// window of egui.exe, exit function and continue
// the enumeration.
if (hwnd == ESETWindow)
return TRUE;
//Otherwise hwnd refers to the confirmation dialog box.
//So store it in the ConfirmationWindow variable.
ConfirmationWindow = hwnd;
return FALSE; //Exit function and stop the enumeration.
}
else
{
//hwnd refers to the main window of ESET Smart Security.
//So store it in the ESETWindow variable.
ESETWindow = hwnd;
return FALSE; //Exit function and stop the enumeration.
}
}
VOID SendAsyncProc(HWND hwnd, UINT uMsg, ULONG_PTR dwData, LRESULT lResult)
{
MessageBox(0, TEXT("ESET Smart Security was successfully terminated."), TEXT("Result"), MB_OK);
}
Although this program accomplishes its task perfectly, the callback function SendAsyncProc doesn't run after the WM_CLOSE message is processed and egui.exe is terminated. Could you tell me why?
The documentation for SendMessageCallback tells you, why your callback will not ever be called:
If the target window belongs to a different thread from the caller, then the callback function is called only when the thread that called SendMessageCallback also calls GetMessage, PeekMessage, or WaitMessage.
The target window obviously belongs to a different thread, because it runs in a different process. Your code doesn't perform any message retrieval. No callback.

C++ CreateWindow: button position gets offset at window maximize

I have a weird problem over here. I created a DLL proxy for Spotify so I can "overlay" a button onto it. Basicially, thats how it works:
DllMain
-> Creates CMain class
-> Creates CToggleButton class
-> Hooks the button onto the Spotify window
It has two methods, one static one which I use for the thread since threads can't call member functions, and one non-static function which gets called by the member function.
With this, I create the thread and pass an instance of the CToggleButton class via lpParam:
CreateThread(0, NULL, WindowThreadStatic, (void*)this, NULL, NULL);
Then, the WindowThreadStatic function:
DWORD WINAPI CToggleButton::WindowThreadStatic(void* lpParam)
{
return ((CToggleButton*)lpParam)->WindowThread();
}
And the main window thread function inside the class:
DWORD CToggleButton::WindowThread()
{
MSG msg;
hButton = CreateWindowA("BUTTON", "Test", (WS_VISIBLE | WS_CHILD), 0, 0, 100, 20, parenthWnd, NULL, hInst, NULL);
bool bQueueRunning = true;
while (bQueueRunning)
{
if (PeekMessage(&msg, parenthWnd, 0, 0, PM_REMOVE))
{
switch (msg.message)
{
case WM_QUIT:
bQueueRunning = false;
break;
case WM_LBUTTONDOWN:
if (msg.hwnd == hButton)
{
MessageBoxA(parenthWnd, "Button!", "Button", MB_OK);
continue;
}
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(10);
}
return 0;
}
As you can see, this also contains the message loop for the button (I didn't use GetMessage() here because it was very unresponsive so I decided to use PeekMessage() together with a 10ms delay, which works fine.)
Little picture to show how it looks like:
All great, but if I maximize the window, the button disappears. When I minimize and maximize the window a few times, the button can be seen again, but with very weird coordinates (not the original 0,0 I gave him).
So what is my problem here? Why do the coordinates get offset?
Thanks for reading my long post :)

Browse For Folder dialog window handle C++

How to get the handle HWND of the dialog which user open when clicking on a button.
I'm using Spy++ to find the window class and tittle, but it says that no such window is found. And how then to get the handle of that dialog in C++ using Win API ?
I hope that I will be able to do that using simple functions as FindWindow, GetParent, any WIN APi function. I do not like to inject something or load DLL. Thanks
UPDATE:
the folder browser dialog is opened by other program. I want to get it's handle from different program , my program. Thanks.
The closest to want i need is for now the function WindowFromPoint
Accessibility will let you capture window creation events from other processes without DLL injection. You can modify the example to accommodate for the browsing window specifically. Here's an example I made previously to test that is based on the one from the article. Modify it however you wish:
#include <iostream>
#include <windows.h>
void CALLBACK proc(HWINEVENTHOOK hook, DWORD event, HWND hwnd, LONG obj, LONG child, DWORD thr, DWORD time) {
if (hwnd && obj == OBJID_WINDOW && child == CHILDID_SELF) {
switch (event) {
case EVENT_OBJECT_CREATE: {
std::cout << "Window created!\n";
break;
}
case EVENT_OBJECT_DESTROY: {
std::cout << "Window destroyed!\n";
break;
}
}
}
}
int main() {
HWINEVENTHOOK hook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_DESTROY, nullptr, proc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (hook) {
UnhookWinEvent(hook);
}
}