Windows API MONITORINFO Structure - c++

I am trying to get monitor data from the windows API.
The GetSystemMetrics() command returns the wrong width in pixels.
According to Microsoft's website this is because I need to SetProcessDPIAware()
which means I should preferably be able to create an application manifest which I do not understand.
In searching for an equally low level alternative I found the multiple display monitors functions and structs. I must pass HMONITOR to access the rect structure I want but getting HMONITOR is where I am having issues.
MonitorFromWindow(hwnd,MONITOR_DEFAULTTOPRIMARY)
This command is out of scope- strange because GetMonitorInfo() [which I need HMONITOR for] doesn't cause any issues. I already have windows.h and windowsx.h included. Am I missing a library or what is the issue?
On a separate note, after looking there it became evident that it might also be nice to make the monitor used user-adjustable. SM_CMONITORS should return a count but I would like to know how to convert these numbers to the HMONITOR data I need to get monitor specific information.
::Edit::
I am putting the edit here because the "comment" feature does not provide me with enough space to place the code clip which was requested
Also, I am using GNU GCC with MinGW
#include <iostream>//using these libraries
#include <Windowsx.h>
#include <windows.h>
using namespace std;
int main()
{
//should print screen width in pixels
LPMONITORINFO target;
//create a monitor info struct to store the data to
HMONITOR Hmon = MonitorFromWindow(hwnd,MONITOR_DEFAULTTOPRIMARY);
//create a handle to the main monitor
//(should start at top left of screen with (0,0) as apposed to other monitors i believe)
//if i could gather aditional info on what monitors are available that might be useful
GetMonitorInfo(Hmon, target);
//Get the necessary data and store it to target
cout << "bottom of selected monitor in pixels: " << target->rcMonitor.bottom
<< "Top of the selected monitor" << target->rcMonitor.top
<< "right extreme of selected monitor" << target->rcMonitor.right
<< "left extreme of selected monitor" << target->rcMonitor.left;
return 0;
}

If you want to use features that appeared after Windows 95/Windows NT 4, you must specify the WINVER before compiling.
Windows 2000 is WINVER 0x0500, so the compile line needs to add -DWINVER=0x500 in order to see the MONITOR_DEFAULTTOPRIMARY constant.
You need to allocate a MONITORINFO struct, not a pointer to a MONITORINFO struct, and intialize the cbSize field so that Windows knows what information to populate, so in your code:
MONITORINFO target;
target.cbSize = sizeof(MONITORINFO);
HMONITOR hMon = MonitorFromWindow(GetDesktopWindow(), MONITOR_DEFAULTTOPRIMARY);
GetMonitorInfo(hMon, &target);
And then display using:
target.rcMonitor
instead of
target->rcMonitor
Using SetProcessDPIAware(), is a feature of Windows Vista, so WINVER needs to be set to 0x0600, but the headers shipped with MinGW don't appear to be a complete set of headers for Windows Vista - That function definition is missing, but is present in the Windows 7 SDK headers (I don't have the Windows Vista SDK at hand to check it on).
So, using a manifest seems like an easier solution than pulling the newer APIs.
Monitor handles are meant to be an opaque representation of a monitor - i.e. the value you get should not be used for anything other than other monitor functions. If you want to walk the monitor structures, you should use the EnumDisplayMonitors function, and an appropriate callback routine.

Related

How to set app icon for linux revisited and how does xfreerdp do it

I discovered that my appimag-ed application does not show any app icon in the window manager when launched, even though it has the icon inside itself. By the way, e.g., Obsidian app does suffer from this problem. In general, from searching on the Web, it looks like appimage fails with icons. Here e.g., a person also answers that appimage fails to provide app icons for a window manager: Electron Linux: .AppImage is not showing the icon, while .deb is. And also, when I load any app from https://appimage.github.io/apps/ -- at least on Fedora 33 and 35 -- I can see no app icons when launching them.
I tried to use workarounds like QMainWindow::setWindowIcon() or setting env variable XDG_DATA_DIRS, but it did not help -- these approaches can be found on appimage-related sites.
I discovered answers on SO like by these links:
Qt Creator - how to set application icon for ubuntu linux?
How do I give a C++ program an icon?
The idea of the answers is that you could not do such a thing and you have to install your .desktop file and icons to /usr/share via deb/rpm/etc. packages.
However, I discovered that it looks like xfreerdp carries its icon with it: I tried to change my system paths to icons (/usr/share/icons to /usr/share/icons_) temporarily and the xfreerdp's icon was still there in the window manager, while those of other apps grayed out. Also, I searched for .svg or .png icons of xfreerdp on the whole os and have not found anything.
So I an just curious how they can do it? I looked into its source code on Github, but could not understand. It's just an enigma for me really. Maybe, anybody has an idea how they do it or how this can be achieved at all?
Here is an incomplete answer, since it only cover the X11 case and does not describe how to translate from QT object to X11 handles. I don't even know if this method will solve your specific problem.
The idea is to talk directly with X server to set the window icon, here, using the XCB API (same thing can be achieved using Xlib).
The X server need the bitmap data to be provided as 32 bit ARGB format, with two 32 bit unsigned integers ahead for image width and height. In a visual way, this what X server wait for:
4 bytes 4 bytes 4 bytes 4 bytes 4 bytes
[ WIDTH ][ HEIGHT ][ ARGB ][ ARGB ][ ARGB ]...
Indeed, if you load image from common encoded image format like PNG, JPEG or other, you'll need to properly decode image data to RGB(A), then convert bitmap to the proper ARGB format...
Here is the function to set the icon of any X windows. The first parameter c is the handle to the X server connection, the second w the handle/identifier (actually it is a simple integer) to X window. The third parameter icon_data is the icon data buffer as described above and the last parameter icon_size is the size, in bytes, of the buffer pointed by icon_data.
setWindowIcon(xcb_connection_t* c, xcb_window_t w, uint32_t* icon_data, size_t icon_size)
{
// get the _NET_WM_ICON atom
xcb_intern_atom_reply_t* r;
r = xcb_intern_atom_reply(c, xcb_intern_atom(c,1,12,"_NET_WM_ICON"), 0);
xcb_atom_t _NET_WM_ICON = r->atom;
free(r);
// get the CARDINAL atom
r = xcb_intern_atom_reply(c, xcb_intern_atom(c,1,8,"CARDINAL"), 0);
xcb_atom_t CARDINAL = r->atom;
free(r);
// change window property
xcb_change_property(c, XCB_PROP_MODE_REPLACE, w, _NET_WM_ICON, CARDINAL, 32, icon_size, icon_data);
// make sure everything is done
free(xcb_get_input_focus_reply(c, xcb_get_input_focus(c), NULL));
}
As you can see, the main purpose of this code is to modify/set a specific window property identified by _NET_WM_ICON. You'll find some information about this X specific protocol and syntax here :
https://specifications.freedesktop.org/wm-spec/1.3/ar01s05.html
https://tronche.com/gui/x/xlib/window-information/properties-and-atoms.html
Notice that, I am not personally a great expert of X server protocols, I only digged some time ago this specific section for some low-level window management purpose.

Trying to understand process mitigation policies that can be set by SetProcessMitigationPolicy function

Sorry, if it's too broad of a question. I'm trying to see what exactly SetProcessMitigationPolicy function does in Windows 10, but I can't find much about it online (besides my previous forays into this subject.) I'm testing its PROCESS_MITIGATION_POLICY options one-by-one, and I have some questions about these:
ProcessSystemCallDisablePolicy states that it "Disables the ability to use NTUser/GDI functions at the lowest layer.". So I'm testing it as such:
PROCESS_MITIGATION_SYSTEM_CALL_DISABLE_POLICY pmscdp = {0};
pmscdp.DisallowWin32kSystemCalls = 1;
BOOL bR = ::SetProcessMitigationPolicy(ProcessSystemCallDisablePolicy, &pmscdp, sizeof(pmscdp));
int err = ::GetLastError();
::GdiFlush(); //Try to trip it here
But it always fails with error code 19, or ERROR_WRITE_PROTECT.
So what exactly is it supposed to do and how do I set it?
ProcessExtensionPointDisablePolicy states that it "... prevents legacy extension point DLLs from being loaded into the process."
PROCESS_MITIGATION_EXTENSION_POINT_DISABLE_POLICY pmepdp = {0};
pmepdp.DisableExtensionPoints = 1;
BOOL bR = ::SetProcessMitigationPolicy(ProcessExtensionPointDisablePolicy, &pmepdp, sizeof(pmepdp));
int err = ::GetLastError();
Sorry for my naivete, but what is the extension point DLL? And how can I test one?
ProcessSignaturePolicy states that it can "restrict image loading to those images that are either signed by Microsoft, by the Windows Store, or by Microsoft, the Windows Store and the Windows Hardware Quality Labs (WHQL)".
First off, it seems to have no effect on CreateProcess and only works with LoadLibrary-type functions. So if I do this:
PROCESS_MITIGATION_BINARY_SIGNATURE_POLICY pmbsp = {0};
pmbsp.MicrosoftSignedOnly = 1;
//pmbsp.StoreSignedOnly = 1; //always seems to fail with this flag
//pmbsp.MitigationOptIn = 1; //Doesn't seem to have any effect
BOOL bR = ::SetProcessMitigationPolicy(ProcessSignaturePolicy, &pmbsp, sizeof(pmbsp));
BOOL err = ::GetLastError();
And then try to load some of my test DLLs:
HMODULE hModDll = ::LoadLibrary(L".\\Dll1.dll");
The LoadLibrary function fails with the MessageBox that reads:
Bad Image
Dll-Name is either not designed to run on Windows or it
contains an error. Try installing the program again using the original
installation media or contact your system administrator or the
software vendor for support. Error status 0xc0000428.
Interestingly, if I call it on some System32 DLL that is not signed:
HMODULE hModDll = ::LoadLibrary(L"iologmsg.dll");
it seems to work fine. But if I place a copy of my test Dll1.dll into System32 folder and load it this way:
HMODULE hModDll = ::LoadLibrary(L"Dll1_.dll");
it still fails with the same message box:
This is interesting. How can it tell the difference between iologmsg.dll and Dll1_.dll? Both files aren't signed.
PS. And that modal message box can throw in a really nasty wrench into the mix if the app (or the service) does not expect any UI to be shown there.
ProcessFontDisablePolicy lastly, I'm totally lost about this one. It states that it "turns off the ability of the process to load non-system fonts."
So after I enable it in my MFC GUI app:
PROCESS_MITIGATION_FONT_DISABLE_POLICY pmfdp = {0};
pmfdp.DisableNonSystemFonts = 1;
BOOL bR = ::SetProcessMitigationPolicy(ProcessFontDisablePolicy, &pmfdp, sizeof(pmfdp));
int err = ::GetLastError();
the app has a Richedit control that I can load a custom font in. So I went online and downloaded a totally random font. Then installed it in Windows Explorer and tried to use it from the app after that policy has been enabled:
//Set format for the text window
CHARFORMAT cf = { 0 };
cf.cbSize = sizeof(cf);
cf.dwMask = CFM_FACE | CFM_SIZE;
cf.yHeight = 18 * 20;
VERIFY(SUCCEEDED(::StringCchCopy(cf.szFaceName, _countof(cf.szFaceName), L"Action Man")));
VERIFY(SetDefaultCharFormat(cf));
The app was able to display and use that (clearly non-system) font without any issues:
So what am I missing here in that policy?
This is guessing, but since many links in the function's documentation are 404s, I believe that the following would be valid:
1.Probably not implemented, yet.
2.Only a guess (since the link is also 404), but it might refer to DLLs used in obsolete situtations (like the XP and below login DLL, replaced in Vista with Credential Providers).
3.Windows DLLs are treated as signed (without actually having a digital signature attached), not only because they reside in System32, but because Windows keeps internally a map for them. For your DLLs, it won't work. Also, this has no point in CreateProcess() because the new process cannot interact with yours (without your knowledge) and, therefore, cannot hijack it, where a DLL loaded with LoadLibrary can do anything to ruin your process.
4.It probably refers to fonts not installed by Explorer, but fonts added with AddFontResource.

How can I change the "Dim the display" and "Dimming display brightness" setting (Windows) from wihin my application?

My application is already able to set the timeout when display should turn off, as well as setting the all over, and also to set the current brightness in general. Windows has an additional feature that dims the display after some time (the "Dim the display after" and "Display dimming brightness" in the advanced power scheme settings).
Does anybody knows how I can query/set the options "Dim display after" and "Display dimming brightness" settings from within my application (its a C/C++ application)- if possible by using "pure" Windows API?
Have much thanks in before.
Yours Willi K.
Ron pointed me in the right direction. Following code expample shows, how an application can control when the backlight should dim to a specific brightness level (error checking etc. has been omitted in order to make code more easy to understand).
#include <iniitguid.h> // Seems to be uncluded before Windows.h for some reason...
#include <windows.h>
#include <powrprof.h>
static const GUID GuidPwrVideoIf = GUID_VIDEO_SUBGROUP;
static const GUID GuidPwrDimTimeout = GUID_VIDEO_DIM_TIMEOUT;
static const GUID GuidPwrDimBrightness = GUID_DEVICE_POWER_POLICY_VIDEO_DIM_BRIGHTNESS;
void setBacklightDimming(DWORD timeOut, DWORD dimmedBrightness)
{
DWORD ret;
GUID *pGuidPwrActiveSheme;
// Attach to the active power scheme
ret = PowerGetActiveScheme(NULL, &pGuidPwrActiveSheme);
// Set the timeout that will elapse before the display will dim
ret = PowerWriteDCValueIndex(NULL, pGuidPwrActiveSheme, &GuidPwrVideoIf, &GuidPwrDimTimeout, timeOut);
// Set the dimmed brightness level
PowerWriteDCValueIndex(NULL, pGuidPwrActiveSheme, &GuidPwrVideoIf, &GuidPwrDimBrightness, dimmedBrightness);
// Apply the new setings immediately
retVal = PowerSetActiveScheme(NULL, pGuidPwrActiveSheme);
// Go on with whatever you want to do...
}
This code sample changes the settings when the system is "On battary" (e.g. a laptop). To set the settings when the system is "On AC power", simply replace PowerWriteDCValueIndex() by PowerWriteACValueIndex().

Sending Keystrokes to a X Window

I am currently experimenting with xdotool to send keys to a process (I understand that it may not work for all processes that does not set _NET_WM_PID). I have trouble sending keystrokes to windows other from the focus. It does work if you are sending keystrokes to the CURRENTWINDOW. Below is the snippet that I used to test xdotool's functionality.
extern "C"{
#include <xdo.h>
}
//extern "C" xdo_window_search
#include <iostream>
#include <string.h>
using namespace std;
int main(){
xdo_t* p_xdo = xdo_new(NULL);
// Allocate memory for search query.
xdo_search_t s;
// Clear the allocated memory.
memset(&s, 0, sizeof(xdo_search_t));
// Set the search query.
s.pid = 1916;
s.max_depth = -1;
s.searchmask = SEARCH_PID;
s.require = xdo_search::SEARCH_ANY;
// Allocate memory for output
Window* windows;
int no_windows;
xdo_window_search(p_xdo,&s,&windows,&no_windows);
cout << no_windows << endl;
// Prints all windows' names with matching criteria
for( int i=0;i<no_windows;i++ ){
unsigned char * name;
int size;
int type;
xdo_get_window_name(p_xdo,windows[i],&name,&size,&type);
cout << i << ":" << name << endl;
}
for( int i=0;i<no_windows;i++ ){
xdo_type(p_xdo,windows[i],"Hello World",0);
}
//xdo_type(p_xdo,CURRENTWINDOW,"Hello World",0); // This does work.
return 0;
}
In additional to testing xdotool's functionality, I've looked into xdotool's source code. Interestingly, I found that they are using Xtest to send keystrokes to the focused window (CURRENTWINDOW) and X11's XSendEvent for other windows. I turned to xdotool because I couldn't get XSendEvent to work and Xtest cannot send keys to any other windows than the focused window.
Am I not using the xdotool correctly? Does xdotool not work with all *nix OS with X11?
[I am running this on Ubuntu 13.04.]
EDIT
So, it looks like that does work but not for all windows that it finds. For example, it works for firefox but not gedit and gnome-terminal although it found gedit and gnome-terminal by its pid. It behaves differently if I used CURRENTWINDOW.
So, it would be great if someone can explain why is this so. Like, is it related the force send flag in an XEvent?
Directly from the xdotool manual:
SENDEVENT NOTES
If you are trying to send key input to a specific window, and it does
not appear to be working, then it's likely your application is ignoring
the events xdotool is generating. This is fairly common.
Sending keystrokes to a specific window uses a different API than
simply typing to the active window. If you specify 'xdotool type
--window 12345 hello' xdotool will generate key events and send them
directly to window 12345. However, X11 servers will set a special flag
on all events generated in this way (see XEvent.xany.send_event in
X11's manual). Many programs observe this flag and reject these events.
It is important to note that for key and mouse events, we only use
XSendEvent when a specific window is targeted. Otherwise, we use XTEST.
Some programs can be configured to accept events even if they are
generated by xdotool. Seek the documentation of your application for
help.
Specific application notes (from the author's testing): * Firefox 3
seems to ignore all input when it does not have focus. * xterm can be
configured while running with ctrl+leftclick, 'Allow SendEvents' *
gnome-terminal appears to accept generated input by default.

C++ Finding out what resolutions are supported by the graphics card

I am writing a small program to let me switch my resolution back and forth because my projector cannot handle the same resolution as my screen. I already know how to set the screen resolution using the windows API. As well as read the current resolution using the windows API or the QT4 toolkit. My problem is I want a menu of all of the different resolutions supported by the screen and graphics card. This program will be distributed so I need the program to actually communicate to the graphics card to find out what it supports. The only API I want to use is the windows API, or the QT4 toolkit, but I don't think QT4 does that unless you are using the graphics widgets in odd ways.
I am pretty sure this is possible with the WINDOWS API. I just don't know how to do it.
Oh and please cut me some slack, I am familiar with QT4 and C++ but I am typically a Linux programmer, I am writing this for someone else. The only thing I have ever done with the windows API is make a message box, set the background, and used system variables. So please explain the process simply. Please don't just post a link to the msdn, I hate their documentation, and I hate Microsoft. I use windows maybe twice a year.
The following should probably work for you in the general case
DEVMODE dm = { 0 };
dm.dmSize = sizeof(dm);
for( int iModeNum = 0; EnumDisplaySettings( NULL, iModeNum, &dm ) != 0; iModeNum++ ) {
cout << "Mode #" << iModeNum << " = " << dm.dmPelsWidth << "x" << dm.dmPelsHeight << endl;
}
This should print out all the supported resolutions on the current display that the .exe is running on. Assuming you're not dealing with a multi-display graphics card this should work. Otherwise you'd have to use EnumDisplayDevices loop over each display.
Once you figure out what resolution you want you can use 'ChangeDisplaySettingsEx' to change the display to the mode you want.
Using DirectX is possible but I wouldn't recommend it as the code is alot more complicated (having to initialize DirectX and using COM pointers) unless you plan to actually use DirectX for more than just determining display resolutions.
EnumDisplaySettings :)
From MSDN:
"To obtain the current display settings, pass the ENUM_CURRENT_SETTINGS constant in the iModeNum parameter to the EnumDisplaySettings API, as illustrated by the following C++ code."
DEVMODE dm;
// initialize the DEVMODE structure
ZeroMemory(&dm, sizeof(dm));
dm.dmSize = sizeof(dm);
if (0 != EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
{
// inspect the DEVMODE structure to obtain details
// about the display settings such as
// - Orientation
// - Width and Height
// - Frequency
// - etc.
}