Category: MFC
MFC Memory Leak Reporting
When using some MFC-Linking DLLs in a non-MFC project, I stubled on sth quite annoying. According to various sources, an wierd destructor calls _CrtDumpMemoryLeaks each time the MFC is unloaded. In my case, that ment every time a DLL was scanned via LoadLibrary/FreeLibrary. As a result, each and every block of allocated memory was reported as leak for each call of FreeLibrary. This lead to a runtime of serveral minutes in which VisualStudio was unusable.
Thankfully, further search turned up a solution by Pieter Op de Beeck posted in microsoft.public.vc.mfc ten years ago. go figure.
In case you stuble onto this, you'll probably want the fix right away, so here it is: MemoryLeakDetector.zip
2010-06-29. 13:06:18. 118 words, 3047 views. Categories: programming, C++, MFC , Leave a comment » • Send a trackback »
Using MFC: The Doc/View Print Loop
One non intuitive thing in the MFC Document / View implementation is the print loop implementation. If you need to override the mechanism in order to print your own data, you my get confused by the overrides. Well, one very practical feature to test if your code behaves correctly is the PrintPreview. If it works there, the printout will probably be ok. At the same time, the PrintPreview can seem somewhat annoying since you have to guess the right functions. Ok it's not that bad. Actually, the MFC-Documentation contains all the explanation you need. Take a look at the following diagram:

Ok, Ill give you a quick tour of my implementation, using a object called printer that handles the actual printing.
So, in order to keep the page numbering correct, you should do sth like the the following iff you know the total page count:
void CMyView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
// let printer prepare for the DC
// e.g. use GetDeviceCaps() to determine resolution,
// create GDI objects such as fonts, pens, brushes ...
printer.prepare(*pDC);
// print info page count is one-based
pInfo->SetMinPage(1);
pInfo->SetMaxPage(1+printer.getPageCount());
}
Note that I am not using OnPreparePrinting since I do not know the number of pages beforehand. It is calculated from the page size via the DC. To be sure, I calculate using the actual font size like this:
void CListCtrlPrinter::prepare(CDC &dc)
{
int width_mm = dc.GetDeviceCaps(HORZSIZE);
int height_mm = dc.GetDeviceCaps(VERTSIZE);
int width_px = dc.GetDeviceCaps(HORZRES);
int height_px = dc.GetDeviceCaps(VERTRES);
int dpi = (int)(width_px / (width_mm / 25.4));
int font_height = (10*dpi) / 72; // 10pt
// ..
font.CreateFont(font_height,0,0,0,FW_NORMAL,0,0,0,
DEFAULT_CHARSET,OUT_TT_PRECIS,CLIP_CHARACTER_PRECIS,
DEFAULT_QUALITY,VARIABLE_PITCH,NULL);
// ..
szex = dc.GetTextExtent("eX");
// ..
pageRect = CRect(0,0,width_px,height_px);
pageRect.DeflateRect(dpi,dpi/2,dpi/2,dpi/4);
// ..
}
int CListCtrlPrinter::getPageCount()
{
if (szex.cy>=1 && itemsPerPage==0) // strip 2.2 lines for header
itemsPerPage = (int)floor((pageRect.Height()-2.2*szex.cy)/szex.cy);
if (itemsPerPage==0)
return -1;
return 1int)ceil( (double)list.GetItemCount() / (double)itemsPerPage );
}
The actual printing is done in the OnDraw function:
void CMyView::OnDraw(CDC* pDC)
{
// ...
if (pDC->IsPrinting())
printer.draw(*pDC);
}
So, we call out own loop. Note that the framework aborts our printing by StartPage.
void CListCtrlPrinter::draw(CDC &dc)
{
dc.StartPage(); // begin new page
while (item<list.GetItemCount())
{
doPage(dc); // counts up item
if (item<list.GetItemCount()) // another page available
{
dc.EndPage();
if (dc.StartPage()<0) break; // no more pages to draw
}
}
}
So, that wasn't so bad. To start at the right page, one should intercept the page number at OnPrepareDC
void CMyView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
if (pDC->IsPrinting())
if (pInfo)
printer.gotoPage(pInfo->m_nCurPage );
CView::OnPrepareDC(pDC, pInfo);
}
Ok, since I already quoted the code, here the straitforward goto implementation:
void CListCtrlPrinter::gotoPage(int index)
{
if (index<=1)
{
item=0;
page=0;
}
else
{
page = index-1;
item = page*itemsPerPage;
}
}
Ok, this was my mini-tutorial on printing with the old MFC.
2005-08-09. 19:22:19. 491 words, 6431 views. Categories: programming, C++, MFC , Leave a comment » • Send a trackback »
MFC: Doc/View & GetActiveDocument
CMDIFrameWnd::GetActiveDocument() function does return NULL, since it is not the window actually holding the document. You should use a function like the following one to get the document in the MDIFrameWnd:
CDocument* CMyFrame::GetActiveDocumentForSure()
{
// Get the active MDI child window.
CMDIChildWnd *child = MDIGetActive();
if (!child) return 0;
// Get the active view
CView *view = (CView *) child->GetActiveView();
if (!view) return 0;
// get the document from the view
return view->GetDocument();
}
2005-07-27. 18:04:51. 82 words, 5696 views. Categories: programming, C++, MFC , Leave a comment » • Send a trackback »