Feeds:
Posts
Comments

Archive for July, 2005

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

Read Full Post »

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

Read Full Post »

A C++ class I wrote that will detect and enumerate the active CLR versions on a machine! I am quite proud of the title I came up with for the article :-)

The coding gentleman’s guide to detecting the .NET Framework

Read Full Post »

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;

Read Full Post »

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
#else
#define _tcout wcout
#endif

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
    if(PathCompactPath(NULL,tmpbuff,pixels))
        _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;
    TruncateShow(buff,300);
    TruncateShow(buff,200);
    TruncateShow(buff,100);
    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

Read Full Post »

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 :-D

Read Full Post »

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)
    ON_WM_LBUTTONDOWN()
    ON_WM_SETCURSOR()
    ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

//. . .

void CLockSplitterWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
    if(m_bLocked)
        CWnd::OnLButtonDown(nFlags, point);
    else
        CSplitterWnd::OnLButtonDown(nFlags, point);
}

BOOL CLockSplitterWnd::OnSetCursor(CWnd* pWnd,
    UINT nHitTest, UINT message)
{
    if(m_bLocked)
        return CWnd::OnSetCursor(pWnd, nHitTest, message);
    else
        return CSplitterWnd::OnSetCursor(pWnd, nHitTest, message);
}

void CLockSplitterWnd::OnMouseMove(UINT nFlags, CPoint point)
{
    if(m_bLocked)
        CWnd::OnMouseMove(nFlags, point);
    else
        CSplitterWnd::OnMouseMove(nFlags, point);
}

Read Full Post »

In my last blog entry, I had said that the set container was better than a vector container only in the fact that its elements were sorted. Well this gives it a huge advantage when it comes to finding an element. Take a look at the following code snippet that populates a vector, a list and a set with 100,000 randomly generated integers :-

srand((unsigned int)time(0));
srand(rand() + rand() + rand());
vector<int> vecint;
list<int> listint;
set<int> setint;
_tcout << _T("Populating numbers... ") << endl;
for(int i=0; i<100000; i++)
{
    if(i%1000 == 0)
        _tcout << _T("\b\b\b") << i/1000 << _T("%");
    int num = rand();
    vecint.push_back(num);
    setint.insert(num);
    listint.push_back(num);
}
_tcout << _T("\b\b\b") << _T("100%") << endl << endl;

Here’s some code that generates a 1000 random numbers to search for :-

vector<int> numstofind;
for(int i=0; i<1000; i++)
    numstofind.push_back(vecint[(int)((
    (double)rand() / (double) RAND_MAX) * 1000)]);

I wrote a templated function that’ll iterate through the entire collection looking for these numbers :-

template<typename T> int FindNum(T t,
    vector<int> numstofind, const TCHAR* mesg)
{
    _tcout << mesg << endl;
    DWORD init = GetTickCount();


    for each(int i in numstofind)
        *find(t.begin(), t.end(), i);


    DWORD diff = GetTickCount() - init;
    _tcout << diff << _T(" milliseconds elapsed") << endl << endl;
    return diff;
}

And I call the function for each container class :-

FindNum< vector<int> >(vecint, numstofind, _T("Find numbers in vector"));
FindNum< list<int> >(listint, numstofind, _T("Find numbers in list"));
FindNum< set<int> >(setint, numstofind, _T("Find numbers in set"));

Here are my results :-

Populating numbers...
100%

Find numbers in vector
360 milliseconds elapsed

Find numbers in list
441 milliseconds elapsed

Find numbers in set
26589 milliseconds elapsed

Hey, something’s wrong. Wasn’t the set container supposed to be a lot faster than vector or list at finding elements? Oops, we’ve used the find() algorithm to find an element which iterates through each element till a match is found. We don’t have to do that for a set, since a set is sorted and has its find() method which we should have used. Here’s a specialization of the above template function for set :-

template<> int FindNum< set<int> >(
    set<int> t, vector<int> numstofind, const TCHAR* mesg)
{
    _tcout << mesg
        << _T(" (specialized version for set<int>) ") << endl;
    DWORD init = GetTickCount();


    for each(int i in numstofind)
        *t.find(i);


    DWORD diff = GetTickCount() - init;
    _tcout << diff << _T(" milliseconds elapsed") << endl << endl;
    return diff;
}

Here are the results I got after I added this specialization :-

Populating numbers...
100%

Find numbers in vector
360 milliseconds elapsed

Find numbers in list
461 milliseconds elapsed

Find numbers in set (specialized version for set)
20 milliseconds elapsed

Ah, now we have got the expected results, haven’t we?

Read Full Post »

Why have a multiset container?

I was wondering about a plausible scenario where people would need to use the STL multiset associative container. On a different note, I am still puzzled as to why set and multiset are even called associative containers considering that they don’t associate their keys with any data like map and multimap do. In fact I was talking to Jambo and Mike and was telling them how people could always use a vector or a deque instead of a multiset (set had its use in the sense it ensured that you had no duplicates in a collection). I tried out some code (shown below) and found that multiset has one advantage over a vector collection – multiset collections were sorted and so when you iterated through them, you got them back in some specialized order – which could be handy in some situations. BTW, note how I’ve used for each to iterate through native STL collections (it’s a non-standard feature added to Unmanaged VC++ 2005).

Using a multiset<int>

multiset<int> s;
s.insert(12);
s.insert(24);
s.insert(12);
s.insert(3);
s.insert(24);
cout << "multiset listing" << endl;
for each(int i in s)
    cout << i << endl;

Output :-

multiset listing
3
12
12
24
24

Using a vector<int>

vector<int> v;
v.push_back(12);
v.push_back(24);
v.push_back(12);
v.push_back(3);
v.push_back(24);
cout << "vector listing" << endl;
for each(int i in v)
    cout << i << endl;

Output :-

vector listing
12
24
12
3
24

Notice that the vector does not return the collection in a sorted manner. BTW, instead of a multiset, you can also use a priority_queue container adaptor (code shown below), though it may not be as efficient.

Using a priority_queue

priority_queue< int, vector<int>, greater<int> > pq;
pq.push(12);
pq.push(24);
pq.push(12);
pq.push(3);
pq.push(24);
cout << "priority_queue (using vector) listing" << endl;
while(!pq.empty())
{
    cout << pq.top() << endl;
    pq.pop();
}

Output :-

priority_queue (using vector) listing
3
12
12
24
24

Read Full Post »

Mike Dunn said that to me a few minutes ago and I thought that, taken out of perspective, that sentence is pretty funny :-D Well, for those who didn’t get it yet, we weren’t talking about posting messages on a bulletin board or Instant Messenger messages; we were talking about posting Win32 messages! It happened this way. I was working on a CEdit-derived class and wanted to call SetWindowText as early in its creation cycle as possible but also late enough for the subclassed message handlers to come into play. Essentially the equivalent of CDialog‘s OnInitDialog or CView‘s OnInitialUpdate. Anyway, the solution we came up with was to handle PreSubclassWindow (by which time the m_hWnd is valid) and PostMessage a user-defined message to ourselves and the handler for this message is where we do our stuff – because now we know that the underlying EDIT window is ready and that subclassing has finished. Pretty cool, huh? Somehow, I hesitated for a couple of seconds and to pep me up and to keep me going, Mike said to me, “There’s nothing wrong in posting messages!“.

Read Full Post »

Follow

Get every new post delivered to your Inbox.