原嘗試用 .ocx 控件傳遞自訂結構,發現無能為力。最終採用 VC++ 6.0 ATL 開發組件。應用於配電自動化饋線自動化 (FA) 功能,自行設計開發。
客戶端調用組件函數 SendData、ReceiveData 的完整代碼:
struct Line {
long id; // ID 號
BOOL Power; // 有電標志
BSTR LineName; // 線路名稱
long StaPoint_x; // 起點 X
long StaPoint_y; // 起點 Y
long EndPoint_x; // 終點 X
long EndPoint_y; // 終點 Y
short EndType; // 1負荷 2電源 0其他
long Longth;
BOOL ShCirFlag; // 短路標志
};
struct Dot {
long id;
BOOL Power; // 開合標志
BSTR DotName; // 線路名稱
long StaPoint_x;
long StaPoint_y;
long EndPoint_x;
long EndPoint_y;
short DotType; // 0不可遙控 1可遙控 2刀閘 3節點 4變壓器
short HighCurrent; // 過流標志 -1無數據 >=0有數據
BOOL CutFlag; // 跳閘標志
};
// --- 發送 Line 陣列 ---
VARIANT LineVal;
SAFEARRAY FAR* pLSA = NULL;
SAFEARRAYBOUND dimension[1];
dimension[0].lLbound = 0;
dimension[0].cElements = MAX * 10;
pLSA = SafeArrayCreate(VT_BSTR, 1, dimension); // 注意:此處 VT_BSTR 實為佔位,實際存結構指標
Line FAR* pLineData = NULL;
::SafeArrayAccessData(pLSA, (void HUGEP* FAR*)&pLineData);
for (i = 0; i < MAX; i++) {
pLineData[i].StaPoint_x = LineData[i].StaPoint_x;
pLineData[i].StaPoint_y = LineData[i].StaPoint_y;
pLineData[i].EndPoint_x = LineData[i].EndPoint_x;
pLineData[i].EndPoint_y = LineData[i].EndPoint_y;
pLineData[i].EndType = LineData[i].EndType;
pLineData[i].id = LineData[i].id;
pLineData[i].LineName = LineData[i].LineName;
pLineData[i].Longth = LineData[i].Longth;
pLineData[i].Power = LineData[i].Power;
pLineData[i].ShCirFlag = LineData[i].ShCirFlag;
}
::SafeArrayUnaccessData(pLSA);
LineVal.vt = VT_ARRAY;
LineVal.parray = pLSA;
// --- 發送 Dot 陣列 (同理) ---
VARIANT DotVal;
SAFEARRAY FAR* pDSA = NULL;
Dot FAR* pDotData = NULL;
pDSA = SafeArrayCreate(VT_BSTR, 1, dimension);
::SafeArrayAccessData(pDSA, (void HUGEP* FAR*)&pDotData);
for (i = 0; i < MAX; i++) {
pDotData[i].CutFlag = DotData[i].CutFlag;
pDotData[i].DotName = DotData[i].DotName;
pDotData[i].DotType = DotData[i].DotType;
pDotData[i].StaPoint_x = DotData[i].StaPoint_x;
pDotData[i].StaPoint_y = DotData[i].StaPoint_y;
pDotData[i].EndPoint_x = DotData[i].EndPoint_x;
pDotData[i].EndPoint_y = DotData[i].EndPoint_y;
pDotData[i].HighCurrent = DotData[i].HighCurrent;
pDotData[i].id = DotData[i].id;
pDotData[i].Power = DotData[i].Power;
}
::SafeArrayUnaccessData(pDSA);
DotVal.vt = VT_ARRAY;
DotVal.parray = pDSA;
// --- 呼叫組件 ---
result = qfa.SendData(LineVal, DotVal, 3);
// --- 接收回傳數據 ---
long LineCount, DotCount;
SAFEARRAY FAR* pReLSA = NULL;
SAFEARRAY FAR* pReDSA = NULL;
Line* pLData = NULL;
Dot* pDData = NULL;
qfa.ReceiveData(&LineVal, &LineCount, &DotVal, &DotCount);
pReLSA = LineVal.parray;
pReDSA = DotVal.parray;
::SafeArrayAccessData(pReDSA, (void HUGEP* FAR*)&pDotData);
::SafeArrayUnaccessData(pReDSA);
// 後續處理接收數據...
typedef
[
uuid(D124B04A-C5F9-4a16-9671-1E67B75DB1A1),
helpstring("NetWork Node Struct")
]
struct Line {
long id;
BOOL Power;
BSTR LineName;
long StaPoint_x;
long StaPoint_y;
long EndPoint_x;
long EndPoint_y;
short EndType;
long Longth;
BOOL ShCirFlag;
} Line;
typedef
[
uuid(D124B04A-C5F9-4a16-9671-1E67B75DB1A2),
helpstring("NetWork Node Struct")
]
struct Dot {
long id;
BOOL Power;
BSTR DotName;
long StaPoint_x;
long StaPoint_y;
long EndPoint_x;
long EndPoint_y;
short DotType;
short HighCurrent;
BOOL CutFlag;
} Dot;
定義後即可在介面方法中直接使用 Line、Dot 類型。
regsvr32 c:\qfa2004.dll (路徑自行調整)。QFA2004 源碼不公開,請見諒。本文展示的方法雖可行,但 SafeArrayCreate(VT_BSTR...) 存放結構指標屬於「非常規用法」,可能存在跨進程封送問題。更標準的做法包括:
VT_RECORD 搭配 IRecordInfo 正確描述結構佈局(需 MIDL 支援 UDT)。size_is) 效能最佳。歡迎高手提供更優雅的自訂結構傳遞方案。