Drawing on the Desktop Background (WIN32) - c++

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.

Related

How do I display a C++/WinRT FileOpenPicker from an exe without a console or window?

From a C++ executable on windows, I want to display a FileOpenPicker.
To do this, I need a window to set as the object's owner:
https://learn.microsoft.com/en-us/windows/apps/develop/ui-input/display-ui-objects#winui-3-with-c
But where do I get the HWND from? I need to call Initialize, but the docs assume you have a hWnd already:
folderPicker.as<::IInitializeWithWindow>()->Initialize(hWnd);
My process does not always have a console window, so ::GetConsoleWindow() will not work.
Here's what I have so far by attempting to use CreateWindow. Nothing happens.
// clang-format off
#include <ShObjIdl.h>
#include <Windows.h>
// clang-format on
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Storage.Pickers.h>
#include <iostream>
#include <string>
#include <string_view>
#include <system_error>
LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_DESTROY:
::PostQuitMessage(0);
return 0;
}
return ::DefWindowProc(hWnd, msg, wParam, lParam);
}
int main() {
try {
winrt::init_apartment();
winrt::Windows::Storage::Pickers::FileOpenPicker openPicker;
WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
L"ImGui Example", NULL};
::RegisterClassEx(&wc);
HWND hwnd = ::CreateWindow(
wc.lpszClassName, L"Dear ImGui DirectX10 Example", WS_OVERLAPPEDWINDOW,
100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL);
if (!hwnd) {
std::cerr
<< std::error_code(::GetLastError(), std::system_category()).message()
<< "\n";
return 1;
}
openPicker.as<::IInitializeWithWindow>()->Initialize(hwnd);
openPicker.SuggestedStartLocation(
winrt::Windows::Storage::Pickers::PickerLocationId::Desktop);
openPicker.FileTypeFilter().Append(L"*");
openPicker.FileTypeFilter().Append(L".jpeg");
openPicker.FileTypeFilter().Append(L".png");
auto file = openPicker.PickSingleFileAsync().get();
std::string str = winrt::to_string(file.Path());
std::cout << "name: " << str << "\n";
return 0;
} catch (std::exception& e) {
std::cerr << "error: " << e.what() << "\n";
return 1;
}
}
This question appears to be asking a similar thing, but OP solved it with ::GetConsoleWindow(), which is not an option.
Based on empirical evidence, IInitializeWithWindow::Initialize() is happy with just about any top-level window handle. A window handle associated with a process running in the CONSOLE subsystem is commonly available through the GetConsoleWindow API:
openPicker.as<::IInitializeWithWindow>()->Initialize(::GetConsoleWindow());
This produces the desired behavior1 when using the standard command prompt (hosted by ConHost.exe). Launching the same program from a process using a pseudoconsole instead (such as Windows Terminal) things start to get flaky: The FilePicker does show up, but it no longer follows the rules of owned windows. It's hiding behind the host process' window, and doesn't move to the foreground, when the (not actually an) owner is activated.
Whether this is how things should work, or are designed to work, or if any of this is within specification is unclear. None of this is documented, which seems to be the most convenient way to ship interfaces these days.
The fact that FileOpenPicker isn't documented to implement IInitializeWithWindow doesn't exactly help, either. All hail to cloaked interfaces of which there is only anecdotal evidence.
Ranting aside, you'll probably want to use std::wcout in place of std::cout. Otherwise you'll see an address printed rather than a string.
1 Just because you can doesn't necessarily mean you should create a window hierarchy across threads.

How to get the content of an edit box of another process in Windows?

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.

How do I add vertical scrollbar to a fullscreen win32 console?

When I set my win32 console to full screen, the vertical scrollbar disappears. When the text goes to the bottom of the screen, it does not scroll up. Newly written output is not presented to the user because it is below.
This is the style:
if (isFullScreen)
{
// Set the full screen window style.
style = GetWindowLong(handle, GWL_STYLE);
style &= ~(WS_BORDER | WS_CAPTION | WS_THICKFRAME | WS_OVERLAPPEDWINDOW);
SetWindowLong(handle, GWL_STYLE, style);
// Minimalize, then show maximized to avoid the cursor blink bug in conhost.exe.
ShowWindow(handle, SW_MINIMIZE);
ShowWindow(handle, SW_SHOWMAXIMIZED);
// Set the font size
setFontSize(fontSize);
}
I searched the web but it's understandably not common.
How can I add the vertical scrollbar to this while in full screen?
On my computer, I can realize the appearance of full screen console and vertical scrollbar. My system is Win10, using vs2017.
This is my code.
#include "pch.h"
#include <iostream>
#include <Windows.h>
void full_screen()
{
HWND hwnd = GetForegroundWindow();
int cx = GetSystemMetrics(SM_CXSCREEN); /* Screen width pixels */
int cy = GetSystemMetrics(SM_CYSCREEN); /* Screen Height Pixel */
LONG l_WinStyle = GetWindowLong(hwnd, GWL_STYLE); /* Get window information */
/* Set window information to maximize the removal of title bar and border*/
SetWindowLong(hwnd, GWL_STYLE, (l_WinStyle | WS_POPUP | WS_MAXIMIZE) & ~WS_CAPTION & ~WS_THICKFRAME & ~WS_BORDER);
SetWindowPos(hwnd, HWND_TOP, 0, 0, cx, cy, 0);
}
int main()
{
full_screen();
while(1)
{
std::cout << "Hello World!\n";
}
return 0;
}
Debug Result:
The official way to set a console to fullscreen is to call SetConsoleDisplayMode().
Under Windows 10 Pro Version 1803 the following code shows a vertical scrollbar without further ado:
#include <iostream>
#include <windows.h>
int main()
{
HANDLE const hConsole = ::GetStdHandle( STD_OUTPUT_HANDLE );
if( hConsole == INVALID_HANDLE_VALUE ||
! ::SetConsoleDisplayMode( hConsole, CONSOLE_FULLSCREEN_MODE, nullptr ) )
{
DWORD const err = ::GetLastError();
std::cerr << "Failed to set console fullscreen mode. System error: " << err << "\n";
return 1;
}
for( int i = 0; i < 200; ++i )
{
std::cout << "Hello World!\n";
}
return 0;
}
Note that SetConsoleDisplayMode() can fail if the process is not attached to a console (e. g. by passing the flag CREATE_NO_WINDOW to CreateProcess()) or if STDOUT is redirected to a file.

How to find jump lists window?

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++.

How can I skip hidden windows when using FindWindow()?

I create a window without showing it:
int main()
{
CreateWindow("SysListView32","Geek",0, 0, 0, 0, 0,NULL, NULL, (HINSTANCE)GetCurrentProcess(), NULL);
getch();
}
...and in another process use FindWindow() to find its handle:
int main()
{
HWND H = FindWindow("SysListView32", "Geek");
std::cout<< "The handle of created window is : " <<H;
getch();
}
How is FindWindow finding its handle? I assumed it would not find it, because process1 is not showing the window.
How can I find only visible windows?
Even if a window is not visible, it is of course in the list of all existing windows that FindWindow enumerates (you can display this list using Spy++ for example). If you do not want to search for hidden windows, you have to check their flags:
HWND H = FindWindow("SysListView32", "Geek");
if (H) {
LONG style = GetWindowLong(H, GWL_STYLE);
if (style & WS_VISIBLE)
std::cout << "The handle of created visible window is : " << H << std::endl;
else
std::cout << "The handle of created hidden window is : " << H << std::endl;
} else {
std::cout << "No such window found" << std::endl;
}
FindWindow finds top-level windows.
While your CreateWindow call is creating a top-level window (i.e. one with no parent) I'm not convinced it will actually work.
It's certainly very unusual (if not wrong) to create a top-level SysListView32. ListView controls should be the children of top-level windows, not top-level windows in their own right.