Criando uma extensão de interface do usuário do minidriver WIA "Olá, Mundo"
Uma extensão de interface do usuário do minidriver WIA é uma DLL simples que exporta algumas funções e implementa pelo menos um dos quatro seguintes IID (identificadores de interface COM):
IID_IWiaUIExtension O IID (identificador de interface) para a interface IWiaUIExtension . Essa é a interface WIA padrão usada para substituir o ícone de dispositivo minidriver em Meu Computador e em Painel de Controle e substituir as caixas de diálogo de interface do usuário do minidriver comum da Microsoft.
IID_IShellExtInit O IID para a interface IShellExtInit . Essa é a interface padrão do Windows Shell usada para inicializar extensões do Shell para folhas de propriedades, menus de atalho e manipuladores de arrastar e soltar (extensões que adicionam itens a menus de atalho durante operações de arrastar e soltar não padrão).
IID_IContextMenu O IID para a interface ContextMenu . Essa é a interface padrão do Windows Shell usada para criar ou mesclar um menu de atalho associado a um objeto Shell (o ícone do minidriver WIA em Meu Computador e em Painel de Controle).
IID_IShellPropSheet O IID para a interface IShellPropSheet . Essa é a interface padrão do Windows Shell usada para adicionar ou substituir páginas na folha de propriedades exibida para um objeto Shell (o ícone do minidriver WIA em Meu Computador e Painel de Controle).
A extensão de interface do usuário do minidriver WIA "Olá, Mundo" consiste nos seguintes arquivos:
hellowld.inf Este é o arquivo de instalação (modificado para instalar essa extensão de interface do usuário com o exemplo hellowld original).
hellowldui.def Este é o arquivo de definição que contém as duas exportações COM, DllGetClassObject e DllCanUnloadNow (ambas são descritas na documentação do SDK do Windows).
hellowldui.cpp Essa é a implementação da extensão de interface do usuário do WIA.
Instalando extensões de interface do usuário do WIA
Para instalar uma DLL de extensão de interface do usuário wia, adicione ID da classe de interface do usuário={<CLSID da DLL da sua extensão> de interface do usuário} ao arquivo INF na seção DeviceData . Esse CLSID permite que os clientes chamem CoCreateInstance (descrito na documentação do SDK do Microsoft Windows) e obtenham as interfaces com suporte da extensão de interface do usuário do WIA.
O snippet INF de exemplo a seguir é derivado do exemplo de minidriver WIA em Criando um minidriver WIA 'Olá, Mundo'. O CLSID usado por padrão deve ser o CLSID fornecido pela Microsoft para caixas de diálogo, ícones e páginas de propriedades comuns.
É recomendável que todas as DLLs de extensão de interface do usuário do WIA sejam objetos COM de registro automático, para promover uma instalação mais fácil. Este exemplo não contém um objeto COM de auto-registro.
[WIADevice.DeviceData]
Server=local
UI DLL=sti.dll
UI Class ID={4DB1AD10-3391-11D2-9A33-00C04FA36145}
O exemplo a seguir é um arquivo INF completo que define a subchave ID da Classe de Interface do Usuário como o CLSID da Extensão de interface do usuário de exemplo hellowldui .
; HELLOWLD.INF -- Hello World WIA Minidriver setup file (with a WIA UI extension DLL)
; Copyright (c) 2002 Hello World Company
; Manufacturer: Hello World Company
[Version]
Signature="$WINDOWS NT$"
Class=Image
ClassGUID={6bdd1fc6-810f-11d0-bec7-08002be2092f}
Provider=%Mfg%
DriverVer=06/26/2001,1.0.0.0
CatalogFile=wia.cat
PnpLockdown=1
[DestinationDirs]
DefaultDestDir=13
[Manufacturer]
%Mfg%=Models,NTx86
[Models.NTx86]
%WIADevice.DeviceDesc% = WIADevice.Scanner, HELLOWORLD_PNP_ID
[WIADevice.Scanner]
Include=sti.inf
Needs=STI.SerialSection
SubClass=StillImage
DeviceType=1
DeviceSubType=0x0
Capabilities=0x30
DeviceData=WIADevice.DeviceData
AddReg=WIADevice.AddReg
CopyFiles=WIADevice.CopyFiles
ICMProfiles="sRGB Color Space Profile.icm"
[WIADevice.Scanner.Services]
Include=sti.inf
Needs=STI.SerialSection.Services
[WIADevice.DeviceData]
Server=local
UI DLL=sti.dll
UI Class ID={7C1E2309-A535-45b1-94B3-9A020EE600C7}
[WIADevice.AddReg]
HKR,,HardwareConfig,1,1
HKR,,USDClass,,"{7C1E2309-A535-45b1-94B3-9A020EE600C6}"
HKCR,CLSID\{7C1E2309-A535-45b1-94B3-9A020EE600C6},,,"Hello World WIA Minidriver"
HKCR,CLSID\{7C1E2309-A535-45b1-94B3-9A020EE600C6}\InProcServer32,,,%13%\hellowld.dll
HKCR,CLSID\{7C1E2309-A535-45b1-94B3-9A020EE600C6}\InProcServer32,ThreadingModel,,Both
HKCR,CLSID\{7C1E2309-A535-45b1-94B3-9A020EE600C7},,,"Hello World WIA Minidriver UI Extension"
HKCR,CLSID\{7C1E2309-A535-45b1-94B3-9A020EE600C7}\InProcServer32,,,%13%\hellowldui.dll
HKCR,CLSID\{7C1E2309-A535-45b1-94B3-9A020EE600C7}\InProcServer32,ThreadingModel,,Both
HKCR,CLSID\{7C1E2309-A535-45b1-94B3-9A020EE600C7}\shellex\WiaDialogExtensionHandlers\{7C1E2309-A535-45b1-94B3-9A020EE600C7}
[WIADevice.CopyFiles]
hellowld.dll
hellowldui.dll
[SourceDisksFiles.x86]
hellowld.dll=1
hellowldui.dll=1
[SourceDisksNames.x86]
1=%Location%,,,
[Strings]
Mfg="Hello World Company"
WIADevice.DeviceDesc="Hello World WIA Minidriver"
Location="Hello World WIA Minidriver Installation Source"
O arquivo hellowldui.def deve conter o seguinte código:
LIBRARY HELLOWLDUI
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
O arquivo hellowldui.cpp deve conter o seguinte código:
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <initguid.h>
#include <wiadevd.h>
#include <shobjidl.h>
#include <shlobj.h>
// {7C1E2309-A535-45b1-94B3-9A020EE600C7}
DEFINE_GUID(CLSID_HelloWorldWIAUIExtension, 0x7c1e2309, 0xa535, 0x45b1, 0x94, 0xb3, 0x9a, 0x2, 0xe, 0xe6, 0x0, 0xc7);
class CWIAUIExtension : public IWiaUIExtension, // WIA UI Extension interface
public IShellExtInit, // SHELL Extension interface
public IContextMenu, // SHELL context menu Extension interface
public IShellPropSheetExt // SHELL property sheet interface
{
public:
/////////////////////////////////////////////////////////////////////////
// Construction/Destruction Section //
/////////////////////////////////////////////////////////////////////////
CWIAUIExtension() : m_cRef(1) {
}
~CWIAUIExtension() {
}
private:
LONG m_cRef; // object reference count.
public:
/////////////////////////////////////////////////////////////////////////
// Standard COM Section //
/////////////////////////////////////////////////////////////////////////
STDMETHODIMP QueryInterface(REFIID riid,LPVOID *ppvObj)
{
if (!ppvObj) {
return E_INVALIDARG;
}
*ppvObj = NULL;
if (IsEqualIID( riid, IID_IUnknown )) {
*ppvObj = reinterpret_cast<IUnknown*>(this);
} else if (IsEqualIID( riid, IID_IWiaUIExtension )) {
*ppvObj = static_cast<IWiaUIExtension*>(this);
} else {
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppvObj)->AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) Release()
{
if(InterlockedDecrement(&m_cRef) == 0) {
delete this;
return 0;
}
return m_cRef;
}
/////////////////////////////////////////////////////////////////////////
// IWiaUIExtension Interface Section //
/////////////////////////////////////////////////////////////////////////
STDMETHODIMP DeviceDialog( PDEVICEDIALOGDATA pDeviceDialogData ) {return E_NOTIMPL;}
STDMETHODIMP GetDeviceIcon( BSTR bstrDeviceId, HICON *phIcon, ULONG nSize ){
HRESULT hr = E_NOTIMPL;
HICON hIcon = reinterpret_cast<HICON>(LoadImage(NULL,
MAKEINTRESOURCE(IDI_APPLICATION),
IMAGE_ICON,
nSize,
nSize,
LR_SHARED));
if (hIcon) {
*phIcon = CopyIcon(hIcon);
hIcon = NULL;
hr = S_OK;
}
return hr;
}
STDMETHODIMP GetDeviceBitmapLogo( BSTR bstrDeviceId, HBITMAP *phBitmap, ULONG nMaxWidth, ULONG nMaxHeight ){return E_NOTIMPL;}
/////////////////////////////////////////////////////////////////////////
// IShellExtInit Interface Section //
/////////////////////////////////////////////////////////////////////////
STDMETHODIMP Initialize (LPCITEMIDLIST pidlFolder,LPDATAOBJECT lpdobj,HKEY hkeyProgID){return E_NOTIMPL;}
/////////////////////////////////////////////////////////////////////////
// IContextMenu Interface Section //
/////////////////////////////////////////////////////////////////////////
STDMETHODIMP QueryContextMenu (HMENU hmenu,UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags) {return E_NOTIMPL;}
STDMETHODIMP InvokeCommand (LPCMINVOKECOMMANDINFO lpici){return E_NOTIMPL;}
STDMETHODIMP GetCommandString (UINT_PTR idCmd, UINT uType,UINT* pwReserved,LPSTR pszName,UINT cchMax) {return E_NOTIMPL;}
/////////////////////////////////////////////////////////////////////////
// IShellPropSheetExt Interface Section //
/////////////////////////////////////////////////////////////////////////
STDMETHODIMP AddPages (LPFNADDPROPSHEETPAGE lpfnAddPage,LPARAM lParam){return E_NOTIMPL;}
STDMETHODIMP ReplacePage (UINT uPageID,LPFNADDPROPSHEETPAGE lpfnReplacePage,LPARAM lParam) {return E_NOTIMPL;}
};
/////////////////////////////////////////////////////////////////////////
// IClassFactory Interface Section (for all COM objects) //
/////////////////////////////////////////////////////////////////////////
class CWIAUIClassFactory : public IClassFactory {
public:
CWIAUIClassFactory() : m_cRef(1) {}
~CWIAUIClassFactory(){}
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv)
{
if (!ppv) {
return E_INVALIDARG;
}
*ppv = NULL;
HRESULT hr = E_NOINTERFACE;
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) {
*ppv = static_cast<IClassFactory*>(this);
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
hr = S_OK;
}
return hr;
}
STDMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&m_cRef);
}
STDMETHODIMP_(ULONG) Release()
{
if(InterlockedDecrement(&m_cRef) == 0) {
delete this;
return 0;
}
return m_cRef;
}
STDMETHODIMP CreateInstance(IUnknown __RPC_FAR *pUnkOuter,REFIID riid,void __RPC_FAR *__RPC_FAR *ppvObject)
{
if ((pUnkOuter)&&(!IsEqualIID(riid,IID_IUnknown))) {
return CLASS_E_NOAGGREGATION;
}
HRESULT hr = E_NOINTERFACE;
CWIAUIExtension *pUIExt = new CWIAUIExtension();
if (pUIExt) {
hr = pUIExt->QueryInterface(riid,ppvObject);
pUIExt->Release();
} else {
hr = E_OUTOFMEMORY;
}
return hr;
}
STDMETHODIMP LockServer(BOOL fLock){return S_OK;}
private:
LONG m_cRef;
};
/////////////////////////////////////////////////////////////////////////
// DLL Entry Point Section (for all COM objects, in a DLL) //
/////////////////////////////////////////////////////////////////////////
extern "C" __declspec(dllexport) BOOL APIENTRY DllEntryPoint(HINSTANCE hinst,DWORD dwReason,LPVOID lpReserved)
{
switch (dwReason) {
case DLL_PROCESS_ATTACH:
break;
}
return TRUE;
}
extern "C" STDMETHODIMP DllCanUnloadNow(void){return S_OK;}
extern "C" STDAPI DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv)
{
if (!ppv) {
return E_INVALIDARG;
}
HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
if (IsEqualCLSID(rclsid, CLSID_HelloWorldWIAUIExtension)) {
CWIAUIClassFactory *pcf = new CWIAUIClassFactory;
if (pcf) {
hr = pcf->QueryInterface(riid,ppv);
pcf->Release();
} else {
hr = E_OUTOFMEMORY;
}
}
return hr;
}
Adicionando um ícone de dispositivo personalizado
O exemplo anterior é um exemplo de como substituir o ícone padrão para seu dispositivo. Substituir o ícone padrão pode ser uma maneira ideal de orientar o usuário no uso do dispositivo correto se houver mais de um dispositivo instalado. Ele será mais intuitivo para o usuário se o ícone se assemelhar ao dispositivo anexado.