这是我第一次try 任何形式的COM.我正在try 以文件夹模式启动打开文件对话框.代码编译了,但应用程序无法启动,并且我得到了一个"Ordinal‘t Locate in the Dynamic Link Library"错误.有谁能找出可能导致这种情况的原因吗?任何帮助都将不胜感激.注意:代码基于我对MSDN示例和文档的解释.现在我知道它什么都做不了,我只是想让它显示对话框.

谢谢!

HRESULT OpenDirectory()
{
    //Initialize the COM library
    COINIT Init = COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE;
    CoInitialize(NULL);

    //CoCreate Folder Open Dialog Object
    IFileDialog *pfd = NULL;
    CLSID OpenFileID = CLSID_FileOpenDialog;
    IID IFileDialog = IID_IFileDialog;
    HRESULT hr = CoCreateInstance(&OpenFileID, NULL, CLSCTX_INPROC_SERVER, &IFileDialog, (void**) ( &pfd));
    


    if (SUCCEEDED(hr))
    {
        IFileDialogEvents *pfde = NULL;
        hr = OpenDirEventHandler(&pfde);

        if (SUCCEEDED(hr))
        {
            //Hook the Event Handler
            DWORD dwHook;
            hr = pfd->lpVtbl->Advise(pfd, pfde, &dwHook);


            if (SUCCEEDED(hr))
            {
                //flags
                DWORD dwFlags;
                hr = pfd->lpVtbl->GetOptions(pfd, &dwFlags);

                if (SUCCEEDED(hr))
                {
                    hr = pfd->lpVtbl->SetOptions(pfd, dwFlags | FOS_FORCEFILESYSTEM | FOS_PICKFOLDERS);

                    if (SUCCEEDED(hr))
                    {
                        hr = pfd->lpVtbl->Show(pfd, NULL);

                        if (SUCCEEDED(hr))
                        {
                            IShellItem *psiResult;
                            
                            hr = pfd->lpVtbl->GetResult(pfd, &psiResult);

                            // We are just going to print out the 
                                          // name of the file for sample sake.
                            PWSTR pszFilePath = NULL;
                            hr = psiResult->lpVtbl->GetDisplayName(pfd, SIGDN_FILESYSPATH,
                                &pszFilePath);
                            
                            if (SUCCEEDED(hr))
                            {
                                TaskDialog(NULL,
                                    NULL,
                                    L"CommonFileDialogApp",
                                    pszFilePath,
                                    NULL,
                                    TDCBF_OK_BUTTON,
                                    TD_INFORMATION_ICON,
                                    NULL);
                                CoTaskMemFree(pszFilePath);
                            }
                            psiResult->lpVtbl->Release(psiResult);
                        }
                    }
                }

            }
            pfd->lpVtbl->Unadvise(pfd, dwHook);
        }
        pfde->lpVtbl->Release(pfde);
    }
    pfd->lpVtbl->Release(pfd);


    return 0;
}


HRESULT STDMETHODCALLTYPE FileOK(IFileDialog *pfd)
{
    return 0;
}

HRESULT STDMETHODCALLTYPE SelectionChange(IFileDialog *pfd)
{
    return 0;
}

HRESULT STDMETHODCALLTYPE DirOverwrite(IFileDialog *pfd)
{
    return 0;
}

 OpenDirEventHandler(IFileDialogEvents *pfde)
{
     pfde->lpVtbl->OnFileOk = &FileOK;
     pfde->lpVtbl->OnSelectionChange = &SelectionChange;
     pfde->lpVtbl->OnOverwrite = &DirOverwrite;
}

推荐答案

"无法在动态链接库中找到顺序"错误是因为TaskDialog需要链接到公共控件DLL,您可以按照此处的说明修复DLL https://stackoverflow.com/a/4308532/403671,即在代码中添加以下行:

#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

或者使用app.manifest文件,如下所述:Enabling Visual Styles

然后你必须完全实现一个对外公开的COM接口,你不能仅仅实现你需要的方法,你必须正确地初始化v表,例如,如下所示:

IFileDialogEvents pfde;

// build the full v-table
pfde.lpVtbl = malloc(sizeof(IFileDialogEventsVtbl)); // make sure you free sometimes in the future
pfde.lpVtbl->AddRef = &OnAddRefOrRelease;
pfde.lpVtbl->Release = &OnAddRefOrRelease;
pfde.lpVtbl->QueryInterface = &OnQueryInterface;
pfde.lpVtbl->OnFolderChange = &OnFolderChange;
pfde.lpVtbl->OnFolderChanging = &OnFolderChanging;
pfde.lpVtbl->OnSelectionChange = &OnSelectionChange;
pfde.lpVtbl->OnOverwrite = &OnOverwrite;
pfde.lpVtbl->OnFileOk = &OnFileOk;
pfde.lpVtbl->OnTypeChange = &OnTypeChange;
pfde.lpVtbl->OnShareViolation = &OnShareViolation;

// hook the Event Handler
DWORD dwHook;
hr = pfd->lpVtbl->Advise(pfd, &pfde, &dwHook);

现在,对于每个方法,您必须声明接口定义声明的所有参数,包括作为第一个参数的"this"指针,如下所示:

HRESULT STDMETHODCALLTYPE OnFolderChanging(IFileDialogEvents* this, IFileDialog* pfd, IShellItem* psiFolder)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE OnFolderChange(IFileDialogEvents* this, IFileDialog* pfd)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE OnShareViolation(IFileDialogEvents* this, IFileDialog* pfd, FDE_SHAREVIOLATION_RESPONSE* pResponse)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE OnTypeChange(IFileDialogEvents* this, IFileDialog* pfd)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE OnFileOk(IFileDialogEvents* this, IFileDialog* pfd)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE OnSelectionChange(IFileDialogEvents* this, IFileDialog* pfd)
{
    return S_OK;
}

HRESULT STDMETHODCALLTYPE OnOverwrite(IFileDialogEvents* this, IFileDialog* pfd, IShellItem* psi, FDE_OVERWRITE_RESPONSE* pResponse)
{
    return S_OK;
}

ULONG STDMETHODCALLTYPE OnQueryInterface(IFileDialogEvents* this, REFIID riid, void** ppvObject)
{
    if (riid == &IID_IFileDialogEvents)
    {
        *ppvObject = this;
        return S_OK;
    }
    return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE OnAddRefOrRelease(IFileDialogEvents* this)
{
    // this is a hack, ok for sample, implement it properly
    return 1;
}

然后,在GetDisplayName中有一个错误,你必须总是传递"this"(这里是psiResult)作为第一个参数:

hr = psiResult->lpVtbl->GetDisplayName(psiResult, SIGDN_FILESYSPATH, &pszFilePath);

C++相关问答推荐

以c格式打印时间戳

字符数组,字符指针,在一种情况下工作,但在另一种情况下不工作?

在32位处理器上优化53—32位模计算>

在C中使用动态内存分配找到最小的负数

使用GOTO从多个嵌套循环C继续

如何在C宏中确定 struct 中元素的类型?

为什么我一直收到分段错误?

tick.q中的Kdb+键控表语法

如何仅使用软件重新初始化STM32微控制器中的USB枚举?

接受任何参数的函数指针是否与接受不同参数的函数兼容

处理来自浏览器的HTTP请求

C程序向服务器发送TCPRST

C中的回文数字

使用mmap为N整数分配内存

如何编写postgresql支持函数

浮点正零何时不全为零?

我正在使用 klib 库 我可以使用 (khash) KHASH_SET_INIT_INT64() 负值作为键.因为我在头文件中看到它使用 unsigned long int

一元运算符

#define X Defined(Y) 是有效的 C/C++ 宏定义吗?

当 a 是代码块时使用逗号运算符 (a, b)