Supporting Windows Search with MFC

Introduction

The revival of MFC that began with the Visual C++ 2008
Feature Pack continues with Visual C++ 2010, and a whole new
range of options that allow rich integration with advanced
Windows features like Windows Search are now provided out-
of-the-box. By providing a link between familiar MFC
features like the Document-View architecture, the new
Windows 7 features can be easily incorporated into a code-
base with minimal work.

Windows Search has been through a number of forms and
iterations before arriving at the consistent and integrated
product available across the supported Windows operating
systems today. Windows Search started life as the Indexing
Service on Windows XP, which was then built upon with
Windows Desktop Search (WDS). The initial versions of WDS
was publicly branded MSN Desktop Search (and came with the
MSN Toolbar), with Version 3 (released in 2007) available as
a stand-alone installation and re-branded to Windows Desktop
Search. For Windows Vista, Windows Server 2008 and Windows
7, WDS was integrated deeply into Windows and had its name
compacted further to simply ‘Windows Search’. Windows Search
4, released in 2008, is available for installation on all
Windows versions from XP onwards, and has a large feature
set as described in Knowledge Base article 940157.

There are two basic techniques that Windows Search uses
to extract and categorize information from a file. The
simplest technique is to catalogue the metadata available
from a file, which is exposed to Windows Search in the form
of properties. Extensible file properties are one of the
surviving remnants of the Object File System and Windows
File System (which were part of the wider ‘Project Cairo’
that was promised at the 1991 PDC and never delivered in
coherent product form) that allow arbitrary metadata
properties to be attached to a file. Digital media files
and Office documents are two of the most successful and
prominent example of files that make use of properties to
expose metadata about their contents, allowing Windows
Search to locate Office documents with a particular Author
property and MP3 files from a particular artist. Windows
ships with a schema that defines over two hundred standard
properties, and this schema can be extended via property
descriptor files and property handlers as defined in the
MSDN library.

For data stored in some file types, simple metadata is
not enough to allow Windows Search to gather enough
information about the data stored in the file. For example,
the Outlook PST file which contains emails, contacts and
calendar appointments cannot adequately expose its contents
to Windows Search through the use of metadata properties,
and this is where Windows Search Filters come in. Filters,
which are implemented through the COM IFilter interface, are
called by Windows Search to extract key pieces of indexable
data for a particular file which can then be used to locate
the indexed item when a user enters search criteria relevant
to it. An IFilter-implementation is associated with a
particular file extension, which makes MFC a natural
candidate for supporting Windows Search Filters with its
simple support for file extension handling.

Choosing to support Search Filters in an MFC application
is done as part of the MFC application wizard as shown in
Figure 1, with the Filter option enabled once a file
extension has been nominated. When the Filter option is
selected (or either of the Preview or Thumbnail options), a
separate ATL COM DLL project will be added to the MFC
solution, and this will contain the skeleton implementation
of IFilter and the other secondary COM interfaces required.
The CDocument-derived MFC class is shared between the main
MFC Windows application project and the ATL handler project,
allowing the same code that is used in standard application
execution to be re-used to extract key data when the file is
indexed by Windows Search.




Figure 1. MFC Options for Windows Integration.

The methods required to support IFilter in the CDocument-
derived class are conditionally compiled by surrounding them
with #ifdef SHARED_HANDLERS directives. SHARED_HANDLERS is
defined for the ATL DLL project, but is not defined for the
main MFC application, and this nifty bit of engineering
allows the same code-base to be effectively used for both
main application flow and Windows integration.

The easiest way to see the effectiveness and simplicity
of the MFC integration with Windows is with a quick
demonstration project–a minimalist note keeping program
that allows a user to create and save notes that have both a
title and body. The familiar and long-serving MFC document-
view architecture makes creating the application
straightforward, with the Document-derived class containing
member variables for the data of each note that is then read
by the View-derived class and displayed on the screen. The
basics of the document definition and archiving are:


class CMfcNoteDoc : public CDocument
{
public:
CString m_title;
CString m_body;
}

void CMfcNoteDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ar << m_title;
ar << m_body;
}
else
{
ar >> m_title;
ar >> m_body;
}
}


The App-Wizard generated code contains the following
IFilter-related methods in the document class:


// Support for Search Handlers
void CMfcNoteDoc::InitializeSearchContent()
{
CString strSearchContent;
// Set search contents from document’s data.
// The content parts should be separated by “;”

// For example: strSearchContent = _T(“point;rectangle;circle;ole object;”);
SetSearchContent(strSearchContent);
}

void CMfcNoteDoc::SetSearchContent(const CString& value)
{
if (value.IsEmpty())
{
RemoveChunk(PKEY_Search_Contents.fmtid, PKEY_Search_Contents.pid);
}
else
{
CMFCFilterChunkValueImpl *pChunk = NULL;
ATLTRY(pChunk = new CMFCFilterChunkValueImpl);
if (pChunk != NULL)
{
pChunk->SetTextValue(PKEY_Search_Contents, value, CHUNK_TEXT);
SetChunkValue(pChunk);
}
}
}


By default, InitializeSearchContent calls
SetSearchContent with an empty string, and when
Windows Search indexes the contents of files created by the
MFC application, no data will be available, and the file
contents will not be indexed. Adding a meaningful
implementation to SetSearchContent is generally
pretty easy–SetSearch contents will be called
by the Windows Search indexer after the MFC infrastructure
has called the standard CDocument Serialize method, so all
the member variables will be fully populated by the
document’s contents. For the MfcNote sample application,
indexing the note title seems like a reasonable compromise
between efficiency and completeness, so the implementation
can be adapted to a single line of code.


void CMfcNoteDoc::InitializeSearchContent()
{
SetSearchContent(m_title); //index note title
}

The sample demonstrates how easily MFC-based applications
can integrate fully into the full-text capabilities of
Windows Search. Without over selling the elegance and power
of Windows Search integration, this new feature is a return
to MFC’s glory days where rich Windows integration was
available with minimal development overhead. In the lead-up
to the full release of Visual C++ 2010, more of the great
new enhancements to MFC will be covered.

More by Author

Must Read