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.
Related
I have been working on a project which needs to detect current active window and get the active window title continuously.
Can anyone explain me how to use SetWinEventHook() function to get Active Window changed message.
[ i used GetForegroundWindow() function with a timer to get the active window. That approach is not very accurate because of the timer. So i need to use it with SetWinEventHook() function. can someone explain me how to do that? ]
hEvent = SetWinEventHook(EVENT_SYSTEM_FOREGROUND , EVENT_SYSTEM_FOREGROUND ,NULL,
WinEventProcCallback, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);
VOID CALLBACK WinEventProcCallback ( HWINEVENTHOOK hWinEventHook, DWORD dwEvent, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
/* how to get active window message */
}
I have found the solution. EVENT_SYSTEM_FOREGROUND Event is the missing piece. The system sends this event even if the foreground window has changed to another window. We can use this event to get the current active window.
VOID CALLBACK WinEventProcCallback ( HWINEVENTHOOK hWinEventHook, DWORD dwEvent, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
if (dwEvent == EVENT_SYSTEM_FOREGROUND)
{
/* do something */
}
}
Is there a clean and easy way to disable "Right to left reading order" and Unicode related messages from a context popup menu for an edit control. Yes, I know that I can subclass and intercept WM_CONTEXTPOPUP, then walk the menu. Attached is the image with menu items in question.
I
I know you said you don't want to subclass, but I don't think it's that painful.
Derive from CEdit, in this case I used the class name CEditContextMenu and add WM_CONTEXTMENU to your message map:
EditContextMenu.cpp
// ...
BEGIN_MESSAGE_MAP(CEditContextMenu, CEdit)
ON_MESSAGE(WM_CONTEXTMENU, &CEditContextMenu::OnContextMenu)
END_MESSAGE_MAP()
// CEditContextMenu message handlers
LRESULT CEditContextMenu::OnContextMenu(WPARAM wParam, LPARAM lParam){
HWINEVENTHOOK hWinEventHook{
SetWinEventHook(EVENT_SYSTEM_MENUPOPUPSTART, EVENT_SYSTEM_MENUPOPUPSTART, NULL,
[](HWINEVENTHOOK hWinEventHook, DWORD Event, HWND hWnd, LONG idObject,
LONG idChild, DWORD idEventThread, DWORD dwmsEventTime){
if (idObject == OBJID_CLIENT && idChild == CHILDID_SELF){
CMenu* pMenu{
CMenu::FromHandle((HMENU)::SendMessage(
hWnd, MN_GETHMENU, NULL, NULL))
};
pMenu->EnableMenuItem(32768, MF_DISABLED);
}
},
GetCurrentProcessId(), GetCurrentThreadId(), WINEVENT_OUTOFCONTEXT)
};
LRESULT ret{ Default() };
UnhookWinEvent(hWinEventHook);
return ret;
}
// ...
Maybe you could do something fancy and watch for WS_EX_RTLREADING and block it some how.
At the end of the day you want to change how the OS functions at a low level. I don't think there is an elegant way to do it organically.
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
How can I detect whether the focused window is an Edit 'type' control? One method I am aware of is using Microsoft Active Accessibility which is looking like it will involve alot of effort using this method.
Is there another method I could use that is simpler?
My use-case is: when an edit control has the focus, store that hwnd.
// Callback set by SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, NULL, (WINEVENTPROC)&winEventProc, 0, 0, WINEVENT_SKIPOWNPROCESS);
void CALLBACK KeyboardComponent::winEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject,
LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
// if hwnd == "Edit Control" store hwnd to send key input events
// One technique but not comprehensive
TCHAR wndClassName[255];
GetClassName(hwnd, wndClassName, 255);
if (_tcsicmp(wndClassName, _T("edit")) == 0)
targetEdit = hwnd;
// Class names I am receiving are subclassed or new window classes that look and operate like Edit controls.
// Ie when clicking the Firefox address bar I get: MozillaWindowClass
// Ie when clicking the Chrome address bar I get: Chrome_WidgetWin_1
}
Active Accessibility is the correct solution. You can use AccessibleObjectFromEvent() to get an IAccessible interface for the HWND that is triggering your winEventProc hook, and then check the IAccessible::AccRole property for ROLE_SYSTEM_TEXT:
ROLE_SYSTEM_TEXT
The object represents selectable text that allows edits or is designated as read-only.
For example:
// Callback set by SetWinEventHook(EVENT_OBJECT_FOCUS, EVENT_OBJECT_FOCUS, NULL, (WINEVENTPROC)&winEventProc, 0, 0, WINEVENT_SKIPOWNPROCESS);
void CALLBACK KeyboardComponent::winEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject,
LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime)
{
IAccessible* pAcc = NULL;
VARIANT varChild;
HRESULT hr = AccessibleObjectFromEvent(hwnd, idObject, idChild, &pAcc, &varChild);
if ((hr == S_OK) && (pAcc != NULL))
{
VARIANT varRole;
hr = pAcc->get_accRole(varChild, &varRole);
if ((hr == S_OK) && (varRole.vt == VT_I4) && (varRole.lVal == ROLE_SYSTEM_TEXT))
{
// ...
}
pAcc->Release();
}
}
For reliable result try using RealGetWindowClass, it should deal with a case when window was subclassed. If you don't care about that use regular GetClassName.
In case you want to handle controls that are not derived from standard Edit class, none of that will work of course.
You can use this code to know if focused window is Edit control
CWnd* pControl;
pControl = this->GetFocus();
if(pControl->IsKindOf(RUNTIME_CLASS(CEdit))){
//----
-----
----//
}
Get more details Here
Convert Cwnd to HWND
pControl->GetSafeHwnd();
I've created a program to identify existing maximized windows and log their locations using EnumWindows and GetWindowPlacement.
Assuming I know the location of a desired EXE, I can open it just by calling the external process caller. But what is the best way to identify the newly opened window and set its location? It's safe to assume that a program with the same name may already be open (two instances of cmd, for instance).
I believe once the window is identified I can set its location with SetWindowPos.
Is this the right question to be asking? Is there a way to open a program and receive a HWND handle back instead?
In the Event Hook vein, I have this code:
HWINEVENTHOOK hook = SetWinEventHook(EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE, NULL, proc, 0, 0, WINEVENT_OUTOFCONTEXT );
BOOL result = CreateProcess(NULL, szPath, &saProcess, &saThread, FALSE, 0, NULL, NULL, &si, &piProcessC);
if (hook) {
UnhookWinEvent(hook);
}
Which creates a hook and then creates a process (I'm opening up Notepad++).
The proc function it calls is:
void CALLBACK proc(HWINEVENTHOOK hook, DWORD event, HWND hWnd, LONG obj, LONG child, DWORD thr, DWORD time) {
if (IsWindow(hWnd)){
WINDOWPLACEMENT *wp = new WINDOWPLACEMENT();
wp->length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hWnd, wp);
wp->rcNormalPosition.top = (long) 363;
wp->rcNormalPosition.bottom = (long) 1021;
wp->rcNormalPosition.left = (long) 1444;
wp->rcNormalPosition.right = (long) 2551;
BOOL tmp = SetWindowPlacement(hWnd, wp);
cout << "FOUND IT\n";
}
}
The proc function does not appear to get called, so is the hook not catching anything?
Oh, and I'm not sure the WINEVENT_OUTOFCONTEXT is right, this is just a simple EXE doing the calling.