http://asawicki.info/ Programming, graphics, games, media, C++, Windows, Internet and more...
.net algorithms c++ competitions compo demoscene directx engine events flash fractals gallery games ggj gpu graphics gui hardware homepage humor ideas igk java libraries life linux literature math mobile music networking origami philosophy politics productions psytrance redmond rendering scripts shopping software software engineering stl studies teaching tools video visual studio warsztat web webdev winapi windows
How to change display mode using WinAPI?
If you write a graphics application or a game, you may want to make it fullscreen and set specific screen resolution. In DirectX there are functions for that, but if you use OpenGL or Vulkan, you need another way to accomplish that. I've researched the topic recently and I've found that Windows API supports enumerating display devices and modes with functions:
EnumDisplaySettings, as well as changing mode with function
ChangeDisplaySettingsEx. It's a programatic access to more or less the same set of features that you can access manually by going to "Display settings" system window.
I've prepared an example C program demonstrating how to use these functions:
First you may want to enumerate available Adapters. To do this, call function
EnumDisplayDevices multiple times. Pass
NULL as first parameter (
LPCWSTR lpDevice). As the second parameter pass subsequent
DWORD Adapter index, starting from 0. Enumeration should continue as long as the function returns
BOOL nonzero. When it returns zero, it means there are no more Adapters and that Adapter with given index and any higher index could not be retrieved.
For each successfully retrieved Adapter,
DISPLAY_DEVICE structure is filled by the function. It contains following members:
WCHAR DeviceName- string with name of the Adapter, like "\\.\DISPLAY1".
WCHAR DeviceString- string with more user-friendly name of the Adapter, like "AMD Radeon (TM) RX 480".
DWORD StateFlags- various flags, like
DISPLAY_DEVICE_ACTIVEif the device is on, or
DISPLAY_DEVICE_PRIMARY_DEVICEif this is the primary device.
There is a second level: Adapters contain Display Devices. To enumerate them, use the same function
EnumDisplayDevices, but this time pass Adapter
DeviceName as first parameter. This way you will enumerate Display Devices inside that Adapter, described by the same structure
DISPLAY_DEVICE. For example, my system returns
DeviceName = "\\.\DISPLAY1\Monitor0",
DeviceString = "Generic PnP Monitor".
The meaning and the difference between "Adapter" and "Display Device" is not fully clear to me. You may think that Adapter is a single GPU (graphics card), but it turns out not to be the case. I have a single graphics card and yet my system reports 6 Adapters, each having 0 or 1 Display Device. That can mean Adapter is more like a single monitor output (e.g. HDMI, DisplayPort, VGA) on the graphics card. This seems true unless you have two monitors running in "Duplicate" mode - then two Display Devices are reported inside one Adapter.
Then there is a list of supported Display Settings (or Modes). You can enumerate them in similar fashion using
EnumDisplaySettings function, which fills
DEVMODE structure. It seems that Modes belong to an Adapter, not a Display Device, so as first parameter to this function you must to pass
DISPLAY_DEVICE::DeviceName returned by
EnumDisplayDevices(NULL, ...), not
EnumDisplaySettings(adapter.DeviceName, ...). The structure is quite complex, but the function fills only following members:
DWORD dmPelsWidth, dmPelsHeight- resolution, in pixels.
DWORD dmBitsPerPel- bits per pixel (all Modes have 32 in my case).
DWORD dmDisplayFrequency- refresh rate, in Hz.
DWORD dmDisplayFlags- additional flags, like
DM_INTERLACEDfor interlaced mode.
I have a single graphics card (AMD Radeon RX 480) with two Full HD (1920 x 1080) monitors connected. You can see example output of the program from my system here: ExampleOutput.txt.
To change display mode, use function
LPCTSTR lpszDeviceName), pass
DeviceNameof the chosen Adapter (again, not Display Device!).
DEVMODE *lpDevMode), pass structure filled with desired Display Settings. You can fill it by yourself, but Microsoft recommends to pass the copy of the structure as it was retrieved from function
DWORD dwFlags), you can pass various flags, e.g. whether new settings should be saved in the registry.
The function returns
DISP_CHANGE_SUCCESSFUL if display mode was successfully changed and one of other
DISP_CHANGE_* constants if it failed.
To restore original display mode, call the function like this:
ChangeDisplaySettingsEx(targetDeviceName, NULL, NULL, 0, NULL);
Unfortunately, display mode changed in the way described here is not automatically restored after user switches to some other application (e.g. using Alt+Tab), like in DirectX fullscreen mode, but you can handle it yourself. Good news is that if you pass
CDS_FULLSCREEN flag to
ChangeDisplaySettingsEx, the previous mode is automatically restored by the system when your application exits or crashes.
First Time on GDC
I came back from my first GDC. I've been dreaming about going there since my university years. My first impression? It's huge! It runs for so many days (Monday to Friday). There are so many talks, more than a dozen at same time, that you really need to choose carefully what is most interesting to you (and stand in a queue before the room, because if you come too late and the talk is very popular, there may be no free seats left).
As the world's largest event of this kind in the industry, it attracts best professionals and offers quality talks. This time there were sponsored talks from Amazon (about their engine Lumberyard), Facebook, Khronos, Google, NVIDIA, Unity, Intel, Microsoft, Oculus, AMD, Epic, ARM, Sony and others - basically every big company that deals with graphics, plus many other talks presented by individual developers. I was interested mostly in graphics programming, but of course there were many other topics covered, like artistic or business aspect of game development.
Expo was also big, with over 100 companies presenting their products, services and technologies. Big difference from Polish Pozna˝ Game Arena is that GDC is targeted to professionals only, which means there aren't such big crowds of people standing in long queues to be able to play any game. I've never played so much VR as on this expo :)
There were other attractions too, like indie game developers presenting their productions or retro zone with working computers from previous decades. So many things to do there! In addition to that, I've met many friends there, who either live in US or came from Poland just like me.
Entrance fee is high, with pass for main conference starting at $1000 up to $2400 (on-site for all access), aside from plane ticket to San Franscisco and hotel there, so it's hard to go there on your own, unless your company pays for it. But if only you have the opportunity, I think GDC is definitely worth visiting.
By the way, gamedev conferences planned for this year in Poland are:
I hope to visit them all :)
Gallery of my photos (mostly from San Francisco):
How to download videos from YouTube and other sites in Full HD (1080p)?
If you, just like me, don't like to rely on data stored in the "cloud" (i.e. someone else's computer) and prefer to have it available offline on your hard drive, you probably tried to find a way to download video and music from YouTube and other similar services. There are web pages for that, but they are full of ads, malware and fake "Download" buttons. That's why my favorite way is to use youtube-dl. It works perfectly, is constantly updated and maintained, is open source and supports downloading from almost 1000 (!) different websites, including YouTube, Vimeo, Facebook videos, Soundcloud, Mixcloud and even XXX websites. The only drawback: it's a command line program, so you have to download it and then run it from console with correct parameters. But it's actually quite simple, as you can see below.
To use it, first go to the youtube-dl website and download "Windows executable". It's a single file -
youtube-dl.exe, which doesn't need any installation. Just put it in some directory on your hard disk, like I did in
Next, browse to YouTube or other website, find the video you want to download and copy its URL (link) from address bar to the clipboard. Example: "https://www.youtube.com/watch?v=9bZkp7q19f0".
Finally, open command prompt. In Windows 10 you can do it e.g. by opening Start menu and searching for "Command Prompt". In the console, issue following commands:
F:- to change drive to correct one, if needed.
cd \Programs- to enter the directory with your program.
youtube-dl.exe https://www.youtube.com/watch?v=9bZkp7q19f0- to download video from specific URL.
The video is downloaded to the same directory where you've put the program. Its file name contains title of the video, its YouTube identifier and correct extension, depending on particular video format. For example, mine was: "PSY - GANGNAM STYLE() M_V-9bZkp7q19f0.mp4".
That's all basically, but please keep reading if you want to avoid unpleasant suprises, because there are still two important things to know.
First is that sometimes downloading doesn't work. It happens probably because YouTube changes the way the video is served on their website, like the details of their HTML code. Fortunately youtube-dl is quickly adjusted to it, so if you encounter any download error, you probably just need to update the program to the latest version. You don't even need to go to their website - the program has a feature to update itself. All you need to do is to issue command:
Second problem is that youtube-dl only downloads YouTube videos in HD (720p) quality, not Full HD (1080p). That's because YouTube provides Full HD video and audio streams separately so they need to be merged on the client side. Good news is that youtube-dl can do it for you. Bad news: it needs additional program for that, called FFmpeg. So to be able to download videos in FullHD quality, you should additionally:
F:\Programs. This software also doesn't need any installation.
binsubdirectory, where you can find
ffmpeg.exeand save its path. In my case it is:
Now, to download Full HD video, issue following console commands:
F:- to change drive to correct one, if needed.
cd \Programs- to enter the directory with youtube-dl.
set PATH=%PATH%;f:\Programs\ffmpeg-20170214-8fa18e0-win64-static\bin- to temporarily add directory with
PATHenvironmental variable, so youtube-dl will be able to use it.
youtube-dl.exe -f bestvideo+bestaudio https://www.youtube.com/watch?v=9bZkp7q19f0- to download video from specific URL using best video and audio quality available.
Now youtube-dl will download the video stream, audio stream and merge them into final file using FFmpeg, so you can enjoy best quality video and audio, downloaded on your hard drive.
Handy Global Hotkeys for Music Control
I now have a keyboard without "media" keys, so I came up with a set of global hotkeys that I've set up in my music player and consider quite handy. ("Global" means they work in the entire system, also when player application is not in focus.) I can't remember where do they come from, but I think it's possible that I've seen them somewhere. These are:
My favorite music player is foobar2000. To setup new global hotkeys there:
I'm sure you can do this in other music players as well, like AIMP.
3 Rules to Make You Image Looking Good on a Projector
As I go to conferences (and sometimes present my slides), do music visualizations on parties and attend demoscene parties, I started noticing what looks good and what doesn't when presented on a big screen using a projector. It's often not the same thing as you expect when preparing your content and see it on a monitor. The problem is that while monitors usually do pretty good job in representing all shades of colors and brightnesses and we adjust them to see the image from the right distance and in good lighting conditions, with image presented from a projector it's often not the case. You never know what to expect from the quality of the image before you actually enter the venue where you are going to present. That's why I have prepared three simple rules to follow if you want your content to look good on a projector:
1. Use High Contrast
White (or almost white) objects on black background are OK. Black (or almost black) objects on white background are also OK. Gray objects on gray background are not OK. In other words: don't rely on subtle differences in brightness.
Why? Because they may not be visible on the big screen. Sometimes the projector is not powerful enough to ensure sufficient contrast and so everything looks very dark. Sometimes the lighting conditions are such that everything looks very bright. Sometimes the gamma of the image is very different than you experience when preparing your content. (By gamma, I basically mean the curve showing how perceived brightness depends on the brightness value of a pixel.) As a result, all the dark colors may be indistinguishable and completely black, or all the bright colors may be indistinguishable and completely white, or conversely - small difference in pixel brightness can make large difference on the big screen.
So basically use high contrast for all your images. Using subtle differences in pixel brightness for adding some details is OK, but make sure the image looks good and conveys all the key information also without them, relying only on the difference between black and white.
2. Don't Rely on Colors
Monitors can represent most of the colors from sRGB space more or less correctly, but you shouldn't expect the same from a projector. Some colors may seem brighter or darker than expected. Sometimes colors just look completely different on the big screen.
That's why you shouldn't rely on them. Showing some details using colors is OK, but make sure your image looks good and conveys all the key information also without them, relying on brightness alone.
I can remember watching a business presentation where some data was shown on a graph using a yellow line on white background. It was completely invisible on the big screen, so the presenter turned his laptop for us so we could see it. Another time I needed to present on a screen that was lit by a blue lamp and there was no way to turn it off. All parts of the image looked more or less blue and there was no point in using any colors. I even seen a situation where one of RGB components didn't work at all because of the broken cable!
3. Use Big Objects
Use only large font size, prefer big objects of uniform brightness/color and make all lines thick. Don't show any important things as small objects or characters and don't use single-pixel width lines.
Why? Because they may not be readable or visible at all. Sometimes the screen is too small or some viewers sit too far from it. Some people have bad vision and might forget their glasses. Sometimes the image gets downscaled. Many projectors have low resolution. The image quality may just be bad - for example long VGA (D-sub) cable introduces some horizontal blur. I sometimes connect my laptop to a HDMI video switcher that presents itself to the laptop as Full HD (1080p) display, while its output is actually connected to a projector having native resolution of 1024 x 768. I once needed to present on an old projector that didn't have either D-sub or HDMI input, only Composite, S-Video and... a DVD player. Not only I needed a special converter, but also image quality was very bad because standard definition PAL TV signal is only 576i.
For good examples, see demos from Cocoon group (see the group on pouet.net, search YouTube). I think they are not only masterpiece of both technology and art, but they are also deliberately prepared to look great on a big screen by following the rules similar to what I described here.
Nonbreaking Space and No-Width Optional Break
Wrapping text on word boundaries instead of single character boundaries is a great invention. A text looks so much better when inserted to Word:
Than when printed in oldschool console:
But there are places where we may not want a line break to be possible despite we insert a space. For example, in Europe we use space as thousand separator (and comma as decimal mark) when writing down numbers.
A special character called "nonbreaking space" is very helpful in such cases. You can insert it in Word by clicking: Insert > Symbol > More Symbols > Special Characters > Nonbreaking space. This character looks like space, but it doesn't cause line break.
You can actually see this "invisible" character when you press Ctrl+*. It looks like a small circle or a degree sign.
In HTML you can specify a non-breaking space as:
I have discovered quite recently that there is also an opposite special character, called "no-width optional break" or "zero-width space". It is useful in cases where you have a long sequence of characters (like a file path) and you want it to be broken across lines despite it doesn't contain any spaces. It is especially important when you use text justification, because such a long text moved to separate line as a whole can cause an ugly effect:
You can insert this special character in Word (e.g. after every backspace in the path) by clicking: Insert > Symbols > More Symbols > Special Characters > No-width optional break. It occupies no space, but it tells the word processor that a line can be broken at this point. Now it looks much better:
When you press Ctrl+*, you can see this special character depicted as a rectangle.
In HTML you can also use it by typing:
​. It's Unicode "Zero Width Space" character.
Operator New and Delete - Unnecessary Conditions
I've seen following constructs many times in C++ code:
MyClass* obj = new MyClass();
if(obj == nullptr)
// Handle allocation error.
if(obj != nullptr)
Both of these conditions are unnecessary. Strictly speaking they are not a bug - program will run correctly, but they make no sense. If you used to write any of these, you should know that:
new doesn't return null on failed allocation. By default it throws an exception of type
std::bad_alloc in this case, so this is what you should handle if you really care about the state of your program after it runs out of memory (or if the allocated object is particularly big).
There is also special
nothrow version of the
new operator that returns null on failure, but you must call it explicitly. An alternative would be to overload
new operator (global or for particular class) to change its behavior. But again, this is not what happens by default.
Note this is different behavior than
malloc function from C. Obviously there are no exceptions in C language, so this function just returns null on failure.
delete doesn't crash when you pass null pointer to it - it just does nothing, so the check for not-null is already inside, you don't have to write it. Of course trying to delete object from any non-null address that was already freed or is just invalid address still crashes, or causes other undefined behavior.
Note this is the same behavior as
free function from C - it also accepts null pointer.
32-bit Applications on 64-bit Windows
As you probably know, the processor, operating system and applications on a PC may be 32-bit or 64-bit. CPU-s we have in our computers are 64-bit for a long time already. Windows XP tended to be used in 32-bit version, but now I can see most people use Windows 7/8/8.1/10 in 64-bit version as well. Only apps still exist in various forms. Shell extensions and drivers must match the version of the operating system, but other programs can be used in 32-bit version even on 64-bit system. Different combinations are possible:
We may ask a question about where does Windows store files and settings of such apps. It is especially interesting as the answer is very counter-intuitive. Location for (2) – 64-bit apps on 64-bit Windows – may contain “32” in its name (because of backward compatibility), while location for (3) – 32-bit apps on 64-bit Windows – may contain “64” (because of the name WoW64). Here is the list of such locations:
Program Files folder:
(Same applies to HKEY_CURRENT_USER.)