Rss Feed
Tweeter button
Facebook button
Technorati button
Reddit button
Myspace button
Linkedin button
Webonews button
Delicious button
Digg button
Flickr button
Stumbleupon button
Newsvine button

How to output to stdout from an MFC program

By , January 31, 2017 1:00 pm

If you’ve ever developed an MFC program with a graphical user interface and then later thought that it would be really nice to also provide a command line version with output to stdout you’ve probably bumped into the problem that there is no stdout for these programs. The program isn’t attached to a console.

So how do you do it?

The secret to this is a Win32 API “AttachConsole” which is available from Windows XP onwards.
AttachConsole takes one argument, a DWORD identifying the process to which to attach. In our case we want to attach to the parent process, so we pass ATTACH_PARENT_PROCESS which is defined as (DWORD)-1.


When you need to print to this console use _cprintf(), which is defined in conio.h.

But we’re still working with legacy systems!

If you need your code to work on old systems as well as modern systems you’ll need to use GetProcAddress() as shown below.


typedef BOOL (WINAPI *AttachConsole_FUNC)(DWORD);


BOOL attachToProcessConsole(DWORD	processId)
	HMODULE				hMod;

	hMod = GetModuleHandle(_T("Kernel32.dll"));
	if (hMod != NULL)
		AttachConsole_FUNC	func;

		func = (AttachConsole_FUNC)GetProcAddress(hMod, "AttachConsole");
		if (func != NULL)
			// valid for Windows XP onwards

			return (*func)(processId);

	return FALSE;

More Effective Line Timing with C++ Performance Validator

By , December 20, 2016 5:06 pm

C++ Performance Validator has always had the ability to provide timing information for each line executed. However it has always been a bit clumsy to use – you could only enable line timing for all the methods that were being timed. This could result in slow execution due to methods you didn’t want line timed being line timed. You could filter them by file using the “Hooked Source Files” filter or the “Hooked File Types” filter, but that was about as granular as it got.

We’ve just introduced the capability to specify which classes, class methods and functions get line timed. So now, if you want to time just one function, or one method in a class, or time just the methods in a class, you can tell C++ Performance Validator to do that.

To introduce this capability we’ve had to add an additional filters setting in the Settings dialog, we’ve updated the line timing warning dialog to allow you to edit line timing filters right from the warning dialog and we’ve had to update the context menus on all the displays to include new options for line timing filters. We’ve also had to update the display of filtering information on the line timing display.

Updated Settings Dialog

We’ve added a new “Line Timing Filters” section to the settings dialog.


The image above shows three filters have been selected and that only the classes, methods and functions identified by the filters will be line timed. All other class, methods and functions will be ignored for line timing. All methods in the class seoPage will be filtered for line timing, as well as the method CSpellCheckTabDlg::addWord and the function strncasecmp.

Updated Line Timing Warnings

The Line Timing Warning dialog has been updated to allow you to edit line timing filters directly from the warning dialog. The Edit Line Timing Filters… button displays the Line Timing Filters dialog previously described.

C++ Performance Validator Line Timing Warning Dialog

Updated Context Menus

We’ve added a new submenu to the context menus on all displays and renamed the existing “Instrumentation” submenu to “Function Filter (instrumentation)”. The new submenu added is “Line Timing Filter (instrumentation)”. These new context menu entries allow you to easily specify that a class, a class method or a function should be selected for line timing.


How we expect these filters to be used

There are two main methods for using the line timing filters that come to mind.

  • Specify the filters ahead of time.
  • Specify the filters in response to function timing data you are looking at.

Specify the filters ahead of time

This method relies on you knowing your software code and having a very good idea which methods you think need line timing. Open the settings dialog, go to “Line Timing Filters” and enter your filters as appropriate. Be sure to set the filters to include or exclude methods for the use case you think is useful. For line timing, most of the time we expect you to be using the include setting and specifying just a few methods to line time.


Specify filters based on data.

The alternative way of using line timing is in response to some profiling data that you already have. Ideally you’ll have recorded this profiling data with line timing turned off (you can turn this on/off from the launch application dialog). Once you have the profiling data, search for functions that you think will benefit from additional tuning. When you have a candidate function, right click to get the context menu, then select if you want to profile the whole class, just that class method or just that function for line timing.


At the point you add line timing filters, if you have no line timing filters or the line timing filters are set to profile all classes, methods and functions, then the line timing filters will be set to profile just the classes, methods and functions identified by the filters. However, if there are pre-existing filters, the include/exclude setting of the line timing filter will not be changed – you will need to visit the Line Timing Filters settings dialog to change that setting if you want to switch from include to exclude or exclude to include. This design is deliberate as the main use case is to profile one or two methods (or all the methods in one class) – that use case is “include”, which is why this is the default behaviour.

If you have already recorded a session with line timing data and you specify some line timing filters, C++ Performance Validator will update the line timing display to grey out the classes, class methods and functions that will not be instrumented on the next run.


Line Timing Results

Once you have the filter(s) you need setup you can run a new profiling session to get the line timing data you need.



The Software Updates Menu

By , December 20, 2016 12:35 pm

We introduced the Software Updates menu in 2012. This coincided with the introduction of automatic software updates. Various bug fixes have been applied to the software update software since then. But we’ve done nothing with the software updates menu at all. Until recently.

In response to some unusual problems a few of our customers have had we thought we could improve the experience of using the software updates function.

Problems with authentication

One customer reported that although he’d entered his login credentials, the login and download were failing. But strangely our software wasn’t prompting him for a correct set of login credentials (which is what should happen). After some investigation we found that some failures on our server were being amalgamated into one global error code sent back to the client. The global error code was then interpreted correctly according to the error code, but that response wasn’t correct with respect to the specific error on the server. We broke all the failure points on the server into discrete error codes and now handle all of these individually. This allowed the problem the customer had to come to the surface – their credentials were in fact incorrect – he’d made a typo while entering his details.

In addition to this we’ve now made changes to the email entry fields that validate only correct characters can be entered in an email address – enter any incorrect ones and the field turns red. Not enough @ characters – red, too many @ characters – red, whitespace in the user name which isn’t quoted – red, whitespace in the domain – red. Etc.


There is also the error use case where a customer enters their login details for, say, C++ Performance Validator but the tool they are using when they enter these details is C++ Memory Validator. The login details are valid, but not for this software tool. The image below shows the error message when using the Test Login Details… button.


We also added two new menu entries for resetting the user credentials and also for setting the user credentials. If the user credentials are reset, no software updates will occur. If the user credentials are set (correctly) software updates will occur.


Problems with TMP security

When a software update for one of our tools downloads it’s downloaded by default to the directory defined by the TMP environment variable. On a Windows 10 machine this most likely points somewhere like c:\users\stephen\AppData\Local\Temp.

The TMP environment variable is used by the _ttempnam() function to provide a temporary filename for use by the software that calls it. _ttempnam() uses the TMP environment variable to do it’s job. We wrote the software updater code, tested it, and didn’t really think much more about it until we recently received an email from a customer. I’m going to quote a bit of it below.

I am an IT manager for a software house that uses your Performance
Validator and Memory Validator. With the new threats from ransomware
we have locked down developers machines so files cannot be executed
under the users Appdata folders which contains the users temp folder.

He wanted to know what our filename policy was so that he could whitelist our software updater to run inside the directory that he’d locked down. _ttempnam() returns names that are different each time. There is a pattern to the names we use. I explained the rules but then suggested that providing a dedicated download directory removes the need for whitelisting and provides a better security environment. He agreed. So that’s what I’m going to discuss next.

Specifying a directory

The first thing we had to do is replace the use of _ttempnam() with a user specified directory.

The user specified directory defaults to the same location that _ttempnam() would have used. Consult the _ttempnam() documentation and follow the rules for generating the default value. This is basically using GetEnvironmentVariable() to query the TMP environment variable.

Provide a means for the user to specify the download directory.


The directory needs to exist. If the directory doesn’t exist, it should be obvious as the directory name is entered.


The directory needs to have execute privileges and write privileges. If either of these privileges does not exist for the specified directory the user should be alerted to the fact.



The Reset button allows the directory to be set to the default value.

Add an entry to the Software Updates menu to enable the user to access this dialog. Update the Startup Wizard to allow the software update directory to be specified.


We’ve also updated the software update code to handle the use cases where a valid software update directory is supplied but is then deleted, or it’s permissions altered to deny write or deny execute privileges. This also accommodates the case where nothing changes with the directory but the settings get damaged or corrupted somehow (editing the registry, a machine crash…).


We’re always trying to improve your experience with our software. Whether it’s making the use of Software Updates so easy you don’t need to talk to us about it, or improving your security environment. If you have an issue that you think will improve the software for everyone please do get in touch.


The Startup Wizard

By , December 20, 2016 11:33 am

We’ve just added a new Startup Wizard to all our C++ tools.

The purpose of the startup wizard is to unify the various different dialogs that would be shown the first time the software ran. These would configure different aspects of the software. Placing them all in one place, a wizard, provides a better first run experience. We’ve also taken this opportunity to configure software updates for non-evaluation users of the software. As a final touch, we’ve included an overview video for the software.


The first panel explains what’s going to happen next.


Symbol Environment Variables

The second panel allows you to configure which environment variables (if any) you wish to use to control the symbol search process for symbols contained in PDB files.


IDE / Compiler

The third panel allows you to configure which IDE / Compiler / Linker you are using. This is important as it affects how symbol lookup is performed (Visual Studio has various quirks in its history of symbol handling, we have to work around that).


Software Updates

The next panel is not shown to people evaluating the software. Only purchasing customers see this panel. The panel allows you to configure your software update information and also where the software updates are downloaded to.

It is important to be able to specify where they are downloaded to because of potential security risks that arise from allowing the TMP directory (c:\users\[username]\AppData\Local\Temp) to be executable. We use the TMP directory as a default, but if you think that’s not a good idea you can specify your own download directory and set permissions for TMP to deny execute privileges.


Video Overview

The final panel is a video overview of the software. The purpose of this video is to quickly show many areas of the software to encourage you to explore the capabilities of the software.



Working with Dev C++

By , December 14, 2016 5:57 pm

We’ve had a few people asking how to configure C++ Memory Validator to work with programs built using Dev C++. Dev C++ is an IDE used for developing programs with the MingW compiler.

We tested using this download of Dev C++.

Debug information

Any program built using the default Dev C++ settings will generate a binary image that contains debugging information that is in a format that our tools cannot read. The MingW compiler can create debug information in many formats, including COFF and STABS, both of which our tools support. You can turn these debugging formats on using the -gCoff and -gstabs flags. We recommend using STABS symbols.

Configuring Dev C++

Open the Project Options… dialog from the Project menu.

Choose the Parameters tab. Add the option -gstabs to all three columns. Click OK.

Now that you have configured the debug options all you need to do is to rebuild your project to ensure the debug information is present.


The correct way to determine if a file is a directory.

By , November 30, 2016 1:41 pm

After writing for Microsoft’s Windows platform for 20 years I thought I knew all I could know about GetFileAttributes(). Until I found a rather odd and subtle bug in some code that interacted with data supplied by the user of the software. A call would succeed that I expected to fail. Naturally this meant the software didn’t make the right choices and instead of being presented with an helpful dialog explaining what had failed, the software sat silently in a corner humming to itself waiting for the user to work out what had happened. The failure was that I was presenting incorrect data to GetFileAttributes() assuming that it would always fail for bad input. How wrong I was!

I thought I’d write up what can go wrong with GetFileAttributes().

It’s tempting to test if a file is a directory by writing code like this:

if ((GetFileAttributes(fileName) & FILE_ATTRIBUTE_DIRECTORY) != 0)
    // file is a directory

The above looks logically correct. But there are problems with it.

First, a refresher on file attribute values…

File Attributes

The list of defined file attributes is in WinNT.h. The values are shown below.

#define FILE_ATTRIBUTE_READONLY             0x00000001  
#define FILE_ATTRIBUTE_HIDDEN               0x00000002  
#define FILE_ATTRIBUTE_SYSTEM               0x00000004  
#define FILE_ATTRIBUTE_DIRECTORY            0x00000010  
#define FILE_ATTRIBUTE_ARCHIVE              0x00000020  
#define FILE_ATTRIBUTE_DEVICE               0x00000040  
#define FILE_ATTRIBUTE_NORMAL               0x00000080  
#define FILE_ATTRIBUTE_TEMPORARY            0x00000100  
#define FILE_ATTRIBUTE_SPARSE_FILE          0x00000200  
#define FILE_ATTRIBUTE_REPARSE_POINT        0x00000400  
#define FILE_ATTRIBUTE_COMPRESSED           0x00000800  
#define FILE_ATTRIBUTE_OFFLINE              0x00001000  
#define FILE_ATTRIBUTE_ENCRYPTED            0x00004000  
#define FILE_ATTRIBUTE_VIRTUAL              0x00010000  

Rather strangely, the invalid attributes flag is defined in a different file, WinBase.h.


Problem 1

What if GetFileAttributes() fails? If the file doesn’t exist, the call fails. If the filename specifies a computer name, the call fails. See GetFileAttributes() documentation for more informtion. When GetFileAttributes() fails it returns INVALID_FILE_ATTRIBUTES. This error status passes the above test. OK, so add an additional check and the code becomes

DWORD attribs;

attribs = GetFileAttributes(fileName);
if ((attribs != INVALID_FILE_ATTRIBUTES) &&
    ((attribs & FILE_ATTRIBUTE_DIRECTORY) != 0))
    // file is a directory

Problem 2

Even with the above file-does-not-exist problem solved there is another problem. The file could be a directory, but it could be a directory that you don’t want. For example what if you’ve allowed the user to specify the directory name and they typed _T(“/”), or what if your filename creation code has a bug in it that fails when passed an empty name, resulting in a calculated filename of _T(“\”). What then?

In these cases the following calls all return 0x16.


0x16 means hidden (0x02), system (0x04), directory (0x10).

It’s a reasonable bet that in your code, any code looking for a directory to use is probably not looking for a hidden directory and almost certainly not intending to use a system directory. OK, time for a new implementation.

DWORD attribs;

attribs = GetFileAttributes(fileName);
if ((attribs != INVALID_FILE_ATTRIBUTES) &&         // check if a valid file
    ((attribs & FILE_ATTRIBUTE_DIRECTORY) != 0) &&  // file is a directory
    ((attribs & FILE_ATTRIBUTE_HIDDEN) == 0) &&     // file is not hidden
    ((attribs & FILE_ATTRIBUTE_SYSTEM) == 0))       // file is not system
    // file is a directory that isn't hidden and isn't system

What about files, rather than directories?

It’s natural to think about implementing checks for if a filename identifies a file rather than a directory. You test for this in exactly the same way but looking for different attributes. You’ll want to exclude FILE_ATTRIBUTE_DIRECTORY and then depending on the job your code is doing you’ll want to consider excluding files depending upon the following attributes:


and of course, you might also want to consider FILE_ATTRIBUTE_HIDDEN and FILE_ATTRIBUTE_SYSTEM.

Additional reading

Microsoft documentation on GetFileAttributes().

Why is GetFileAttributes the way old-timers test file existence? Old New Thing.


How to make your MFC (or non MFC) program support high DPI monitors. The easy way.

By , November 29, 2016 10:35 am

A few years ago Microsoft introduced support for very high resolution monitors. Such monitors might have nearly 4000 pixels horizontally and over 2000 pixels vertically. This provides wonderful scope for editing photographs and providing great graphics. But at your normal scaling the text on your displays starts looking a bit small. This is typical if you’ve specified your text height in pixels. Which from what I’ve seen is how a lot of people (most?) do it. “Oh, 14 look looks OK, I’ll go with that”. Looks fab for a 21 year. No so good for your customers over 40 though, most of them are wearing glasses, and so will you be when you get there (or contacts, you know what I mean).

This approach isn’t going to work with high DPI displays. You need to think in terms of point sizes for text, like you would if you are printing a document. Once you have an appropriate point size for your normal non-scaled (non high-DPI) display you can then just get the correct font height in pixels (based on the point size) and multiply by a scale factor to determine the correct column width for any columns in grids, or any graphics that need scaling.

Getting the scale factor

Non scaled monitors are deemed to be monitors that display at 96 DPI. From this the following table follows:

DPI scaling
96 100%
120 125%
144 150%
192 200%

You can calculate a scale factor for the whole system, or a scale factor per monitor – if you have monitors with different display facilities. The ability to calculate a scale factor per monitor only works on Windows 8.1 and Windows 10 onwards. You can find out more about this using the GetDpiForMonitor() function. For the purposes of this discussion we will only cover getting the system scale factor.

If you are thinking of doing per-monitor scaling, you might be well served by first doing system wide scaling, because it is simpler and will introduce you to most of the problems you will face, but in an easier to manage problem space than per-monitor scaling. Stepping from a working system wide scaling to per monitor scaling should be a lot easier than going from non-scaling to per-monitor scaling in one go.

double getSystemScaleFactor()				// returns 1.0 for no scaling
	// some simple caching to speed things up

	static int		calculatedScale = FALSE;
	static double	scale = 0;

	if (calculatedScale)
		return scale;

	// get DPI for the system

	HDC		hdc;

	hdc = ::GetDC(NULL);

	UINT	dpiX = 96;		// default DPI

	dpiX = GetDeviceCaps(hdc, LOGPIXELSX);

	scale = (double)dpiX / 96.0;
	if (scale < 1.0)
		scale = 1.0;		// prevent funny business with super large monitors returning very low DPI values

	::ReleaseDC(NULL, hdc);

	calculatedScale = TRUE;
	return scale;

We also need some supporting functions that will assist us during the following phases.

  • We need to be able to calculate a font point size based on a font pixel height.

  • We need to be able to calculate a font pixel height based on a font point size.

Getting a font point size


double getFontPointSize(HDC		hDC,
			DWORD	pixelSize)
	LONG	pixPerInch = GetDeviceCaps(hDC, LOGPIXELSY);
	double	points = (pixelSize * 72.0) / pixPerInch;

	return points;


double getFontPointSize(CDC		*dc,
			DWORD	pixelSize)
	if (dc == NULL)
		return getFontPointSizeForDefaultDC(pixelSize);
		return getFontPointSize(dc->GetSafeHdc(), pixelSize);

Getting a font pixel height

LONG getFontHeightForDefaultDC(double	pointSize)		// returns font height for the appropriate screen
	// this function can be optimized by using a simple cache on the point size (worth it in some situations!)

	HDC		hdc;

	hdc = ::GetDC(NULL);
	height = getFontHeight(hdc, pointSize);
	::ReleaseDC(NULL, hdc);
LONG getFontHeight(HDC		hDC,
		   double	pointSize)		// returns font height for the appropriate screen
	LONG	pixPerInch = GetDeviceCaps(hDC, LOGPIXELSY);
	LONG	lfHeight = (LONG)((pointSize * (double)pixPerInch) / 72.0);

	return lfHeight;
LONG getFontHeight(CDC		*dc,			// can be NULL for default screen
		   double	pointSize)		// returns font height for the appropriate screen
	if (dc == NULL)
		return getFontHeightForDefaultDC(pointSize);
		return getFontHeight(dc->GetSafeHdc(), pointSize);

Updating your code

Versions of MFC since Visual Studio 2010 support MFC scaling, although nothing happens by default. You still have to supply the scale factor for the fonts in use. These fonts will mainly be for any text drawn on graphics displays and for any owner drawn controls such as lists and grid controls which sit on top of huge amounts of data that can't be reliably stored inside the control. You need to find the places where you create fonts and set the font height. Often this will be when you create a font or when you set the lfHeight member of a LOGFONT structure. Once we have these locations we can update the code.

The sequence of operations to update your code is as follows:

  • You need to find each location where a font height is set.

  • For each location you need to calculate the point height and replace the integer height with a call to calculate a height based on a point height.

  • For each location verify that the calculated height is correct for a non-scaled display.

  • For each location verify that the font now scales with the display.

Because the new height calculated by getFontHeight() is based on a point size we don't need to worry about scaling the returned value with getSystemScaleFactor(), the point size is relative to how we view the display, so is automatically the correct scale.


Search for uses of the MFC method CFont::CreateFont(), or the Win32 function ::CreateFont(). The first parameter is the height of the font.

#define FONT_SIZE		16


font.CreateFont(FONT_SIZE,		// default height
		0,			// default width

We need to know what point size of the specified font equates to our chosen (above) font height of 16 pixels. The font height may change according to the font face, italics, weight etc. So you do need to check this for each one and not just rely on it being what you think it is. This is why I haven't provided a table of values for you to plug in.

We can calculate the font point size using the following code, passing in the device context of the appropriate display.

double testPointSize;

testPointSize = getFontPointSize(hDC, FONT_SIZE);

Just add the code before the call to CreateFont, build it, put a breakpoint there and when it stops in the debugger make a note of the value testPointSize. In our tests, a point size of 11.0 gave us a pixel height of 16 (FONT_SIZE).

Once we know testPointSize we can update the code, as shown below. We notated our code with info about how it was tested to help anyone that ends up at this code wondering why these sizes are used. People won't always search the version history and disk space is cheap. Comments help. Use them.

LONG	lfHeight;

lfHeight = getFontHeight(GetDC(), 11.0);		// aiming for lfHeight == 16 (at "small" 1920x1080);

// set font for tab control

font.CreateFont(lfHeight,		// default height (used to be hard coded at 16)
		0,			// default width

If the above font is going to be created many times, caching the value of getSystemScaleFactor() and/or caching the fonts created will be a good idea.


Search for uses of the MFC method CFont::CreateFontIndirect(), or the Win32 function ::CreateFontIndirect(). With this usage you are interested in the lfHeight value of the LOGFONT structure passed to CreateFontIndirect. The procedure is identical as for CreateFont() described above.

Before scaling:

pDispInfo->item.lfFont.lfWeight = FW_NORMAL;
pDispInfo->item.lfFont.lfHeight = -11;

After scaling:

pDispInfo->item.lfFont.lfWeight = FW_NORMAL;
pDispInfo->item.lfFont.lfHeight = -getFontHeightForDefaultDC(8.5);		// aiming for lfHeight == -11 (at "small" 1920x1080);

Alternative implementation

Ignore point sizes and just multiply your existing font pixel heights by getSystemScaleFactor(). This is less work to implement, but results in lots of calls to getSystemScaleFactor() throughout your code base. If you eventually decide to implement per-monitor scaling I think you will regret choosing this implementation method.

pDispInfo->item.lfFont.lfWeight = FW_NORMAL;
pDispInfo->item.lfFont.lfHeight = -11 * getSystemScaleFactor();

Setting column widths

If you are setting column widths in a grid control you'll need to scale these appropriately.

Before scaling:

m_Grid.SetColumnWidth(0, 200);
m_Grid.SetColumnWidth(1, 400);

After scaling:

 double scaleFactor;

scaleFactor = getSystemScaleFactor();
m_Grid.SetColumnWidth(0, (UINT)(200 * scaleFactor));
m_Grid.SetColumnWidth(1, (UINT)(400 * scaleFactor));

Implementation note: For per-monitor scaling you'll need to update these calls to get the scale factor for the appropriate monitor.

How to test

To test you don't need to purchase a high DPI monitor. Although if you do have a high DPI monitor you will be more aware of the issues your high DPI using users have.

  • Change the text scaling size from 100% to another value.

  • Right click on the Windows desktop.

  • Choose Screen Resolution from the context menu.

  • Click the link Make text and other items larger or smaller.

  • Change the text size slider larger or smaller as appropriate. Notice that as you change it a warning notice is displayed about different scaling results. Click Apply. Now close the dialog box.

When you click Apply you should notice the text and graphics scale up or down in relation to the choice you made. "Aha! I've done it!" you think. Not so fast. This is just Windows pretending everything is OK. You'll notice some of the items that have been scaled up don't look so perfect, a bit blurry. This is because this is Windows virtualising the scaling. This also means that many of the fonts you need to change will have been automatically changed for you - for this session only! Don't let this fool you into thinking your job is done. If you want to see what they'll look like for your customers you need to log out and then log back in. You don't need to shutdown the computer or reboot it. Just log out and then log in (not lock the screen and log in!).

When you log in, start your application. Now look at the text you are updating to be responsive to scaling. Has it scaled? Yes? Great! No? You must have missed something. Failed to update it to work from point sizes? Columns too narrow? Forgot to add the multiply by scaling factor? Debug as necessary. Just add developer.

When you've got this working, you're going to have to go back to normal font size (same procedure as before, but just move the text slider all the way to the left), then log out and log in. Now do your tests for the next font. Rinse and repeat. You are going to be logging out and logging back in a lot during this work. Or purchase a modern laptop with a QHD screen or a nice QHD monitor (or better!).

Optimisations and improvements

We've placed all the helper functions I described in their own namespace to separate them from the rest of the code.

We've also used some caches to improve the query time of some requests. We didn't find this bothersome until we had a grid with a lot of items (about a million) that wanted to do a specific query. We thought the delay was unacceptable. Adding a cache fixed that quite simply.

Per Monitor DPI.
You could look into supporting different DPI values for each monitor. See the GetDpiForMonitor() link we mentioned earlier in the article.

You may also need to scale icons (in toolbars etc) accordingly. In practice we haven't found this to be a huge problem so long as your non-scaled icons are reasonably large. Ideally you could scale your icons, but we've found scaling icons to be the least important thing for users of our software. What they really want is legible text, hence our focus on that in this article.

X and Y scaling.
If you've been paying attention you've noticed that getSystemScaleFactor() returns the horizontal scale factor. We've used this everywhere, for both scaling of font heights (vertical) and scaling of column widths (horizontal). You could choose to calculate a vertical scale factor and use that for the scaling of font heights.

The vertical scale factor should be the same (barring any hardware restrictions) to the horizontal scale factor in order to preserve image integrity - so we haven't bothered to calculate a vertical scaling factor. In practice we've been happy with the results returned from using one scale factor.


Now you know everything you need to know to get your Win32 or MFC program displaying well on high DPI displays. There's a lot of great information about this on the web, but reading it can make it seem quite daunting, when in actual fact it's very straight forward. We recommend changing one font at a time, then test, then check with a scaled display, then move on to the next font. Don't try to do them all at once.

If you're testing without a high DPI display, once you think it's all good to go, show it to some of your customers that have high DPI displays that have been bending your ear about supporting high DPI displays. They'll be pleased to tell you what isn't quite right. Across all our applications, we missed on thing that a customer spotted.

I'd also like to extend a big Thank You to Anna Jayne Metcalfe at Riverblade for some helpful pointers when we started this work. Riverblade make the excellent Visual Lint static analysis tool analyser, an excellent complement to our dynamic analysis tools.

Further Reading

Writing Win32 applications and high DPI.

MFC applications default to being DPI aware.

Getting the DPI per Monitor.

Getting the Logical Monitor Width.

High DPI Tutorial.


We’ve been quiet for a while, sorry about that.

By , November 28, 2016 3:29 pm


It’s been a while since we posted anything on the blog. If you weren’t a customer, regularly receiving our software update emails you might think we weren’t going anything.

That’s an oversight on our part. We’re hoping to rectify this over the next few months, posting more useful information both here and in the library.

_tempnam and friends

Our most recent update has been to update C++ Memory Validator provide memory tracking for the _tempnam group of functions. These are _tempnam, _tempnam_dbg, _wtempnam, _wtempnam_dbg.

This support is for all supported compilers, from Visual Studio 2015, Visual Studio 2013, Visual Studio 2012, Visual Studio 2010, Visual Studio 2008, Visual Studio 2005, Visual Studio 2003, Visual Studio 2002, Visual Studio 6. Delphi and C++ Builder, Metrowerks compiler, MingW compiler.

.Net support, for the future

Internal versions of C++ Coverage Validator can provide code coverage statistics for .Net (C#, VB.Net, J#, F#, etc) as well as native languages (C++, C, Delphi, Fortran 95, etc).

Internal versions of C++ Performance Validator can provide performance profiling statistics for .Net (C#, VB.Net, J#, F#, etc) as well as native languages (C++, C, Delphi, Fortran 95, etc).

UX improvements

All tools, free and paid, have had the UX for filename and directory editing improved so that if a filename doesn’t exist it is displayed in red and if it does exist it is displayed in it’s normal colour (typically black). See screenshots (from Windows 8.1).

Non existent filename:

Existing filename:


Fix for FALSE positive memory leak report VS 2015 Update 1

By , December 18, 2015 12:39 pm

We’ve just released a V6.54 of C++ Memory Validator.

This contains a bug fix for FALSE positive memory leak reports when working with Release mode builds of programs built using Visual Studio 2015 Update 1.

Existing customers with valid software maintenance have been emailed about this release. The download is available from the customer login and also from the Software Updates menu in the software.


New graphics in Performance Validator

By , December 18, 2015 12:32 pm

We’ve just introduced some new visualisations of performance data into C++ Performance Validator and .Net Performance Validator.

The new visualisations make it much easier to understand what is happening – the relationship between child and parent functions and where you should be looking to make performance improvements to your code.

The past

First, lets look at what the existing visualisations were:



These are not awful, but they’re not brilliant – they don’t really help you understand what’s happening.

The new visualisations

We’ve replaced the above visualisations with some new visualisations that are easier to read, easier to understand and allow you make better conclusions as to where to focus in your code.


The top bar shows the function time and the average function time as fractions of the total runtime.

The middle bar shows the shortest function time and longest function time as fractions of the total runtime.

The bottom bar shows the function time, the average function and the child time as fractions of the total time for the function.

You can improve your code by looking at each performance bar and evaluating them as shown below.




The top bar shows the line time and the average line time as fractions of the function time.

The bottom bar shows the shortest line time and longest lines time as fractions of the function time.

These allow you to identify the lines that are most dominant and also which have the greatest variability in execution time.


The new visualisations provide more insight into the performance data than the previous visualisations.


I’d like to mention the user experience consultancy Think UI for providing the design for these performance bars and for the very useful explanatory graphic that goes with them.


Panorama Theme by Themocracy