// RobotDlg.cpp : インプリメンテーション ファイル
//

#include "stdafx.h"
#include "Robot.h"
#include "RobotDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#include "CAO_i.c"

/////////////////////////////////////////////////////////////////////////////
// CRobotDlg ダイアログ

CRobotDlg::CRobotDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CRobotDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CRobotDlg)
		// メモ: この位置に ClassWizard によってメンバの初期化が追加されます。
	//}}AFX_DATA_INIT
	// メモ: LoadIcon は Win32 の DestroyIcon のサブシーケンスを要求しません。
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CRobotDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CRobotDlg)
		// メモ: この場所には ClassWizard によって DDX と DDV の呼び出しが追加されます。
		DDX_Control(pDX, IDC_CMB_PARAM, m_cmbParam);

		DDX_Control(pDX, IDC_CMB_COMP, m_cmbComp);
		DDX_Control(pDX, IDC_CMB_PATH, m_cmbPath);
		DDX_Control(pDX, IDC_CMB_TYPE, m_cmbType);
		DDX_Control(pDX, IDC_CHECK_MOVE_NEXT, m_optMove);
		DDX_Text(pDX, IDC_EDIT_VARINDEX, m_editVarIndex);

		DDX_Control(pDX, IDC_CMB_CHANGE, m_cmbChange);
		DDX_Text(pDX, IDC_EDIT_CHANGE, m_editChange);

		DDX_Text(pDX, IDC_EDIT_ACCEL, m_editAccel);
		DDX_Text(pDX, IDC_EDIT_DECEL, m_editDecel);
		DDX_Text(pDX, IDC_EDIT_SPEED, m_editSpeed);

		DDX_Control(pDX, IDC_CMB_DRVAT, m_cmbDrvat);
		DDX_Control(pDX, IDC_CMB_AXIS, m_cmbAxis);
		DDX_Control(pDX, IDC_CHECK_DRIVE_NEXT, m_optDrive);
		DDX_Text(pDX, IDC_EDIT_DRIVE, m_editDrive);

		DDX_Control(pDX, IDC_CMB_ROTATE, m_cmb_Rotate);
		DDX_Text(pDX, IDC_EDIT_ROTDEG, m_editRotdeg);
		DDX_Control(pDX, IDC_CHECK_ROTATE_NEXT, m_optRotate);
		DDX_Radio(pDX, IDC_OPT_SUF1, m_optSuf);
		DDX_Control(pDX, IDC_CMB_SUF, m_cmbSuf);

		DDX_Control(pDX, IDC_APPROACH_COMP, m_cmbApproachComp);
		DDX_Control(pDX, IDC_APPROACH_TYPE, m_cmbApproachType);
		DDX_Text(pDX, IDC_APPROACH_VARINDEX, m_nApproachIndex);
		DDX_Control(pDX, IDC_APPROACH_PATH, m_cmbApproachPath);
		DDX_Text(pDX, IDC_APPROACH_LENGTH, m_fApproachLength);
		DDX_Control(pDX, IDC_CHECK_APPROACH_NEXT, m_optApproach);

		DDX_Control(pDX, IDC_DEPART_COMP, m_cmbDepartComp);
		DDX_Control(pDX, IDC_DEPART_PATH, m_cmbDepartPath);
		DDX_Text(pDX, IDC_DEPART_LENGTH, m_fDepartLength);
		DDX_Control(pDX, IDC_CHECK_DEPART_NEXT, m_optDepart);

		DDX_Text(pDX, IDC_EDIT_EXECUTE, m_editExecute);
		DDX_Text(pDX, IDC_EDIT_REPLY, m_editReply);

		DDX_Control(pDX, IDC_GO, m_cmdGo);
		DDX_Control(pDX, IDC_CHANGE, m_cmdChange);
		DDX_Control(pDX, IDC_ACCEL, m_cmdAccel);
		DDX_Control(pDX, IDC_DECEL, m_cmdDecel);
		DDX_Control(pDX, IDC_SPEED, m_cmdSpeed);
		DDX_Control(pDX, IDC_DRIVE, m_cmdDrive);
		DDX_Control(pDX, IDC_ROTATE, m_cmdRotate);
		DDX_Control(pDX, IDC_CANCEL, m_cmdCancel);
		DDX_Control(pDX, IDC_EXECUTE, m_cmdExecute);

//		DDX_Text(pDX, IDC_MOVING, m_staMoving);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CRobotDlg, CDialog)
	//{{AFX_MSG_MAP(CRobotDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_CONNECT, OnConnect)
	ON_BN_CLICKED(IDC_DISCONNECT, OnDisconnect)
	ON_BN_CLICKED(IDC_GO, OnGo)
	ON_BN_CLICKED(IDC_CHANGE, OnChange)
	ON_BN_CLICKED(IDC_ACCEL, OnAccel)
	ON_BN_CLICKED(IDC_DECEL, OnDecel)
	ON_BN_CLICKED(IDC_SPEED, OnSpeed)
	ON_BN_CLICKED(IDC_DRIVE, OnDrive)
	ON_BN_CLICKED(IDC_ROTATE, OnRotate)
	ON_BN_CLICKED(IDC_APPROACH, OnApproach)
	ON_BN_CLICKED(IDC_DEPART, OnDepart)
	ON_BN_CLICKED(IDC_CANCEL, OnCmdCancel)
	ON_BN_CLICKED(IDC_EXECUTE, OnExecute)
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CRobotDlg メッセージ ハンドラ

BOOL CRobotDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// このダイアログ用のアイコンを設定します。フレームワークはアプリケーションのメイン
	// ウィンドウがダイアログでない時は自動的に設定しません。
	SetIcon(m_hIcon, TRUE);			// 大きいアイコンを設定
	SetIcon(m_hIcon, FALSE);		// 小さいアイコンを設定
	
	// TODO: 特別な初期化を行う時はこの場所に追加してください。
	HRESULT	hr = S_OK;
	CoInitialize(0);
	
	// Create CaoEngine object
	hr = CoCreateInstance(CLSID_CaoEngine, NULL, CLSCTX_LOCAL_SERVER, IID_ICaoEngine, (void**)&m_pIEng);
	if (FAILED(hr)) {
		return FALSE;
	}

	// Get Workespaces object
	hr = m_pIEng->get_Workspaces(&m_pIWss);
	if (FAILED(hr)) {
		return FALSE;
	}

	// Get Workspaces(0)
	hr = m_pIWss->Item(CComVariant(0L), &m_pIWs);
	if (FAILED(hr)) {
		return FALSE;
	}

	// Create CaoControllers object
	hr = m_pIWs->get_Controllers(&m_pICtrls);
	if (FAILED(hr)) {
		return FALSE;
	}

	m_cmbParam.SetCurSel(0);
	m_cmbComp.SetCurSel(0);
	m_cmbType.SetCurSel(0);
	m_editVarIndex = 100;

	m_cmbChange.SetCurSel(0);
	m_editChange = 1;

	m_editAccel  = 50.0f;
	m_editDecel  = 50.0f;
	m_editSpeed  = 80.0f;

	m_cmbAxis.SetCurSel(0);
	m_editDrive  = 30.0f;

	m_editRotate[0] = "1";
	m_editRotate[1] = "2";
	m_editRotate[2] = "3";
	m_editRotate[3] = "0";

	m_editRotdeg    = 30.0;

	m_optSuf        = 0;
	m_cmbSuf.SetCurSel(0);

	m_nApproachIndex  = 0;
	m_fApproachLength = 0;

	m_fDepartLength = 0;

	m_editExecute   = "10004, 1, 1";

	m_cmdGo.EnableWindow(FALSE);
	m_cmdChange.EnableWindow(FALSE);
	m_cmdAccel.EnableWindow(FALSE);
	m_cmdDecel.EnableWindow(FALSE);
	m_cmdSpeed.EnableWindow(FALSE);
	m_cmdDrive.EnableWindow(FALSE);
	m_cmdRotate.EnableWindow(FALSE);
	m_cmdCancel.EnableWindow(FALSE);
	m_cmdExecute.EnableWindow(FALSE);

	SetTimer(ID_TIMER, 1000, NULL);

	UpdateData(FALSE);

	return TRUE;  // TRUE を返すとコントロールに設定したフォーカスは失われません。
}

void CRobotDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	// TODO: この位置にメッセージ ハンドラ用のコードを追加してください
	OnDisconnect();

	m_pICtrls.Release();
	m_pIWs.Release();
	m_pIWss.Release();
	m_pIEng.Release();
}

BOOL CRobotDlg::PreTranslateMessage(MSG* pMsg) 
{
	// TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください
	if(pMsg->message == WM_KEYDOWN){
		switch(pMsg->wParam){
			case VK_ESCAPE:	// Escキー押下
				return TRUE;

			default:
				break;
		}
	}

	return CDialog::PreTranslateMessage(pMsg);
}

// もしダイアログボックスに最小化ボタンを追加するならば、アイコンを描画する
// コードを以下に記述する必要があります。MFC アプリケーションは document/view
// モデルを使っているので、この処理はフレームワークにより自動的に処理されます。

void CRobotDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 描画用のデバイス コンテキスト

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// クライアントの矩形領域内の中央
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// アイコンを描画します。
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// システムは、ユーザーが最小化ウィンドウをドラッグしている間、
// カーソルを表示するためにここを呼び出します。
HCURSOR CRobotDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CRobotDlg::OnConnect() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CString					strParam;
	CComPtr<ICaoController>	pICtrl;
	CComPtr<ICaoRobot>		pIRobot;
	CComBSTR				bstrParam;
	HRESULT					hr;

	OnDisconnect();

	// パラメータを取得
	UpdateData();
	if(m_cmbParam.GetCurSel() < 0)
		m_cmbParam.GetWindowText(strParam);
	else
		m_cmbParam.GetLBText(m_cmbParam.GetCurSel(), strParam);

	// コントローラオブジェクトを追加
	bstrParam = CComBSTR("Conn=" + strParam);
	hr = m_pICtrls->Add(CComBSTR(L"Sample"), CComBSTR(L"CaoProv.DENSO.NetwoRC"), CComBSTR(L""), bstrParam, &pICtrl);
	if(FAILED(hr)) {
		AfxTrace("Error : AddController( %X )\n", hr);
		return;
	}

	// ロボットオブジェクトを追加
	hr = pICtrl->AddRobot(CComBSTR(L"RobSlave"), CComBSTR(L""), &pIRobot);
	if(FAILED(hr)) {
		AfxTrace("Error : AddRobot( %X )\n", hr);
		return;
	}

	hr = pIRobot->AddVariable(CComBSTR(L"@BUSY_STATUS"), CComBSTR(L""), &m_pIBusyStatusVariable);
	if(FAILED(hr)) {
		AfxTrace("Error : AddVariable( %X )\n", hr);
		return;
	}

	hr = pIRobot->AddVariable(CComBSTR(L"@CURRENT_POSITION"), CComBSTR(L""), &m_pICurrentPositionVariable);
	if(FAILED(hr)) {
		AfxTrace("Error : AddVariable( %X )\n", hr);
		return;
	}

	m_cmdGo.EnableWindow(TRUE);
	m_cmdChange.EnableWindow(TRUE);
	m_cmdAccel.EnableWindow(TRUE);
	m_cmdDecel.EnableWindow(TRUE);
	m_cmdSpeed.EnableWindow(TRUE);
	m_cmdDrive.EnableWindow(TRUE);
	m_cmdRotate.EnableWindow(TRUE);
	m_cmdCancel.EnableWindow(TRUE);
	m_cmdExecute.EnableWindow(TRUE);
}

void CRobotDlg::OnDisconnect() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	long					longValue;
	HRESULT					hr;

	hr = m_pICtrls->get_Count(&longValue);
	if(FAILED(hr)){
		AfxTrace("Error : get_Count( %X )\n", hr);
		return;
	}

	if(longValue > 0){
		m_pIBusyStatusVariable.Release();
		m_pICurrentPositionVariable.Release();
		m_pICtrls->Clear();
	}

	m_cmdGo.EnableWindow(FALSE);
	m_cmdChange.EnableWindow(FALSE);
	m_cmdAccel.EnableWindow(FALSE);
	m_cmdDecel.EnableWindow(FALSE);
	m_cmdSpeed.EnableWindow(FALSE);
	m_cmdDrive.EnableWindow(FALSE);
	m_cmdRotate.EnableWindow(FALSE);
	m_cmdCancel.EnableWindow(FALSE);
	m_cmdExecute.EnableWindow(FALSE);
}

void CRobotDlg::OnGo() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CString				strPath, strType, strVar;

	CComPtr<ICaoRobot>	pIRobot;
	HRESULT				hr;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			UpdateData();

			m_cmbPath.GetWindowText(strPath);
			m_cmbType.GetWindowText(strType);
			strVar.Format("%d", m_editVarIndex);

			hr = pIRobot->Move(m_cmbComp.GetCurSel() + 1, CComVariant(strPath + " " + strType + strVar), (m_optMove.GetCheck() == 1)? CComBSTR(L"NEXT") : CComBSTR(L""));
			if(FAILED(hr)) {
				AfxTrace("Error : Move( %X )\n", hr);
			}
		}
	}
}

void CRobotDlg::OnChange() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CString				strChange, strWork;

	CComPtr<ICaoRobot>	pIRobot;
	HRESULT				hr;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			UpdateData();

			m_cmbChange.GetWindowText(strChange);
			strWork.Format("%d", m_editChange);
			strChange += strWork;
			hr = pIRobot->Change(CComBSTR(strChange));
			if(FAILED(hr)) {
				AfxTrace("Error : Accelerate( %X )\n", hr);
			}
		}
	}
}

void CRobotDlg::OnAccel() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CComPtr<ICaoRobot>	pIRobot;
	HRESULT				hr;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			UpdateData();

			hr = pIRobot->Accelerate(-1, m_editAccel);
			if(FAILED(hr)) {
				AfxTrace("Error : Accelerate( %X )\n", hr);
			}
		}
	}
}

void CRobotDlg::OnDecel() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CComPtr<ICaoRobot>	pIRobot;
	HRESULT				hr;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			UpdateData();

			hr = pIRobot->Accelerate(-1, -1, m_editDecel);	// -1:Do not care
			if(FAILED(hr)) {
				AfxTrace("Error : Accelerate( %X )\n", hr);
			}
		}
	}
}

void CRobotDlg::OnSpeed() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CComPtr<ICaoRobot>	pIRobot;
	HRESULT				hr;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			UpdateData();

			hr = pIRobot->Speed(-1, m_editSpeed);
			if(FAILED(hr)) {
				AfxTrace("Error : Speed( %X )\n", hr);
			}
		}
	}
}

void CRobotDlg::OnDrive() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CString				strOption, strWork;

	SAFEARRAYBOUND		rgb[1];
	SAFEARRAY*			psa;
	CComVariant*		pVarData;

	CComVariant			pData, pResult;
	CComPtr<ICaoRobot>	pIRobot;
	HRESULT				hr;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			UpdateData();

			m_cmbDrvat.GetWindowText(strWork);	strOption = strWork + " ";
			strOption += "(";
			m_cmbAxis.GetWindowText(strWork);	strOption += strWork;
			strWork.Format(",%f", m_editDrive);	strOption += strWork;
			strOption += ")";

			if(m_optDrive.GetCheck() == 1){
				rgb[0].cElements = 2;
				rgb[0].lLbound   = 0;

				if(psa = SafeArrayCreate(VT_VARIANT, 1, rgb)){
					hr = SafeArrayAccessData(psa, (void **)&pVarData);
					if(SUCCEEDED(hr)){
						pVarData[0] = static_cast<LPCTSTR>(strOption);
						pVarData[1] = L"NEXT";

						pData.parray = psa;
						pData.vt     = VT_ARRAY | VT_VARIANT;

						SafeArrayUnaccessData(psa);
					}
				}
			} else {
				pData = CComVariant(static_cast<LPCTSTR>(strOption));
			}

			hr = pIRobot->Execute(CComBSTR(L"DriveEx"), pData, &pResult);
			if(FAILED(hr)) {
				AfxTrace("Error : Execute( %X )\n", hr);
			}
		}
	}
}

void CRobotDlg::OnRotate() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CString				strRotSuf, strOption;
	CComPtr<ICaoRobot>	pIRobot;
	HRESULT				hr;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			UpdateData();

			m_cmb_Rotate.GetWindowText(strOption);
			if(m_optRotate.GetCheck() == 1)
				strOption += ",NEXT";

			switch(m_optSuf){
			case 0:	// Vn1,Vn2,Vn3
				strRotSuf = m_editRotate[0] + "," + m_editRotate[1] + "," + m_editRotate[2];
				break;

			case 1: // XY,YZ,ZX ...
				m_cmbSuf.GetWindowText(strRotSuf);
				break;
			}
			hr = pIRobot->Rotate(CComVariant(static_cast<LPCTSTR>(strRotSuf)), m_editRotdeg, CComVariant(static_cast<LPCTSTR>(m_editRotate[3])), CComBSTR(strOption));
			if(FAILED(hr)) {
				AfxTrace("Error : Rotate( %X )\n", hr);
			}
		}
	}
}

void CRobotDlg::OnApproach()
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	SAFEARRAY*			psa;
	SAFEARRAYBOUND		rgb[1];

	CString				strOption;
	CComPtr<ICaoRobot>	pIRobot;
	CComVariant			*pVarData, pData, pResult;
	HRESULT				hr;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			UpdateData();

			rgb[0].cElements = (m_optApproach.GetCheck())? 4 : 3;
			rgb[0].lLbound   = 0;
			if(psa = SafeArrayCreate(VT_VARIANT, 1, rgb)){

				hr = SafeArrayAccessData(psa, (void **)&pVarData);
				if(SUCCEEDED(hr)){
					CString strVariable = _T("");
					CString strPath     = _T("");
					CString strVarIndex, strLength;
					if (m_cmbApproachType.GetCurSel() != CB_ERR) {
						m_cmbApproachType.GetLBText(m_cmbApproachType.GetCurSel(), strVariable);
					}
					if (m_cmbApproachPath.GetCurSel() != CB_ERR) {
						m_cmbApproachPath.GetLBText(m_cmbApproachPath.GetCurSel(), strPath);
					}
					strVarIndex.Format("%d", m_nApproachIndex);
					strLength.Format(" %f", m_fApproachLength);

					// 補完指定
					pVarData[0] = static_cast<short>(m_cmbApproachComp.GetCurSel() != CB_ERR)? m_cmbApproachComp.GetCurSel() + 1 : 0;
					// 基準位置
					pVarData[1] = static_cast<LPCTSTR>(strVariable + strVarIndex);
					// アプローチ長
					pVarData[2] = static_cast<LPCTSTR>(strPath + strLength);
					if (m_optApproach.GetCheck()) {
						pVarData[3] = L"NEXT";
					}

					pData.parray = psa;
					pData.vt     = VT_ARRAY | VT_VARIANT;

					SafeArrayUnaccessData(psa);
				}
			}
			hr = pIRobot->Execute(CComBSTR(L"Approach"), pData, &pResult);
			if(FAILED(hr)) {
				AfxTrace("Error : Approach( %X )\n", hr);
			}
		}
	}
}

void CRobotDlg::OnDepart()
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	SAFEARRAY*			psa;
	SAFEARRAYBOUND		rgb[1];

	CString				strOption;
	CComPtr<ICaoRobot>	pIRobot;
	CComVariant			*pVarData, pData, pResult;
	HRESULT				hr;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			UpdateData();

			rgb[0].cElements = (m_optDepart.GetCheck())? 3 : 2;
			rgb[0].lLbound   = 0;
			if(psa = SafeArrayCreate(VT_VARIANT, 1, rgb)){

				hr = SafeArrayAccessData(psa, (void **)&pVarData);
				if(SUCCEEDED(hr)){
					CString strPath = _T("");
					CString strLength;
					if (m_cmbDepartPath.GetCurSel() != CB_ERR) {
						m_cmbDepartPath.GetLBText(m_cmbDepartPath.GetCurSel(), strPath);
					}
					strLength.Format(" %f", m_fDepartLength);

					// 補完指定
					pVarData[0] = static_cast<short>(m_cmbDepartComp.GetCurSel() != CB_ERR)? m_cmbDepartComp.GetCurSel() + 1 : 0;
					// デパート長
					pVarData[1] = static_cast<LPCTSTR>(strPath + strLength);
					if (m_optDepart.GetCheck()) {
						pVarData[2] = L"NEXT";
					}

					pData.parray = psa;
					pData.vt     = VT_ARRAY | VT_VARIANT;

					SafeArrayUnaccessData(psa);
				}
			}

			hr = pIRobot->Execute(CComBSTR(L"Depart"), pData, &pResult);
			if(FAILED(hr)) {
				AfxTrace("Error : Depart( %X )\n", hr);
			}
		}
	}
}

void CRobotDlg::OnCmdCancel() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CComPtr<ICaoRobot>	pIRobot;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			pIRobot->Halt(CComBSTR(L""));
		}
	}
}

void CRobotDlg::OnExecute() 
{
	// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
	CComPtr<ICaoRobot>	pIRobot;
	CComVariant			pOption, pResult;
	HRESULT				hr;

	if(IsRobSlaveRunning()){
		pIRobot = GetRobotObject();
		if(pIRobot){
			UpdateData();

			if(GetExecuteData(m_editExecute, &pOption)){
				hr = pIRobot->Execute(CComBSTR(L"UserExt"), pOption, &pResult);
				if(FAILED(hr)) {
					AfxTrace("Error : Execute( %X )\n", hr);
				}

				m_editReply = GetResultData(pResult);
				UpdateData(FALSE);
			}
		}
	}
}

CComPtr<ICaoController> CRobotDlg::GetControllerObject()
{
	long					longValue;
	long					i;

	CComPtr<ICaoController>	pICtrl;
	CComVariant				varIndex;
	HRESULT					hr;

	// コントローラオブジェクト取得
	if(m_pICtrls){
		hr = m_pICtrls->get_Count(&longValue);
		if(SUCCEEDED(hr)){
			for(i = 0; i < longValue; i++){
				varIndex = CComVariant(i);
				hr = m_pICtrls->Item(varIndex, &pICtrl);
				if(SUCCEEDED(hr))
					break;
			}

			if(i < longValue)
				return pICtrl;
		}
	}
	return NULL;
}

CComPtr<ICaoRobot> CRobotDlg::GetRobotObject()
{
	long					longValue;
	long					i;

	CComPtr<ICaoController>	pICtrl;
	CComPtr<ICaoRobots>		pIRobots;
	CComPtr<ICaoRobot>		pIRobot;
	CComVariant				varIndex;
	HRESULT					hr;

	// コントローラオブジェクト取得
	pICtrl = GetControllerObject();
	if(pICtrl){
		hr = pICtrl->get_Robots(&pIRobots);
		if(SUCCEEDED(hr)){
			hr = pIRobots->get_Count(&longValue);
			if(SUCCEEDED(hr)){
				for(i = 0; i < longValue; i++){
					varIndex = CComVariant(i);
					hr = pIRobots->Item(varIndex, &pIRobot);
					if(SUCCEEDED(hr))
						break;
				}
				if(i < longValue)
					return pIRobot;
			}
		}
	}
	return NULL;
}

BOOL CRobotDlg::IsRobSlaveRunning()
{
	long					longValue;
	CComPtr<ICaoController>	pICtrl;
	CComPtr<ICaoTask>		pITask;
	CComPtr<ICaoTasks>		pITasks;
	CComPtr<ICaoVariables>	pIVars;
	CComPtr<ICaoVariable>	pIVar;
	CComVariant				varIndex;
	HRESULT					hr;

	BOOL					bResult = FALSE;

	// コントローラオブジェクト取得
	pICtrl = GetControllerObject();
	if(pICtrl){
		hr = pICtrl->AddTask(CComBSTR(L"ROBSLAVE"), CComBSTR(L""), &pITask);
		if(SUCCEEDED(hr)){
			hr = pITask->AddVariable(CComBSTR(L"@STATUS"), CComBSTR(L""), &pIVar);
			if(SUCCEEDED(hr)){
				hr = pIVar->get_Value(&varIndex);
				if(SUCCEEDED(hr) && varIndex.iVal == 3){
					bResult = TRUE;
				}

				hr = pIVar->get_Index(&longValue);
				if(FAILED(hr)) {
					AfxTrace("Error : get_Index( %X )\n", hr);
				}

				hr = pITask->get_Variables(&pIVars);
				if(FAILED(hr)) {
					AfxTrace("Error : get_Variables( %X )\n", hr);
				}

				hr = pIVars->Remove(CComVariant(longValue));
				if(FAILED(hr)) {
					AfxTrace("Error : Remove( %X )\n", hr);
				}

				hr = pITask->get_Index(&longValue);
				if(FAILED(hr)) {
					AfxTrace("Error : get_Index( %X )\n", hr);
				}

				hr = pICtrl->get_Tasks(&pITasks);
				if(FAILED(hr)) {
					AfxTrace("Error : get_Tasks( %X )\n", hr);
				}

				hr = pITasks->Remove(CComVariant(longValue));
				if(FAILED(hr)) {
					AfxTrace("Error : Remove( %X )\n", hr);
				}
			}
		}
	}

	if(!bResult)
		AfxMessageBox("\"ROBSLAVE\" task is not running into the controller !");

	return bResult;
}

BOOL CRobotDlg::GetExecuteData(CString str, CComVariant* varData)
{
	CString					strData = "";
	CArray<float, float>	arrayData;

	SAFEARRAYBOUND			rgb[1];
	SAFEARRAY*				psa;
	HRESULT					hr;

	float*					fltData;
	int i;
	for(i = 0; i < str.GetLength(); i++){
		switch(str[i]){
		case ',':
		case '\0':
			arrayData.Add((float)atof(strData));
			strData = "";
			break;

		case ' ':
			break;

		default:
			strData += str[i];
			break;
		}
	}

	if(strData.GetLength())
		arrayData.Add((float)atof(strData));

	rgb[0].cElements = arrayData.GetSize();
	rgb[0].lLbound   = 0;

	if(psa = SafeArrayCreate(VT_R4, 1, rgb)){
		hr = SafeArrayAccessData(psa, (void **)&fltData);
		if(SUCCEEDED(hr)){
			for(i = 0; i < arrayData.GetSize(); i++)
				fltData[i] = arrayData[i];

			varData->parray = psa;
			varData->vt     = VT_ARRAY | VT_R4;

			SafeArrayUnaccessData(psa);

			return TRUE;
		}
	}
	return FALSE;
}

CStringArray* CRobotDlg::GetResultDataArray(CComVariant varResult)
{
	long			longlBound, longUBound;
	
//	void			*voidResult = NULL;
	CString			strWork;
	CString			fmtType;
	CStringArray	*arrayResult;

	SAFEARRAY*		psa;

	HRESULT			hr;
	long			i;

	arrayResult = new CStringArray;

	if(varResult.vt & VT_ARRAY){
		psa = varResult.parray;
		SafeArrayGetLBound(psa, 1, &longlBound);
		SafeArrayGetUBound(psa, 1, &longUBound);

		hr = SafeArrayLock(psa);
		if(SUCCEEDED(hr)){
			for(i = longlBound; i <= longUBound; i++){
				strWork = "";
				switch(varResult.vt & VT_TYPEMASK){
				case VT_I1:
				case VT_I2:
				case VT_I4:
				case VT_UI1:
				case VT_UI2:
				case VT_UI4:
				case VT_INT:
				case VT_UINT:
					long	longResult;
					SafeArrayGetElement(psa, &i, &longResult);
					strWork.Format("%d", longResult);
					break;

				case VT_R4:
					float	fltResult;
					SafeArrayGetElement(psa, &i, &fltResult);
					strWork.Format("%.2f", fltResult);
					break;

				case VT_R8:
					double	dblResult;
					SafeArrayGetElement(psa, &i, &dblResult);
					strWork.Format("%.2f", dblResult);
					break;

				case VT_BSTR:
					BSTR	bstrResult;
					SafeArrayGetElement(psa, &i, &bstrResult);
					strWork.Format("%s", bstrResult);
					break;

				case VT_VARIANT:
					VARIANT	varResult;
					SafeArrayGetElement(psa, &i, &varResult);
					if(varResult.vt == VT_R4)
						strWork.Format("%f", varResult.fltVal);
					break;


				case VT_BOOL:
					BYTE	byteResult;
					SafeArrayGetElement(psa, &i, &byteResult);
					strWork.Format("%d", byteResult);
					break;

				default:
					AfxTrace("Variant Type : ( %d )", varResult.vt & VT_TYPEMASK);
					break;
				}
				arrayResult->Add(strWork);
			}
			SafeArrayUnlock(psa);
		}

	} else {
		switch(varResult.vt & VT_TYPEMASK){
		case VT_EMPTY:
			strWork = "(No Return)";
			arrayResult->Add(strWork);
			break;

		case VT_I1:
		case VT_I2:
		case VT_I4:
			strWork.Format("%d", varResult.iVal);
			arrayResult->Add(strWork);
			break;

		case VT_UI1:
		case VT_UI2:
		case VT_UI4:
			strWork.Format("%d", varResult.uiVal);
			arrayResult->Add(strWork);
			break;

		case VT_I8:
			strWork.Format("%d", varResult.lVal);
			arrayResult->Add(strWork);
			break;

		case VT_UI8:
			strWork.Format("%d", varResult.ulVal);
			arrayResult->Add(strWork);
			break;

		case VT_INT:
			strWork.Format("%d", varResult.intVal);
			arrayResult->Add(strWork);
			break;

		case VT_UINT:
			strWork.Format("%d", varResult.uintVal);
			arrayResult->Add(strWork);
			break;

		case VT_R4:
			strWork.Format("%d", varResult.fltVal);
			arrayResult->Add(strWork);
			break;

		case VT_R8:
			strWork.Format("%d", varResult.dblVal);
			arrayResult->Add(strWork);
			break;

		case VT_BSTR:
			arrayResult->Add(varResult.bstrVal);
			break;

		case VT_BOOL:
			strWork.Format((varResult.boolVal == 0x0000)? "False" : "True");
			arrayResult->Add(strWork);
			break;

		default:
			AfxTrace("Variant Type : ( %d )", varResult.vt & VT_TYPEMASK);
			break;
		}
	}

	return arrayResult;
}

CString CRobotDlg::GetResultData(CComVariant varResult)
{
	CStringArray*	arrayResult = GetResultDataArray(varResult);
	CString			strResult;

	int i;
	for(i = 0; i < arrayResult->GetSize(); i++){
		strResult += arrayResult->GetAt(i);
	}

	delete arrayResult;

	return strResult;
}


void CRobotDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: この位置にメッセージ ハンドラ用のコードを追加するかまたはデフォルトの処理を呼び出してください
	CStringArray*	CurrentPositionData;
	CString			strCurrentPosition = "";

	CComVariant	varValue;
	HRESULT		hr;
	int			i;

	switch(nIDEvent){
	case ID_TIMER:
		// Moving = True / False
		if(m_pIBusyStatusVariable){
			hr = m_pIBusyStatusVariable->get_Value(&varValue);
			if(FAILED(hr)) {
				AfxTrace("Error : get_Value( %X )\n", hr);
				break;
			}
			((CEdit*)GetDlgItem(IDC_MOVING))->SetWindowText(GetResultData(varValue));
		}

		// Current Position
		if(m_pICurrentPositionVariable){
			hr = m_pICurrentPositionVariable->get_Value(&varValue);
			if(FAILED(hr)) {
				AfxTrace("Error : get_Value( %X )\n", hr);
				break;
			}

			CurrentPositionData = GetResultDataArray(varValue);
			strCurrentPosition = "P(";
			for(i = 0; i < CurrentPositionData->GetSize() - 1; i++)
				strCurrentPosition += CurrentPositionData->GetAt(i) + ",";
			strCurrentPosition += CurrentPositionData->GetAt(i) + ")";
			((CEdit*)GetDlgItem(IDC_POSITION))->SetWindowText(strCurrentPosition);

			delete CurrentPositionData;
		}
		break;

	default:
		break;
	}
	CDialog::OnTimer(nIDEvent);
}
