【问题标题】:how to get printer icons如何获取打印机图标
【发布时间】:2020-01-10 16:55:03
【问题描述】:

抱歉,这可能看起来像一个重复的问题,因为发布了类似的问题,但给出的答案不完整。我想创建一个可用打印机列表,说明打印机的状态以及与每台打印机关联的图标。此时我能够获取列表及其相关状态,但失败的地方是获取图标。从之前发布的问题中,答案涉及使用 SHGetFileInfo,但是当我尝试它时,没有返回任何图标。我怀疑在调用 SHGetFileInfo 之前我需要做一些事情,因为答案包括一个涉及组合两个 PIDL 的语句,现在因为它不是实际代码而是一个我无法完全理解如何实现它的注释。 here is a link to the question

for (int i=0; i < dwReturned; i++)
{
    HICON hIcon = NULL;

    LPITEMIDLIST pidlPrinters = NULL;
    LPITEMIDLIST pidl = NULL;
    LPENUMIDLIST pEnum = NULL;
    LPSHELLFOLDER pDesktopFolder = NULL;
    IShellFolder* psfPrinters = NULL;
    STRRET strName;
    TCHAR pszDisplayName[MAX_PATH];
    HRESULT hr;
    SHFILEINFO sfi;

    hr = SHGetFolderLocation(m_pParentWnd->m_hWnd, CSIDL_PRINTERS, 0, 0, &pidlPrinters);

    if(hr == S_OK)
    {
        hr = SHGetDesktopFolder(&pDesktopFolder);
    }

    if(hr == S_OK)
    {
        hr = pDesktopFolder->BindToObject(pidlPrinters, 0, IID_IShellFolder, reinterpret_cast<void**> 
             (&psfPrinters));
    }

    if(hr == S_OK)
    {
        hr = psfPrinters->EnumObjects(m_pParentWnd->m_hWnd, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 
            &pEnum);
    }

    if(hr == S_OK)
    {
        while (pEnum->Next(1, &pidl, 0) == S_OK)
        {
            psfPrinters->GetDisplayNameOf(pidl,SHGDN_NORMAL, &strName);

            StrRetToBuf(&strName, pidl, pszDisplayName, MAX_PATH);

            //pInfo is PRINTER_INFO_2 *

            if (_wcsicmp(pszDisplayName, pInfo[i].pPrinterName) == 0)
            {
                SHGetFileInfo((LPCTSTR)pidl, 0, &sfi, sizeof(SHFILEINFO),  SHGFI_PIDL | SHGFI_ICON | 
                SHGFI_DISPLAYNAME | SHGFI_TYPENAME); 
                hIcon = sfi.hIcon;
            }

            IMalloc* Malloc = NULL;
            SHGetMalloc(&Malloc);
            Malloc->Free(pidl);
            Malloc->Release();
       }

       pDesktopFolder->Release();
       pEnum->Release();

       //Some other code
    }
}

【问题讨论】:

  • IEnumObjects::Next 返回一个相对 pidl,您需要将它与父文件夹的完整 pidl 结合起来才能得到 SHGetFileInfo 可以使用的东西。这就像拥有“file.txt”并将其添加到“c:\folder\”以获取完整路径名。您可以使用ILCombine 函数来执行此操作。
  • 感谢您的回答,但我仍然无法获得图标。它现在显示此“GlowWindow.exe 中 0x758F35D2 (KernelBase.dll) 处的第一次机会异常:0x40080201:WinRT 发起错误(参数:0x80040155、0x00000052、0x03E5F3F8)。onecore\com\combase\dcomrem\marshal.cxx(1111) )\combase.dll!753F49E8: (caller: 7538747C) ReturnHr(19) tid(1348) 80040155 Interface not registered Msg:[Failed to marshal with IID={000214EB-0000-0000-C000-000000000046}]“输出窗口
  • 不知道抱歉。不过看起来是个不同的问题。
  • 我认为 ILCombine 函数可以解决问题的任何方式,我只需要找到解决该异常的方法
  • 只要有处理异常的东西,第一次机会异常就不是问题。如果您的程序没有崩溃,我会说不要担心。

标签: winapi visual-c++ printing


【解决方案1】:

你可以使用IShellFolder::GetUIObjectOf提取图标,下面是一个例子你可以试试。

            psfPrinters->GetDisplayNameOf(pidl, SHGDN_NORMAL, &strName);

            IExtractIcon* eIcon = NULL;
            hr = psfPrinters->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pidl, IID_IExtractIcon, NULL, reinterpret_cast<void**>(&eIcon));
            if (hr == S_OK)
            {
                WCHAR iconFileLocation[200];
                int index;
                UINT flag = 0;
                hr = eIcon->GetIconLocation(NULL, iconFileLocation, sizeof(iconFileLocation), &index, &flag);
                if (hr == S_OK)
                {
                    UINT size = 100;
                    eIcon->Extract(iconFileLocation, index, &hIcon, NULL, size);
                    if (hr == S_OK)
                    {
                        // Draw printer icon on client area for checking purpose
                        DrawIcon(hdc, xNew, y, hIcon);
                        xNew += size;
                    }
                }
            }

上述代码的示例输出:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-30
    • 2015-12-26
    • 1970-01-01
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多