// PLCDlg.cpp : 実装ファイル
//

#include "stdafx.h"
#include "PLC.h"
#include "PLCDlg.h"

#include "CAO_i.c"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CPLCDlg ダイアログ
CPLCDlg::CPLCDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CPLCDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	m_eng = NULL;
	m_wss = NULL;
	m_ws  = NULL;
	m_ctrl = NULL;
	m_varD = NULL;
	m_varM = NULL;
	m_varX = NULL;
	m_varY = NULL;
}

void CPLCDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_BUTTON_CONNECT, btnConnect);
	DDX_Control(pDX, IDC_BUTTON_DISCONNECT, btnDisconnect);
	DDX_Control(pDX, IDC_LABEL_DISP, lblDsp);
	DDX_Control(pDX, IDC_BUTTON_READ_D, btnReadD);
	DDX_Control(pDX, IDC_BUTTON_WRITE_D, btnWriteD);
	DDX_Control(pDX, IDC_BUTTON_READ_M, btnReadM);
	DDX_Control(pDX, IDC_BUTTON_WRITE_M, btnWriteM);
	DDX_Control(pDX, IDC_BUTTON_READ_X, btnReadX);
	DDX_Control(pDX, IDC_BUTTON_WRITE_X, btnWriteX);
	DDX_Control(pDX, IDC_BUTTON_READ_Y, btnReadY);
	DDX_Control(pDX, IDC_BUTTON_WRITE_Y, btnWriteY);
}

BEGIN_MESSAGE_MAP(CPLCDlg, CDialog)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	//}}AFX_MSG_MAP
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_BUTTON_CONNECT, &CPLCDlg::OnBnClickedButtonConnect)
	ON_BN_CLICKED(IDC_BUTTON_DISCONNECT, &CPLCDlg::OnBnClickedButtonDisconnect)
	ON_BN_CLICKED(IDC_BUTTON_READ_D, &CPLCDlg::OnBnClickedButtonReadD)
	ON_BN_CLICKED(IDC_BUTTON_WRITE_D, &CPLCDlg::OnBnClickedButtonWriteD)
	ON_BN_CLICKED(IDC_BUTTON_READ_M, &CPLCDlg::OnBnClickedButtonReadM)
	ON_BN_CLICKED(IDC_BUTTON_WRITE_M, &CPLCDlg::OnBnClickedButtonWriteM)
	ON_BN_CLICKED(IDC_BUTTON_READ_X, &CPLCDlg::OnBnClickedButtonReadX)
	ON_BN_CLICKED(IDC_BUTTON_WRITE_X, &CPLCDlg::OnBnClickedButtonWriteX)
	ON_BN_CLICKED(IDC_BUTTON_READ_Y, &CPLCDlg::OnBnClickedButtonReadY)
	ON_BN_CLICKED(IDC_BUTTON_WRITE_Y, &CPLCDlg::OnBnClickedButtonWriteY)
END_MESSAGE_MAP()


// CPLCDlg メッセージ ハンドラ

BOOL CPLCDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// このダイアログのアイコンを設定します。アプリケーションのメイン ウィンドウがダイアログでない場合、
	//  Framework は、この設定を自動的に行います。
	SetIcon(m_hIcon, TRUE);			// 大きいアイコンの設定
	SetIcon(m_hIcon, FALSE);		// 小さいアイコンの設定

	CoInitialize(NULL);
	CoCreateInstance(CLSID_CaoEngine, NULL, CLSCTX_LOCAL_SERVER, IID_ICaoEngine, (void**)&m_eng);
	m_eng->get_Workspaces(&m_wss);
	m_wss->Item(CComVariant(0L), &m_ws);

	return TRUE;  // フォーカスをコントロールに設定した場合を除き、TRUE を返します。
}

void CPLCDlg::OnDestroy()
{
	CDialog::OnDestroy();

	OnBnClickedButtonDisconnect();

	if(m_ws != NULL) {
		m_ws->Release();
		m_ws = NULL;
	}

	if(m_wss != NULL) {
		m_wss->Release();
		m_wss = NULL;
	}

	if(m_eng != NULL) {
		m_eng->Release();
		m_eng = NULL;
	}

	CoUninitialize();
}

// ダイアログに最小化ボタンを追加する場合、アイコンを描画するための
//  下のコードが必要です。ドキュメント/ビュー モデルを使う MFC アプリケーションの場合、
//  これは、Framework によって自動的に設定されます。

void CPLCDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // 描画のデバイス コンテキスト

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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 CPLCDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CPLCDlg::OnBnClickedButtonConnect()
{
	HRESULT hr = E_FAIL;

	if(m_ws != NULL)
	{
		// Connect Dummy.Panel Provider
		hr = m_ws->AddController(CComBSTR(L"PLC"), CComBSTR(L"CaoProv.Dummy.PLC"), CComBSTR(L""), CComBSTR(L""), &m_ctrl);

		if(SUCCEEDED(hr))
		{
			// Get Variable object
			hr = m_ctrl->AddVariable(CComBSTR(L"D16"), CComBSTR(L""), &m_varD);
			hr = m_ctrl->AddVariable(CComBSTR(L"M16"), CComBSTR(L"Type=Word"), &m_varM);
			hr = m_ctrl->AddVariable(CComBSTR(L"X1E"), CComBSTR(L""), &m_varX);
			hr = m_ctrl->AddVariable(CComBSTR(L"Y1E"), CComBSTR(L"Elements=2"), &m_varY);
		}
	}

	if(SUCCEEDED(hr))
	{
		// Enable command buttons
		btnConnect.EnableWindow(FALSE);
		btnDisconnect.EnableWindow(TRUE);
		btnReadD.EnableWindow(TRUE);
		btnReadM.EnableWindow(TRUE);
		btnReadX.EnableWindow(TRUE);
		btnReadY.EnableWindow(TRUE);
		btnWriteD.EnableWindow(TRUE);
		btnWriteM.EnableWindow(TRUE);
		btnWriteX.EnableWindow(TRUE);
		btnWriteY.EnableWindow(TRUE);
	}
	else
	{
		OnBnClickedButtonDisconnect();
		ShowErrorMessage(hr);
	}	
}

void CPLCDlg::OnBnClickedButtonDisconnect()
{
	if(m_varY){
		m_varY->Release();
		m_varY = NULL;
	}

	if(m_varX){
		m_varX->Release();
		m_varX = NULL;
	}

	if(m_varM){
		m_varM->Release();
		m_varM = NULL;
	}

	if(m_varD){
		m_varD->Release();
		m_varD = NULL;
	}

	// Disconnect Provider
	if(m_ctrl)
	{
		if(m_ws)
		{
			CComVariant vntCtrlName;
			CComPtr<ICaoControllers> ctrls;

			m_ws->get_Controllers(&ctrls);

			vntCtrlName.vt = VT_BSTR;
			m_ctrl->get_Name(&vntCtrlName.bstrVal);

			ctrls->Remove(vntCtrlName);
		}

		m_ctrl->Release();
		m_ctrl = NULL;
	}

	// disable command buttons
	btnConnect.EnableWindow(TRUE);
	btnDisconnect.EnableWindow(FALSE);
	btnReadD.EnableWindow(FALSE);
	btnReadM.EnableWindow(FALSE);
	btnReadX.EnableWindow(FALSE);
	btnReadY.EnableWindow(FALSE);
	btnWriteD.EnableWindow(FALSE);
	btnWriteM.EnableWindow(FALSE);
	btnWriteX.EnableWindow(FALSE);
	btnWriteY.EnableWindow(FALSE);
}

void CPLCDlg::OnBnClickedButtonReadD()
{
	CComVariant vntValue;
	CString strValue;

	HRESULT hr = m_varD->get_Value(&vntValue);
	if(SUCCEEDED(hr)) {
		strValue.Format(_T("%d"), vntValue.iVal);
		lblDsp.SetWindowText(strValue);
	} else {
		ShowErrorMessage(hr);
	}
}

void CPLCDlg::OnBnClickedButtonWriteD()
{
	CComVariant vntValue;
	vntValue.vt   = VT_I2;
	vntValue.iVal = -32768;

	HRESULT hr = m_varD->put_Value(vntValue);
	if(FAILED(hr)) {
		ShowErrorMessage(hr);
	}
}

void CPLCDlg::OnBnClickedButtonReadM()
{
	CComVariant vntValue;
	CString strValue;

	HRESULT hr = m_varM->get_Value(&vntValue);
	if(SUCCEEDED(hr)) {
		strValue.Format(_T("%d"), vntValue.iVal);
		lblDsp.SetWindowText(strValue);
	} else {
		ShowErrorMessage(hr);
	}
}

void CPLCDlg::OnBnClickedButtonWriteM()
{
	CComVariant vntValue;
	vntValue.vt   = VT_I2;
	vntValue.iVal = 32767;

	HRESULT hr = m_varM->put_Value(vntValue);
	if(FAILED(hr)) {
		ShowErrorMessage(hr);
	}
}

void CPLCDlg::OnBnClickedButtonReadX()
{
	CComVariant vntValue;
	CString strValue;

	HRESULT hr = m_varX->get_Value(&vntValue);
	if(SUCCEEDED(hr)) {
		strValue.Format(_T("%d"), vntValue.iVal);
		lblDsp.SetWindowText(strValue);
	} else {
		ShowErrorMessage(hr);
	}
}

void CPLCDlg::OnBnClickedButtonWriteX()
{
	CComVariant vntValue;
	vntValue.vt   = VT_I2;
	vntValue.iVal = 1;

	HRESULT hr = m_varX->put_Value(vntValue);
	if(FAILED(hr)) {
		ShowErrorMessage(hr);
	}
}

void CPLCDlg::OnBnClickedButtonReadY()
{
	CComVariant vntValue;
	CString strValue;
	short *psData;

	HRESULT hr = m_varY->get_Value(&vntValue);
	if(SUCCEEDED(hr)) {
		SafeArrayAccessData(vntValue.parray, (void**)&psData);
		strValue.Format(_T("%d, %d"), psData[1], psData[0]);
		SafeArrayUnaccessData(vntValue.parray);
		lblDsp.SetWindowText(strValue);
	} else {
		ShowErrorMessage(hr);
	}
}

void CPLCDlg::OnBnClickedButtonWriteY()
{
	CComVariant vntValue;
	short *psData;
	vntValue.vt     = VT_I2 | VT_ARRAY;
	vntValue.parray = SafeArrayCreateVector(VT_I2, 0, 2);
	SafeArrayAccessData(vntValue.parray, (void**)&psData);
	psData[0] = 1;
	psData[1] = 1;
	SafeArrayUnaccessData(vntValue.parray);

	HRESULT hr = m_varY->put_Value(vntValue);
	if(FAILED(hr)) {
		ShowErrorMessage(hr);
	}
}

void CPLCDlg::ShowErrorMessage(HRESULT hr)
{
	CString strMsg;
	strMsg.Format(_T("%X"), hr);
	MessageBox(strMsg, _T("Error"));
}