Is MFC dead? Does MFC have a future?

“Is MFC dead?” is arguably the most common question appearing on the VC++ newsgroups along with variants like “Does MFC have a future?” and “Can MFC applications run on Longhorn?”. A short answer would be, “No, MFC is not dead, and you can continue to develop applications using MFC and be assured that they will run on Longhorn (or Vista).” For a more involved answer, continue reading.

What makes a technology dead? The fact that nobody uses it any more? If so, MFC is not dead now nor will it die in the next 10 years – because, the number of people using MFC must be in the millions right now and even assuming that newer adopters would be fewer as the years go by, the amount of MFC code is so extensive that there will be a large number of developers continuing to work on it. Okay, so that definition of death wouldn’t apply here. How about considering a technology to be dead if its development is frozen? If so, same results – MFC is simply not dead! MFC has got some new additions (mostly classes that allow it to interact easily with Windows Forms) and MFC will continue to be enhanced – if I have not grossly got my facts wrong, support for Avalon (or Windows Presentation Foundation) is being added to MFC for the Orcas release. Okay, so all this talk of a dead MFC is rubbish! Next point.

Does it have a future? My answer – YES, it does. One major concern people have is that with .NET all over the place, why would someone choose MFC. Well, one big reason would be that for Win32 GUI frameworks, I (and many others far more knowledgeable and technically recognized than I am) find MFC a far better option to Windows Forms. The CFrameWnd, CView, CDialog, CWnd set of classes do not have functionally equivalent classes under Windows Forms – so the whole GUI programming approach is different with Windows Forms than it’s with MFC. At the same time, it’d be terminally stupid to ignore .NET – but then using MFC does not require you to ignore .NET. VC++ lets you mix native applications (including MFC applications) with .NET seamlessly. So, there’re going to a be a good number of applications whose UI is developed with MFC but will extensively take advantage of the .NET classes for enhanced functionality with minimal lines of code. .NET is not MFC’s nemesis, rather .NET is something that can be used to enhance your MFC programming experience. Next point.

Will MFC apps run on Longhorn? They better do so else no one’s going to be using Longhorn or Vista or whatever it’s going to be called. MFC applications are essentially Win32 applications and right now, so are your .NET applications. While, .NET apps contain a lot of IL code as their primary content, they are PE executables just like other Win32 executables. There are millions of applications developed with MFC, ATL, WTL, Visual Basic, Windows Forms, Delphi etc. that will need to run on Longhorn. So, yes, your MFC apps will run on Longhorn. Will they look ugly? Uhm, I don’t know. They definitely won’t look like Longhorn apps unless you use the MFC-Avalon framework, but then the same applies to your Windows Forms applications.

Concluding, MFC is not dead now nor is it going to die any time soon; .NET is not going to kill MFC, rather it’s going to complement it; and MFC applications will not only work on Longhorn, but MFC is being updated/enhanced to support the Avalon framework. So if you are using MFC now, continue using it with confidence and pride, and next time you see this question asked in some forum, feel free to redirect the poster to this blog entry.


A rational attempt to substantiate C++/CLI as a first class CLI language

This is my latest Code Project article and one that I’d been meaning to write for quite some time now. It explains why I think C++/CLI has an irreplaceable place among the CLI languages and demonstrates its advantages over other languages using simple code snippets where applicable.

A rational attempt to substantiate C++/CLI as a first class CLI language

The _countof macro

VC++ 2005 provides an _countof macro that returns the number of elements in a statically-allocated array. You cannot use it with a pointer type. It’s different from sizeof in the sense that sizeof returns the size in bytes and also works on pointers, though for pointers, it actually returns the size of the pointer (4 bytes on a 32-bit system).

The following code snippet shows them both in action :-

char s1[20] = "hello";
wchar_t s2[20] = L"hello";
const char* s3 = "hello";
const wchar_t* s4 = L"hello";
char* s5 = new char[128];

cout << sizeof s1 << endl;//20
cout << sizeof s2 << endl;//40
cout << sizeof s3 << endl;//4
cout << sizeof s4 << endl;//4
cout << sizeof s5 << endl;//4

cout << _countof(s1) << endl;//20
cout << _countof(s2) << endl;//20
//cout << _countof(s3) << endl; <-- won't compile
//cout << _countof(s4) << endl; <-- won't compile
//cout << _countof(s5) << endl; <-- won't compile

delete[] s5;

The PathCompactPath function

PathCompactPath is a not-so-well-known function that truncates a file path to fit within a specific pixel-width and uses ellipses to show that it’s been truncated. Here’s some sample code that shows how you can use it :-

#ifndef UNICODE
#define _tcout cout
#define _tcout wcout

void TruncateShow(LPCTSTR buff, UINT pixels)
    TCHAR tmpbuff[MAX_PATH*4] = {0};
    _tcsncat(tmpbuff, buff, MAX_PATH*4);
    //While not mentioned in the docs, you can pass NULL for HDC
        _tcout << pixels << _T(" pixel width : ")
        << tmpbuff << endl;

int main()
    const TCHAR buff[MAX_PATH*4] = _T("C:\\Program Files\\Microsoft")
        _T(" Visual Studio .NET 2003\\Vc7\\lib");
    _tcout << _T("Original string : ") << buff << endl;
    return 42;

And here’s the output :-

Original string : C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\lib
300 pixel width : C:\Program Files\Microsoft Visual Studio ...\lib
200 pixel width : C:\Program Files\Microsof...\lib
100 pixel width : C:\Progra...\lib

Mr .NET colorized my articles!

I just installed SyntaxHighlighter for .NET written by Jambo Johnson (Mr .NET) on my website, and now the articles on my site have syntax colorization for the code snippets – just as in my blog. My blog uses Jambo’s WordPress colorizer plugin developed in PHP and this new .NET colorizer is a .NET port of the PHP version, though Jambo has re-done the entire design. To add any new language, you just need to add a new language template (very easy to do); in fact Jambo gave me just his C# and plain text language templates, and it took me less than 15 minutes to generate a C++ language template (this time I have decided to use a single template for native C++, Managed C++ and C++/CLI). Anyway, please feel free to check out the now syntax colorized articles here :- Nish’s Articles. Thanks goes to Jambo for developing a really awesome component – BTW, he has plans of writing an ASP.NET web control wrapping the colorizer that you can just drag/drop into your ASP.NET web-application projects, so those of you who want it can keep reminding him frequently till he succumbs to pressure 😀

Locking splitter windows

Earlier today, someone asked on the vc.mfc NG how he can lock his splitter windows. I replied to him asking him to handle WM_SETCURSOR, WM_LBUTTONDOWN and WM_LBUTTONUP in a CSplitterWnd derived class and to call the base class implementation only if locking is disabled. Later, I decided to try it out and found that there was no need to handle WM_LBUTTONUP but that WM_MOUSEMOVE should be handled. I replied to him again, correcting my earlier post. For future reference, I thought it best to blog about it here and the relevant code snippets are posted below :-

class CLockSplitterWnd : public CSplitterWnd;

//. . .

BEGIN_MESSAGE_MAP(CLockSplitterWnd, CSplitterWnd)

//. . .

void CLockSplitterWnd::OnLButtonDown(UINT nFlags, CPoint point)
        CWnd::OnLButtonDown(nFlags, point);
        CSplitterWnd::OnLButtonDown(nFlags, point);

BOOL CLockSplitterWnd::OnSetCursor(CWnd* pWnd,
    UINT nHitTest, UINT message)
        return CWnd::OnSetCursor(pWnd, nHitTest, message);
        return CSplitterWnd::OnSetCursor(pWnd, nHitTest, message);

void CLockSplitterWnd::OnMouseMove(UINT nFlags, CPoint point)
        CWnd::OnMouseMove(nFlags, point);
        CSplitterWnd::OnMouseMove(nFlags, point);