How to get Windows 7 jump list window via ::FindWindow or ::EnumWindows?
What's it's class or parent?
I can't Spy++ it because it disappears if loses focus.
Thank you.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa511446.aspx
Here's a way, similar to the Spy++ technique, to find it through code as soon as it's shown using an event hook:
void CALLBACK WinEventProc(HWINEVENTHOOK, DWORD, HWND hwnd, LONG, LONG, DWORD, DWORD) {
std::wstring className(256, L'\0');
std::wstring windowText;
windowText.resize(GetWindowTextLengthW(hwnd) + 1);
GetWindowTextW(hwnd, &windowText[0], windowText.size());
windowText = windowText.c_str();
GetClassNameW(hwnd, &className[0], className.size());
className = className.c_str();
std::wcout << "Class: \"" << className << "\"\n";
std::wcout << "Window: \"" << windowText << "\"\n";
}
int main() {
HWINEVENTHOOK hWinEventHook = SetWinEventHook(
EVENT_OBJECT_SHOW, EVENT_OBJECT_SHOW,
nullptr, WinEventProc,
0, 0,
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS
);
MSG msg;
while (GetMessage(&msg, nullptr, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (hWinEventHook) {
UnhookWinEvent(hWinEventHook);
}
}
As each window is shown, it appears in the console (or whatever stdout is at the time) output as a class name of DV2ControlHost and text of Jump List. If you want to interact with it, however, I believe there's a much more structured API, though I might be mistaken.
Open spy++, open jump list, click the refresh button on spy++.
Related
Question:
In my program, I want to get the content of a specific edit box (or input box, text box...) of another process. For example, when the cursor is in the first column, "TextBox1" should be returned.
What I have tried
Use GetDlgItem and GetWindowText
Send WM_GETTEXT message to the window, which was suggested in a Q&A in from the august 2001 issue of MSDN Magazine and a stackoverflow question
char currentContext[256];
SendMessage(cfg.mainWnd,
WM_GETTEXT, sizeof(currentContext) / sizeof(currentContext[0]), (LPARAM)currentContext);
// cfg.mainWnd is the window which edit boxes lie in.
EnumChildWindows and callback
HWND GetInputWindow()
{
HWND activeWindow = GetForegroundWindow();
// lpdwProcessId cannot be null...
DWORD a = 1;
LPDWORD lpdwProcessId = &a;
auto threadId = GetWindowThreadProcessId(activeWindow, lpdwProcessId);
std::cout << "ThreadId: " << threadId << " ProcessId: " << *lpdwProcessId << "\n";
return activeWindow;
}
BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)
{
std::cout << "Being called.\n";
char temp1[256];
char temp2[256];
GetClassNameA(hWnd, temp1, 255);
if (!strcmp(temp1, "Edit"))
{
SendMessage(hWnd, WM_GETTEXT, sizeof(temp2) / sizeof(char), (LPARAM)temp2);
return false;
}
printf("text: %s", temp2);
MessageBox(NULL, temp2, L"test", MB_OK);
return true;
}
// ...
HWND activeWindow = GetInputWindow();
EnumChildWindows(activeWindow, EnumChildProc, 0);
All the methods above just get "MainWindow", i.e. the title of the window in the example above.
Appendix
I used spy++ to monitor the window in the example. Just one window was catched.
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 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);
}
}
I am trying to detect when a USB drive is inserted. Right now, I'm creating a dummy window and RegisterDeviceNotificationing it. However, I don't think my approach is correct, as the window doesn't seem to be receiving messages.
#include <iostream>
#define WINVER 0x501
#include <windows.h>
#include <dbt.h>
#include "devicehandler.h"
#include "remover.h"
DeviceHandler::DeviceHandler(Remover* remover)
{
this->remover = remover;
this->hWnd = this->createHandleWindow();
this->registerDeviceHandler();
this->messageLoop(this->hWnd);
}
DeviceHandler::~DeviceHandler()
{
this->unregisterDeviceHandler();
}
void DeviceHandler::messageLoop(HWND hWnd)
{
std::cerr << "Entering message loop." << std::endl; // Gets here!
MSG msg;
while (GetMessage(&msg, this->hWnd, 0, 0)) {
std::cerr << "Loop!" << std::endl; // Does not get here!
switch (msg.message) {
case WM_DEVICECHANGE:
{
PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR) msg.lParam;
switch(msg.wParam) {
case DBT_DEVICEARRIVAL:
std::cerr << "Device added!" << std::endl;
break;
default:
std::cerr << "Other device event." << std::endl;
break;
}
break;
}
default:
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
HWND DeviceHandler::createHandleWindow()
{
std::cerr << "Creating handle window... ";
HWND hWnd = CreateWindow(NULL, NULL, WS_ICONIC, 0, 0, CW_USEDEFAULT, 0,
NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(hWnd, SW_HIDE);
std::cerr << "done!" << std::endl;
return hWnd;
}
void DeviceHandler::registerDeviceHandler()
{
std::cerr << "Device notification handling... ";
// GUID guid = { 0xa5dcbf10, 0x6530, 0x11d2, { 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed } };
GUID guid = { 0x25dbce51, 0x6c8f, 0x4a72, { 0x8a, 0x6d, 0xb5, 0x4c, 0x2b, 0x4f, 0xc8, 0x35 } };
DEV_BROADCAST_DEVICEINTERFACE notificationFilter;
ZeroMemory(¬ificationFilter, sizeof(notificationFilter));
notificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
notificationFilter.dbcc_classguid = guid;
this->deviceNotifier = RegisterDeviceNotification(this->hWnd,
¬ificationFilter,
DEVICE_NOTIFY_WINDOW_HANDLE);
std::cerr << "done!" << std::endl;
}
void DeviceHandler::unregisterDeviceHandler()
{
UnregisterDeviceNotification(this->deviceNotifier);
}
I'm guessing that this is not the right place to put the message loop, but I'm not very good with WinAPI. How do I get my program to enter the message loop? (And also preferably register device notifications.)
You should be creating a message only Window. It can receive messages it registers like device notification and power events, but it will never be shown.
Message only window must be registered with RegisterClassEx.
With you window class registered, you then pass your window class name to CreateWindowEx along with HWND_MESSAGE as a parent. Your CreateWindow should use CreateWindowEx instead to look like this :
HWND hWnd = CreateWindowEx(0, myClassName, _T("This is not the class name"),
0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, this);
You will still use GetMessage along with TranslateMessage and DispathMessage which will call your WNDPROC like a callback. Nothing wrong with that, but you loose the pointer to your DeviceHandler class in your windows procedure.
This is why you pass this as the last parameter of CreateWindowEx. You can retreive it when you receive the WM_CREATE message and set it to your windows class user data with SetWindowLongPtr and GWLP_USERDATA. Every call after that will retreive the pointer with GetWindowLongPtr and cast it to a DeviceHandler object.
Here is a good example of the technique.
To play by the rules, you should register your own window class to use GWLP_USERDATA, although it should still work using the STATIC window class.
Final note : be sure to call DefWindowProc for messages you don't handle.
Looks like the problem is that your window is not created because you didn't specified valid class name. HWND returned in this case is NULL and device fails to register it and send messages to it.
As proposed in other answer you could use Message-Only Window for purpose to receive device notifications. But would like to mention that registering window class is not necessary in this case, you could use predefined class name, e.g. STATIC (as you don't need actually to specify your own window proc):
HWND hwnd = CreateWindowEx(0, "STATIC", 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
Is there any way to draw on the desktop background in WIN32 and also receive notifications when the desktop background is repainted?
I tried this:
desk = GetDesktopWindow();
dc = GetDC(desk);
MoveToEx(dc,0,0,NULL);
LineTo(dc,1680,1050);
ReleaseDC(desk,dc);
But it draws on the whole screen, even over windows that are on the screen.
You can use Spy++ to find which window is the desktop background window.
On my system I see the following hierarchy:
Window 000100098 "Program Manager" Progman
Window 0001009E "" SHELLDLL_DefView
Window 00100A0 "FolderView" SysListView32
I guess you are referring to the SysListView32 - the window with all the icons. You can use FindWindowEx to find this window.
Edit
You should use a combination of FindWindowEx and EnumerateChildWindows. The code presented below can be compiled in a command line box like this: cl /EHsc finddesktop.cpp /DUNICODE /link user32.lib
#include <windows.h>
#include <iostream>
#include <string>
BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
{
std::wstring windowClass;
windowClass.resize(255);
unsigned int chars = ::RealGetWindowClass(hwnd, &*windowClass.begin(), windowClass.size());
windowClass.resize(chars);
if (windowClass == L"SysListView32")
{
HWND* folderView = reinterpret_cast<HWND*>(lParam);
*folderView = hwnd;
return FALSE;
}
return TRUE;
}
int wmain()
{
HWND parentFolderView = ::FindWindowEx(0, 0, L"Progman", L"Program Manager");
if (parentFolderView == 0)
{
std::wcout << L"Couldn't find Progman window, error: 0x" << std::hex << GetLastError() << std::endl;
}
HWND folderView = 0;
::EnumChildWindows(parentFolderView, EnumChildProc, reinterpret_cast<LPARAM>(&folderView));
if (folderView == 0)
{
std::wcout << L"Couldn't find FolderView window, error: 0x" << std::hex << GetLastError() << std::endl;
}
HWND desktopWindow = ::GetDesktopWindow();
std::wcout << L"Folder View: " << folderView << std::endl;
std::wcout << L"Desktop Window: " << desktopWindow << std::endl;
return 0;
}
Here are the results after running finddesktop.exe
Folder View: 000100A0
Desktop Window: 00010014
As you can see the window handles are quite different.
Just quoting MSDN:
The GetDesktopWindow function returns
a handle to the desktop window. The
desktop window covers the entire
screen. The desktop window is the area
on top of which other windows are
painted.
So you are getting a Window with nested windows on them.
I'm not quite a WIN32 user, but I think the approach here is get to the lower level, take control of the graphic object that is painting the background picture, and draw there.