Nish’s thoughts on Visual C++, C++/CX, C# and .NET

Archive for the ‘Win32/MFC’ Category

A month or two back, I had to write a launcher app that would allow/disallow the running of select installers based on various conditions and config files. Since this would run prior to any of the MSIs, and thus couldn’t assume the presence of any dependencies like .NET or the VC++ runtime, I wrote it as a statically linked MFC dialog app using VC++ 2008. All was well with initial testing. But during a final testing phase, the launcher failed to run on a fresh Windows 2000 box with an error about a missing gdiplus.dll.

Windows XP and later OSes like Vista and Windows 7 have GDI+ by default though you may need to apply patches for the latest updates on XP. Windows 2000 predates GDI+ and thus does not have GDI+ by default though a redistributable is available as a separate download. So that’s why it failed. But why is there a dependency at all? I had always assumed that a statically linked MFC app would run anywhere. The it struck me – the BCG stuff that they added to MFC starting VC++ 2008! That code used GDI+ and thus had a GDI+ dependency.

Obviously I couldn’t include the GDI+ redistributable for the launcher app and I didn’t want to remotely take the risk of manually copying along the GDI+ DLL (or any extra files it needs) what with the various updates out there. Eventually, I rewrote the app as a plain Win32 API dialog app (the app was kinda simple, so it didn’t take me too long). I know not many people support Windows 2000 today, but some of our clients are still on that OS, and so it was important for us to support it. Anyway, this is just something to keep in mind when using MFC to write a stub executable that should run anywhere.

Recently I had the task of deploying an MFC application suite along with its dependencies via ClickOnce. Visual Studio does not directly support deployment of MFC applications (even if it’s compiled with /clr) and one of the suggested solutions I found on the web was to have a stub C# executable which would launch the main MFC application. That way you could take advantage of Visual Studio’s built-in deployment functionality. My friend Rama Vavilala had a better suggestion for me – he asked me to try putting in a dummy cpp file into the main project that was compiled using /clr. If ClickOnce accepted such an executable as a .NET assembly, then all I would have to do would be to create the required manifest files on my own. Well all I can say is hats off to Rama for his elegant solution – because it actually did work. This article is a step-by-step pictorial on how you would deploy an MFC application using this trick.

Someone recently asked in the MSDN forums how to create an unmovable dialog using MFC. The simplest way to do this is to remove SC_MOVE from the dialog’s system menu. This can be easily done in OnInitDialog :-

Obviously, you need to think of why you’d want to do soemthing like this. I personally would find it very annoying if some app I installed prevented me from moving its main dialog. Though perhaps it would be okay if there was a way to minimize the app. An alternate way would be to prevent the dialog from moving via the mouse, but to still enable keyboard-based moving. To do that, we handle WM_NCHITTEST and do something like this :-

We treat HTCAPTION like HTCLIENT, so now the user cannot drag/move using the title bar. He can still move it via the keyboard (assuming you have not removed SC_MOVE). Once again, unless you have a very good reason, this is not something I would recommend at all.

Here’s an article I wrote for The Code Project that shows how you can drag and drop a virtual file (one that does not physically exist on disk) from your app into Windows Explorer. It’s useful for scenarios like extracting a file from an archive or where the source file is on a remote machine.

Very frequently in the forums, someone posts a question asking for a function that will create a full directory path for them. For example, they may want to create c:\a\b\c\d\e\f with one call, where the intermediate folders may not exist. The answer, if you are on Win 2000 or later, is to use the SHCreateDirectoryEx function that’ll do this for you. Here’s some sample code :

SHCreateDirectoryEx(NULL,
_T("d:\\abc\\def\\ghi\\nish"), NULL);

It’s a really useful API function, just not that well known. Anyway this blog entry will serve as a link which I’ll point to, if I see this question popping up in the forums again.

Today, there was an article posted on the Code Project website that showed how to use SHBrowseForFolder, and there was a question from a reader in the forum, asking how a default folder can be specified. This is pretty easy to do, and all you need to do is to set the BIF_VALIDATE flag, specify a callback, and in the callback, handle BFFM_INITIALIZED which indicates that the dialog is ready, and then SendMessage a BFFM_SETSELECTION message to the HWND of the dialog. Here’s some commented code that shows how this is done.

This is my latest Code Project article, and it shows you how to use the Windows Forms 2.0 MenuStrip and ToolStrip controls in your MFC applications to give them an Office 2003 look and feel. These Forms controls are pretty well written, and if you change the XP theme/style, they change accordingly, just like Word or Excel would!