CDialogEventHandler_CreateInstance标识符未找到。

8

我一直在遵循几个创建Vista/7打开文件对话框的指南/示例,但现在由于一个错误消息而陷入了死局,该消息指出main.cpp(189):错误C3861:未找到标识符'CDialogEventHandler_CreateInstance'。

除了一个页面上有人重写了示例代码以不使用CDialogEventHandler类外,我在Google上找不到任何信息。

这是我的代码。 CDialogEventHandler类和函数定义直接来自Windows 7 SDK CommonFileDialogApp示例:

#include "resource.h"

#include <windows.h>      // For common windows data types and function headers
#define STRICT_TYPED_ITEMIDS
#include <objbase.h>      // For COM headers
#include <shobjidl.h>     // for IFileDialogEvents and IFileDialogControlEvents
#include <shlwapi.h>
#include <knownfolders.h> // for KnownFolder APIs/datatypes/function headers
#include <propvarutil.h>  // for PROPVAR-related functions
#include <propkey.h>      // for the Property key APIs/datatypes
#include <propidl.h>      // for the Property System APIs
#include <strsafe.h>      // for StringCchPrintfW
#include <shtypes.h>      // for COMDLG_FILTERSPEC
#include <new>

// Controls
#define CONTROL_GROUP           2000
#define CONTROL_RADIOBUTTONLIST 2
#define CONTROL_RADIOBUTTON1    1
#define CONTROL_RADIOBUTTON2    2       // It is OK for this to have the same IDas     CONTROL_RADIOBUTTONLIST,
                                        // because it is a child control under CONTROL_RADIOBUTTONLIST

// IDs for the Task Dialog Buttons
#define IDC_BASICFILEOPEN                       100
#define IDC_ADDITEMSTOCUSTOMPLACES              101
#define IDC_ADDCUSTOMCONTROLS                   102
#define IDC_SETDEFAULTVALUESFORPROPERTIES       103
#define IDC_WRITEPROPERTIESUSINGHANDLERS        104
#define IDC_WRITEPROPERTIESWITHOUTUSINGHANDLERS 105

HWND ghMainWnd = 0;
HINSTANCE ghAppInst = 0;
RECT winRect;

void centerWnd(HWND parent_window);
void openDB();

class CDialogEventHandler : public IFileDialogEvents,
                            public IFileDialogControlEvents
{
public:
    // IUnknown methods
    IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv)
    {
        static const QITAB qit[] = {
            QITABENT(CDialogEventHandler, IFileDialogEvents),
            QITABENT(CDialogEventHandler, IFileDialogControlEvents),
            { 0 },
        };
        return QISearch(this, qit, riid, ppv);
    }

    IFACEMETHODIMP_(ULONG) AddRef()
    {
        return InterlockedIncrement(&_cRef);
    }

    IFACEMETHODIMP_(ULONG) Release()
    {
        long cRef = InterlockedDecrement(&_cRef);
        if (!cRef)
            delete this;
        return cRef;
    }

    // IFileDialogEvents methods
    IFACEMETHODIMP OnFileOk(IFileDialog *) { return S_OK; };
    IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; };
    IFACEMETHODIMP OnFolderChanging(IFileDialog *, IShellItem *) { return S_OK; };
    IFACEMETHODIMP OnHelp(IFileDialog *) { return S_OK; };
    IFACEMETHODIMP OnSelectionChange(IFileDialog *) { return S_OK; };
    IFACEMETHODIMP OnShareViolation(IFileDialog *, IShellItem *, FDE_SHAREVIOLATION_RESPONSE *) { return S_OK; };
    IFACEMETHODIMP OnTypeChange(IFileDialog *pfd);
    IFACEMETHODIMP OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; };

    // IFileDialogControlEvents methods
    IFACEMETHODIMP OnItemSelected(IFileDialogCustomize *pfdc, DWORD dwIDCtl, DWORD dwIDItem);
    IFACEMETHODIMP OnButtonClicked(IFileDialogCustomize *, DWORD) { return S_OK; };
    IFACEMETHODIMP OnCheckButtonToggled(IFileDialogCustomize *, DWORD, BOOL) { return S_OK; };
    IFACEMETHODIMP OnControlActivating(IFileDialogCustomize *, DWORD) { return S_OK; };

    CDialogEventHandler() : _cRef(1) { };
private:
    ~CDialogEventHandler() { };
    long _cRef;
};

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case ID_FILE_OPENDB:
            openDB();
            break;

        default:
            break;


        }

        break;
    case WM_LBUTTONDOWN:
        MessageBox(0, "WM_LBUTTONDOWN message.", "Msg", MB_OK);
        return 0;

    case WM_KEYDOWN:
        if (wParam == VK_ESCAPE)
            DestroyWindow(ghMainWnd);
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, msg, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR cmdLine, int showCmd)
{
    ghAppInst = hInstance;

    HMENU mMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));

    WNDCLASS wc;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = ghAppInst;
    wc.hIcon = ::LoadIcon(0, IDI_APPLICATION);
    wc.hCursor = ::LoadCursor(0, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) ::GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = 0;
    wc.lpszClassName = "MyWndClassName";

    RegisterClass(&wc);

    centerWnd(GetDesktopWindow());

    ghMainWnd = ::CreateWindow("MyWndClassName", "Space Crusade Database Editor V1.0", WS_OVERLAPPEDWINDOW, winRect.left, winRect.top, 1280, 720, 0, mMenu, ghAppInst, 0);

    if(ghMainWnd == 0)
    {
        ::MessageBox(0, "CreateWindow - Failed", 0, 0);
        return false;
    }

    ShowWindow(ghMainWnd, showCmd);
    UpdateWindow(ghMainWnd);

    MSG msg;
    ZeroMemory(&msg, sizeof(MSG));

    while (GetMessage(&msg, 0, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

void centerWnd(HWND parent_window)
{
    GetClientRect(parent_window, &winRect);
    winRect.left = (winRect.right/2) - (1280/2);
    winRect.top = (winRect.bottom/2) - (720/2);
}

void openDB()
{
    //Cocreate the file open dialog object
    IFileDialog *pfd = NULL;

    HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pfd));

    if (SUCCEEDED(hr))
    {
        //Stuff needed for later
        const COMDLG_FILTERSPEC rgFExt[] = {{L"SQLite3 Database (*.sqlite)", L"*.sqlite"}};
        WCHAR fPath[MAX_PATH] = {};

        //Create event handling
        IFileDialogEvents *pfde = NULL;
        hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));

        if(SUCCEEDED(hr))
        {
            //Hook the event handler
            DWORD dwCookie;

            hr = pfd->Advise(pfde, &dwCookie);

            if (SUCCEEDED(hr))
            {
                //Set options for the dialog
                DWORD dwFlags;

                //Get options first so we do not override
                hr = pfd->GetOptions(&dwFlags);

                if (SUCCEEDED(hr))
                {
                    //Get shell items only
                    hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);

                    if (SUCCEEDED(hr))
                    {
                        //Types of files to display (not default)
                        hr = pfd->SetFileTypes(ARRAYSIZE(rgFExt), rgFExt);

                        if (SUCCEEDED(hr))
                        {
                            //Set default file type to display
                            hr = pfd->SetDefaultExtension(L"sqlite");

                            if (SUCCEEDED(hr))
                            {
                                //Show dialog
                                hr = pfd->Show(NULL);

                                if (SUCCEEDED(hr))
                                {
                                    //Get the result once the user clicks on open
                                    IShellItem *result;

                                    hr = pfd->GetResult(&result);

                                    if (SUCCEEDED(hr))
                                    {
                                        //Print out the file name
                                        PWSTR fName = NULL;

                                        hr = result->GetDisplayName(SIGDN_FILESYSPATH, &fName);

                                        if (SUCCEEDED(hr))
                                        {
                                            TaskDialog(NULL,NULL,L"File Name",fName,NULL,TDCBF_OK_BUTTON,TD_INFORMATION_ICON,NULL);
                                            CoTaskMemFree(fName);
                                        }

                                        result->Release();
                                    }
                                }
                            }
                        }
                    }
                }
            }

            pfd->Unadvise(dwCookie);
        }

        pfde->Release();
    }

    pfd->Release();
}


HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void **ppv)
{
    *ppv = NULL;
    CDialogEventHandler *pDialogEventHandler = new (std::nothrow) CDialogEventHandler();
    HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
    if (SUCCEEDED(hr))
    {
        hr = pDialogEventHandler->QueryInterface(riid, ppv);
        pDialogEventHandler->Release();
    }
    return hr;
}

HRESULT CDialogEventHandler::OnTypeChange(IFileDialog *pfd)
{
    IFileSaveDialog *pfsd;
    HRESULT hr = pfd->QueryInterface(&pfsd);
    if (SUCCEEDED(hr))
    {
        UINT uIndex;
        hr = pfsd->GetFileTypeIndex(&uIndex);   // index of current file-type
        if (SUCCEEDED(hr))
        {
            IPropertyDescriptionList *pdl = NULL;


        }
        pfsd->Release();
    }
    return hr;
}

// IFileDialogControlEvents
// This method gets called when an dialog control item selection happens (radio-button selection. etc).
// For sample sake, let's react to this event by changing the dialog title.
HRESULT CDialogEventHandler::OnItemSelected(IFileDialogCustomize *pfdc, DWORD dwIDCtl, DWORD dwIDItem)
{
    IFileDialog *pfd = NULL;
    HRESULT hr = pfdc->QueryInterface(&pfd);
    if (SUCCEEDED(hr))
    {
        if (dwIDCtl == CONTROL_RADIOBUTTONLIST)
        {
            switch (dwIDItem)
            {
            case CONTROL_RADIOBUTTON1:
                hr = pfd->SetTitle(L"Longhorn Dialog");
                break;

            case CONTROL_RADIOBUTTON2:
                hr = pfd->SetTitle(L"Vista Dialog");
                break;
            }
        }
        pfd->Release();
    }
    return hr;
}

1
http://www.daniweb.com/software-development/cpp/threads/394132/how-do-i-create-attach-an-event-handler-to-a-win7-style-ifilesavedialog - user1793036
@user1793036 这是我在原帖中提到的帖子。我想使用微软提供的代码。不过我认为我已经找到了问题所在。请查看我的回答获取更多信息。 - Geowil
4个回答

1
我设法让代码工作了。我使用原始帖子中提到的示例文件解决方案,并尝试构建和运行它。这是成功的,这使我相信问题在项目设置中。我尝试切换回Unicode类型集,但这并没有解决问题。
最后,我只是利用了示例项目,现在正在修改它以符合我的需求。我不确定需要哪些项目选项才能使其正常工作,但我几乎确定它与链接器选项中的某些内容有关。

3
当前文档说明CDialogEventHandler_CreateInstance不是Windows API函数,而是一个辅助函数,其源代码是示例项目的一部分。这就是为什么当你获取了示例项目时能够使用它,因为它只是在其中一个源文件中定义的,而你没有注意到。 - LB--

1

请稍微解释一下。 - surajs1n
提供的代码示例在今天9/8/19与Windows 10一起工作。创建一个新的Visual Studio 2017(已测试),win32 cpp项目。将默认项目代码(例如WindowsProject4.cpp)替换为来自github链接的示例代码。在#pragma comment部分中添加上面提供的库到代码中。编译,测试并且对我有效。 - user11905894

0

CDialogEventHandler_CreateInstance 是一个在微软的 CommonFileDialogue 示例应用 中定义的辅助函数。你也可以从 MSDN 页面 找到 GitHub 页面。

HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void **ppv)
{
    *ppv = NULL;
    CDialogEventHandler *pDialogEventHandler = new (std::nothrow) CDialogEventHandler();
    HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
    if (SUCCEEDED(hr))
    {
        hr = pDialogEventHandler->QueryInterface(riid, ppv);
        pDialogEventHandler->Release();
    }
    return hr;
}

-1
你在centerWnd和openDB函数中使用了函数原型(我相信这就是它们被称为的前向函数声明,即在主函数之前声明函数),但没有在CDialogEventHandler_CreateInstance函数中使用。尝试添加
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void **ppv);

void openDB();
下面。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接