最近接到一个任务
开发POS系统打印机的OPOS driver,用ATL COM撰写 service object
搞得头都大了,查了很多资料,知道了大致的流程。
CO组件是通用的,有现成的可以下。SO就要自已写了。
于是用VC写了一个ATL 的DLL(第一次写,什么都不懂),编译完成注册,先在VB中试一下,工程引用新建的ATL COM 库,在代码中可以new出来并调用相应的方法。但是通过OCX就不行了,未提供所需的方法。资料介绍: 应用程序调用 CO 的 open(deviceName)方法
CO 通过RegQueryValueEx 读注册表,得到SO的ProgID, 再用CLSIDFromProgID 得到SO的 CLSID, 再
CoCreateInstance 和 QueryInterface 得到SO的接口, 通过GetIDsOfNames,Invoke调用SO接口中的函数
OpenService(deviceClass,deviceName,pDispatch)打开设备。所有这些,都是现成的,不用做,我要做的只是一个SO
但问题来了,这个SO我是不是需要重写QueryInterface,GetIDsOfName和Invoke函数?要怎么写?还是根本不需要,IDE自动完成了?希望哪位大侠能拉小弟一把。资料上写OCX固定在注册表项[ HKEY_LOCAL_MACHINE\SOFTWARE\OLEforRetail\ServiceOPOS\POSPrinter ]
"Unit1"="MyPrinter"
[ HKEY_LOCAL_MACHINE\SOFTWARE\OLEforRetail\ServiceOPOS\POSPrinter\MyPrinter ]
@="XXXX.POSPrinter.1"找到unit1对应的SO
我手工建好这些项了,"XXXX.POSPrinter.1"是ATL DLL注册后的ProID
但那个OCX就是报找不到,肯定是SO写的不好,但不知道问题出在哪里,好郁闷哦。
// SoCitaqPtr.idl : IDL source for SoCitaqPtr.dll
//// This file will be processed by the MIDL tool to
// produce the type library (SoCitaqPtr.tlb) and marshalling code.import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(2BF8F234-1C69-451B-B70F-83237FDE7E29),
dual,
helpstring("Iposprinter Interface"),
pointer_default(unique)
]
interface Iposprinter : IDispatch
{
[id(1), helpstring("method OpenService")] HRESULT OpenService([in] BSTR DeviceClass, [in] BSTR DeviceName, [in] IDispatch* pDispatch,[out,retval] long* pRC);
[id(2), helpstring("method GetOpenResult")] HRESULT GetOpenResult([out,retval] long* pRC);
};[
uuid(641254CF-5ACA-4ECA-BCFF-327F69F3A13A),
version(1.0),
helpstring("SoCitaqPtr 1.0 Type Library")
]
library SOCITAQPTRLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb"); [
uuid(D4CB9470-7E8C-442D-8465-72B377BA865F),
helpstring("posprinter Class")
]
coclass posprinter
{
[default] interface Iposprinter;
};
};// posprinter.h : Declaration of the Cposprinter#ifndef __POSPRINTER_H_
#define __POSPRINTER_H_#include "resource.h" // main symbols/////////////////////////////////////////////////////////////////////////////
// Cposprinter
class ATL_NO_VTABLE Cposprinter :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<Cposprinter, &CLSID_posprinter>,
public IDispatchImpl<Iposprinter, &IID_Iposprinter, &LIBID_SOCITAQPTRLib>
{
public:
Cposprinter()
{
}DECLARE_REGISTRY_RESOURCEID(IDR_POSPRINTER)DECLARE_PROTECT_FINAL_CONSTRUCT()BEGIN_COM_MAP(Cposprinter)
COM_INTERFACE_ENTRY(Iposprinter)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()// Iposprinter
public:
STDMETHOD(OpenService)(/*[in]*/ BSTR DeviceClass, /*[in]*/ BSTR DeviceName, /*[in]*/ IDispatch* pDispatch,/*[out,retval]*/ long* pRC);
STDMETHOD(GetOpenResult)(/*[out,retval]*/ long* pRC);};#endif //__POSPRINTER_H_
开发POS系统打印机的OPOS driver,用ATL COM撰写 service object
搞得头都大了,查了很多资料,知道了大致的流程。
CO组件是通用的,有现成的可以下。SO就要自已写了。
于是用VC写了一个ATL 的DLL(第一次写,什么都不懂),编译完成注册,先在VB中试一下,工程引用新建的ATL COM 库,在代码中可以new出来并调用相应的方法。但是通过OCX就不行了,未提供所需的方法。资料介绍: 应用程序调用 CO 的 open(deviceName)方法
CO 通过RegQueryValueEx 读注册表,得到SO的ProgID, 再用CLSIDFromProgID 得到SO的 CLSID, 再
CoCreateInstance 和 QueryInterface 得到SO的接口, 通过GetIDsOfNames,Invoke调用SO接口中的函数
OpenService(deviceClass,deviceName,pDispatch)打开设备。所有这些,都是现成的,不用做,我要做的只是一个SO
但问题来了,这个SO我是不是需要重写QueryInterface,GetIDsOfName和Invoke函数?要怎么写?还是根本不需要,IDE自动完成了?希望哪位大侠能拉小弟一把。资料上写OCX固定在注册表项[ HKEY_LOCAL_MACHINE\SOFTWARE\OLEforRetail\ServiceOPOS\POSPrinter ]
"Unit1"="MyPrinter"
[ HKEY_LOCAL_MACHINE\SOFTWARE\OLEforRetail\ServiceOPOS\POSPrinter\MyPrinter ]
@="XXXX.POSPrinter.1"找到unit1对应的SO
我手工建好这些项了,"XXXX.POSPrinter.1"是ATL DLL注册后的ProID
但那个OCX就是报找不到,肯定是SO写的不好,但不知道问题出在哪里,好郁闷哦。
// SoCitaqPtr.idl : IDL source for SoCitaqPtr.dll
//// This file will be processed by the MIDL tool to
// produce the type library (SoCitaqPtr.tlb) and marshalling code.import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(2BF8F234-1C69-451B-B70F-83237FDE7E29),
dual,
helpstring("Iposprinter Interface"),
pointer_default(unique)
]
interface Iposprinter : IDispatch
{
[id(1), helpstring("method OpenService")] HRESULT OpenService([in] BSTR DeviceClass, [in] BSTR DeviceName, [in] IDispatch* pDispatch,[out,retval] long* pRC);
[id(2), helpstring("method GetOpenResult")] HRESULT GetOpenResult([out,retval] long* pRC);
};[
uuid(641254CF-5ACA-4ECA-BCFF-327F69F3A13A),
version(1.0),
helpstring("SoCitaqPtr 1.0 Type Library")
]
library SOCITAQPTRLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb"); [
uuid(D4CB9470-7E8C-442D-8465-72B377BA865F),
helpstring("posprinter Class")
]
coclass posprinter
{
[default] interface Iposprinter;
};
};// posprinter.h : Declaration of the Cposprinter#ifndef __POSPRINTER_H_
#define __POSPRINTER_H_#include "resource.h" // main symbols/////////////////////////////////////////////////////////////////////////////
// Cposprinter
class ATL_NO_VTABLE Cposprinter :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<Cposprinter, &CLSID_posprinter>,
public IDispatchImpl<Iposprinter, &IID_Iposprinter, &LIBID_SOCITAQPTRLib>
{
public:
Cposprinter()
{
}DECLARE_REGISTRY_RESOURCEID(IDR_POSPRINTER)DECLARE_PROTECT_FINAL_CONSTRUCT()BEGIN_COM_MAP(Cposprinter)
COM_INTERFACE_ENTRY(Iposprinter)
COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()// Iposprinter
public:
STDMETHOD(OpenService)(/*[in]*/ BSTR DeviceClass, /*[in]*/ BSTR DeviceName, /*[in]*/ IDispatch* pDispatch,/*[out,retval]*/ long* pRC);
STDMETHOD(GetOpenResult)(/*[out,retval]*/ long* pRC);};#endif //__POSPRINTER_H_
如果想很快上手,建议用MFC。第一次写COM的话自己手动编写COM+nt service可能还要来得快些。
而后再用ATL才会发现它的妙味。
可以参考《atl开发指南》
有电子版的
还可以到codeproject上 http://www.codeproject.com/KB/atl/SimpleATLCom.aspx
照着做一遍就会了