項目中用到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