描述:
最近接到一个任务
开发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_
解决方案1:
打印的程序网上有现成的
可以参考《atl开发指南》
有电子版的
还可以到codeproject上 http://www.codeproject.com/KB/atl/SimpleATLCom.aspx
照着做一遍就会了
这个打印机厂家会提供的,不需要自己写
解决方案3: ATL不是简单易用的东西,它设计给懂COM的人用的,强调的是性能。
如果想很快上手,建议用MFC。第一次写COM的话自己手动编写COM+nt service可能还要来得快些。
而后再用ATL才会发现它的妙味。
这只是一个普通的com组件,如果要实现ocx,还要实现其它的接口。
解决方案5: QueryInterface,GetIDsOfName和Invoke这些都不用写。
你可以按atl/com appwizard创建一个简单工程看看先,熟悉后再把已经有的代码加进来。