13.5.  Miscellaneous Continued (3/3)

Microsoft Visual C++/Microsoft Foundation Classes


13.5.  Miscellaneous Continued (3/3)

13.5.10. How do I use CMemoryState?

In MFC 2.0 and above built in diagnostic facilities are provided. Hence it is not necessary to include CMemoryState explicitly in your app. The MFC version 2.0 debugging libraries automatically perform memory leak detection. The detection code is in AFXMEM.CPP. This code detects the case in which an application dynamically allocates an object and fails to delete the object before the program terminates.

In fact,CMemoryState may not function properly. You can refer to the following article in KB(Go MDKB in CIS) for more details:

ID:Q99022 "Foundation Class Debug Library Detects Memory Leaks"

#define new DEBUG_NEW should be defined in every .CPP source file. Also, insert the following code in InitInstance of the application:

#ifdef _DEBUG
    afxMemDF |= checkAlwaysMemDF;
#endif

You can refer to the following article in KB for more details:

ID: Q117326, Foundation Classes Common Asserts, Causes and Solutions.

Muniraju, netquest, MSMFC, 8/1/95

13.5.11. How do I customize the MFC idle time processing?

In my opinion, MFC's idle processing happens too often. Unfortunately, we can't change it because it might break apps when not necessary. But.. we have built in to the code a way for applications to customize the times in which they "enter idle". The secret? CWinThread::IsIdleMessage!!

Here's an example which disables idle entry for mouse & timer messages:

BOOL CMyApp::IsIdleMessage(MSG* pMsg)
{
    if (!CWinApp::IsIdleMessage(pMsg))
        return FALSE;
    if ((pMsg->message >= WM_MOUSEFIRST &&
        pMsg->message <= WM_MOUSELAST) ||
        (pMsg->message >= WM_NCMOUSEMOVE
        && pMsg->message <= WM_NCMBUTTONDBLCLK))
        return FALSE;
    if (pMsg->message == WM_TIMER)
        return FALSE;
    // otherwise msg must kick in idle processing...
    return TRUE;
}

Now, what would happen if you had a clock on your status bar, and were relying on a WM_TIMER to kick in a call to your update handler for that pane? Well... as you might have guessed, the above code would break you. There is an easy way to fix that, as there is a backdoor method of forcing an idle to kick in: WM_KICKIDLE defined in afxpriv.h can be used to make this happen.

So, in your timer handler (most likely a handler in your derived CStatusBar class), you would add some code which does:

if (TimeIsDifferentEnough()) PostMessage(WM_KICKIDLE);

If you take a look at CWinThread::IsIdleMessage, you'll see that we go through a fair amount of pane to avoid unnecessary OnIdle calls. Like checking for mouse moves to the same location as last time (I don't know why NT does that, but it does... every time the caret flashes). We are doing just about everything we can without breaking backward compatibility.

[email protected], via email.

13.5.12. How do I display a choose directory dialog, instead of a choose file dialog?

/* Work's only if we're 95 capable */
if (afxData.bWin4)
{
    LPMALLOC pMalloc;
   
    /* Get's the Shell's default allocator */
    if (::SHGetMalloc(&pMalloc) == NOERROR)
    {
        BROWSEINFO bi;
        char pszBuffer[MAX_PATH];
        LPITEMIDLIST pidl;
       
        // Get help on BROWSEINFO struct - it's got all the bit settings
        bi.hwndOwner = GetSafeHwnd();
        bi.pidlRoot = NULL;
        bi.pszDisplayName = pszBuffer;
        bi.lpszTitle = _T("Select a Starting Directory");
        bi.ulFlags = BIF_RETURNFSANCESTORS | BIF_RETURNONLYFSDIRS;
        bi.lpfn = NULL; bi.lParam = 0;
       
        // This next call issues the dialog box
        if ((pidl = ::SHBrowseForFolder(&bi)) != NULL)
        {
            if (::SHGetPathFromIDList(pidl, pszBuffer))
            {
                //At this point pszBuffer contains the selected path 
                DoingSomethingUseful(pszBuffer);
            }
           
            // Free the PIDL allocated by SHBrowseForFolder
            pMalloc->Free(pidl);
        }
       
        // Release the shell's allocator
        pMalloc->Release();
    }
}

NOTE: This code will work on Win95 only - it's part of the shell.

[email protected] mfc-l, 9/9/95

13.5.13. I'm having problems using MFC 4.0 and the STL, what could be wrong?

The trick is to include "new.h" (and also "iostream.h" for similar reasons) before you include any stl headers. For example:

#include <new.h>
#include <iostream.h>
 
namespace std
{
    #include <map.h>
}

<[email protected]>, mfc-l

NEW!! 13.5.14.  What is MFC's Y2K compliance for CTimeSpan, COleDateTimeSpan, CTime, and COleDateTime?

If you read the online documenation you will see that all of these classes are Y2K compliant. The first problem for these classes will be in 2038 for CTime (underlying C runtimes fails) and 9999 for COleDateTime. The time span classes will fail by the fact that the date classes fail. If you are looking for date classes with an even larger range then have a look at DTime, a collection of MFC classes which I have the developed. The URL is http://indigo.ie/~pjn

The MFC documentation for CTime::CTime states that the valid range for the nYear parameter is 1970 to 2038 (actual range is midnight, January 1, 1970, to January 18, 19:14:07, 2038). These limits are based on the underlying time_t value that mktime creates from the struct tm. Most, if not all, ANSI C systems use 1970 as the reference date and overflow in 2038 (time_t is a long int that holds the number of seconds since the reference date). Microsoft TechNet http://www.microsoft.com/ithome/topics/year2k/product/ctime.htm

PJ Naughter, [email protected], mfc-l, 6/23/1998

BACK...