基于Visua C++2010 与 Windows 7 SDK开发Window Search应用(1)-查询文件夹结构

Windows 7 新功能、新发现 - 超强的Windows Search
Windows 7 强化了Windows Search功能,方便使用者在电脑中检索所有的东西,只要按Windows Button在Search Program and File按入你想要的东西就可找尋到相關的Programs, Folder, Documents等在用戶的电脑中。

Windows Search,一个小型的繁忙的后台Windows服务,每个Window用户对它既爱又恨。 Windows Search占用你宝贵的CPU周期并翻来覆去地搜索你的硬盘,用户对它的态度也是爱恨交加,但是它很少得到应有的重视。

就有利方面而言,Windows Search使得查找隐藏文件、数据---以Vista为例---功能、设置等几乎非常容易。你只需要在任何Explorer窗口的搜索框中输入你要搜索的内容,那么你想要的目标几乎可以立刻就能出现。虽然这一功能在Windows XP操作系统中集成地不太好(例如,你不能组织搜索结果或搜索特定的Windows对象),而免费下载的Windows桌面搜索工具(Windows Desktop Search)提供了一个非常不错的集中接口,使得你可以在以数据为中心的数字世界里任意驰骋。

Windows Search for windows7,可以帮助用户轻松找到PC上的文件、Email消息或附件、日程、照片等等任何东西,甚至还可以快速找到其他PC共享文件,或邮件服务器上的内容。

Windows Search for windows7提高了搜索速度和可靠性,并能够同Windows操作系统无缝整合。其他新特性包括:

•支持索引在线邮件,即使没有将邮件下载到本地也可随时搜索其内容,减轻Exchange Server服务器负担。

•支持加密文件系统(EFS)搜索。

•支持远程搜索其他PC上的共享文件。

•支持组策略设置。

 

我们来亲自体验下基于VS2010与windows 7sdk开发Window Search应用,查询文件夹结构,

代码在windows7上用VS2010调试通过,

详情请见代码

 

#include <stdio.h>
#include <propsys.h>
#include <propvarutil.h>
#include <shlwapi.h>
#include <structuredquery.h>

#pragma comment(lib, "propsys.lib")
#pragma comment(lib, "shlwapi.lib")

// 一个条件操作返回一个结果。非任意结果。

#define MAP_ENTRY(x) {L#x, x}

PCWSTR GetOperationLabel(CONDITION_OPERATION op)
{
    PCWSTR pszLabel = NULL;

    static struct { PCWSTR pszLabel; CONDITION_OPERATION op; } const c_rgOperationLabels[] =
    {
        MAP_ENTRY(COP_IMPLICIT),
        MAP_ENTRY(COP_EQUAL),
        MAP_ENTRY(COP_NOTEQUAL),
        MAP_ENTRY(COP_LESSTHAN),
        MAP_ENTRY(COP_GREATERTHAN),
        MAP_ENTRY(COP_LESSTHANOREQUAL),
        MAP_ENTRY(COP_GREATERTHANOREQUAL),
        MAP_ENTRY(COP_VALUE_STARTSWITH),
        MAP_ENTRY(COP_VALUE_ENDSWITH),
        MAP_ENTRY(COP_VALUE_CONTAINS),
        MAP_ENTRY(COP_VALUE_NOTCONTAINS),
        MAP_ENTRY(COP_DOSWILDCARDS),
        MAP_ENTRY(COP_WORD_EQUAL),
        MAP_ENTRY(COP_WORD_STARTSWITH),
        MAP_ENTRY(COP_APPLICATION_SPECIFIC),
    };

    for (ULONG i = 0 ; !pszLabel && i < ARRAYSIZE(c_rgOperationLabels) ; ++i)
    {
        if (c_rgOperationLabels[i].op == op)
        {
            pszLabel = c_rgOperationLabels[i].pszLabel;
        }
    }

    if (!pszLabel)
    {
        pszLabel = L"???";
    }

    return pszLabel;
}

//显示在标准输出上一个条件与缩进树。
//代码只针对Windows 7和更高版本可以利用ICondition2和IObjectArray优势。
//代码为Windows早期版本的搜索也应该使用ICondition和IEnumUnknown。
//请注意,这两个函数显示,没有留下明确原因使用搜索条件有所不同

#if _WIN32_WINNT >= _WIN32_WINNT_WIN7
HRESULT DisplayQuery(ICondition2* pc, int cIndentation)
{
    CONDITION_TYPE ct;
    HRESULT hr = pc->GetConditionType(&ct);
    if (SUCCEEDED(hr))
    {
        switch (ct)
        {
        case CT_AND_CONDITION:
        case CT_OR_CONDITION:
            {
                wprintf(L"%*s%s/n", 2 * cIndentation, L"", (ct == CT_AND_CONDITION ? L"AND" : L"OR"));
                IObjectArray* poaSubs;
                hr = pc->GetSubConditions(IID_PPV_ARGS(&poaSubs));
                if (SUCCEEDED(hr))
                {
                    UINT cSubs;
                    hr = poaSubs->GetCount(&cSubs);
                    for (UINT i = 0 ; SUCCEEDED(hr) && i < cSubs ; ++i)
                    {
                        ICondition2* pcSub;
                        hr = poaSubs->GetAt(i, IID_PPV_ARGS(&pcSub));
                        if (SUCCEEDED(hr))
                        {
                            DisplayQuery(pcSub, cIndentation + 1);
                            pcSub->Release();
                        }
                    }
                    poaSubs->Release();
                }
            }
            break;
        case CT_NOT_CONDITION:
            {
                wprintf(L"%*s%s/n", 2 * cIndentation, L"", L"NOT");
                // ICondition::GetSubConditions返回一个检索的结果
                ICondition2* pcSub;
                hr = pc->GetSubConditions(IID_PPV_ARGS(&pcSub));
                if (SUCCEEDED(hr))
                {
                    DisplayQuery(pcSub, cIndentation + 1);
                    pcSub->Release();
                }
            }
            break;
        case CT_LEAF_CONDITION:
            {
                PROPERTYKEY propkey;
                CONDITION_OPERATION op;
                PROPVARIANT propvar;
                hr = pc->GetLeafConditionInfo(&propkey, &op, &propvar);
                if (SUCCEEDED(hr))
                {
                    IPropertyDescription* ppd;
                    hr = PSGetPropertyDescription(propkey, IID_PPV_ARGS(&ppd));
                    if (SUCCEEDED(hr))
                    {
                        PWSTR pszPropertyName;
                        hr = ppd->GetCanonicalName(&pszPropertyName);
                        if (SUCCEEDED(hr))
                        {
                            PROPVARIANT propvarString;
                            hr = PropVariantChangeType(&propvarString, propvar, PVCHF_ALPHABOOL, VT_LPWSTR); // 实际应用中应选择PSFormatForDisplay,但我们希望有更多的“原始”的数据。
                            if (SUCCEEDED(hr))
                            {
                                PWSTR pszSemanticType;
                                hr = pc->GetValueType(&pszSemanticType);
                                if (SUCCEEDED(hr))
                                {
                                    //语义类型可以是NULL;若有,不显示它。
                                    if (!pszSemanticType)
                                    {
                                        hr = SHStrDup(L"", &pszSemanticType);
                                    }

                                    if (SUCCEEDED(hr))
                                    {
                                        wprintf(L"%*sLEAF %s %s %s %s/n", 2 * cIndentation, L"", pszPropertyName, GetOperationLabel(op), propvarString.pwszVal, pszSemanticType);
                                    }
                                    CoTaskMemFree(pszSemanticType);
                                }
                                PropVariantClear(&propvarString);
                            }
                            CoTaskMemFree(pszPropertyName);
                        }
                        ppd->Release();
                    }
                    PropVariantClear(&propvar);
                }
            }
            break;
        }
    }
    return hr;
}
#else // _WIN32_WINNT >= _WIN32_WINNT_WIN7
HRESULT DisplayQuery(ICondition* pc, int cIndentation)
{
    CONDITION_TYPE ct;
    HRESULT hr = pc->GetConditionType(&ct);
    if (SUCCEEDED(hr))
    {
        switch (ct)
        {
        case CT_AND_CONDITION:
        case CT_OR_CONDITION:
            {
                wprintf(L"%*s%s/n", 2 * cIndentation, L"", (ct == CT_AND_CONDITION ? L"AND" : L"OR"));
                IEnumUnknown* peuSubs;
                hr = pc->GetSubConditions(IID_PPV_ARGS(&peuSubs));
                if (SUCCEEDED(hr))
                {
                    IUnknown* punk;
                    while ((hr = peuSubs->Next(1, &punk, NULL)) == S_OK)
                    {
                        ICondition* pcSub;
                        hr = punk->QueryInterface(IID_PPV_ARGS(&pcSub));
                        if (SUCCEEDED(hr))
                        {
                            DisplayQuery(pcSub, cIndentation + 1);
                            pcSub->Release();
                        }
                        punk->Release();
                    }
                    peuSubs->Release();
                }
            }
            break;
        case CT_NOT_CONDITION:
            {
                wprintf(L"%*s%s/n", 2 * cIndentation, L"", L"NOT");
                // ICondition::GetSubConditions 返回一个检索的结果
                ICondition* pcSub;
                hr = pc->GetSubConditions(IID_PPV_ARGS(&pcSub));
                if (SUCCEEDED(hr))
                {
                    DisplayQuery(pcSub, cIndentation + 1);
                    pcSub->Release();
                }
            }
            break;
        case CT_LEAF_CONDITION:
            {
                PWSTR pszPropertyName;
                CONDITION_OPERATION op;
                PROPVARIANT propvar;
                hr = pc->GetComparisonInfo(&pszPropertyName, &op, &propvar);
                if (SUCCEEDED(hr))
                {
                    // The property name may be NULL or "*"; if NULL, display it as such.
                    if (!pszPropertyName)
                    {
                        hr = SHStrDup(L"(NULL)", &pszPropertyName);
                    }

                    PROPVARIANT propvarString;
                    hr = PropVariantChangeType(&propvarString, propvar, PVCHF_ALPHABOOL, VT_LPWSTR); // 实际应用中应选择PSFormatForDisplay,但我们希望有更多的“原始”的数据。
                    if (SUCCEEDED(hr))
                    {
                        PWSTR pszSemanticType;
                        hr = pc->GetValueType(&pszSemanticType);
                        if (SUCCEEDED(hr))
                        {
                            // 语义类型可以是NULL;若有,不显示它。
                            if (!pszSemanticType)
                            {
                                hr = SHStrDup(L"", &pszSemanticType);
                            }

                            if (SUCCEEDED(hr))
                            {
                                wprintf(L"%*sLEAF %s %s %s %s/n", 2 * cIndentation, L"", pszPropertyName, GetOperationLabel(op), propvarString.pwszVal, pszSemanticType);
                            }
                            CoTaskMemFree(pszSemanticType);
                        }
                        PropVariantClear(&propvarString);
                    }
                    CoTaskMemFree(pszPropertyName);
                    PropVariantClear(&propvar);
                }
            }
            break;
        }
    }
    return hr;
}
#endif // _WIN32_WINNT >= _WIN32_WINNT_WIN7

int wmain(int /* argc */, wchar_t* /* argv */ [])
{
    wprintf(L"文件夹机构查询范例/n");
    wprintf(L"请输入一个在高级查询语法(AQS),或一个空行查询退出/n");
    wprintf(L"该程序。该项目将解析查询,解决由此产生的条件n");
    wprintf(L"尝试树的形式显示它:/n");
    wprintf(L"from:bill               modified:last week      subject:(cats OR dogs)/n");
    wprintf(L"name:(bubble NOT bath)  author:~~george         taken:<October 2007/n");
    wprintf(L"kind:=folder            has:attachment          rating:****/n");
    wprintf(L"flower                  readstatus:read         size:42KB/n");
    wprintf(L"System.IsShared:=FALSE  exposuretime:>=0.125    received:5/25/2006 .. 7/17/2007/n");
    wprintf(L"请注意,这些问题是英语语言的界面。如果您的界面语言/n");
    wprintf(L"不同的,你可以使用该语言的关键字。需要注意的是/n");
    wprintf(L"System.IsShared:=否则是一个查询的例子/"canonical syntax/", which/n");
    wprintf(L"适用于任何用户界面语言,应在使用旧AQS./n");
    wprintf(L"MSDN on AQS: http://msdn.microsoft.com/en-us/library/aa965711(VS.85).aspx)/n");
    wprintf(L"还要注意,在任何时间条件下的树结构在星期六,而不是本地时间./n");
    HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    if (SUCCEEDED(hr))
    {
        //这是可能的CoCreateInstance的查询分析器直接使用__uuidof(QueryParser的),但由于使用QueryParserManager,我们可以从查询分析器某用户界面语言和目录编制。
        IQueryParserManager* pqpm;
        hr = CoCreateInstance(__uuidof(QueryParserManager), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pqpm));
        if (SUCCEEDED(hr))
        {
          //给IQueryParserManager的语言::CreateLoadedParser应该是用户界面语言应用程序,它通常是作为操作系统的默认界面此用户的语言相同。它用于决定什么语言时使用的解释的关键字
            IQueryParser* pqp;
            hr = pqpm->CreateLoadedParser(L"SystemIndex", GetUserDefaultUILanguage(), IID_PPV_ARGS(&pqp));
            if (SUCCEEDED(hr))
            {
              //此示例关闭“自然查询语法”,这是更为宽松和人类的语言一样搜索符号,也使自动搜索的词用了什么的开始位置指定的(这样的投入“的:法案”将搜索来自任何人的名字开头“规则”。
                hr = pqpm->InitializeOptions(FALSE, TRUE, pqp);
                WCHAR szLine[1024];
                while (SUCCEEDED(hr) && fgetws(szLine, ARRAYSIZE(szLine), stdin)[0] != L'/n')
                {
                    //在解析查询字符串的实际工作都是在这里完成
                    IQuerySolution* pqs;
                    hr = pqp->Parse(szLine, NULL, &pqs);
                    if (SUCCEEDED(hr))
                    {
                      //在这个示例,我们也懒得各方的解析错误,但我们可以区分。请注意,将有一个解决办法,即使有解析错误,它只是可能不用户意图
                        IEnumUnknown* peu;
                        hr = pqs->GetErrors(IID_PPV_ARGS(&peu));
                        if (SUCCEEDED(hr))
                        {
                            if (peu->Skip(1) == S_OK)
                            {
                                wprintf(L"Some part of the query string could not be parsed./n");
                            }
                            ICondition* pc;
                            hr = pqs->GetQuery(&pc, NULL);
                            if (SUCCEEDED(hr))
                            {
                               


                                //IQueryCondition::Resolve and IConditionFactory2::ResolveCondition 转任何日期/时间引用(相对,如“今天”,绝对的,如“2009年5月7日”)为绝对日期/时间引用(在星期二的时区),并简化了各种方式的结果。
                                //请注意,电脑是不变的,可以解决对其他日期/时间。代码只针对Windows 7和更高版本可以利用IConditionFactory2::ResolveCondition优势。代码为目标的Windows和Windows早期版本的搜索也应使用IQueryCondition::Resolve。
                                SYSTEMTIME st;
                                GetLocalTime(&st);
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN7)
                                IConditionFactory2* pcf;
                                hr = pqs->QueryInterface(IID_PPV_ARGS(&pcf));
                                if (SUCCEEDED(hr))
                                {
                                    ICondition2* pcResolved;
                                    hr = pcf->ResolveCondition(pc, SQRO_DEFAULT, &st, IID_PPV_ARGS(&pcResolved));
                                    if (SUCCEEDED(hr))
                                    {
                                        hr = DisplayQuery(pcResolved, 0);
                                        pcResolved->Release();
                                    }
                                    pcf->Release();
                                }
#else // _WIN32_WINNT >= _WIN32_WINNT_WIN7
                                ICondition* pcResolved;
                              
//由于IConditionFactory::Resolve ,我们必须使用SQRO_DONT_SPLIT_WORDS表现得像IConditionFactory2::ResolveCondition,我们希望保持自然短语间断。
                                hr = pqs->Resolve(pc, SQRO_DONT_SPLIT_WORDS, &st, &pcResolved);
                                if (SUCCEEDED(hr))
                                {
                                    hr = DisplayQuery(pcResolved, 0);
                                    pcResolved->Release();
                                }
#endif // _WIN32_WINNT >= _WIN32_WINNT_WIN7
                                pc->Release();
                            }
                            peu->Release();
                        }
                        pqs->Release();
                    }
                }
                pqp->Release();
            }
            pqpm->Release();
        }
        CoUninitialize();
    }
    return SUCCEEDED(hr) ? EXIT_SUCCESS : EXIT_FAILURE;
}

欢迎技术交流!

 

本文作者专著《Visual C++2010开发权威指南》即将推出,敬请关注,Visual C++2010最近技术,Windows7开发最新技术!


原文链接: http://blog.csdn.net/yincheng01/article/details/5417097

你可能感兴趣的:(基于Visua C++2010 与 Windows 7 SDK开发Window Search应用(1)-查询文件夹结构)