VC自動化嚮導的bug2(vs2005使用Labview控件類時的錯誤)

   項目中用到Labview的slider控件,需要在程序中控制slider填充區域的顏色(圖中綠色區域)
.
   顏色參數爲屬性分組中的Pointer中的FillColor屬性.

   查找slider類的成員函數,希望找到能設置FillColor的函數,發現其中並沒有直接設置的函數,但有一個獲取CwPointer指針的函數

CWPointer * GetActivePointer()
{
	CWPointer * result;
	GetProperty(0x105, VT_DISPATCH, (void*)&result);
	return result;
}
   接着查找CwPointer的成員變量,發現了設置FillColor屬性的方法

CWPointer : IDispatch
{
    OLE_COLOR GetFillColor ( );
    void PutFillColor ( OLE_COLOR _val );
  於是嘗試先通過slider變量獲取Cwpointer屬性,在調用Cwpointer的方法設置顏色,結果程序報錯:提示CwPointer類爲抽象類,不能實例化。由此發現了vs2005自動化嚮導的一個Bug:沒有正確的定義控件類包含的所有接口類(根本就沒有定義),需要自己手動添加這些接口類。

   手動添加接口類的方法:類視圖->添加類->MFC->TypeLib中的MFC類


   在類型庫中找到National Instrucments UI

   接口中找到CwPointer,生成類:

   查看剛剛添加的類,發現內部居然是CwBinding_CI的方法

// CCWPointer 包裝類

class CCWPointer : public COleDispatchDriver
{
public:
	CCWPointer(){} // 調用 COleDispatchDriver 默認構造函數
	CCWPointer(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
	CCWPointer(const CCWPointer& dispatchSrc) : COleDispatchDriver(dispatchSrc) {}

	// 屬性
public:

	// 操作
public:


	// CWBinding_CI 方法
public:
	CString get_BindProperty()
	{
		CString result;
		InvokeHelper(0x2, DISPATCH_PROPERTYGET, VT_BSTR, (void*)&result, NULL);
		return result;
	}
	void put_BindProperty(LPCTSTR newValue)
	{
		static BYTE parms[] = VTS_BSTR ;
		InvokeHelper(0x2, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue);
	}

   而不是Cwpointer的方法,由此發現自動化嚮導的第二個Bug:添加的接口類名稱與內部方法不匹配,是錯亂的。之後爲了找到真正的CwPointer方法類,將所有的接口都生成類,發現其類名和內部方法全是不匹配的,而且並沒有CwPointer方法。

   控件研究到這一步,似乎無法再繼續下去了,也已經對vs2005的自動化嚮導不報任何期望了(注:要不是開發Vega Pirme 2.2,必須要用vs2005,早就不用這個開發平臺了!).這時想起上一次碰到自動化嚮導的bug,是參考vc6.0中的控件類解決的。因此這次再次嘗試在VC6.0中使用slider控件並設置顏色。VS2005和VC6.0添加控件類的過程有所區別:

   vs2005:只創建slider類,類中要用到的其他接口類,一律不自動創建,而是直接定義爲tlh文件中的抽象類(根本不能實例化,無法使用);

   vc6.0:在創建slider類的同時,直接創建類中用到的其他接口類(創建的是派生自COleDispatchDriver的接口類,可直接實例化調用)。

   經查看,vc6.0生成的接口類和方法是匹配的:

class CCWPointer : public COleDispatchDriver
{
public:
	CCWPointer() {}		// Calls COleDispatchDriver default constructor
	CCWPointer(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
	CCWPointer(const CCWPointer& dispatchSrc) : COleDispatchDriver(dispatchSrc) {}

// Attributes
public:
	VARIANT GetValue();
	void SetValue(const VARIANT&);
	long GetFillStyle();
	void SetFillStyle(long);
	CString GetName();
	void SetName(LPCTSTR);
	unsigned long GetFillColor();
	void SetFillColor(unsigned long);
	long GetIndex();
	void SetIndex(long);
	long GetStyle();
	void SetStyle(long);
	BOOL GetVisible();
	void SetVisible(BOOL);
	long GetMode();
	void SetMode(long);
	unsigned long GetColor();
	void SetColor(unsigned long);
	long GetValuePairIndex();
	void SetValuePairIndex(long);

// Operations
public:
};

   於是將CCwpointer接口類拷至vs2005工程中,並對slider類做相應的修改:

CCWPointer GetActivePointer()
{
	LPDISPATCH pDispatch;
	GetProperty(0x105, VT_DISPATCH, (void*)&pDispatch);
	return CCWPointer(pDispatch);
}

   返回類型由Cwpointer*改爲CCWpointer,成功調用接口:

	m_PowerVoltSlider.SetValue(20);
	CCWPointer cwPointer = m_PowerVoltSlider.GetActivePointer();
	COLORREF colorRed = RGB(255,0,0);
	cwPointer.SetFillColor((OLE_COLOR)colorRed);

   最後:vc6.0生成的接口類也有個不影響使用的小錯誤:

void CCWPointer::SetFillColor(unsigned long propVal)
{
	SetProperty(0x4, VT_I4, propVal);
}

   方法的參數爲unsigned long型,但是SetProperty設置的屬性VI_I4是signed int型,應改爲VT_UI4.

// VARENUM usage key,
// 
// [V] - May appear in a VARIANT.
// [T] - May appear in a TYPEDESC.
// [P] - may appear in an OLE property set.
// [S] - May appear in a Safe Array.
// 
// 
VT_EMPTY            [V]   [P]         // Not specified.
VT_NULL               [V]                // SQL-style Null.
VT_I2               [V][T][P][S]      // 2-byte signed int.
VT_I4               [V][T][P][S]      // 4-byte-signed int.
VT_R4               [V][T][P][S]      // 4-byte real. 
VT_R8               [V][T][P][S]      // 8-byte real.
VT_CY               [V][T][P][S]      // Currency.
VT_DATE               [V][T][P][S]      // Date.
VT_BSTR               [V][T][P][S]      // Automation string.
VT_DISPATCH         [V][T]   [S]      // IDispatch.Far*
VT_ERROR            [V][T]   [S]      // Scodes.
VT_BOOL               [V][T][P][S]      // Boolean; True=-1, False=0.
VT_VARIANT            [V][T][P][S]      // VARIANT FAR*.
VT_DECIMAL            [V][T]   [S]      // 16 byte fixed point.
VT_RECORD            [V]   [P][S]      // User defined type
VT_UNKNOWN            [V][T]   [S]      // IUnknown FAR*.
VT_I1               [V][T]   [S]      // Char.
VT_UI1               [V][T]   [S]      // Unsigned char.
VT_UI2               [V][T]   [S]      // 2 byte unsigned int.
VT_UI4               [V][T]   [S]      // 4 byte unsigned int. 
VT_INT               [V][T]   [S]      // Signed machine int.
VT_UINT             [V][T]   [S]      // Unsigned machine int.
VT_VOID                  [T]            // C-style void.
VT_HRESULT               [T]                                    
VT_PTR                  [T]            // Pointer type.
VT_SAFEARRAY            [T]            // Use VT_ARRAY in VARIANT.
VT_CARRAY               [T]            // C-style array.
VT_USERDEFINED         [T]            // User-defined type.
VT_LPSTR               [T][P]         // Null-terminated string.
VT_LPWSTR               [T][P]         // Wide null-terminated string.
VT_FILETIME               [P]         //FILETIME
VT_BLOB                     [P]         //Length prefixed bytes
VT_STREAM                  [P]         //Name of the stream follows
VT_STORAGE                  [P]         //Name of the storage follows
VT_STREAMED_OBJECT         [P]         //Stream contains an object
VT_STORED_OBJECT         [P]         //Storage contains an object
VT_BLOB_OBJECT            [P]         //Blob contains an object
VT_CF                     [P]         //Clipboard format
VT_CLSID                  [P]         //A Class ID
VT_VECTOR                  [P]         //simple counted array
VT_ARRAY            [V]               // SAFEARRAY*.
VT_BYREF            [V]
VT_RESERVED


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章