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

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

Related

How to disable a secondary monitor (with ChangeDisplaySettingsEx)?

I'm trying to follow the instructions on MSDN given here to disable a secondary monitor.
I'm trying to use specifically this set of functions to allow compatibility with older versions of Windows.
However, I can't manage to disable a monitor. I'm running and testing this on Windows 7 x64.
All I get is a flickering screen. The code definitely detects the monitor properly - I managed to change resolution and view it's display modes easily.
Here are (parts) of my code - I tried a lot of variations on the fields for DEVMODE
DEVMODE deleteScreenMode;
ZeroMemory(&deleteScreenMode, sizeof(DEVMODE));
deleteScreenMode.dmSize = sizeof(DEVMODE);
deleteScreenMode.dmDriverExtra = 0;
deleteScreenMode.dmFields = DM_POSITION | DM_PELSHEIGHT | DM_PELSWIDTH;
deleteScreenMode.dmPelsWidth = 0;
deleteScreenMode.dmPelsHeight = 0;
POINTL delete;
deleteion.x=0;
deleteion.y=0;
deleteScreenMode.dmPosition = deleteion;
LONG result = ChangeDisplaySettingsEx(devName,
&deleteScreenMode,
NULL,
CDS_UPDATEREGISTRY,
NULL);
Does anyone have experience with this? Thanks
I've decided to advance into a different problem - setting a primary display - and by pure luck I've stumbled into the solution.
There are 2 conditions to disable a monitor that aren't specified anywhere:
1) You can't disable the monitor dynamically - you must use CDS_UPDATEREGISTRY to write it into the registry.
2) More importantly, for some weird reason, you must first store the change in the registry (with or without CDS_NORESET, it doesn't matter), and then use again ChangeDisplaySettingsEx with NULL values to make the changes happen. This might have something to do both monitors connected to the same display device, I'm not sure...
Anyway here is the code that worked for me:
result = ChangeDisplaySettingsEx(devName, &deleteScreenMode,
NULL,
CDS_UPDATEREGISTRY | CDS_NORESET ,
NULL);
ChangeDisplaySettingsEx (NULL, NULL, NULL, NULL, NULL);
Hope it'll help someone somewhere someday.
A similar solution is hinted at here:
http://support.microsoft.com/kb/308216
This works for attaching screens. However, even armed with that knowledge, the ChangeDisplaySettingsEx documentation on how to detach a screen is also wrong about the DevMode fields that need to be set. As you noticed, you have to set not only DM_POSITION, but also DM_PELSHEIGHT | DM_PELSWIDTH.
In Windows 7 there's a new SetDisplayConfig API, but I have no personal experience with it yet. Hopefully it's better documented!

Windows API MONITORINFO Structure

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.

Keyboard / Mouse input in C++

I'm wondering how to accept keyboard and mouse input in C++, using Visual Studio 2010, for Windows 7 32-bit.
--EDIT: I forgot to mention that I need keyboard / mouse input without interrupting the flow of the program. Something like a listener. I don't want to have to pause the program and ask for input, and then have the user type it out and press enter. What I'm looking for is more like:
If user presses W, S, A, D -> something happens.
Or: If user presses leftmousebutton in -> something happens.
I have to mention that I'm still very new to programming as a whole. I know basic OOP programming but that's about it. I'm definitely sure that this will involve things I don't know about yet, and I don't mind, I just ask that you explain it thoroughly, and possibly give an example so I know how to use it.
Thanks.
keyboard / mouse input without interrupting the flow
#include <windows.h>
#include <iostream>
using namespace std;
int main()
{
HANDLE hIn;
HANDLE hOut;
COORD KeyWhere;
COORD MouseWhere;
COORD EndWhere;
bool Continue = TRUE;
int KeyEvents = 0;
int MouseEvents = 0;
INPUT_RECORD InRec;
DWORD NumRead;
hIn = GetStdHandle(STD_INPUT_HANDLE);
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
cout << "Key Events : " << endl;
cout << "Mouse Events : " << flush;
KeyWhere.X = 15;
KeyWhere.Y = 0;
MouseWhere.X = 15;
MouseWhere.Y = 1;
EndWhere.X = 0;
EndWhere.Y = 3;
while (Continue)
{
ReadConsoleInput(hIn,
&InRec,
1,
&NumRead);
switch (InRec.EventType)
{
case KEY_EVENT:
++KeyEvents;
SetConsoleCursorPosition(hOut,
KeyWhere);
cout << KeyEvents << flush;
if (InRec.Event.KeyEvent.uChar.AsciiChar == 'x')
{
SetConsoleCursorPosition(hOut,
EndWhere);
cout << "Exiting..." << endl;
Continue = FALSE;
}
break;
case MOUSE_EVENT:
++MouseEvents;
SetConsoleCursorPosition(hOut,
MouseWhere);
cout << MouseEvents << flush;
break;
}
}
return 0;
}
There are a number of related concepts behind this.
At the very low level, the keyboard and the mouse are hardware devices that generates some "interrupts" (in the form of electric signals) to the CPU.
The operating system provides some drivers that handle such interrupts by decoding the device communication specific protocol, and "standardizing" (at OS level) those signals in the form of events.
With "console applications", the operating system handles those events (the keyboard in particular) by filling up an input buffer (essentially a char[]) that is made accessible as a "virtually infinite sequence of characters" (complicated name for "file") named "CON", thus mimicking the "infinite teletype model" of the early days computers.
In a C++ program, the standard library -at program startup- associates to that "file" the std::cin and std::cout stream objects, so you can read the input character sequence using the std::istream functions and operators.
With "graphical applications", unfortunately, there is no "early days model" to mimic, and "events" are left available as the operating system native structure.
Different operating system differs in the way such events are represented and handled, but certain similitude can be seen.
For Windows (since your question is about), a typical program retrieves those events in sequence with a "message loop" in which calling certain OS APIs.
In that loop, the typical program will also give call another OS API to dispatch those event to appropriate "call-back" procedure, associated to a previously created "window".
That callback procedure has to detect the event code, cast the parameter as appropriate and manage them doing the action required.
A more precise detail can be seen with a WIN32 programming tutorial like http://www.winprog.org/tutorial/.
The most of the code is essentially C, since C is the language the API are formalized.
For C++, a number of libraries have then been written to represent OS objects is the form of C++ classes, and mapping the OS APIs to those classes members.
These libraries can be either OS specific (like MFC, WTL ...) or "multi-platform" (they exist in different version, mapping the API of various OSs into a same C++ interface) like WxWidget, Qt, Gtk, Fltk ...
Hope this can give you more hints to think about.
If you're writing a console application, you can use scanf or cin to get keyboard input. Console applications don't have any support for the mouse.
If you're writing a GUI application, you'll build the app out of standard windows controls that have built-in behaviors for mouse and keyboard input. You can use these re-usable controls as is, or you can augment them to make them behave exactly how you want for your application.
For example, in a GUI application, there's a standard edit control you can use that the user can type into. Your program receives messages when the user enters text into it, and based on those messages, or on other events, you can retrieve the text and do things with it as required by your program.
Windows or Console?
If console, use:
std::cin >> myVar;

Virtual Webcam Driver

I want to develop a virtual webcam driver which from User mode I'll pass image to it and it will display as webcam output.
I don't want to use DirectX filter and CSourceStream etc. Because they don't work on some programs which doesn't use DirectX for capturing webcam image.
I have to write a kernel mode device driver so.
Any ideas? I tried testcap from DDK samples, but it doesn't process image from user mode and doesn't get any input, just it displays 7 colors in webcam...
Any help would be greatly appreciated.
Thanks
Thank you all!
I tried code from here:
http://tmhare.mvps.org/downloads.htm (find Capture Source Filter)
It worked well when I compiled it in Yahoo, MSN, but it crashed AIM, Internet Explorer Flash Webcam, Firefox Flash webcam and Skype... I got crash in QueryInterface after 8 time call to that, I found it with tracing it with a lot of tricks..
Now I know, it crashes on 8th call to
HRESULT CVCamStream::QueryInterface(REFIID riid, void **ppv)
8th call when it reaches to last if, I mean:
return CSourceStream::QueryInterface(riid, ppv);
It's in 17th line of Filters.cpp
Why do you think I'm getting crash??
Thank you all for guiding me to find correct solution which is DirectShow, not driver
There are several APIs from Microsoft which provide access to image data.
Twain: Used for single image capture from scanners, etc.
WIA: This seems to have degenerated to a single image codec library.
VfW: A very old (Win16) API which really works only Video-File encoding/decoding, but has support for some video acquisition.
DirectShow: previously part in the DirectX SDK, currently in the Platform SDK. This is the place to go for current (general) streaming solutions.
Windows Media/Media Foundation: This seems more to be geared at video playback/reencoding.
Manufacturer Specific Libraries: Pylon/Halcon/Imaging Control/...
DirectShow specific :
To create image acquisition devices under windows, you have to provide either a device (driver) which implements the streamclasses interfaces (or newer Avstream) or you have to write a usermode COM object which has to be added to the VideoInputCategory enumerator.
The Avstream sample provides everything for a real image acquisition device. Only the lower layer for the actual device really is missing.
If you can design a device, you should either create it DCAM or UVC compatible. For both there are built-in drivers supplied by windows.
How to write a software source device :
You have to create a DirectShow filter which provides at least one output pin and register this under the VideoInputCategory. There may be several interfaces certain applications require from a capture application, but these depend on the application itself. Simple applications to try out filters are GraphEdit and AMCap which are supplied in the Plattform SDK.
Some code :
#include <InitGuid.h>
#include <streams.h>
const AMOVIESETUP_MEDIATYPE s_VideoPinType =
{
&MEDIATYPE_Video, // Major type
&MEDIATYPE_NULL // Minor type
};
const AMOVIESETUP_PIN s_VideoOutputPin =
{
L"Output", // Pin string name
FALSE, // Is it rendered
TRUE, // Is it an output
FALSE, // Can we have none
FALSE, // Can we have many
&CLSID_NULL, // Connects to filter
NULL, // Connects to pin
1, // Number of types
&s_VideoPinType // Pin details
};
const AMOVIESETUP_FILTER s_Filter =
{
&CLSID_MyFilter, // Filter CLSID
L"bla", // String name
MERIT_DO_NOT_USE, // Filter merit
1, // Number pins
&s_VideoOutputPin // Pin details
};
REGFILTER2 rf2;
rf2.dwVersion = 1;
rf2.dwMerit = MERIT_DO_NOT_USE;
rf2.cPins = 1;
rf2.rgPins = s_Filter.lpPin;
HRESULT hr = pFilterMapper->RegisterFilter( CLSID_MyFilter, _FriendlyName.c_str(), 0,
&CLSID_VideoInputDeviceCategory, _InstanceID.c_str(), &rf2 );
if( FAILED( hr ) )
{
return false;
}
std::wstring inputCat = GUIDToWString( CLSID_VideoInputDeviceCategory );
std::wstring regPath = L"CLSID\\" + inputCat + L"\\Instance";
win32_utils::CRegKey hKeyInstancesDir;
LONG rval = openKey( HKEY_CLASSES_ROOT, regPath, KEY_WRITE, hKeyInstancesDir );
if( rval == ERROR_SUCCESS )
{
win32_utils::CRegKey hKeyInstance;
rval = createKey( hKeyInstancesDir, _InstanceID, KEY_WRITE, hKeyInstance );
....
_InstanceID is a GUID created for this 'virtual device' entry.
You can not decide how other program would call your driver. Most of programs will use DirectShow. Some would use the win3.x technology VFW. Many new programs, including Windows XP's scanner and camera wizard, may call you via the WIA interface. If you do not want to implement all that, you need to at least provide the DirectShow interface via WDM and let vfwwdm32.dll gives you a VFW interface, or write your own VFW driver.

How to programmatically get the resolution of a window and that of the system in Linux?

I'm trying to get the resolution of the screen as well as the resolution of a specific window (in which a program is running) on Linux system. I don't need to modify the resolution, I only need the current values. As far as I know, we can call some system functions to do so on Windows, how can we do that on Linux, preferably using C/C++ language? Thanks in advance.
update: Actually, I don't need to do a GUI, although I know Qt and GTK+ can do it, I'm reluctant to include an external library for just getting the resolution.
To get screen resolution, you can use XRandR extension, like in xrandr sources:
SizeID current_size;
XRRScreenSize *sizes;
dpy = XOpenDisplay (display_name);
// ...
root = RootWindow (dpy, screen);
sc = XRRGetScreenInfo (dpy, root);
current_size = XRRConfigCurrentConfiguration (sc, &current_rotation);
sizes = XRRConfigSizes(sc, &nsize);
for (i = 0; i < nsize; i++) {
printf ("%c%-2d %5d x %-5d (%4dmm x%4dmm )",
i == current_size ? '*' : ' ',
i, sizes[i].width, sizes[i].height,
sizes[i].mwidth, sizes[i].mheight);
// ...
}
You can see the output typing "xrandr" in your xterm.
Or, better, use the xdpyinfo method:
Display *dpy;
// dpy = ...
int scr = /* ... */
printf (" dimensions: %dx%d pixels (%dx%d millimeters)\n",
DisplayWidth (dpy, scr), DisplayHeight (dpy, scr),
DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
In X11, you'd need to call the Xlib's XGetWindowAttributes to get the various window info, including the size and position relative to parent. For an example of how it is used, you can google for 'xwininfo.c'.
That said, probably you are going to use some more highlevel framework to do your window programming - and the chances are high that it already has some other primitives for this, see an example for Qt - so you might want to give a bit more background about the question.
Depends:
If you're hardcore and you want to use Xlib, have a look at XDisplayWidth() and XDisplayHeight().
If you use Qt4 (my preference), try QApplication::desktop()->screenGeometry() (see http://doc.qt.digia.com/4.0/qdesktopwidget.html )
Or in Gtk, see http://library.gnome.org/devel/gdk/stable/GdkScreen.html
The command line tool xdpyinfo provides this information for you; to do it programmatically you need to to use Xlib, as Andrew Y explains.