How to get names of the icons on desktop - c++

guys.
I want to obtain names of icons on desktop in c++. And I know how to get their handle:
HWND hwnd = FindWindow("Progman","Program Manager");
HWND hwndSHELLDLL_DefView = ::FindWindowEx( hwnd, NULL, "SHELLDLL_DefView", NULL );
HWND hwndSysListView32 = ::FindWindowEx( hwndSHELLDLL_DefView, NULL, "SysListView32", "FolderView" );
What's next?

First, you need to get the location of the desktop folder using SHGetFolderLocation.. Next, you enumerate the contents of this folder using IShellFolder::EnumObjects
From here, the sky is the limit. Tons of information on interacting with the windows shell here.
Have fun!
Update:
A quick google search turns up this sample which seems to do exactly what you want.

Related

Detect external devices insertion on Windows

I'm a little bit confused about how to notify my c++ application with event that the user has plugged in a device (USB, HID etc.). Application type is not defined. I'm trying to play around with console/message-only/service example apps, but there is no result. I'm using VS2015 and Windows 10.
I've found out that there are multiple ways to deal with it:
Using WMI like here. But I can not actually understand where is WMI here.
Using RegisterDeviceNotification and WM_DEVICECHANGE. As far as I can understand, there is no way to do that for the console applications, only for once with the GUI (real window) or for the message-only window. I've tried the last one with the example from this answer but my app doesn't receive any notifications when I plug in my USB flash drive. I've found this answer (from the same question as the answer mentioned above) and tried to use ChangeWindowMessageFilterEx() function with GetProcAddress from user32.dll to load it without connection dll to my app in such way:
BOOL InitInstance(HWND hWnd)
{
HMODULE hDll = GetModuleHandle(TEXT("user32.dll"));
if (hDll)
{
typedef BOOL(WINAPI *MESSAGEFILTERFUNCEX)(HWND hWnd, UINT message, DWORD action, VOID* pChangeFilterStruct);
const DWORD MSGFLT_ALLOW = 1;
MESSAGEFILTERFUNCEX ChangeWindowMessageFilterEx= (MESSAGEFILTERFUNCEX)::GetProcAddress(hDll, "ChangeWindowMessageFilterEx");
if (ChangeWindowMessageFilterEx) return func(hWnd, WM_COPYDATA, MSGFLT_ALLOW, NULL);
}
return FALSE; }
And the usage of this function is:
hWnd = CreateWindowEx(0, CLS_NAME, "DevNotifWnd", WS_ICONIC,
0, 0, CW_USEDEFAULT, 0, HWND_MESSAGE,
NULL, GetModuleHandle(0), (void*)&guid);
InitInstance(hWnd);
But there is no effect.
Using while(true){...} loop and call appropriate Win API functions like in this answer. But this way seems not be a perfect solution for my problem.
My questions are:
Could anybody explain me what is the best way? And if it is the second one with RegisterDeviceNotification, why it's not working in case of message-only window app?
Do other ways exist? And if not, what can I do, for example, to notify application when some certain software was installed?
Any comments are appreciated.
So I've finally found sort of answers to the questions.
The issue was with the GUID I've provided for the NotificationFilter. So I've set it to receive notifications from all devices with this code:
DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
// No need to set up dbcc_classguid as it is ignored when
// DEVICE_NOTIFY_ALL_INTERFACE_CLASSES is setted (see line down below)
HDEVNOTIFY dev_notify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);
As far as for other types of notifications in windows that the app could sign up for, I found only one partially deprecated list of all Win32 API functions, where I found some new Notifications with Ctrl+F search :)
Hope this could save somebody's time.

how to get text from a window with specific HWND?

I'm new to win32 programming and haven't worked around with cpp for a long time. What I intend to do is to get a window's HWND via spy++, and get the text of this window. The problem is that I don't know how to create a HWND object, could anyone give me some idea? Thanks a lot!
If you have the numeric value of the HWND, you can cast it to the right type. Start with an integer of the right size, e.g.:
uintptr_t numeric_hwnd = 0x987654;
HWND hwnd = reinterpret_cast<HWND>(numeric_hwnd);

force SHBrowseForFolder() to show desired directory

I've been searching online and fighting this thing for over an hour and still can't seem to get it to work. Most people seem to be satisfied when they get it this far on forums etc. but mine still doesn't work.
I'm trying to force the SHBrowseForFolder() function to start in a folder of my choosing.
char current[MAX_PATH];
strcpy(current,"C:\\Users");
char outbuf[MAX_PATH];
BROWSEINFO bis;
bis.hwndOwner = NULL;
bis.pidlRoot = NULL;
bis.pszDisplayName = outbuf;
bis.lpszTitle = (LPCSTR)"HERE";
bis.ulFlags = BIF_NEWDIALOGSTYLE|BIF_RETURNONLYFSDIRS;
bis.lpfn = NULL;
bis.lParam = (LPARAM)current;
SHBrowseForFolder(
&bis
);
It seems like this should be a relatively simple task. :/
At the moment, the above code is still showing the default: the Desktop folder.
Beyond starting in a specific folder, if possible, I'd also like it to ONLY show that folder and below, with no access to parent directories.
What am I missing here?
You can also send a BFFM_SETSELECTION message from your BrowseCallbackProc, like:
int FAR PASCAL BrowseNotify(HWND hWnd, UINT iMessage, long wParam, LPARAM lParam)
{ if (iMessage == BFFM_INITIALIZED)
{ SendMessage(hWnd, BFFM_SETSELECTION, 1, (LPARAM) szInitialPathName); // Set initial folder
return 1;
}
return 0;
}
Set the BFFCALLBACK (lpfn) to a BrowseCallbackProc. From there you can call SendMessage with BFFM_SETEXPANDED to specify the path of a folder to expand in the Browse dialog box.
See:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb773205(v=vs.85).aspx and
http://msdn.microsoft.com/en-us/library/windows/desktop/bb762598(v=vs.85).aspx
From my experience, that folder dialog is a bit flaky - it often scrolls the desired directory out of view and looks suboptimal. Just one of the joys of Windows...
Also, there is no way I have discovered to get it to show only that directory and its subs. The parent directories always seem to be there.
Set BIF.PidlRoot to the PIDL you don't want the user to browse below, select and expand the folder you want initially focused and selected - do as above - and it should work.
Jens. :)

Getting Window info from its HWND

I have this code:
HWND WindowHandle;
WindowHandle = FindWindowA( WindowClass, WindowName );
if( WindowHandle != NULL)
{
// here I want to populate a listbox with the window's information like
// its process name and PID, executable file name, and its window title.
}
I already know how to get the Window Title, with SendMessage(); and WM_GETTEXT, but I want to know how to get it's process name and PID, and also the executable file location and name.
Could anyone help me?
Please note that I am working with C++ MFC.
Windows offers a function called GetWindowThreadProcessId.
It sounds like what you want.
Disclaimer: I haven't used it.
You can find the PID in PROCESS_INFORMATION. Just declare say: PROCESS_INFORMATION pi and access PID like this: pi.hProcesss pi.dwProcessId.

Reading from a text field in another application's window

Is there a way for a Windows application to access another applications data, more specifically a text input field in the GUI, and grab the text there for processing in our own application?
If it is possible, is there a way to "shield" your application to prevent it?
EDIT: The three first answers seem to be about getting the another applications window title, not a specific text input field in that window.
I'm no Windows API expert, so could you be more exact how do I find a certain text field in that window, what are the prerequisites for it (seems like knowing a window handle something is required, does it require knowing the text field handle as well? How do I get that? etc...)
Code snippets in C++ really would be really appreciated. MSDN help is hard to browse since Win32-API has such horrible naming conventions.
Completed! See my answer below for a how-to in C++.
For reading text content from another application's text box you will need to get that text box control's window handle somehow. Depending on how your application UI is designed (if it has a UI that is) there are a couple of different ways that you can use to get this handle. You might use "FindWindow"/"FindWindowEx" to locate your control or use "WindowFromPoint" if that makes sense. Either way, once you have the handle to the text control you can send a "WM_GETTEXT" message to it to retrieve its contents (assuming it is a standard text box control). Here's a concocted sample (sans error checks):
HWND hwnd = (HWND)0x00310E3A;
char szBuf[2048];
LONG lResult;
lResult = SendMessage( hwnd, WM_GETTEXT, sizeof( szBuf ) / sizeof( szBuf[0] ), (LPARAM)szBuf );
printf( "Copied %d characters. Contents: %s\n", lResult, szBuf );
I used "Spy++" to get the handle to a text box window that happened to be lying around.
As for protecting your own text boxes from being inspected like this, you could always sub-class your text box (see "SetWindowLong" with "GWL_WNDPROC" for the "nIndex" parameter) and do some special processing of the "WM_GETTEXT" message to ensure that only requests from the same process are serviced.
OK, I have somewhat figured this out.
The starting point is now knowing the window handle exactly, we only know partial window title, so first thing to do is find that main window:
...
EnumWindows((WNDENUMPROC)on_enumwindow_cb, 0);
...
which enumerates through all the windows on desktop. It makes a callback with each of these window handles:
BOOL CALLBACK on_enumwindow_cb(HWND hwndWindow, LPARAM lParam) {
TCHAR wsTitle[2048];
LRESULT result;
result = SendMessage(hwndWindow, WM_GETTEXT, (WPARAM) 2048, (LPARAM) wsTitle);
...
and by using the wsTitle and little regex magic, we can find the window we want.
By using the before mentioned Spy++ I could figure out the text edit field class name and use it to find wanted field in the hwndWindow:
hwndEdit = FindWindowEx(hwndWindow, NULL, L"RichEdit20W", NULL);
and then we can read the text from that field:
result = SendMessage(hwndEdit, WM_GETTEXT, (WPARAM) 4096, (LPARAM) wsText);
I hope this helps anyone fighting with the same problem!
Look at AutoHotkey. If you need an API for your application, look at their sources.
To prevent it, use a custom widget instead of WinForms, MFC or Win32 API. That is not foolproof, but helps.
Yes it is possible in many ways (one way is to use WINAPI GetWindow and GetWindowText).
First, get a handle to the textbox you want to retrieve text from (using FindWindow, EnumChildWindows and other APIs), then:
Old VB6-codeexample, declaration of API:
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Private Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Code to extract text:
Dim MyStr As String
MyStr = String(GetWindowTextLength(TextBoxHandle) + 1, Chr$(0))
GetWindowText TextBoxHandle, MyStr, Len(MyStr)
MsgBox MyStr
About how to shield the application to prevent it, you could do many things.
One way would be to have a own control to handle text input that build up the text from lets say a couple of labels placed where the text would be, or that draws the text graphically.
You can also get text from a richedit control with EM_GETTEXTRANGE message, but it works only in the same process in which the control was created.