Winapi 未解析外部符号_QISearch@16

Winapi 未解析外部符号_QISearch@16,winapi,linker-errors,common-dialog,Winapi,Linker Errors,Common Dialog,在过去的8个小时里,我一直在努力解决这个问题,但我在任何地方都找不到任何关于这个问题的答案 我正在尝试创建一个应用程序,可以使用“Microsoft方式”,如本文所述,打开Windows Vista和更高版本的文件对话框窗口。但是,由于以下链接器错误,我无法将代码调整到我的项目中 以下是我得到的完整链接器错误: main.obj:错误LNK2019:未解析的外部符号_QISearch@16函数“public:virtual long\u stdcall CDialogEventHandler::

在过去的8个小时里,我一直在努力解决这个问题,但我在任何地方都找不到任何关于这个问题的答案

我正在尝试创建一个应用程序,可以使用“Microsoft方式”,如本文所述,打开Windows Vista和更高版本的文件对话框窗口。但是,由于以下链接器错误,我无法将代码调整到我的项目中

以下是我得到的完整链接器错误:

main.obj:错误LNK2019:未解析的外部符号_QISearch@16函数“public:virtual long\u stdcall CDialogEventHandler::QueryInterface(struct\u GUID const&,void**)”中引用(?QueryInterface@CDialogEventHandler@@乌加巴乌@@PAPAX@Z)

下面是有问题的函数声明和定义:

// 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);
    }
最后,这里是我在main.cpp中的全部代码,请注意,许多代码取自:

#包含//用于常见的windows数据类型和函数头
#定义严格的\u类型的\u项目ID
#包括
#包含//用于COM头
#包括//用于IFileDialogEvents和IFileDialogControlEvents
#包括
#包含//用于KnownFolder API/数据类型/函数头
#包含//用于PROPVAR相关函数
#包含//属性键API/数据类型
#属性系统API的include//
#包括//用于字符串CCHPRINTFW
#包括//用于COMDLG_过滤器规格
#包括
#包括“resource.h”
#pragma注释(链接器“\”/manifestdependency:type='Win32'name='Microsoft.Windows.Common Controls'version='7.0.0.0'processorArchitecture='*'publicKeyToken='6595b64144ccf1df'language='*'\“”)
常数COMDLG_过滤器规格rgFExt[]=
{
{L“SQLite数据库(*.SQLite)”,L“*.SQLite”}
};
HWND-ghMainWnd=0;
HWND-ghtbn=0;
HINSTANCE Ghappist=0;
RECT-winRect;
PWSTR fName=NULL;
//控制
#定义控制组2000
#定义控制按钮列表2
#定义控制按钮1 1
#定义控件\u RADIOBUTTON2//此控件可以与控件\u RADIOBUTTONLIST具有相同的ID,
//因为它是control\u RADIOBUTTONLIST下的子控件
//任务对话框按钮的ID
#定义IDC_BASICFILEOPEN 100
#定义IDC_ADDITEMSTOCUSTOMPLACES 101
#定义IDC_ADDCUSTOMCONTROLS 102
#定义IDC_SETDEFAULTVALUESFORPROPERTIES 103
#使用处理程序104定义IDC_WriteProperties
#在不使用处理器的情况下定义IDC_WriteProperties 105
/*文件对话框事件处理程序*****************************************************************************************************/
类别CDIAlogeEventHandler:公共IFiledIAlogeEvents,
公共IFileDialogControlEvents
{
公众:
//未知方法
IFACEMETHODIMP查询接口(refid riid,void**ppv)
{
静态常数QITAB qit[]={
QITABENT(CDialogEventHandler,IFileDialogEvents),
QITABENT(CDialogEventHandler,IFileDialogControlEvents),
{ 0 },
};
返回QISearch(此、qit、riid、ppv);
}
IFACEMETHODIMP_ULONG)AddRef()
{
返回联锁增量(&_-cRef);
}
IFACEMETHODIMP(ULONG)发布()
{
长cRef=联锁减量(&U cRef);
如果(!cRef)
删除此项;
返回cRef;
}
//IFileDialogEvents方法
IFACEMETHODIMP OnFileOk(IFileDialog*){返回S_OK;};
ifacemethodimponfolderchange(IFileDialog*){返回S_OK;};
IFACEMETHODIMP OnFolderChanging(IFileDialog*,IShellItem*){返回S_OK;};
ifacemethodimponhelp(IFileDialog*){返回S_OK;};
IfaceMethodImponSelectionChange(IFileDialog*){返回S_OK;};
IFACEMETHODIMP OnShareViolation(iFaleDialog*、IShellItem*、FDE_SHAREVIOLATION_RESPONSE*){返回S_OK;};
IFACEMETHODIMP OnTypeChange(IFileDialog*pfd);
IFACemethodip OnOverwrite(IFileDialog*、IShellItem*、FDE_OVERWRITE_RESPONSE*){return S_OK;};
//IFileDialogControlEvents方法
如果选择了IFiceMethodImp(IFileDialogCustomize*pfdc、DWORD dwIDCtl、DWORD dwIDItem);
IfaceMethodImponButtonClicked(IFileDialogCustomize*,DWORD){返回S_OK;};
IfaceMethodImponCheckButtonggled(IFileDialogCustomize*,DWORD,BOOL){返回S_OK;};
IFACEMETHODIMP OnControlActivating(IFileDialogCustomize*,DWORD){返回S_OK;};
CDialogEventHandler():_cRef(1){};
私人:
~CDialogEventHandler(){};
长克里夫;
};
//IFileDialogEvents方法
//当文件类型更改(组合框选择更改)时,将调用此方法。
//出于示例考虑,让我们通过更改显示的属性来响应此事件。
HRESULT CDialogEventHandler::OnTypeChange(IFileDialog*pfd)
{
IFileSaveDialog*pfsd;
HRESULT hr=pfd->查询接口(&pfsd);
如果(成功(hr))
{
单位指数;
hr=pfsd->GetFileTypeIndex(&uIndex);//当前文件类型的索引
如果(成功(hr))
{
IPropertyDescriptionList*pdl=NULL;
开关(uIndex)
{
/*案例索引\u WORDDOC:
//选择.doc后,让我们询问一些任意属性,例如Title。
hr=PSGetPropertyDescriptionListFromString(L“prop:System.Title”,IID_PPV_ARGS(&pdl));
如果(成功(hr))
{
//FALSE作为第二个参数==不显示默认属性。
hr=pfsd->SetCollectedProperties(pdl,FALSE);
pdl->Release();
}
打破
案例索引_网页:
//当选择.html时,让我们询问一些其他任意属性,比如关键字。
hr=PSGetPropertyDescriptionListFromString(L“prop:System.Keywords”,IID_PPV_ARGS(&pdl));
如果(成功(hr))
{
//FALSE作为第二个参数==不显示默认属性。
#include <windows.h>      // For common windows data types and function headers
#define STRICT_TYPED_ITEMIDS
#include <shlobj.h>
#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>

#include "resource.h"

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

const COMDLG_FILTERSPEC rgFExt[] =
{
    {L"SQLite Database (*.sqlite)",       L"*.sqlite"} 
};

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

PWSTR fName = NULL;

// 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 ID as 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

/* File Dialog Event Handler *****************************************************************************************************/

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;
};

// IFileDialogEvents methods
// This method gets called when the file-type is changed (combo-box selection changes).
// For sample sake, let's react to this event by changing the properties show.
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;

            switch (uIndex)
            {
            /*case INDEX_WORDDOC:
                // When .doc is selected, let's ask for some arbitrary property, say Title.
                hr = PSGetPropertyDescriptionListFromString(L"prop:System.Title", IID_PPV_ARGS(&pdl));
                if (SUCCEEDED(hr))
                {
                    // FALSE as second param == do not show default properties.
                    hr = pfsd->SetCollectedProperties(pdl, FALSE);
                    pdl->Release();
                }
                break;

            case INDEX_WEBPAGE:
                // When .html is selected, let's ask for some other arbitrary property, say Keywords.
                hr = PSGetPropertyDescriptionListFromString(L"prop:System.Keywords", IID_PPV_ARGS(&pdl));
                if (SUCCEEDED(hr))
                {
                    // FALSE as second param == do not show default properties.
                    hr = pfsd->SetCollectedProperties(pdl, FALSE);
                    pdl->Release();
                }
                break;

            case INDEX_TEXTDOC:
                // When .txt is selected, let's ask for some other arbitrary property, say Author.
                hr = PSGetPropertyDescriptionListFromString(L"prop:System.Author", IID_PPV_ARGS(&pdl));
                if (SUCCEEDED(hr))
                {
                    // TRUE as second param == show default properties as well, but show Author property first in list.
                    hr = pfsd->SetCollectedProperties(pdl, TRUE);
                    pdl->Release();
                }*/

            default:
                break;
            }
        }
        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;
}

// Instance creation helper
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;
}


/* Common File Dialog Snippets ***************************************************************************************************/

// This code snippet demonstrates how to work with the common file dialog interface
HRESULT BasicFileOpen()
{
    // 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))
    {
        // Create an event handling object, and hook it up to the dialog.
        IFileDialogEvents *pfde = NULL;
        hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
        if (SUCCEEDED(hr))
        {
            // Hook up the event handler.
            DWORD dwCookie;
            hr = pfd->Advise(pfde, &dwCookie);
            if (SUCCEEDED(hr))
            {
                // Set the options on the dialog.
                DWORD dwFlags;

                // Before setting, always get the options first in order not to override existing options.
                hr = pfd->GetOptions(&dwFlags);
                if (SUCCEEDED(hr))
                {
                    // In this case, get shell items only for file system items.
                    hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);
                    if (SUCCEEDED(hr))
                    {
                        // Set the file types to display only. Notice that, this is a 1-based array.
                        hr = pfd->SetFileTypes(ARRAYSIZE(rgFExt), rgFExt);
                        if (SUCCEEDED(hr))
                        {
                            // Set the selected file type index to Word Docs for this example.
                            hr = pfd->SetFileTypeIndex(0);
                            if (SUCCEEDED(hr))
                            {
                                // Set the default extension to be ".doc" file.
                                hr = pfd->SetDefaultExtension(L"doc");
                                if (SUCCEEDED(hr))
                                {
                                    // Show the dialog
                                    hr = pfd->Show(NULL);
                                    if (SUCCEEDED(hr))
                                    {
                                        // Obtain the result, once the user clicks the 'Open' button.
                                        // The result is an IShellItem object.
                                        IShellItem *psiResult;
                                        hr = pfd->GetResult(&psiResult);
                                        if (SUCCEEDED(hr))
                                        {
                                            // We are just going to print out the name of the file for sample sake.
                                            PWSTR pszFilePath = NULL;
                                            hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH, &fName);
                                            if (SUCCEEDED(hr))
                                            {
                                                MessageBox(0,"File Name: " + *fName, "Success",MB_OK);
                                                CoTaskMemFree(pszFilePath);
                                            }
                                            psiResult->Release();
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                // Unhook the event handler.
                pfd->Unadvise(dwCookie);
            }
            pfde->Release();
        }
        pfd->Release();
    }
    return hr;
}

void createWnd(HINSTANCE hInst, HWND* ghMainWnd);
void createBtns(HINSTANCE hInst, HWND* ghTBtn, HWND main);

// Application entry point
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_COMMAND:
        switch(LOWORD(wParam))
        {
        case ID_FILE_OPENDB:

            BasicFileOpen();
            MessageBox(0,"Open Database option works","Msg",MB_OK);
            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;

    createWnd(ghAppInst, &ghMainWnd);

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

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

    createBtns(ghAppInst, &ghTBTN, ghMainWnd);

    if (ghTBTN == 0)
    {
        ::MessageBox(0,"CreateButton - Failed", 0,0);
    }

    ShowWindow(ghTBTN, showCmd);
    UpdateWindow(ghTBTN);
    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 createWnd(HINSTANCE hInst, HWND* ghMainWnd)
{
    HMENU mMenu = LoadMenu(hInst, 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);
}

void createBtns(HINSTANCE hInst, HWND* ghTBtn, HWND main)
{
    *ghTBtn = ::CreateWindow(WC_BUTTON, "Test Button", WS_TABSTOP|WS_VISIBLE|WS_CHILD|BS_DEFPUSHBUTTON,10,10,100,100,main,NULL,(HINSTANCE)GetWindowLong(main, GWL_HINSTANCE),NULL);
}