// SampleDlg.cpp : implementation file
//

#include "stdafx.h"
#include "Sample.h"
#include "SampleDlg.h"
#include "SelectCameraDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSampleDlg dialog

const int CSampleDlg::s_nMaxMsgsCount = 100;

SHOOT_COMPLETED_PARAM		CSampleDlg::s_ShootCompletedParam;
DOWNLOAD_COMPLETED_PARAM	CSampleDlg::s_DownloadCompletedParam;
PREVIEW_FRAME_PARAM			CSampleDlg::s_PreviewFrameParam;
CAMERALIST_CHANGED_PARAM	CSampleDlg::s_CameraListChangedParam;

UINT CAMERAEVENT_INFO_MESSAGE = ::RegisterWindowMessage (_T("CAMERAEVENT_INFO_MESSAGE"));
UINT CAMERAEVENT_GETFRAME_MESSAGE = ::RegisterWindowMessage (_T("CAMERAEVENT_GETFRAME_MESSAGE"));
UINT CAMERAEVENT_ZOOMCHANGED_MESSAGE = ::RegisterWindowMessage (_T("CAMERAEVENT_ZOOMCHANGED_MESSAGE"));
UINT CAMERAEVENT_CAMLISTCHANGED_MESSAGE = ::RegisterWindowMessage (_T("CAMERAEVENT_CAMLISTCHANGED_MESSAGE"));
UINT CAMERAEVENT_PROPLISTCHANGED_MESSAGE = ::RegisterWindowMessage (_T("CAMERAEVENT_PROPLISTCHANGED_MESSAGE"));
UINT CAMERAEVENT_PROPCHANGED_MESSAGE = ::RegisterWindowMessage (_T("CAMERAEVENT_PROPCHANGED_MESSAGE"));

struct CAMERAEVENT_INFO_STRUCT
{
	CAMERAEVENT_INFO_STRUCT () : strMessage () {}

	CString strMessage;
} s_CamInfo;

IMPLEMENT_DYNAMIC(CSampleDlg, CDialog)

CSampleDlg::CSampleDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CSampleDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CSampleDlg)
	m_strInfo = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

	m_bConnected = FALSE;
	m_bPreviewEnabled = FALSE;

	memset( &m_PreviewSurface, 0, sizeof(DIBData) );
	m_pPreviewWnd = NULL;
	m_PreviewWidth	= 320;	// The default settings of preview frame
	m_PreviewHeight	= 240;
	m_PreviewBitCount = 24;
	m_PreviewWidth	= 800;	// The default settings of preview frame
	m_PreviewHeight	= 600;
	m_PreviewBitCount = 32;

	m_CamManager = 0;
	m_Session = 0;

	m_hPreviewFrameEvent = 0;
	m_hCameraListEvent = 0;
	m_hPropertyListEvent = 0;
	m_hPropertyEvent = 0;

	// data for dialog resizing
	m_sizeDlgMin = CSize (0, 0);
	m_sizeDlgMargins = CSize (0, 0);
	m_sizeDlgSpacings = CSize (0, 0);
	m_nInfoHeight = 0;
}

void CSampleDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CSampleDlg)
	DDX_Control(pDX, IDC_VIEWIMG, m_PreviewLocation);
	DDX_Control(pDX, IDC_RELEASE, m_btnRelease);
	DDX_Control(pDX, IDC_PREVIEW, m_btnPreview);
	DDX_Control(pDX, IDC_PREVIEWCLOSE, m_btnPreviewClose);
	DDX_Control(pDX, IDC_AEAF, m_btnAEAF);
	DDX_Control(pDX, IDC_CONNECT, m_btnConnect);
	DDX_Control(pDX, IDC_DISCONNECT, m_btnDisconnect);
	DDX_Text(pDX, IDC_INFORMATION, m_strInfo);
	DDX_Control(pDX, IDC_ZOOMSLIDER, m_sliderZoom);
	//}}AFX_DATA_MAP

	if (!pDX->m_bSaveAndValidate)
	{
		UpdateControls ();
	}
}

BEGIN_MESSAGE_MAP(CSampleDlg, CDialog)
	//{{AFX_MSG_MAP(CSampleDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_SIZE()
	ON_WM_GETMINMAXINFO()
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_CONNECT, OnConnect)
	ON_BN_CLICKED(IDC_DISCONNECT, OnDisconnect)
	ON_BN_CLICKED(IDC_AEAF, OnAEAF)
	ON_BN_CLICKED(IDC_PREVIEW, OnPreview)
	ON_BN_CLICKED(IDC_PREVIEWCLOSE, OnPreviewClose)
	ON_BN_CLICKED(IDC_RELEASE, OnRelease)
	ON_WM_HSCROLL()
	//}}AFX_MSG_MAP
	ON_REGISTERED_MESSAGE(CAMERAEVENT_INFO_MESSAGE, OnCameraInfo)
	ON_REGISTERED_MESSAGE(CAMERAEVENT_GETFRAME_MESSAGE, OnGetPreviewFrame)
	ON_REGISTERED_MESSAGE(CAMERAEVENT_ZOOMCHANGED_MESSAGE, OnZoomChanged)
	ON_REGISTERED_MESSAGE(CAMERAEVENT_CAMLISTCHANGED_MESSAGE, OnCamListChanged)
	ON_REGISTERED_MESSAGE(CAMERAEVENT_PROPLISTCHANGED_MESSAGE, OnPropertyListChanged)
	ON_REGISTERED_MESSAGE(CAMERAEVENT_PROPCHANGED_MESSAGE, OnPropertyChanged)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CSampleDlg message handlers

BOOL CSampleDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// Create tabs:
	m_PropPage1.SetOwnerDlg (this);
	m_PropSheet.AddPage(&m_PropPage1);
	m_PropSheet.Create (this, WS_CHILD | WS_VISIBLE, 0);
	m_PropSheet.ModifyStyleEx (0, WS_EX_CONTROLPARENT);
	m_PropSheet.ModifyStyle (0, WS_TABSTOP);

	CRect rcSheet;
	GetDlgItem (IDC_PROPSHEET)->GetWindowRect (rcSheet );
	ScreenToClient (rcSheet);
	m_PropSheet.SetWindowPos (NULL, rcSheet.left-7, rcSheet.top-7, rcSheet.Width (), rcSheet.Height (),
		SWP_NOZORDER | SWP_NOACTIVATE);

	SetWindowPos (NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);

	// Get file save path
	m_strSavePath = GetPath ();

	//--------------------------------
	// Dialog controls are initialized
	//--------------------------------
	UpdateControls ();

	//-------------
	// PS-SDK START
	//-------------
	PSResult psErr = PS_OK;
	psErr = PSInitializeSDK();
	if ( psErr != PS_OK )
	{
		goto camerr;
	}

	//----------------------------
	// Connection of camera device
	//----------------------------
	m_CamManager = PSGetCameraManager ();
	if (m_CamManager == 0)
	{
		MessageBox (_T("PSGetCameraManager failed"));
	}

	//------------------------------------------
	// Set handler for PSCameraListChanged event
	//------------------------------------------
	m_hCameraListEvent = PSCameraListChangedSubscribe (m_CamManager,
		(PSCameraListChangedCallback) pfnCamListChangedCallback,
		(void*) GetSafeHwnd ());

	if (!m_hCameraListEvent)
	{
		MessageBox (_T("PSCameraListChangedSubscribe failed"));
	}
	
	//----------------------------
	// A picture buffer is created
	//----------------------------
	m_pPreviewWnd = &m_PreviewLocation;
	if (!CreateDIBBuffer ())
	{
		MessageBox( "Error creating the picture buffer" );
		EndDialog( 0 );
		return	FALSE;
	}

	return TRUE;  // return TRUE  unless you set the focus to a control


camerr:

	CString strErr;
	if ( psErr != PS_OK )
	{
		strErr.Format(_T("ErrorCode = 0x%08X"), psErr);
	}
	else
	{
		strErr = _T("Unknown error");
	}

	MessageBox (strErr);
	EndDialog (1);
	return FALSE;
}
//*****************************************************************************
void CSampleDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}
//*****************************************************************************
// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.
void CSampleDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		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;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}
//*****************************************************************************
// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSampleDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}
//*****************************************************************************
void CSampleDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	ResizeControls ();	
}
//*****************************************************************************
void CSampleDlg::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 
{
	CDialog::OnGetMinMaxInfo(lpMMI);

	if (m_sizeDlgMin.cx != 0)
	{
		lpMMI->ptMinTrackSize.x = m_sizeDlgMin.cx;
		lpMMI->ptMinTrackSize.y = m_sizeDlgMin.cy;
	}
}
//*****************************************************************************
void CSampleDlg::ResizeControls ()
{
	if (GetSafeHwnd () == NULL)
	{
		return;
	}

	CWnd* pInfoWnd = GetDlgItem (IDC_INFORMATION);
	if (pInfoWnd->GetSafeHwnd () == NULL)
	{
		return;
	}

	ASSERT_VALID(this);
	ASSERT_VALID(pInfoWnd);

	CRect rectClient;
	GetClientRect (rectClient);

	CRect rectInfo;
	pInfoWnd->GetWindowRect(rectInfo);
	ScreenToClient (rectInfo);

	CRect rectPreview;
	m_PreviewLocation.GetWindowRect (rectPreview);
	ScreenToClient (rectPreview);

	if (m_sizeDlgMin.cx == 0)		// first call - save size
	{
		CRect rectDlg;
		GetWindowRect (rectDlg);

		m_sizeDlgMin = rectDlg.Size ();

		m_sizeDlgMargins.cx = rectClient.right - rectInfo.right;
		m_sizeDlgMargins.cy = rectClient.bottom - rectInfo.bottom;
		m_sizeDlgSpacings.cy = rectInfo.top - rectPreview.bottom;
		m_nInfoHeight = rectInfo.Height ();

		return;
	}

	// Resize controls:
	rectInfo.top		= rectClient.bottom - m_sizeDlgMargins.cy - m_nInfoHeight;
	rectInfo.right		= rectClient.right - m_sizeDlgMargins.cy;
	rectPreview.right	= rectClient.right - m_sizeDlgMargins.cy;
	rectPreview.bottom	= rectClient.bottom - m_sizeDlgMargins.cy - m_nInfoHeight - m_sizeDlgSpacings.cy;

	m_PreviewLocation.SetWindowPos (NULL, 
		rectPreview.left, rectPreview.top, rectPreview.Width (), rectPreview.Height (), 
		SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | (m_bPreviewEnabled ? 0 : SWP_NOCOPYBITS));

	pInfoWnd->SetWindowPos (NULL, 
		rectInfo.left, rectInfo.top, rectInfo.Width (), m_nInfoHeight, 
		SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS);
}
//*****************************************************************************
void CSampleDlg::UpdateControls ()
{
	m_btnConnect.EnableWindow (!m_bConnected);
	m_btnDisconnect.EnableWindow (m_bConnected);

	m_btnAEAF.EnableWindow (m_bConnected);
	m_btnPreview.EnableWindow (m_bConnected && !m_bPreviewEnabled);
	m_btnPreviewClose.EnableWindow (m_bConnected && m_bPreviewEnabled);
	m_btnRelease.EnableWindow (m_bConnected);

	GetDlgItem (IDC_INFORMATION)->SendMessage (WM_VSCROLL, MAKEWPARAM(SB_BOTTOM, 0));

	m_sliderZoom.EnableWindow (m_bConnected);

	if (m_PropSheet.GetSafeHwnd () != NULL)
	{
		//m_PropSheet.ShowWindow (m_bConnected ? SW_SHOWNOACTIVATE : SW_HIDE);
		m_PropSheet.EnableWindow (m_bConnected);
	}
}
//*****************************************************************************
void CSampleDlg::OnDestroy() 
{
	CDialog::OnDestroy();
	
	CleanUp ();
}
//*****************************************************************************
void CSampleDlg::CleanUp ()
{
	CleanUpSession ();

	if (m_hCameraListEvent != 0)
	{
		PSFree (m_hCameraListEvent);
		m_hCameraListEvent = 0;
	}

 	if (m_CamManager != 0)
 	{
		PSFree (m_CamManager);
 		m_CamManager = 0;
 	}

	FreeDIBBuffer ();

	//--------------------------------------
	// End processing of PS-SDK is performed
	//--------------------------------------
	PSTerminateSDK();

}
//*****************************************************************************
void CSampleDlg::CleanUpSession ()
{
	if (m_hPreviewFrameEvent != 0)
	{
		PSFree (m_hPreviewFrameEvent);
		m_hPreviewFrameEvent = 0;
	}

	if (m_hPropertyListEvent != 0)
	{
		PSFree (m_hPropertyListEvent);
		m_hPropertyListEvent = 0;
	}

	if (m_hPropertyEvent != 0)
	{
		PSFree (m_hPropertyEvent);
		m_hPropertyEvent = 0;
	}

	if (m_Session != 0)
	{
		PSFree (m_Session);
		m_Session = 0;
	}
}
//*****************************************************************************
void CSampleDlg::OnConnect() 
{
	if (m_CamManager == 0)
	{
		m_bConnected = FALSE;
		UpdateData (FALSE);

		return;
	}

	CleanUpSession ();

	//----------------
	// Get camera list
	//----------------
	int nCount = 0;
	PSCameraInfo* pCamList = 0;
	PSGetCameraList (m_CamManager, &pCamList, &nCount);

	if (nCount == 0)
	{
		AddInformationMessage (_T("No camera devices available"));

		m_bConnected = FALSE;
		UpdateData (FALSE);

		return;
	}

	if (pCamList == 0)
	{
		MessageBox (_T("PSGetCameraList failed: empty outCameraList"));

		m_bConnected = FALSE;
		UpdateData (FALSE);

		return;
	}

	CStringList lstCameras;

	for (int i = 0; i < nCount; i++)
	{
		PSCameraInfo camInfo;
		memcpy( &camInfo, (pCamList + sizeof(PSCameraInfo) * i), sizeof(PSCameraInfo) );

		CString strModelName;

#ifdef _UNICODE
		strModelName = camInfo.name;
#else
 		char pMBStringName[PS_MAX_NAME_LEN * 2];
		memset (pMBStringName, 0, sizeof (pMBStringName));
		::WideCharToMultiByte(CP_ACP, 0, camInfo.name, -1, pMBStringName, sizeof (pMBStringName) - 1, 0, 0);
 		strModelName = (const char *)pMBStringName;
#endif

		lstCameras.AddTail (strModelName);
	}

	//--------------
	// Select camera
	//--------------
	CSelectCameraDlg selectDlg (this);
	selectDlg.SetCameraList (lstCameras);
	if (selectDlg.DoModal () != IDOK || selectDlg.m_nSelectedCamera == -1)
	{
		m_bConnected = FALSE;
		UpdateData (FALSE);

		return;
	}

	//--------------------
	// Get selected camera
	//--------------------
	int index = selectDlg.m_nSelectedCamera;

	PSCameraInfo camInfo;
	memcpy( &camInfo, (pCamList + sizeof(PSCameraInfo) * index), sizeof(PSCameraInfo) );

	CString strModelName;
	CString strSystemId;

#ifdef _UNICODE
	strModelName = camInfo.name;
	strSystemId = camInfo.systemId;
#else
 	char pMBStringName[PS_MAX_NAME_LEN * 2];
	memset (pMBStringName, 0, sizeof (pMBStringName));
	::WideCharToMultiByte(CP_ACP, 0, camInfo.name, -1, pMBStringName, sizeof (pMBStringName) - 1, 0, 0);
 	strModelName = (const char *)pMBStringName;

 	char pMBStringSystemId[PS_MAX_SYSTEMID_LEN * 2];
	memset (pMBStringSystemId, 0, sizeof (pMBStringSystemId));
	::WideCharToMultiByte(CP_ACP, 0, camInfo.systemId, -1, pMBStringSystemId, sizeof (pMBStringSystemId) - 1, 0, 0);
 	strSystemId = (const char *)pMBStringSystemId;
#endif

	{
		CString strMsg;
		strMsg.Format (_T("Camera selected:\r\n   id: %d\r\n   name: %s\r\n   systemId: %s"), 
			(int)camInfo.id, strModelName, strSystemId);
		AddInformationMessage (strMsg);
	}

	ASSERT(pCamList->id == camInfo.id);

	if (pCamList != 0)
	{
		PSFree (pCamList);
		pCamList = 0;
	}

	//--------------------------------------
	// Open session of camera remote control
	//--------------------------------------
	PSResult psErr = PSOpenSession (m_CamManager, camInfo.id, &m_Session);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSOpenSession failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);

		m_bConnected = FALSE;
		UpdateData (FALSE);

		return;
	}

	if (m_Session == 0)
	{
		CString strErr;
		strErr.Format(_T("PSOpenSession failed: Wrong session handle. ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);

		m_bConnected = FALSE;
		UpdateData (FALSE);

		return;
	}

	{
		CString strMsg;
		strMsg.Format (_T("New camera connected:\r\n   id: %d\r\n   name: %s\r\n   systemId: %s"), 
			(int)camInfo.id, strModelName, strSystemId);
		AddInformationMessage (strMsg);
	}

	//----------------------------------------------
	// Set handler for PSShootAsync callback
	//----------------------------------------------
	s_ShootCompletedParam.session = m_Session;
	s_ShootCompletedParam.strSavePath = m_strSavePath;
	s_ShootCompletedParam.hwndDlg = GetSafeHwnd ();

	//----------------------------------------------
	// Set handler for PSDownloadFileToAsync callback
	//----------------------------------------------
	s_DownloadCompletedParam.hwndDlg = GetSafeHwnd ();

	//------------------
	// Set up properties
	//------------------
	UpdateProperty (PS_ImageSize,	 m_PropPage1.m_cbImageSize);
	UpdateProperty (PS_JpegQuality,	 m_PropPage1.m_cbImageQuality);
	UpdateProperty (PS_WBmode,		 m_PropPage1.m_cbWhiteBalance);
	UpdateProperty (PS_FlashMode,	 m_PropPage1.m_cbFlashMode);
	UpdateProperty (PS_RedEyeMode,	 m_PropPage1.m_cbRedEye);
	UpdateProperty (PS_FlashComp,	 m_PropPage1.m_cbFlashComp);
	UpdateProperty (PS_ISOSpeed,	 m_PropPage1.m_cbISOSpeed);
	UpdateProperty (PS_Av,			 m_PropPage1.m_cbAV);
	UpdateProperty (PS_Tv,			 m_PropPage1.m_cbTV);
	UpdateProperty (PS_ExposureComp, m_PropPage1.m_cbExposureComp);
	UpdateProperty (PS_AFMode,		 m_PropPage1.m_cbAFMode);
	UpdateProperty (PS_FocusingZone, m_PropPage1.m_cbFocusingZone);
	UpdateProperty (PS_MeteringMode, m_PropPage1.m_cbMeteringMode);
	UpdateProperty (PS_ShootingMode, m_PropPage1.m_cbShootingMode);
	UpdateProperty (PS_BatteryLevel, m_PropPage1.m_cbBatteryLevel);

	//-------------------
	// Set up zoom slider
	//-------------------
	UpdateZoom ();

	//-------------------------------------------------
	// Set handler for PSPropertyListChangedEvent event
	//-------------------------------------------------
	m_hPropertyListEvent = PSPropertyListChangedSubscribe (m_Session,
		(PSGenericEventCallback) pfnPropertyListCallback,
		(void *) GetSafeHwnd ());

	if (!m_hPropertyListEvent)
	{
		MessageBox (_T("PSPropertyListChangedSubscribe failed"));

		PSFree (m_Session);
		m_Session = 0;

		m_bConnected = FALSE;
		UpdateData (FALSE);

		return;
	}

	//---------------------------------------------
	// Set handler for PSPropertyChangedEvent event
	//---------------------------------------------
	m_hPropertyEvent = PSPropertyChangedSubscribe (m_Session,
		(PSPropertyChangedCallback) pfnPropertyCallback,
		(void *) GetSafeHwnd ());

	if (!m_hPropertyEvent)
	{
		MessageBox (_T("PSPropertyChangedSubscribe failed"));

		PSFree (m_Session);
		m_Session = 0;

		m_bConnected = FALSE;
		UpdateData (FALSE);

		return;
	}

	m_bConnected = TRUE;
	UpdateData (FALSE);

	m_btnPreview.SetFocus ();
}
//*****************************************************************************
void CSampleDlg::OnDisconnect() 
{
	OnPreviewClose ();

	//---------------------------------------
	// Get information about connected camera
	//---------------------------------------
	if (m_CamManager == 0)
	{
		ASSERT(FALSE);
		return;
	}

// 	PSCameraInfo camInfo;
// 	memset (&camInfo, 0, sizeof (camInfo));
// 
// 	if (m_Session != 0)
// 	{
// 		PSCameraInfo camInfo;
// 		memset (&camInfo, 0, sizeof (camInfo));
// 
// 		PSGetCameraInfo (m_Session, &camInfo);
// 	}

	int nCount = 0;
	PSCameraInfo* pCamList = 0;
	PSGetCameraList (m_CamManager, &pCamList, &nCount);

	if (nCount == 0)
	{
		AddInformationMessage (_T("No camera devices available"));

		m_bConnected = FALSE;
		UpdateData (FALSE);

		return;
	}

	if (pCamList == 0)
	{
		MessageBox (_T("PSGetCameraList failed: empty outCameraList"));

		m_bConnected = FALSE;
		UpdateData (FALSE);

		return;
	}

	int index = 0;

	PSCameraInfo camInfo;
	memcpy( &camInfo, (pCamList + sizeof(PSCameraInfo) * index), sizeof(PSCameraInfo) );

	if (pCamList != 0)
	{
		PSFree (pCamList);
		pCamList = 0;
	}

	CString strModelName;
	CString strSystemId;

#ifdef _UNICODE
	strModelName = camInfo.name;
	strSystemId = camInfo.systemId;
#else
 	char pMBStringName[PS_MAX_NAME_LEN * 2];
	memset (pMBStringName, 0, sizeof (pMBStringName));
	::WideCharToMultiByte(CP_ACP, 0, camInfo.name, -1, pMBStringName, sizeof (pMBStringName) - 1, 0, 0);
 	strModelName = (const char *)pMBStringName;

 	char pMBStringSystemId[PS_MAX_SYSTEMID_LEN * 2];
	memset (pMBStringSystemId, 0, sizeof (pMBStringSystemId));
	::WideCharToMultiByte(CP_ACP, 0, camInfo.systemId, -1, pMBStringSystemId, sizeof (pMBStringSystemId) - 1, 0, 0);
 	strSystemId = (const char *)pMBStringSystemId;
#endif

	CString strMsg;
	strMsg.Format (_T("Camera disconnected:\r\n   id: %d\r\n   name: %s\r\n   systemId: %s"), 
		(int)camInfo.id, strModelName, strSystemId);

	//------------------
	// Disconnect camera
	//------------------
	CleanUpSession ();

	//------------
	// Inform user
	//------------
	AddInformationMessage (strMsg);

	m_bConnected = FALSE;
	UpdateData (FALSE);

	m_btnConnect.SetFocus ();
}
//*****************************************************************************
void CSampleDlg::OnAEAF() 
{
	if (m_Session == 0)
	{
		return;
	}

	//----------------------------------
	// Autoexposure and autofocus update
	//----------------------------------
	PSResult psErr = PSUpdateAEAF (m_Session);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSUpdateAEAF failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);
	}
}
//*****************************************************************************
void CSampleDlg::OnPreview() 
{
	if (m_Session == 0)
	{
		return;
	}

	if (!m_hPreviewFrameEvent)
	{
		//---------------------------------------------
		// Set handler for PSNewPreviewFrameEvent event
		//---------------------------------------------
		s_PreviewFrameParam.hwndDlg = GetSafeHwnd ();

		m_hPreviewFrameEvent = PSNewPreviewFrameSubscribe (m_Session, 
			(PSGenericEventCallback) pfnNewPreviewFrameCallback, (void*) &s_PreviewFrameParam);

		if (!m_hPreviewFrameEvent)
		{
			MessageBox (_T("PSNewPreviewFrameSubscribe failed"));

			m_bPreviewEnabled = FALSE;
			UpdateData (FALSE);

			return;
		}

		PSResult psErr = PSSetPreviewState (m_Session, PS_PREVIEW_ENABLED);

		if (psErr != PS_OK)
		{
			CString strErr;
			strErr.Format(_T("PSSetPreviewState failed: ErrorCode = 0x%08X"), psErr);
			MessageBox (strErr);
		}
	}

	m_bPreviewEnabled = TRUE;
	UpdateData (FALSE);
}
//*****************************************************************************
void CSampleDlg::OnPreviewClose()
{
	//-----------------------------------------------
	// Remove handler of PSNewPreviewFrameEvent event
	//-----------------------------------------------
	if (m_hPreviewFrameEvent != 0)
	{
		PSFree (m_hPreviewFrameEvent);
		m_hPreviewFrameEvent = 0;
	}

	if (m_Session != 0)
	{
		PSResult psErr = PSSetPreviewState (m_Session, PS_PREVIEW_DISABLED);

		if (psErr != PS_OK)
		{
			CString strErr;
			strErr.Format(_T("PSSetPreviewState failed: ErrorCode = 0x%08X"), psErr);
			MessageBox (strErr);
		}
	}

	m_bPreviewEnabled = FALSE;
	UpdateData (FALSE);

	Invalidate();
	UpdateWindow();
}
//*****************************************************************************
void CSampleDlg::OnRelease() 
{
	if (m_Session == 0)
	{
		return;
	}

	//----------------
	// Release command
	//----------------
	PSResult psErr = PSShootAsync (m_Session, 
		(PSNewFileAsyncCallback) pfnShootCompletedCallback, 
		(void*) &s_ShootCompletedParam);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSRelease failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);
	}
}
//*****************************************************************************
void CSampleDlg::pfnShootCompletedCallback (void* context, PSFileInfo* resFileId)
{
	if (!context || !resFileId)
	{
		ASSERT(FALSE);
		return;
	}

	const SHOOT_COMPLETED_PARAM*	pParam	= (SHOOT_COMPLETED_PARAM*)context;

	if (pParam->session == 0)
	{
		ASSERT(FALSE);
		return;
	}

	if (pParam->hwndDlg == NULL)
	{
		ASSERT(FALSE);
		return;
	}

	CString strFileName;
#ifdef _UNICODE
	strFileName = resFileId->name;
#else
	char pMBStringFileName[PS_MAX_FILE_NAME_LEN * 2];
	memset (pMBStringFileName, 0, sizeof (pMBStringFileName));
	::WideCharToMultiByte(CP_ACP, 0, resFileId->name, -1, pMBStringFileName, sizeof (pMBStringFileName) - 1, 0, 0);
	strFileName = (const char *)pMBStringFileName;
#endif

	CString strMsg;
	strMsg.Format (_T("Release completed:\r\n   id: %d\r\n   name: %s\r\n   size: %d"),
		(int)resFileId->id, strFileName, (int)resFileId->size);
	s_CamInfo.strMessage = strMsg;
	::SendMessage (pParam->hwndDlg, CAMERAEVENT_INFO_MESSAGE, ::GetDlgCtrlID (pParam->hwndDlg), LPARAM (&s_CamInfo));

	//------------------------------------------
	// Get the name of the downloaded image file
	//------------------------------------------
	CString strFilePath;
	strFilePath.Format (_T("%s%s"), pParam->strSavePath, strFileName);

// 	CSaveDialog dlg = new COpenSaveDlg();
// 	dlg.FileName = fi.Name;
// 	dlg.Filter = "jpg files (*.jpg)|*.jpg|All files (*.*)|*.*";
// 	dlg.RestoreDirectory = true;
// 
// 	if (dlg.ShowDialog() == DialogResult.OK)

	const int nWFilePathLen = strFilePath.GetLength ();
	wchar_t* pWFilePath = new wchar_t [nWFilePathLen + 1];
	memset (pWFilePath, 0, sizeof (wchar_t) * (nWFilePathLen + 1));

#ifdef _UNICODE
	lstrcpy (pWFilePath, (LPCTSTR)strFilePath);
#else
	::MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPCTSTR)strFilePath, -1, pWFilePath, nWFilePathLen);
#endif

	strMsg.Format (_T("Try to download:\r\n   Id: %d\r\n   FilePath: %s"),
		(int)resFileId->id, strFilePath);
	s_CamInfo.strMessage = strMsg;
	::SendMessage (pParam->hwndDlg, CAMERAEVENT_INFO_MESSAGE, ::GetDlgCtrlID (pParam->hwndDlg), LPARAM (&s_CamInfo));

	//--------------
	// Download file
	//--------------
 	PSResult psErr = PSDownloadFileToAsync ((PSSessionHandle)pParam->session, 
		(PSFileId)resFileId->id, (wchar_t*)pWFilePath, true,
		(PSDownloadFileToAsyncCallback) pfnDownloadCompletedCallback,
		(void*) &s_DownloadCompletedParam);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSDownloadFileTo failed: ErrorCode = 0x%08X"), psErr);
		AfxMessageBox (strErr);
	}

	delete [] pWFilePath;
}
//*****************************************************************************
void CSampleDlg::pfnDownloadCompletedCallback (void* context, PSFileId fileId)
{
	if (!context)
	{
		ASSERT(FALSE);
		return;
	}

	const DOWNLOAD_COMPLETED_PARAM*	pParam	= (DOWNLOAD_COMPLETED_PARAM*)context;

	if (pParam->hwndDlg == NULL)
	{
		ASSERT(FALSE);
		return;
	}

	CString strMsg;
	strMsg.Format (_T("Download completed:\r\n   Id: %d"), (int)fileId);
	s_CamInfo.strMessage = strMsg;
	::SendMessage (pParam->hwndDlg, CAMERAEVENT_INFO_MESSAGE, ::GetDlgCtrlID (pParam->hwndDlg), LPARAM (&s_CamInfo));
}
//*****************************************************************************
void CSampleDlg::pfnNewPreviewFrameCallback (void* context)
{
	if (!context)
	{
		ASSERT(FALSE);
		return;
	}

	const PREVIEW_FRAME_PARAM*	pParam	= (PREVIEW_FRAME_PARAM*)context;

	if (pParam->hwndDlg == NULL)
	{
		ASSERT(FALSE);
		return;
	}

	::SendMessage (pParam->hwndDlg, CAMERAEVENT_GETFRAME_MESSAGE, 0, 0);
}
//*****************************************************************************
CString CSampleDlg::GetPath () const
{
	CString strPath;
	
	TCHAR lpszFilePath [_MAX_PATH];
	if (::GetModuleFileName (NULL, lpszFilePath, _MAX_PATH) > 0)
	{
		TCHAR path_buffer[_MAX_PATH];   
		TCHAR drive[_MAX_DRIVE];   
		TCHAR dir[_MAX_DIR];
		
#if _MSC_VER < 1400
		_tsplitpath (lpszFilePath, drive, dir, NULL, NULL);
		_tmakepath (path_buffer, drive, dir, NULL, NULL);
#else
		_tsplitpath_s (lpszFilePath, drive, _MAX_DRIVE, dir, _MAX_DIR, NULL, 0, NULL, 0);
		_tmakepath_s (path_buffer, drive, dir, NULL, NULL);
#endif
		
		strPath = path_buffer;
	}
	
	return strPath;
}
//*****************************************************************************
void CSampleDlg::AddInformationMessage (const CString& str)
{
	ASSERT_VALID (this);

	// implement queue - remove last string
	if (m_lstAllMsgs.GetCount () == s_nMaxMsgsCount)
	{
		m_lstAllMsgs.RemoveHead ();
	}
	m_lstAllMsgs.AddTail (str);

	// update textbox
	if (!m_strInfo.IsEmpty ())
	{
		m_strInfo += _T("\r\n");
	}
	m_strInfo += str;
	UpdateData (FALSE);
}
//*****************************************************************************
LRESULT CSampleDlg::OnCameraInfo (WPARAM, LPARAM lp)
{
	ASSERT_VALID (this);

	const CAMERAEVENT_INFO_STRUCT* pInfo = (CAMERAEVENT_INFO_STRUCT*)lp;
	if (pInfo == NULL)
	{
		return 0;
	}

	AddInformationMessage (pInfo->strMessage);

	return 0;
}
//*****************************************************************************
LRESULT CSampleDlg::OnGetPreviewFrame(WPARAM, LPARAM)
{
	ASSERT_VALID (this);

	//------------------
	// Get preview frame
	//------------------
	void* pBMPData = NULL;
	int nDataSize = 0;
	PSResult psErr = PSGetPreviewFrame(m_Session, &pBMPData, &nDataSize);

	if (psErr != PS_OK)
	{
		OnPreviewClose ();

		CString strErr;
		strErr.Format(_T("PSGetPreviewFrame failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);

		return 1;
	}

	if (!pBMPData || nDataSize <= 0)
	{
		ASSERT(FALSE);
		OnPreviewClose ();
		return 1;
	}

	//------------------------
	// Load bitmap information
	//------------------------
	PBITMAPFILEHEADER	pBmpFileheader = (PBITMAPFILEHEADER)pBMPData;
	PBITMAPINFOHEADER	pBmpInfoheader = (PBITMAPINFOHEADER)((LPBYTE)pBMPData + sizeof(BITMAPFILEHEADER));
	LPBYTE				bpPixel = (LPBYTE)pBMPData + pBmpFileheader->bfOffBits;

	if (pBmpInfoheader->biWidth != m_PreviewWidth ||
		pBmpInfoheader->biHeight != m_PreviewHeight ||
		pBmpInfoheader->biBitCount != m_PreviewBitCount)
	{
		//-----------------------
		// Recreate bitmap buffer
		//-----------------------
		FreeDIBBuffer ();

		ASSERT(pBmpInfoheader->biWidth > 0);
		ASSERT(pBmpInfoheader->biHeight > 0);
		ASSERT(pBmpInfoheader->biBitCount > 0);

		m_PreviewWidth		= pBmpInfoheader->biWidth;
		m_PreviewHeight		= pBmpInfoheader->biHeight;
		m_PreviewBitCount	= pBmpInfoheader->biBitCount;

		if (!CreateDIBBuffer ())
		{
			PSFree (pBMPData);
			return 1;
		}
	}

	ASSERT(pBmpInfoheader->biWidth == m_PreviewWidth);
	ASSERT(pBmpInfoheader->biHeight == m_PreviewHeight);
	ASSERT(pBmpInfoheader->biPlanes == 1);
	ASSERT(pBmpInfoheader->biBitCount == m_PreviewBitCount);
	ASSERT(pBmpInfoheader->biCompression == BI_RGB);

	ASSERT(m_PreviewSurface.vpBits != NULL);
	memcpy(m_PreviewSurface.vpBits, bpPixel, pBmpInfoheader->biSizeImage);

	//----------------
	// Free SDK buffer
	//----------------
	PSFree (pBMPData);

	//------------------------
	// Display preview picture
	//------------------------
	ASSERT_VALID (m_pPreviewWnd);

	CRect rectPreview;
	m_pPreviewWnd->GetWindowRect(&rectPreview);
	BOOL bStretch = TRUE;

	HDC hdcDest = ::GetDC (m_pPreviewWnd->GetSafeHwnd ());
	HDC hdcSrc = ::CreateCompatibleDC (hdcDest);
	::SelectObject (hdcSrc, m_PreviewSurface.hBmp);
	if (bStretch)
	{
		::StretchBlt(	hdcDest,
						1, 1, rectPreview.Width () - 2, rectPreview.Height () - 2,
						hdcSrc,
						0, 0, m_PreviewWidth, m_PreviewHeight,
						SRCCOPY );
	}
	else
	{
		::BitBlt(	hdcDest,
					0, 0, m_PreviewWidth, m_PreviewHeight,
					hdcSrc,
					0, 0,
					SRCCOPY );
	}
	::DeleteDC (hdcSrc);
	::ReleaseDC (m_pPreviewWnd->GetSafeHwnd (), hdcDest);

	return 0;
}
//*****************************************************************************
BOOL CSampleDlg::CreateDIBBuffer ()
{
	//-----------
	// Create DIB
	//-----------
	BITMAPINFO	BmpInfo;

	memset( &BmpInfo, 0, sizeof(BITMAPINFO) );
	BmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	BmpInfo.bmiHeader.biWidth = m_PreviewWidth;
	BmpInfo.bmiHeader.biHeight = m_PreviewHeight;
	BmpInfo.bmiHeader.biPlanes = 1;
	BmpInfo.bmiHeader.biBitCount = m_PreviewBitCount;
	BmpInfo.bmiHeader.biCompression = BI_RGB;

	m_PreviewSurface.hBmp = ::CreateDIBSection(	NULL,
		&BmpInfo,
		DIB_RGB_COLORS,
		&m_PreviewSurface.vpBits,
		NULL,
		0	);
	if( !m_PreviewSurface.hBmp )
	{
		return	FALSE;
	}

	return	TRUE;
}
//*****************************************************************************
void CSampleDlg::FreeDIBBuffer ()
{
	if (m_PreviewSurface.hBmp != NULL)
	{
		VERIFY(::DeleteObject(m_PreviewSurface.hBmp));
		memset( &m_PreviewSurface, 0, sizeof(DIBData) );
	}
}
//*****************************************************************************
void CSampleDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	if (m_Session == 0)
	{
		CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
		return;
	}

	//------------
	// Change zoom
	//------------
	if (nSBCode == TB_ENDTRACK)
	{
		int nZoomValue = m_sliderZoom.GetPos();

		PSResult psErr = PSSetZoom (m_Session, nZoomValue);

		if (psErr != PS_OK)
		{
			CString strErr;
			strErr.Format(_T("PSSetZoom failed: ErrorCode = 0x%08X"), psErr);
			MessageBox (strErr);
		}
	}

	CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
//*****************************************************************************
LRESULT CSampleDlg::OnZoomChanged(WPARAM, LPARAM)
{
	ASSERT_VALID (this);

	if (m_Session == 0)
	{
		return 1;
	}

	int nZoomValue = 0;
	PSResult psErr = PSGetZoom(m_Session, &nZoomValue);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSGetZoom failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);
	}

	CString strMsg;
	strMsg.Format (_T("Zoom completed:\r\n   New value: %d"), (int)nZoomValue);
	AddInformationMessage(strMsg);

	return 0;
}
//*****************************************************************************
void CSampleDlg::UpdateZoom ()
{
	if (m_Session == 0)
	{
		return;
	}

	//-------------------
	// Set up zoom slider
	//-------------------
	int nZoomMax = 0;
	PSResult psErr = PSGetMaximumZoom (m_Session, &nZoomMax);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSGetMaximumZoom failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);

		UpdateData (FALSE);
		return;
	}

	int nZoomTickFrequency = (nZoomMax > 10) ? nZoomMax / 10 : 1;

	int nZoomValue = 0;
	psErr = PSGetZoom (m_Session, &nZoomValue);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSGetZoom failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);

		UpdateData (FALSE);
		return;
	}

	m_sliderZoom.SetRangeMax(nZoomMax);
	m_sliderZoom.SetPos(nZoomValue);
	m_sliderZoom.SetTicFreq(nZoomTickFrequency);

	UpdateData (FALSE);
}
//*****************************************************************************
void CSampleDlg::UpdateProperty (const int nPropID, CComboBox& cb)
{
	if (m_Session == 0)
	{
		return;
	}

	if (cb.GetSafeHwnd() == NULL)
	{
		ASSERT(FALSE);
		return;
	}

	//-----------------------------
	// Enable Property if supported
	//-----------------------------
	if (!IsPropertySupported (nPropID))
	{
		cb.EnableWindow (FALSE);
		return;
	}

	//-------------------------------------
	// Get available values of the Property
	//-------------------------------------
	PSProp_Desc* pPropDesc = NULL;
	PSResult psErr = PSGetPropertyDesc (m_Session, nPropID, &pPropDesc);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSGetPropertyDesc failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);
	}

	if(pPropDesc == NULL)
	{
		ASSERT(FALSE);
		return;
	}

	cb.ResetContent ();
	cb.Clear ();

	int i;
	for (i = 0; i < pPropDesc->availableValuesLength; i++)
	{
		int* pValue = ((int*)pPropDesc->availableValues) + i;

		const char* pValueName = NULL;
		psErr = PSGetPropertyValName (nPropID, *pValue, &pValueName);

		if (psErr != PS_OK)
		{
			break;
		}

		cb.InsertString(i, CString ((LPCSTR) pValueName));
		cb.SetItemData(i, *pValue);
	}

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSGetPropertyValName failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);
	}

	//-------------------
	// Get Property value
	//-------------------
	int nValue = 0;
	psErr = PSGetPropertyData (m_Session, nPropID, &nValue);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSGetPropertyData failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);
	}

	for (i = 0; i < (int) cb.GetCount(); i++)
	{
		if ((int) cb.GetItemData (i) == nValue)
		{
			cb.SetCurSel (i);
			break;
		}
	}

	cb.EnableWindow (!pPropDesc->isReadOnly);

	if (pPropDesc != NULL)
	{
		PSFree (pPropDesc);
	}
}
//*****************************************************************************
BOOL CSampleDlg::IsPropertySupported (const int nPropID)
{
	if (m_Session == 0)
	{
		return FALSE;
	}

	//---------------------------------
	// Get list of available Properties
	//---------------------------------
	int* pPropList = NULL;
	int nPropListLen = 0;
	PSResult psErr = PSGetPropertyList (m_Session, &pPropList, &nPropListLen);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSGetPropertyList failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);
	}

	if (!pPropList)
	{
		return FALSE;
	}

	BOOL bPropEvailable = FALSE;

	for (int i = 0; i < nPropListLen; i++)
	{
		if (*((int*)pPropList + i) == nPropID)
		{
			bPropEvailable = TRUE;
			break;
		}
	}

	if (pPropList != NULL)
	{
		PSFree (pPropList);
	}

	return bPropEvailable;
}
//*****************************************************************************
BOOL CSampleDlg::SetProperty (const int nPropID, CComboBox& cb)
{
	if (m_Session == 0)
	{
		return FALSE;
	}

	if (cb.GetSafeHwnd() == NULL)
	{
		ASSERT(FALSE);
		return FALSE;
	}

	int nIndex = cb.GetCurSel ();
	ASSERT(nIndex >= 0 && nIndex < cb.GetCount ());

	int nValue = (int) cb.GetItemData(nIndex);

	//-----------------
	// Set the Property
	//-----------------
	PSResult psErr = PSSetPropertyData (m_Session, nPropID, nValue);

	if (psErr != PS_OK)
	{
		CString strErr;
		strErr.Format(_T("PSSetPropertyData failed: ErrorCode = 0x%08X"), psErr);
		MessageBox (strErr);

		return FALSE;
	}

	return TRUE;
}
//*****************************************************************************
void CSampleDlg::pfnCamListChangedCallback (void* context, PSCameraInfo* devInfo, int connectionState)
{
	const HWND hwnd	= (HWND)context;

	if (hwnd == NULL)
	{
		ASSERT(FALSE);
		return;
	}

	if (devInfo == NULL)
	{
		ASSERT(FALSE);
		return;
	}

	memcpy( &s_CameraListChangedParam.camInfo, devInfo, sizeof(PSCameraInfo) );
	s_CameraListChangedParam.state = connectionState;

	::SendMessage (hwnd, CAMERAEVENT_CAMLISTCHANGED_MESSAGE, 0, 0);
}
//*****************************************************************************
LRESULT CSampleDlg::OnCamListChanged(WPARAM, LPARAM)
{
	ASSERT_VALID (this);

	//------------
	// Inform user
	//------------
	CString strModelName;
	CString strSystemId;

#ifdef _UNICODE
	strModelName = s_CameraListChangedParam.camInfo.name;
	strSystemId = s_CameraListChangedParam.camInfo.systemId;
#else
 	char pMBStringName[PS_MAX_NAME_LEN * 2];
	memset (pMBStringName, 0, sizeof (pMBStringName));
	::WideCharToMultiByte(CP_ACP, 0, s_CameraListChangedParam.camInfo.name, -1, pMBStringName, sizeof (pMBStringName) - 1, 0, 0);
 	strModelName = (const char *)pMBStringName;

 	char pMBStringSystemId[PS_MAX_SYSTEMID_LEN * 2];
	memset (pMBStringSystemId, 0, sizeof (pMBStringSystemId));
	::WideCharToMultiByte(CP_ACP, 0, s_CameraListChangedParam.camInfo.systemId, -1, pMBStringSystemId, sizeof (pMBStringSystemId) - 1, 0, 0);
 	strSystemId = (const char *)pMBStringSystemId;
#endif

	CString strMsg;
	if (s_CameraListChangedParam.state == PS_CS_CONNECTED)
	{
		strMsg.Format (_T("New camera is available:\r\n   id: %d\r\n   name: %s\r\n   systemId: %s"), 
			(int)s_CameraListChangedParam.camInfo.id, strModelName, strSystemId);
	}
	else
	{
		strMsg.Format (_T("Camera is not available now:\r\n   id: %d\r\n   name: %s\r\n   systemId: %s"), 
			(int)s_CameraListChangedParam.camInfo.id, strModelName, strSystemId);
	}

	AddInformationMessage (strMsg);

	// Update dialog
	if (s_CameraListChangedParam.state != PS_CS_CONNECTED)
	{
		OnDisconnect ();
	}

	return 0;
}
//*****************************************************************************
void CSampleDlg::pfnPropertyListCallback (void* context)
{
	const HWND hwnd	= (HWND)context;

	if (hwnd == NULL)
	{
		ASSERT(FALSE);
		return;
	}

	::SendMessage (hwnd, CAMERAEVENT_PROPLISTCHANGED_MESSAGE, 0, 0);
}
//*****************************************************************************
LRESULT CSampleDlg::OnPropertyListChanged(WPARAM, LPARAM)
{
	ASSERT_VALID (this);

	if (m_Session == 0)
	{
		return 1;
	}

	//------------------
	// Set up properties
	//------------------
	UpdateProperty (PS_ImageSize,	 m_PropPage1.m_cbImageSize);
	UpdateProperty (PS_JpegQuality,	 m_PropPage1.m_cbImageQuality);
	UpdateProperty (PS_WBmode,		 m_PropPage1.m_cbWhiteBalance);
	UpdateProperty (PS_FlashMode,	 m_PropPage1.m_cbFlashMode);
	UpdateProperty (PS_RedEyeMode,	 m_PropPage1.m_cbRedEye);
	UpdateProperty (PS_FlashComp,	 m_PropPage1.m_cbFlashComp);
	UpdateProperty (PS_ISOSpeed,	 m_PropPage1.m_cbISOSpeed);
	UpdateProperty (PS_Av,			 m_PropPage1.m_cbAV);
	UpdateProperty (PS_Tv,			 m_PropPage1.m_cbTV);
	UpdateProperty (PS_ExposureComp, m_PropPage1.m_cbExposureComp);
	UpdateProperty (PS_AFMode,		 m_PropPage1.m_cbAFMode);
	UpdateProperty (PS_FocusingZone, m_PropPage1.m_cbFocusingZone);
	UpdateProperty (PS_MeteringMode, m_PropPage1.m_cbMeteringMode);
	UpdateProperty (PS_ShootingMode, m_PropPage1.m_cbShootingMode);
	UpdateProperty (PS_BatteryLevel, m_PropPage1.m_cbBatteryLevel);

	UpdateData (FALSE);

	//-------------------
	// Set up zoom slider
	//-------------------
	UpdateZoom ();

	CString strMsg;
	strMsg.Format (_T("Property list was changed"));
	AddInformationMessage (strMsg);

	return 0;
}
//*****************************************************************************
void CSampleDlg::pfnPropertyCallback (void* context, int prop)
{
	const HWND hwnd	= (HWND)context;

	if (hwnd == NULL)
	{
		ASSERT(FALSE);
		return;
	}

	::SendMessage (hwnd, CAMERAEVENT_PROPCHANGED_MESSAGE, 0, LPARAM (prop));
}
//*****************************************************************************
LRESULT CSampleDlg::OnPropertyChanged(WPARAM, LPARAM lp)
{
	ASSERT_VALID (this);

	if (m_Session == 0)
	{
		return 1;
	}

	int nPropID = (int)lp;

	switch (nPropID)
	{
	case PS_ImageSize:		UpdateProperty (PS_ImageSize,	 m_PropPage1.m_cbImageSize);	break;
	case PS_JpegQuality:	UpdateProperty (PS_JpegQuality,	 m_PropPage1.m_cbImageQuality);	break;
	case PS_WBmode:			UpdateProperty (PS_WBmode,		 m_PropPage1.m_cbWhiteBalance);	break;
	case PS_FlashMode:		UpdateProperty (PS_FlashMode,	 m_PropPage1.m_cbFlashMode);	break;
	case PS_RedEyeMode:		UpdateProperty (PS_RedEyeMode,	 m_PropPage1.m_cbRedEye);		break;
	case PS_FlashComp:		UpdateProperty (PS_FlashComp,	 m_PropPage1.m_cbFlashComp);	break;
	case PS_ISOSpeed:		UpdateProperty (PS_ISOSpeed,	 m_PropPage1.m_cbISOSpeed);		break;
	case PS_Av:				UpdateProperty (PS_Av,			 m_PropPage1.m_cbAV);			break;
	case PS_Tv:				UpdateProperty (PS_Tv,			 m_PropPage1.m_cbTV);			break;
	case PS_ExposureComp:	UpdateProperty (PS_ExposureComp, m_PropPage1.m_cbExposureComp);	break;
	case PS_AFMode:			UpdateProperty (PS_AFMode,		 m_PropPage1.m_cbAFMode);		break;
	case PS_FocusingZone:	UpdateProperty (PS_FocusingZone, m_PropPage1.m_cbFocusingZone);	break;
	case PS_MeteringMode:	UpdateProperty (PS_MeteringMode, m_PropPage1.m_cbMeteringMode);	break;
	case PS_ShootingMode:	UpdateProperty (PS_ShootingMode, m_PropPage1.m_cbShootingMode);	break;
	case PS_BatteryLevel:	UpdateProperty (PS_BatteryLevel, m_PropPage1.m_cbBatteryLevel);	break;
	}

	UpdateData (FALSE);

	CString strMsg;
	strMsg.Format (_T("Property #%d was changed"), nPropID);
	AddInformationMessage (strMsg);

	return 0;
}
