製作Sample軟體的SOP
開發環境:VC++6參考文件:4: CA-SDK Software Explanation(某份文件的第四章,網路找不到,要跟廣柏要)
Driver:CA-SDK 4.20
目的:在過程中熟悉VC++操作,得到初步的成就感。
聲明:
此篇文章之所有程式碼,皆由官方參考文件上剪下貼上,並無做任何修改。純粹是要練習官方參考文件中的Sample(只是它寫得很亂,所以我自己另外整理了這一篇)
我們要做出一個這樣的軟體
示範程式使用的工具:VC++6
開啟VC++之後就要開始了。
Step 1.開啟新專案
-
File→New(Ctrl+N)
- 點選Project標籤,選MCF AppWizard(exe)
- 命名:Ca200Sample
- 決定路徑:x:\xx\Ca200Sample
- 其它(Platforms要選Win32)
- OK
New對話框就出現了
第三頁Automation、ActiveX Controls打勾,其它用預設值→Next
第四頁全預設值→Next
第五頁直接Finish
OK之後就可以看見新增好的專案,如下: 可以看見有一個對話框,有一個預設的「確定」和「取消」的Button。
Step 2.新增物件
新增十個static text再新增兩個Button。
對它們其中一個按右鍵選擇Properties(屬性)
- ID是被呼叫的名字
- Caption是顯示的字(不管函數呼叫名稱)
- 設定屬性
- Static6-10的Properties選Style標籤,勾選「Sunken」它就會看起來凹下去。
- 預設的「取消鍵」的Properties選General標籤
- 取消勾選「Visible」執行程式時就看不到它了。
物件 | ID | Caption | 作用 |
State1: | IDC_STATIC | Lv: | 標示Lv |
State2: | IDC_STATIC | x: | 標示x |
State3: | IDC_STATIC | y: | 標示y |
State4: | IDC_STATIC | T: | 標示T |
State5: | IDC_STATIC | duv: | 標示duv |
State6: | IDC_STATIC_LV | NULL | 顯示Lv值 |
State7: | IDC_STATIC_X | NULL | 顯示x 值 |
State8: | IDC_STATIC_Y | NULL | 顯示y 值 |
State9: | IDC_STATIC_T | NULL | 顯示T 值 |
State10: | IDC_STATIC_DUV | NULL | 顯示 duv 值 |
button1: | IDC_BUTTON_MSR | Measure | 按 |
button2: | IDC_BUTTON_CAL0 | 0-Cal | 按 |
Step 3.準備事件觸發設定
用BN_CLICKED觸發0-Cal和Measure按View→ClassWizard(Ctrl+W)
MFC ClassWizard就出現了
- Project:Ca200Sample
- Calss name:CCa200SampleDlg(對話視窗)
- Object IDs:IDC_BUTTON_CAL0(0-Cal的按鈕物件)
- Message:BN_CLICKED(按一下的事件)
- 新增IDC_BUTTON_CAL0物件有BN_CLICKED事件的程式編輯段
- 新增IDC_BUTTON_MSR物件有BN_CLICKED事件的程式編輯段
成功之後,可以在MFC ClassWizard的「Message Maps」標籤中,下面的「member functions:」看見
在MFC ClassWizard切到Member Variables標籤
按Add Variables
新增下列的DDX(Dialog Data Exchange)成員到static text
Control IDs | Type Variable Type | Member Member variable name | Category |
IDC_STATIC_LV | CString | m_strLv | Value |
IDC_STATIC_X | CString | m_strx | Value |
IDC_STATIC_Y | CString | m_stry | Value |
IDC_STATIC_T | CString | m_strT | Value |
IDC_STATIC_DUV | CString | m_strduv | Value |
IDC_BUTTON_MSR | |||
IDC_BUTTON_CAL0 |
Step 4.事件觸發程式
貼上下列式碼將0-Cal程式段放在Cal0按鈕中執行
Ca200SampleDlg.cpp
...
void CCa200SampleDlg::OnButtonCal0()
{
// TODO: Add your control notification handler code here
// CA-SDK
try{
m_pCaObj->CalZero();
}
catch(_com_error e){
CString strerr;
strerr.Format(_T("HR:0x%08x\nMSG:%s"), e.Error(), (LPCSTR)e.Description());
AfxMessageBox((LPCSTR)strerr);
return;
}
CButton* pb;
pb = (CButton *)GetDlgItem(IDC_BUTTON_MSR);
pb->EnableWindow(TRUE);
...
}
貼上下列式碼將量測程式段放在Measure按鈕中執行
Ca200SampleDlg.cpp
...void CCa200SampleDlg::OnButtonMsr()
{
// TODO: Add your control notification handler code here
// CA-SDK
int i;
float fLv;
float fx;
float fy;
long lT;
float fduv;
for (i = 0; i < 10; i++)
{
m_pCaObj->Measure(0);
fLv = m_pProbeObj ->Lv;
fx = m_pProbeObj ->sx;
fy = m_pProbeObj ->sy;
lT = m_pProbeObj ->T;
fduv = m_pProbeObj ->duv;
m_strLv.Format("%4.2f",fLv);
m_strx.Format("%1.4f",fx);
m_stry.Format("%1.4f",fy);
m_strT.Format("%4d",lT);
m_strduv.Format("%1.4f",fduv);
UpdateData(FALSE);
}
}
...
其中m_pProbObj、m_pCaObj...等,在Step 5.會解釋怎麼出現的。
PORT_USB、SYNC_NTSC、AVRG_FAST、DSP_LXY、DIGT_4...等,會在Const.h檔裡
Step 5.儀器初始化
到主畫面中,左邊的欄位選FileView貼上下列式碼
Ca200SampleDlg.h
..
#if !defined(AFX_CA200SAMPLEDLG_H__ACD091F1_B9F2_4561_8FD0_F7D37051F8AC__INCLUDED_)
#define AFX_CA200SAMPLEDLG_H__ACD091F1_B9F2_4561_8FD0_F7D37051F8AC__INCLUDED_
//CA-SDK
#import "C:\Program Files\CA-SDK\SDK\CA200Srvr.dll" no_namespace no_implementation
...
Ca200SampleDlg.cpp
...
#include "Ca200SampleDlg.h"
#include "DlgProxy.h"
//CA-SDK
#import "C:\Program Files\CA-SDK\SDK\CA200Srvr.dll" no_namespace implementation_only
在此CA200Srvr.tlh和CA200Srvr.tli檔自動產生CA200Srvr.tli包含下列的Class
ICa200Ptr
ICasPtr(以下簡稱smart pointer)
ICa200,ICas等是由CA200Srvr.dll提供
嗯...基本上是屁話!
還是要自己Keyin進去
而且不同於上一步在MFC Wizard的Member Variables中的方式
在這好像是先建立公開的類別成員,但是並沒有對應的元件,之前的步驟有對應的元件
在Ca200SampleDlg類別原型中建立這些公開成員
Variable Type | Variable Name |
IOutputProbesPtr | m_pOutputProbesObj |
IProbesPtr | m_pProbesObj |
ICasPtr | m_pCasObj |
IMemoryPtr | m_pMemoryObj |
IProbePtr | m_pProbeObj |
ICaPtr | m_pCaObj |
ICa200Ptr | m_pCa200Obj |
進行CA儀器的初始化
Ca200SampleDlg.cpp
...
BOOL CCa200SampleDlg::OnInitDialog()
{
...
// TODO: Add extra initialization here
//CA-SDK
long lcan = 1;
_bstr_t strcnfig(_T("1"));
long lprt = PORT_USB;
long lbr = 38400;
_bstr_t strprbid(_T("P1"));
_variant_t vprbid(_T("P1"));
try
{
m_pCa200Obj = ICa200Ptr(__uuidof(Ca200));
m_pCa200Obj->SetConfiguration(lcan, strcnfig, lprt, lbr);
}
catch(_com_error e)
{
CString strerr;
strerr.Format(_T("HR:0x%08x\nMSG:%s"), e.Error(), (LPCSTR)e.Description());
AfxMessageBox((LPCSTR)strerr);
return TRUE;
}
m_pCasObj = m_pCa200Obj->Cas;
m_pCaObj = m_pCasObj ->ItemOfNumber[lcan];
m_pOutputProbesObj = m_pCaObj ->OutputProbes;
m_pOutputProbesObj ->RemoveAll();
m_pOutputProbesObj ->Add(strprbid);
m_pProbeObj = m_pOutputProbesObj ->Item[vprbid];
m_pMemoryObj = m_pCaObj->Memory;
m_pCaObj->SyncMode = SYNC_NTSC;
m_pCaObj->AveragingMode = AVRG_FAST;
m_pCaObj->SetAnalogRange(2.5, 2.5);
m_pCaObj->DisplayMode = DSP_LXY;
m_pCaObj->DisplayDigits = DIGT_4;
m_pMemoryObj->ChannelNO = 0;
return TRUE;
}
...
Step 6.Sink Object
用MFC ClassWizard建立新類別CCaEvent按Add Class→New...來新增新類別
新增一個類別CCaEvent是以CCmdTarget為基礎的類別
再來,新增CCaEvent的成員函數(Method)
到MFC ClassWizard的Automation標籤
設定Class name:CCaEvent
選Add Method...
出現對話框如下
在此設定的東西,將會出現在CCaEvent.ccp
定義CCaEvent的成員函數及內容
- External name:ExeCalZero
- Internal name:ExeCalZero
- Return type:void(無回傳值)
- 無回傳值的Method是一種介面函數,定義呼叫時要存取Class靜態成員的方法
Ca200Sample.odl
...
// Class information for CCaEvent
//CA-SDK
//[ uuid(D8D16B03-170A-4340-B718-0A4402531938) ]
[uuid(f7663750-5900-45eb-905f-78c5d5378481) ]
coclass CaEvent
{
[default] dispinterface ICaEvent;
...
IID_ICaEvent在CaEvent實現檔中,應該也要對成員函數下相同的定義。也要移除掉static繼承成員。
參考此IID也貼到下列的程式段,才會OK。
CaEvent.cpp
...
//CA-SDK
// {8DCF1114-787E-446C-BF4F-D283C178FA49}
//static const IID IID_ICaEvent =
//{ 0x8dcf1114, 0x787e, 0x446c, { 0xbf, 0x4f, 0xd2, 0x83, 0xc1, 0x78, 0xfa, 0x49 } };
//f7663750-5900-45eb-905f-78c5d5378481
const IID IID_ICaEvent =
{ 0xf7663750, 0x5900, 0x45eb, { 0x90, 0x5f, 0x78, 0xc5, 0xd5, 0x37, 0x84, 0x81 } };
...
CaEvent.h
...
//CA-SDK
extern const IID IID_ICaEvent;
/////////////////////////////////////////////////////////////////////////////
// CCaEvent command target
class CCaEvent : public CCmdTarget
{
DECLARE_DYNCREATE(CCaEvent)
...
新增0-Cal的事件觸發程式碼,相同的軟體,當事件發生時,Measure會變不能按。CaEvent.cpp
...
void CCaEvent::ExeCalZero()
{
// TODO: Add your dispatch handler code here
// CA-SDK
CWinApp* papp = AfxGetApp();
CCa200SampleDlg* pdlg = reinterpret_cast(papp -> m_pMainWnd);
CButton* pb;
pb = (CButton *)(pdlg ->GetDlgItem(IDC_BUTTON_MSR));
pb->EnableWindow(FALSE);
}
改變sink class裡的public成員構造貼上程式到下列程式段中,直接建立sink object,才會OK。
CaEvent.h
...
class CCaEvent : public CCmdTarget
{
DECLARE_DYNCREATE(CCaEvent)
//CA-SDK
// CCaEvent(); // protected constructor used by dynamic creation
// Attributes
public:
// Operations
public:
//CA-SDK
CCaEvent();
...
};
...
最後,沒錯!這一步快結束啦!就是要在CaEvent.cpp裡include Ca200SampleDlg.h檔
不然現在compiler會出問題
CCa200SampleDlg* pdlg無定義
CaEvent.cpp
// CaEvent.cpp : implementation file//
#include "stdafx.h"
#include "Ca200Sample.h"
#include "CaEvent.h"
#include "Ca200SampleDlg.h"
...
最後的最後,沒錯!剛剛是「快」結束啦!這次是真的...這一步之後就結束啦!增加下列的Public成員變數到Ca200SampleDlg
Variable Type | Variable Name |
IConnectionPointPtr | m_pIConnectionPointObj |
IDispatch* | m_pIDispatch |
DWORD | m_dwCk |
Step 7. Sink Object建立連結和事件觸發
貼上下列式碼初始化Sink Object
Ca200Sample.cpp
BOOL CCa200SampleDlg::OnInitDialog()
...
m_dwCk = 0;
CCaEvent* pevntobj;
if (NULL != (pevntobj = new CCaEvent)){ //{bmc circle1.bmp}
m_pIDispatch = pevntobj ->GetIDispatch(FALSE);
IConnectionPointContainerPtr pcpcobj;
DWORD dwck;
pcpcobj = m_pCaObj;
pcpcobj -> FindConnectionPoint(IID_ICaEvent, &m_pIConnectionPointObj);
m_pIConnectionPointObj ->Advise(m_pIDispatch, &dwck);
m_dwCk = dwck;
}
...
}
貼上下列式碼
結束CA儀器到PC的遠端連線
Ca200Sample.cpp
void CCa200SampleDlg::OnOK()
{
if (CanExit())
//CA-SDK
{
if (m_dwCk != 0)
{
m_pIConnectionPointObj ->Unadvise(m_dwCk);
}
m_pIDispatch ->Release();
m_pCaObj ->RemoteMode = 0;
CDialog::OnOK();
}
}
在Ca200SampleDlg.cpp上include CaEvent.h檔Ca200Sample.cpp
// Ca200SampleDlg.cpp : implementation file
//
#include "stdafx.h"
#include "Ca200Sample.h"
#include "Ca200SampleDlg.h"
#include "DlgProxy.h"
#include "CaEvent.h"
...
Step 8. 錯誤觸發
其實可以略,因為它早就存在不用貼上了。但是還是介紹一下好了
Ca200SampleDlg.cpp
BOOL CCa200SampleDlg::OnInitDialog()
{
...
try
{
m_pCa200Obj = ICa200Ptr(__uuidof(Ca200));
m_pCa200Obj->SetConfiguration(lcan, strcnfig, lprt, lbr);
}
catch(_com_error e)
{
CString strerr;
strerr.Format(_T("HR:0x%08x\nMSG:%s"), e.Error(), (LPCSTR)e.Description());
AfxMessageBox((LPCSTR)strerr);
return TRUE;
}
...
}
Step 9. Const.h檔
這是最後一步了!貼完就完了!File→New
等等!在貼上之前(因為貼上是最後一步)
要先將Const.h include 到Ca200SampleDlg.cpp檔裡
Ca200SampleDlg.cpp
// Ca200SampleDlg.cpp : implementation file//
#include "stdafx.h"
#include "Ca200Sample.h"
#include "Ca200SampleDlg.h"
#include "DlgProxy.h"
#include "CaEvent.h"
#include "Const.h"
...
最後貼上Const.h檔內容,就完成啦!檔案:Const.h
程式碼:
// Const.h
// Definitions file
// Comm port type
#define PORT_USB 0
#define PORT_COM1 1
#define PORT_COM2 2
#define PORT_COM3 3
#define PORT_COM4 4
#define PORT_COM5 5
#definee PORT_COMMAX 255
// CA display mode
#define DSP_LXY 0
#define DSP_DUV 1
#define DSP_ANL 2
#define DSP_ANLG 3
#define DSP_ANLR 4
#define DSP_PUV 5
#define DSP_FMA 6
#define DSP_XYZC 7
#define DSP_JEITA 8
#define DSP_XYZ 9
// CA sync mode
#define SYNC_NTSC 0
#define SYNC_PAL 1
#define SYNC_EXT 2
#define SYNC_UNIV 3
#define SYNC_INT 4
// CA display digits
#define DIGT_3 0
#define DIGT_4 1
// CAFAST/SLOW setting
#define AVRG_SLOW 0
#define AVRG_FAST 1
#define AVRG_AUTO 2
// CA luminance units
#define BUNIT_FL 0
#define BUNIT_CD 1
// Konica Minolta calibration standard
#define CAL_D65 1
#define CAL_9300 2
#define CAL_CA100 3
// CA type
#define CATYPE_210 0
#define CATYPE_210S 1
#define CATYPE_100PLUS 2
#define CATYPE_200 3
// Probe type
#define PROBETYPE_CA100PLUS 1001
#define PROBETYPE_CA100PLUSH 1002
#define PROBETYPE_CA210 2100
#define PROBETYPE_CA210S 2101
// Remote mode
#define REMOTE_OFF 0
#define REMOTE_ON 1
#define REMOTE_LOCK 2
// Reference color
#define CAL_RED 0
#define CAL_GREEN 1
#define CAL_BLUE 2
#define CAL_WHITE 3
結束!compiler一下看看吧!