Creazione di un'estensione dell'interfaccia utente "Hello World" WIA Minidriver
Un'estensione dell'interfaccia utente di minidriver WIA è una semplice DLL che esporta alcune funzioni e implementa almeno uno dei quattro identificatori di interfaccia COM seguenti (IID):
IID_IWiaUIExtension Identificatore dell'interfaccia (IID) per l'interfaccia IWiaUIExtension . Questa è l'interfaccia WIA standard usata per sostituire l'icona del dispositivo minidriver in My Computer e in Pannello di controllo e sostituire le finestre di dialogo comuni dell'interfaccia utente del minidriver Microsoft.
IID_IShellExtInit IID per l'interfaccia IShellExtInit . Questa è l'interfaccia standard di Windows Shell usata per inizializzare le estensioni shell per i fogli delle proprietà, i menu di scelta rapida e i gestori di trascinamento (estensioni che aggiungono elementi ai menu di scelta rapida durante operazioni di trascinamento non predefinite).
IID_IContextMenu IID per l'interfaccia ContextMenu . Questa è l'interfaccia standard di Windows Shell usata per creare o unire un menu di scelta rapida associato a un oggetto Shell (l'icona del minidriver WIA in My Computer e in Pannello di controllo).
IID_IShellPropSheet IID per l'interfaccia IShellPropSheet . Si tratta dell'interfaccia standard di Windows Shell usata per aggiungere o sostituire pagine nel foglio delle proprietà visualizzato per un oggetto Shell (icona del minidriver WIA in My Computer e Pannello di controllo).
L'estensione dell'interfaccia utente "Hello World" WIA è costituita dai file seguenti:
hellowld.inf Questo è il file di installazione (modificato per installare questa estensione dell'interfaccia utente con l'esempio hellowld originale).
hellowldui.def Questo è il file di definizione contenente le due esportazioni COM, DllGetClassObject e DllCanUnloadNow (entrambe sono descritte nella documentazione di Windows SDK).
hellowldui.cpp Questa è l'implementazione dell'estensione dell'interfaccia utente WIA.
Installazione delle estensioni dell'interfaccia utente WIA
Per installare una DLL dell'estensione dell'interfaccia utente WIA, aggiungere ID classe ui={<CLSID della DLL dell'estensione> dell'interfaccia utente} al file INF nella sezione DeviceData . Questo CLSID consente ai client di chiamare CoCreateInstance (descritto nella documentazione di Microsoft Windows SDK) e di ottenere le interfacce supportate dell'estensione dell'interfaccia utente WIA.
Il frammento di codice INF seguente è derivato dall'esempio di minidriver WIA in Creazione di un minidriver WIA 'Hello World'. Il CLSID usato per impostazione predefinita deve essere CLSID fornito da Microsoft per le finestre di dialogo, le icone e le pagine delle proprietà comuni.
È consigliabile che tutte le DLL dell'estensione dell'interfaccia utente WIA siano autoregistrazioni degli oggetti COM, per promuovere un'installazione più semplice. Questo esempio non contiene un oggetto COM autoregistrato.
[WIADevice.DeviceData]
Server=local
UI DLL=sti.dll
UI Class ID={4DB1AD10-3391-11D2-9A33-00C04FA36145}
L'esempio seguente è un file INF completo che imposta la sottochiave ID classe dell'interfaccia utente sul CLSID dell'estensione dell'interfaccia utente di esempio 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"
Il file hellowldui.def deve contenere il codice seguente:
LIBRARY HELLOWLDUI
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
Il file hellowldui.cpp deve contenere il codice seguente:
#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;
}
Aggiunta di un'icona del dispositivo personalizzata
L'esempio precedente è un esempio di come sostituire l'icona predefinita per il dispositivo. La sostituzione dell'icona predefinita può essere un modo ideale per guidare l'utente nell'uso del dispositivo corretto se è installato più di un dispositivo. Sarà più intuitivo per l'utente se l'icona è simile al dispositivo collegato.