2025-11-27 16:46:48 +09:00

1802 lines
50 KiB
C++

// OXSoundCustomizeDlg.cpp : implementation file
//
// Version: 9.3
#include "stdafx.h"
#include "OXSoundCustomizeDlg.h"
#include "UTBStrOp.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// COXSoundCustomizeDlg dialog
// array of predefined sound events descriptions
//
static LPTSTR arrPredefinedEventDescription[][2] = {
{_T("Mouse enter"), _T("HWM_MOUSEENTER")},
{_T("Mouse leave"), _T("HWM_MOUSELEAVE")},
{_T("Left button down"), _T("WM_LBUTTONDOWN")},
{_T("Left button up"), _T("WM_LBUTTONUP")},
{_T("Left button double click"), _T("WM_LBUTTONDBLCLK")},
{_T("Right button down"), _T("WM_RBUTTONDOWN")},
{_T("Right button up"), _T("WM_RBUTTONUP")},
{_T("Right button double click"), _T("WM_RBUTTONDBLCLK")},
{_T("Middle button down"), _T("WM_MBUTTONDOWN")},
{_T("Middle button up"), _T("WM_MBUTTONUP")},
{_T("Middle button double click"), _T("WM_MBUTTONDBLCLK")},
};
int arrSoundDescriptionID [11]=
{
IDS_OX_SOUNDCSTMZDLGMOUSEENTER,
IDS_OX_SOUNDCSTMZDLGMOUSELEAVE,
IDS_OX_SOUNDCSTMZDLGLBDOWN,
IDS_OX_SOUNDCSTMZDLGLBUP,
IDS_OX_SOUNDCSTMZDLGLBDBL,
IDS_OX_SOUNDCSTMZDLGRBDOWN,
IDS_OX_SOUNDCSTMZDLGRBUP,
IDS_OX_SOUNDCSTMZDLGRBDBL,
IDS_OX_SOUNDCSTMZDLGMBDOWN,
IDS_OX_SOUNDCSTMZDLGMBUP,
IDS_OX_SOUNDCSTMZDLGMBDBL
};
TCHAR arrDescrs [11][_MAX_PATH];
/////////////////////////////////////////////////////////////////////////////
// array of predefined sound events identificators
//
static UINT arrPredefinedEventID[11] = {
HWM_MOUSEENTER,
HWM_MOUSELEAVE,
WM_LBUTTONDOWN,
WM_LBUTTONUP,
WM_LBUTTONDBLCLK,
WM_RBUTTONDOWN,
WM_RBUTTONUP,
WM_RBUTTONDBLCLK,
WM_MBUTTONDOWN,
WM_MBUTTONUP,
WM_MBUTTONDBLCLK,
};
/////////////////////////////////////////////////////////////////////////////
// constructor
COXSoundCustomizeDlg::COXSoundCustomizeDlg(CWnd* pParent,
COXSoundEffectOrganizer* pSoundEffectOrganizer,
enum LEVELTYPE nStartLevel/*=LT_EVENT*/,
DWORD dwDlgStyle/*=SCDS_NOTOGGLE*/)
: CDialog(COXSoundCustomizeDlg::IDD, pParent),
m_cmbFileName(COXHistoryCombo::TBPHorizontalTopRight,TRUE)
{
//{{AFX_DATA_INIT(COXSoundCustomizeDlg)
m_nEvent = -1;
m_sFileName = _T("");
m_bForceToStart = FALSE;
m_nLoopCount = 0;
m_nLoopType = -1;
//}}AFX_DATA_INIT
// save specified parameters for future use
//
ASSERT(pSoundEffectOrganizer!=NULL);
m_pSoundEffectOrganizer=pSoundEffectOrganizer;
m_nStartLevel=nStartLevel;
m_dwDlgStyle=dwDlgStyle;
/////////////////////////////////////////////////////////////////////////////
// initialize internal variables
//
m_bEditing=FALSE;
m_bAddingNew=FALSE;
m_dwControlState=0xffffffff;
/////////////////////////////////////////////////////////////////////////////
// fill array of all predefined events
//
for(int nIndex=0;
nIndex<sizeof(arrPredefinedEventID)/sizeof(arrPredefinedEventID[0]);
nIndex++)
{
CString sItem;
VERIFY(sItem.LoadString(arrSoundDescriptionID[nIndex]));
lstrcpy((LPTSTR) &arrDescrs[nIndex], sItem);
LPTSTR lpszString=(LPTSTR) &arrDescrs[nIndex];
arrPredefinedEventDescription[nIndex][0]=lpszString;
SetEvent(arrPredefinedEventID[nIndex],
(LPCTSTR*) arrPredefinedEventDescription[nIndex]);
}
/////////////////////////////////////////////////////////////////////////////
}
// destructor
COXSoundCustomizeDlg::~COXSoundCustomizeDlg()
{
// delete all the structures we allocated and clear up all arrays
//
LPITEMINFO pItemInfo;
HANDLE hItem;
POSITION pos=m_allTreeItems.GetStartPosition();
while(pos!=NULL)
{
m_allTreeItems.GetNextAssoc(pos,hItem,pItemInfo);
ASSERT(hItem!=NULL);
ASSERT(pItemInfo!=NULL);
delete pItemInfo;
}
m_allTreeItems.RemoveAll();
m_allDefinedEvents.RemoveAll();
/////////////////////////////////////////////////////////////////////////////
}
void COXSoundCustomizeDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(COXSoundCustomizeDlg)
DDX_Control(pDX, IDC_OX_BUTTON_RESTORE_OXSOUND, m_btnRestore);
DDX_Control(pDX, IDC_OX_EDIT_LOOPCOUNT_OXSOUND, m_editLoopCount);
DDX_Control(pDX, IDC_OX_CHECK_FORCE_OXSOUND, m_btnForceToStart);
DDX_Control(pDX, IDOK, m_btnOk);
DDX_Control(pDX, IDCANCEL, m_btnCancel);
DDX_Control(pDX, IDC_OX_EXTTREE_EFFECTSLIST_OXSOUND, m_treeEffect);
DDX_Control(pDX, IDC_OX_COMBO_FILENAME_OXSOUND, m_cmbFileName);
DDX_Control(pDX, IDC_OX_COMBO_EVENT_OXSOUND, m_cmbEvent);
DDX_Control(pDX, IDC_OX_BUTTON_STOP_OXSOUND, m_btnStop);
DDX_Control(pDX, IDC_OX_BUTTON_SAVE_OXSOUND, m_btnSave);
DDX_Control(pDX, IDC_OX_BUTTON_REMOVE_OXSOUND, m_btnRemove);
DDX_Control(pDX, IDC_OX_BUTTON_PLAY_OXSOUND, m_btnPlay);
DDX_Control(pDX, IDC_OX_BUTTON_ADD_OXSOUND, m_btnAdd);
DDX_CBIndex(pDX, IDC_OX_COMBO_EVENT_OXSOUND, m_nEvent);
DDX_CBString(pDX, IDC_OX_COMBO_FILENAME_OXSOUND, m_sFileName);
DDX_Check(pDX, IDC_OX_CHECK_FORCE_OXSOUND, m_bForceToStart);
DDX_Text(pDX, IDC_OX_EDIT_LOOPCOUNT_OXSOUND, m_nLoopCount);
DDX_Radio(pDX, IDC_OX_RADIO_LOOPONCE_OXSOUND, m_nLoopType);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(COXSoundCustomizeDlg, CDialog)
//{{AFX_MSG_MAP(COXSoundCustomizeDlg)
ON_BN_CLICKED(IDC_OX_BUTTON_ADD_OXSOUND, OnButtonAdd)
ON_BN_CLICKED(IDC_OX_BUTTON_PLAY_OXSOUND, OnButtonPlay)
ON_BN_CLICKED(IDC_OX_BUTTON_REMOVE_OXSOUND, OnButtonRemove)
ON_BN_CLICKED(IDC_OX_BUTTON_SAVE_OXSOUND, OnButtonSave)
ON_BN_CLICKED(IDC_OX_BUTTON_STOP_OXSOUND, OnButtonStop)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_OX_EXTTREE_EFFECTSLIST_OXSOUND, OnItemchangedExttreeEffectslist)
ON_BN_CLICKED(IDC_OX_BUTTON_RESTORE_OXSOUND, OnButtonRestore)
ON_BN_CLICKED(IDC_OX_CHECK_FORCE_OXSOUND, OnCheckForce)
ON_CBN_EDITCHANGE(IDC_OX_COMBO_EVENT_OXSOUND, OnEditchangeComboEvent)
ON_CBN_SELCHANGE(IDC_OX_COMBO_EVENT_OXSOUND, OnSelchangeComboEvent)
ON_CBN_EDITCHANGE(IDC_OX_COMBO_FILENAME_OXSOUND, OnEditchangeComboFilename)
ON_CBN_SELCHANGE(IDC_OX_COMBO_FILENAME_OXSOUND, OnSelchangeComboFilename)
ON_EN_CHANGE(IDC_OX_EDIT_LOOPCOUNT_OXSOUND, OnChangeEditLoopcount)
ON_BN_CLICKED(IDC_OX_RADIO_LOOPINFINITELY_OXSOUND, OnRadioLoopinfinitely)
ON_BN_CLICKED(IDC_OX_RADIO_LOOPONCE_OXSOUND, OnRadioLooponce)
ON_BN_CLICKED(IDC_OX_RADIO_LOOPREPEAT_OXSOUND, OnRadioLooprepeat)
ON_NOTIFY(TVN_ITEMEXPANDING, IDC_OX_EXTTREE_EFFECTSLIST_OXSOUND, OnItemExpandingExttreeEffectslist)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_KICKIDLE, OnKickIdle)
ON_MESSAGE(WM_OX_SOUNDPLAYBACKCOMPLETE, OnPlaybackComplete)
ON_MESSAGE(SMDM_UPDATEVARS, OnUpdateVars)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// COXSoundCustomizeDlg message handlers
BOOL COXSoundCustomizeDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
// initialize event multi combo box
//
m_cmbEvent.SetColumnCount(ID_EVENTINFOCOLUMNS);
m_cmbEvent.SetColumnWidth(0,130);
m_cmbEvent.SetColumnWidth(1,100);
POSITION posDefinedEvents=m_allDefinedEvents.GetStartPosition();
while(posDefinedEvents!=NULL)
{
LPCTSTR* ppszText=NULL;
UINT nMsgID;
m_allDefinedEvents.GetNextAssoc(posDefinedEvents,nMsgID,ppszText);
ASSERT(ppszText!=NULL);
ASSERT(nMsgID!=SNDEVENT_NONE);
m_cmbEvent.AddString(ppszText,ID_EVENTINFOCOLUMNS);
}
//////////////////////////////////////////////
// initialize file name history combo box
//
// Use auto persistence
m_cmbFileName.SetAutoPersistent(_T("History - FileName"));
m_cmbFileName.SetFileDialogParams(TRUE,_T("wav"),NULL,
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
_T("WAV Files (*.wav)|*.wav|All Files (*.*)|*.*|"));
m_cmbFileName.SetMaxHistoryCount(-1);
m_cmbFileName.SetFlatToolbar(TRUE);
m_cmbFileName.RefreshToolbar();
//////////////////////////////////////////////
// initialize tree control
//
// columns' width
UINT nEventColWidth=150;
UINT nFileNameColWidth=150;
UINT nEventInfoColWidth=120;
UINT nLoopColWidth=70;
// sort order
BOOL bSortAscending=TRUE;
// sorted column
int nSortCol=-1;
// load saved state from registry if corresponding style is specified
//
if((m_dwDlgStyle&SCDS_LOADSTATE)!=0)
{
CWinApp* pApp=AfxGetApp();
if(pApp!=NULL)
{
nEventColWidth=pApp->GetProfileInt(_T("Sound Customize Dialog"),
_T("EventColWidth"),nEventColWidth);
nFileNameColWidth=pApp->GetProfileInt(_T("Sound Customize Dialog"),
_T("FileNameColWidth"),nFileNameColWidth);
nEventInfoColWidth=pApp->GetProfileInt(_T("Sound Customize Dialog"),
_T("EventInfoColWidth"),nEventInfoColWidth);
nLoopColWidth=pApp->GetProfileInt(_T("Sound Customize Dialog"),
_T("LoopColWidth"),nLoopColWidth);
bSortAscending=pApp->GetProfileInt(_T("Sound Customize Dialog"),
_T("SortAscending"),bSortAscending);
nSortCol=pApp->GetProfileInt(_T("Sound Customize Dialog"),
_T("SortCol"),nSortCol);
}
}
// create the image list that will be associated with the tree control
m_ilTree.Create(IDB_OX_TREELIST_OXSOUND,16,1,RGB(255,0,255));
// insert tree columns
LV_COLUMN lvc;
memset(&lvc,0,sizeof(lvc));
lvc.fmt=LVCFMT_LEFT;
lvc.cx=nEventColWidth;
CString sItem;
VERIFY(sItem.LoadString(IDS_OX_SOUND_EVENT));//"Event"
lvc.pszText=sItem.GetBuffer(sItem.GetLength());
lvc.mask=LVCF_FMT|LVCF_WIDTH|LVCF_TEXT;
m_treeEffect.SetColumn(0,&lvc);
sItem.ReleaseBuffer();
VERIFY(sItem.LoadString(IDS_OX_SOUNDFILE));//"Sound File"
m_treeEffect.InsertColumn(1,sItem,LVCFMT_LEFT,nFileNameColWidth,1);
VERIFY(sItem.LoadString(IDS_OX_SOUNDEVENT));//"Event Info"
m_treeEffect.InsertColumn(2,sItem,LVCFMT_LEFT,nEventInfoColWidth,2);
VERIFY(sItem.LoadString(IDS_OX_SOUNDLOOP));//"Loop"
m_treeEffect.InsertColumn(3,sItem,LVCFMT_CENTER,nLoopColWidth,3);
m_treeEffect.SetImageList(&m_ilTree,TVSIL_NORMAL);
// create fonts to customize tree items appearance
LOGFONT lf;
CFont fontRoot, fontSubroot;
CFont* pFont=GetFont();
if(pFont->GetLogFont(&lf))
{
lf.lfHeight=-14;
UTBStr::tcsncpy(lf.lfFaceName, 6, _T("Arial"),LF_FACESIZE);
fontRoot.CreateFontIndirect(&lf);
UTBStr::tcsncpy(lf.lfFaceName, 16, _T("Times New Roman"),LF_FACESIZE);
fontSubroot.CreateFontIndirect(&lf);
}
// loop through all registered windows
POSITION pos=m_pSoundEffectOrganizer->GetFirstRegisteredWindow();
while(pos!=NULL)
{
CWnd* pWnd=m_pSoundEffectOrganizer->GetNextRegisteredWindow(pos);
ASSERT(pWnd);
ASSERT(pWnd->GetSafeHwnd());
// get corresponding COXSoundEffectManager object
COXSoundEffectManager* pSoundEffectManager=
m_pSoundEffectOrganizer->GetManager(pWnd);
ASSERT(pSoundEffectManager);
// get item text
//
CString sItemText;
// for items that represent registered windows level we use type
// of the control and window's text as item text
CString sWindowText;
pWnd->GetWindowText(sItemText);
sWindowText=GetSubString(sItemText,1,_T('\n'));
if(sWindowText.IsEmpty())
sWindowText=GetSubString(sItemText,2,_T('\n'));
// flag that specifies if we have to add the window's text to the
// window's type
BOOL bAddWindowText=!sWindowText.IsEmpty();
// get windows type
CString sWindowType=_T("Window");
if(pWnd->IsKindOf(RUNTIME_CLASS(CStatic)))
sWindowType=_T("Static");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CButton)))
sWindowType=_T("Button");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CAnimateCtrl)))
sWindowType=_T("Animation");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CTreeCtrl)))
sWindowType=_T("Tree Control");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CListCtrl)))
sWindowType=_T("List Control");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CComboBox)))
sWindowType=_T("ComboBox");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CListBox)))
sWindowType=_T("ListBox");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CSliderCtrl)))
sWindowType=_T("Slider");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CTabCtrl)))
sWindowType=_T("Tab Control");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CEdit)))
sWindowType=_T("Edit");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CRichEditCtrl)))
sWindowType=_T("RichEdit");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CProgressCtrl)))
sWindowType=_T("Progress Bar");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CSpinButtonCtrl)))
sWindowType=_T("Spin Button");
else if(pWnd->IsKindOf(RUNTIME_CLASS(CScrollBar)))
sWindowType=_T("Scroll Bar");
sItemText=sWindowType;
if(bAddWindowText)
sItemText.Format(_T("%s: %s"),sItemText,sWindowText);
TV_ITEM tvi;
HTREEITEM htiSubroot;
POSITION posEvent;
LPITEMINFO pItemInfo;
// registered window
HTREEITEM htiRoot=m_treeEffect.InsertItem(sItemText);
ASSERT(htiRoot);
// associate new font
if((HFONT)fontRoot)
VERIFY(m_treeEffect.SetItemFont(htiRoot,&fontRoot));
// and new color
VERIFY(m_treeEffect.SetItemColor(htiRoot,RGB(0,0,255)));
// create description of the new tree item
pItemInfo=new ITEMINFO;
pItemInfo->type=IT_WINDOW;
pItemInfo->pWnd=pWnd;
pItemInfo->dwControlState=CTL_OK|CTL_CANCEL|CTL_TREE|CTL_REMOVE;
m_allTreeItems.SetAt((HANDLE)htiRoot,pItemInfo);
// expand it if otherwise wasn't specified
if(m_nStartLevel!=LT_WINDOW)
m_treeEffect.Expand(htiRoot,TVE_EXPAND);
///////////////////////////
// registered play events
//
// item for list of all start playing sound events
CString sItem;
VERIFY(sItem.LoadString(IDS_OX_SOUNDPLAYSOUND));//"Play sound events"
htiSubroot=m_treeEffect.InsertItem(sItem,htiRoot);
ASSERT(htiSubroot);
// expand it if otherwise wasn't specified
if(m_nStartLevel==LT_EVENT)
m_treeEffect.Expand(htiSubroot,TVE_EXPAND);
// associate new font
if((HFONT)fontSubroot)
VERIFY(m_treeEffect.SetItemFont(htiSubroot,&fontSubroot));
// and new color
VERIFY(m_treeEffect.SetItemColor(htiSubroot,RGB(128,0,0)));
// insert the item
memset(&tvi,0,sizeof(tvi));
tvi.mask=TVIF_IMAGE|TVIF_HANDLE|TVIF_SELECTEDIMAGE;
tvi.hItem=htiSubroot;
tvi.iImage=1;
tvi.iSelectedImage=1;
m_treeEffect.SetItem(&tvi);
// create description of the new tree item
pItemInfo=new ITEMINFO;
pItemInfo->type=IT_PLAYEVENTLIST;
pItemInfo->pWnd=pWnd;
pItemInfo->dwControlState=CTL_OK|CTL_CANCEL|CTL_TREE|CTL_REMOVE|CTL_ADD;
m_allTreeItems.SetAt((HANDLE)htiSubroot,pItemInfo);
// loop through all play events
posEvent=pSoundEffectManager->GetFirstPlayEvent();
while(posEvent!=NULL)
{
// get the registered event ID
UINT nPlayMsgID=pSoundEffectManager->GetNextPlayEvent(posEvent);
ASSERT(nPlayMsgID!=SNDEVENT_NONE);
// add new play event item to the tree
AddEventItem(pWnd,htiSubroot,nPlayMsgID,pSoundEffectManager,TRUE);
}
///////////////////////////
// registered stop events
//
// item for list of all stop playing sound events
VERIFY(sItem.LoadString(IDS_OX_SOUNDSTOPPLAYING));//"Stop playing events"
htiSubroot=m_treeEffect.InsertItem(sItem,htiRoot);
ASSERT(htiSubroot);
// expand it if otherwise wasn't specified
if(m_nStartLevel==LT_EVENT)
m_treeEffect.Expand(htiSubroot,TVE_EXPAND);
// associate new font
if((HFONT)fontSubroot)
VERIFY(m_treeEffect.SetItemFont(htiSubroot,&fontSubroot));
// and new color
VERIFY(m_treeEffect.SetItemColor(htiSubroot,RGB(128,0,0)));
// insert the item
memset(&tvi,0,sizeof(tvi));
tvi.mask=TVIF_IMAGE|TVIF_HANDLE|TVIF_SELECTEDIMAGE;
tvi.hItem=htiSubroot;
tvi.iImage=2;
tvi.iSelectedImage=2;
m_treeEffect.SetItem(&tvi);
// create description of the new tree item
pItemInfo=new ITEMINFO;
pItemInfo->type=IT_STOPEVENTLIST;
pItemInfo->pWnd=pWnd;
pItemInfo->dwControlState=CTL_OK|CTL_CANCEL|CTL_TREE|CTL_REMOVE|CTL_ADD;
m_allTreeItems.SetAt((HANDLE)htiSubroot,pItemInfo);
// loop through all stop events
posEvent=pSoundEffectManager->GetFirstStopEvent();
while(posEvent!=NULL)
{
// get the registered event ID
UINT nStopMsgID=pSoundEffectManager->GetNextStopEvent(posEvent);
ASSERT(nStopMsgID!=SNDEVENT_NONE);
// add new stop event item to the tree
AddEventItem(pWnd,htiSubroot,nStopMsgID,pSoundEffectManager,FALSE);
}
///////////////////////////
}
// set COXTreeCtrl styles
m_treeEffect.ModifyExStyle(0,TVOXS_PICKANYWHERE|TVOXS_ROWSEL|TVOXS_MULTISEL);
m_treeEffect.ModifyStyle(0,TVS_SHOWSELALWAYS);
// sort the tree control if needed
if(nSortCol!=-1)
{
ASSERT(nSortCol>=0 && nSortCol<m_treeEffect.GetColumnsCount());
m_treeEffect.SortChildren(NULL,nSortCol,bSortAscending);
}
//////////////////////////////////////////////
// initialize bitmap buttons
//
SetupBitmapButton(&m_btnPlay);
SetupBitmapButton(&m_btnStop);
VERIFY(m_btnPlay.LoadBitmap(IDB_OX_BITMAP_PLAY_OXSOUND, FALSE, RGB(255,0,255)));
VERIFY(m_btnStop.LoadBitmap(IDB_OX_BITMAP_STOP_OXSOUND, FALSE, RGB(255,0,255)));
//////////////////////////////////////////////
// initialize sound object
//
m_TestSound.SetCallbackWnd(this);
//////////////////////////////////////////////
// change the dialog caption text if read-only style was specified
if((m_dwDlgStyle&SCDS_READONLY)!=0)
{
CString sWindowText;
GetWindowText(sWindowText);
CString sText;
VERIFY(sText.LoadString(IDS_OX_SOUNDREADONLY));//" (Read Only)"
sWindowText+=sText;
SetWindowText(sWindowText);
}
// populate the dialog controls
GetVars();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void COXSoundCustomizeDlg::GetVars()
{
// initialize
//
m_nEvent=-1;
m_sFileName=_T("");
m_bForceToStart=FALSE;
m_nLoopCount=0;
m_nLoopType=-1;
DWORD dwControlState=CTL_OK|CTL_CANCEL|CTL_TREE;
//////////////////////
// populate the dialog controls depending on the selected tree item(s)
HTREEITEM htiSelected=m_treeEffect.GetNextItem(m_treeEffect.GetRootItem(),
TVGN_FIRSTSELECTED);
// loop through all selected items
BOOL bForFirstTime=TRUE;
while(htiSelected!=NULL)
{
LPITEMINFO pItemInfo;
VERIFY(m_allTreeItems.Lookup(htiSelected,pItemInfo));
ASSERT(pItemInfo!=NULL);
// control's state flag
if(bForFirstTime)
dwControlState=pItemInfo->dwControlState;
else
dwControlState&=pItemInfo->dwControlState;
// populate controls depending on the type of the item
switch(pItemInfo->type)
{
case IT_WINDOW:
case IT_PLAYEVENTLIST:
case IT_STOPEVENTLIST:
{
if(!bForFirstTime)
{
m_nEvent=-1;
m_sFileName.Empty();
m_nLoopCount=0;
m_nLoopType=-1;
}
break;
}
case IT_PLAYEVENT:
{
ASSERT(pItemInfo->nMsgID!=SNDEVENT_NONE);
// sound event info
LPCTSTR* ppszText=NULL;
if(m_allDefinedEvents.Lookup(pItemInfo->nMsgID,ppszText))
{
ASSERT(ppszText!=NULL);
CString sEvent=ppszText[0];
if(bForFirstTime)
m_nEvent=m_cmbEvent.FindStringExact(-1,sEvent);
else if(m_nEvent!=m_cmbEvent.FindStringExact(-1,sEvent))
m_nEvent=-1;
}
else
m_nEvent=-1;
ASSERT(pItemInfo->pWnd!=NULL);
ASSERT(::IsWindow(pItemInfo->pWnd->GetSafeHwnd()));
LPSOUNDEFFECT pSoundEffect=pItemInfo->pSoundEffect;
if(pSoundEffect!=NULL)
{
// sound source info
LPSOUNDSOURCEINFO pSoundSourceInfo=pItemInfo->pSoundSourceInfo;
ASSERT(pSoundSourceInfo!=NULL);
CString sFileName;
switch(pSoundSourceInfo->source)
{
case SNDSRC_FILE:
sFileName=pSoundSourceInfo->sFileName;
break;
case SNDSRC_CFILE:
VERIFY(sFileName.LoadString(IDS_OX_SOUNDOPENCFILE));//"Opened CFile object"
//sFileName=_T();
break;
case SNDSRC_INTRESOURCE:
sFileName.Format(IDS_OX_SOUNDRESOURCEID,//"Resource: ID=%d"
pSoundSourceInfo->nResourceID);
break;
default:
ASSERT(FALSE);
}
if(bForFirstTime)
m_sFileName=sFileName;
else if(m_sFileName!=sFileName)
m_sFileName.Empty();
// "Force To Start" flag
if(bForFirstTime)
m_bForceToStart=pSoundEffect->bForceToStart;
else if(m_bForceToStart!=pSoundEffect->bForceToStart)
m_bForceToStart=2;
// loop type
int nLoopCount=pSoundEffect->nLoopCount;
int nLoopType=0;
if(!pSoundEffect->bLoop || nLoopCount==0 || nLoopCount==1)
{
nLoopCount=0;
nLoopType=0;
}
else if(nLoopCount==-1)
{
nLoopCount=0;
nLoopType=1;
}
else if(nLoopCount>1)
nLoopType=2;
else
ASSERT(FALSE);
if(bForFirstTime)
m_nLoopCount=nLoopCount;
else if(m_nLoopCount!=nLoopCount)
m_nLoopCount=0;
if(bForFirstTime)
m_nLoopType=nLoopType;
else if(m_nLoopType!=nLoopType)
m_nLoopType=-1;
}
break;
}
case IT_STOPEVENT:
{
ASSERT(pItemInfo->nMsgID!=SNDEVENT_NONE);
if(!bForFirstTime)
{
m_sFileName.Empty();
m_nLoopCount=0;
m_nLoopType=-1;
}
// sound event info
LPCTSTR* ppszText=NULL;
if(m_allDefinedEvents.Lookup(pItemInfo->nMsgID,ppszText))
{
ASSERT(ppszText!=NULL);
CString sEvent=ppszText[0];
if(bForFirstTime)
m_nEvent=m_cmbEvent.FindStringExact(-1,sEvent);
else if(m_nEvent!=m_cmbEvent.FindStringExact(-1,sEvent))
m_nEvent=-1;
}
else
m_nEvent=-1;
break;
}
default:
ASSERT(FALSE);
}
bForFirstTime=FALSE;
htiSelected=m_treeEffect.GetNextItem(htiSelected,TVGN_NEXTSELECTED);
}
// setupo availability of "Add" and "Remove" buttons
if(m_treeEffect.GetSelectedCount()>1)
dwControlState&=~(CTL_ADD|CTL_REMOVE);
if(m_nEvent==-1)
dwControlState&=~(CTL_EVENT);
// enable/disable controls
ShowControls(dwControlState);
// show it
UpdateData(FALSE);
}
LRESULT COXSoundCustomizeDlg::OnKickIdle(WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
UNUSED(wParam);
//use this function to let History Combo's toolbars to get messages
ASSERT_VALID(this);
ASSERT(wParam == MSGF_DIALOGBOX);
BOOL bContinueIdle = TRUE;
// Pass on to the history combo
m_cmbFileName.OnIdle();
return bContinueIdle;
}
LRESULT COXSoundCustomizeDlg::OnUpdateVars(WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(wParam);
UNREFERENCED_PARAMETER(lParam);
// update only once !!!
//
MSG msg;
while(::PeekMessage(&msg,GetSafeHwnd(),SMDM_UPDATEVARS,
SMDM_UPDATEVARS,PM_REMOVE));
GetVars();
//////////////////////////
return (LRESULT)0;
}
void COXSoundCustomizeDlg::SetupBitmapButton(COXBitmapButton* m_pctl)
{
// new font
CFont* pFont=m_pctl->GetTextFont();
if(pFont)
{
LOGFONT lf;
if(pFont->GetLogFont(&lf))
{
lf.lfWeight=FW_BOLD;
lf.lfHeight=-14;
UTBStr::tcsncpy(lf.lfFaceName, 16, _T("Times New Roman"),LF_FACESIZE);
pFont->DeleteObject();
if(pFont->CreateFontIndirect(&lf))
m_pctl->SetTextFont(pFont);
}
}
// new color
m_pctl->SetTextColor(RGB(128,0,0));
// tooltip is enabled
m_pctl->SetToolTip(TRUE);
// track look is set
m_pctl->SetTrackLook(TRUE);
// alignment
m_pctl->SetVerticalAlignment(BS_VCENTER);
m_pctl->SetHorizontalAlignment(BS_LEFT);
}
CString COXSoundCustomizeDlg::GetSubString(LPCTSTR pszFullString, int nSubIndex,
TCHAR cDelimiter)
// --- In : pszFullString : The full string
// nSubIndex : The ONE-based index of the substring requested
// cDelimiter : Delimiter character used between all substrings
// --- Out :
// --- Returns : The requested substring or an empty string otherwise
// --- Effect :
{
ASSERT(0 < nSubIndex);
CString sSubString;
if (pszFullString == NULL)
{
// Nothing to search : nothing to find
ASSERT(sSubString.IsEmpty());
return sSubString;
}
// Set pszStart to first charecter and pszEnd after last charecter
LPCTSTR pszBegin = pszFullString;
LPCTSTR pszEnd = pszFullString + _tcslen(pszFullString);
LPCTSTR pszDelimiter = _tcschr(pszBegin, cDelimiter);
if (pszDelimiter == NULL)
pszDelimiter = pszEnd;
ASSERT((*pszDelimiter == cDelimiter) || (*pszDelimiter == _T('\0')));
ASSERT(pszBegin <= pszDelimiter);
while (--nSubIndex != 0)
{
if (*pszDelimiter == _T('\0'))
{
// Search to end of string and not found
ASSERT(sSubString.IsEmpty());
return sSubString;
}
pszBegin = pszDelimiter + 1;
pszDelimiter = _tcschr(pszBegin, cDelimiter);
if (pszDelimiter == NULL)
pszDelimiter = pszEnd;
ASSERT((*pszDelimiter == cDelimiter) || (*pszDelimiter == _T('\0')));
ASSERT(pszBegin <= pszDelimiter);
}
int nLen = PtrToInt(pszDelimiter) - PtrToInt(pszBegin);
ASSERT(0 <= nLen);
LPTSTR pszSubString = sSubString.GetBufferSetLength(nLen);
::CopyMemory(pszSubString, pszBegin, nLen * sizeof(TCHAR));
return sSubString;
}
HTREEITEM COXSoundCustomizeDlg::AddEventItem(CWnd* pWnd,
HTREEITEM htiParent,
UINT nMsgID,
COXSoundEffectManager* pSoundEffectManager,
BOOL bPlayEvent)
{
CString sEvent=_T("");
CString sFileName=_T("");
CString sEventID=_T("");
CString sLoop=_T("");
BOOL bIsSoundEditable=FALSE;
// search for specified sound event ID
LPCTSTR* ppszText=NULL;
if(m_allDefinedEvents.Lookup(nMsgID,ppszText))
{
ASSERT(ppszText!=NULL);
sEvent=ppszText[0];
sEventID=ppszText[1];
}
else
{
VERIFY(sEvent.LoadString(IDS_OX_SOUNDUNDEFINED));//"Undefined"
sEventID.Format(_T("ID=%d"),nMsgID);
}
LPSOUNDEFFECT pSoundEffect=NULL;
LPSOUNDSOURCEINFO pSoundSourceInfo=NULL;
if(bPlayEvent)
{
pSoundEffect=pSoundEffectManager->GetSoundEffect(nMsgID);
ASSERT(pSoundEffect!=NULL);
COXSound* pSound=pSoundEffect->pSound;
ASSERT(pSound!=NULL);
// setup file name combo box
pSoundSourceInfo=pSound->GetSoundSourceInfo();
ASSERT(pSoundSourceInfo!=NULL);
switch(pSoundSourceInfo->source)
{
case SNDSRC_FILE:
sFileName=pSoundSourceInfo->sFileName;
bIsSoundEditable=TRUE;
break;
case SNDSRC_INTRESOURCE:
sFileName.Format(IDS_OX_SOUNDRESOURCEID,pSoundSourceInfo->nResourceID);
break;
case SNDSRC_CFILE:
VERIFY(sFileName.LoadString(IDS_OX_SOUNDOPENCFILE));//"Opened CFile object"
break;
default:
ASSERT(FALSE);
}
// loop type
if(pSoundEffect->bLoop && pSoundEffect->nLoopCount!=0 &&
pSoundEffect->nLoopCount!=1)
{
if(pSoundEffect->nLoopCount==-1)
VERIFY(sLoop.LoadString(IDS_OX_SOUNDINFINITELY));//"Infinitely"
else
{
CString sExt;
VERIFY(sExt.LoadString(IDS_OX_SOUNDEXT));
sLoop.Format(IDS_OX_SOUNDTIMES/*"%d time%s"*/,pSoundEffect->nLoopCount,
(pSoundEffect->nLoopCount>1 ? sExt : _T("")));
}
}
else
VERIFY(sLoop.LoadString(IDS_OX_SOUNDONETIME)); //"One time"
}
// insert item
HTREEITEM hti=m_treeEffect.InsertItem(sEvent,htiParent);
if(hti==NULL)
return NULL;
// customize the inserted tree item
//
TV_ITEM tvi;
memset(&tvi,0,sizeof(tvi));
tvi.mask=TVIF_IMAGE|TVIF_HANDLE|TVIF_SELECTEDIMAGE;
tvi.hItem=hti;
tvi.iImage=bIsSoundEditable ? 3 : 4;
tvi.iSelectedImage=tvi.iImage;
VERIFY(m_treeEffect.SetItem(&tvi));
// setup subitems
VERIFY(m_treeEffect.SetSubItem(hti,1,OX_SUBITEM_TEXT|OX_SUBITEM_COLOR,
sFileName,0,NULL,RGB(0,128,0)));
VERIFY(m_treeEffect.SetItemDrawEllipsis(hti,DT_PATH_ELLIPSIS,1));
VERIFY(m_treeEffect.SetSubItem(hti,2,OX_SUBITEM_TEXT|OX_SUBITEM_COLOR,
sEventID,0,NULL,RGB(0,0,128)));
VERIFY(m_treeEffect.SetSubItem(hti,3,OX_SUBITEM_TEXT|OX_SUBITEM_COLOR,
sLoop,0,NULL,RGB(255,0,0)));
// create new item description
LPITEMINFO pItemInfo=new ITEMINFO;
pItemInfo->type=bPlayEvent ? IT_PLAYEVENT : IT_STOPEVENT;
pItemInfo->pWnd=pWnd;
pItemInfo->nMsgID=nMsgID;
if(pSoundEffect!=NULL)
{
pItemInfo->pSoundEffect=new SOUNDEFFECT;
*pItemInfo->pSoundEffect=*pSoundEffect;
}
if(pSoundSourceInfo!=NULL)
{
pItemInfo->pSoundSourceInfo=new SOUNDSOURCEINFO;
*pItemInfo->pSoundSourceInfo=*pSoundSourceInfo;
}
pItemInfo->dwControlState=CTL_OK|CTL_CANCEL|CTL_TREE|CTL_REMOVE|CTL_ADD|CTL_EVENT;
if(bPlayEvent)
{
pItemInfo->dwControlState|=CTL_LOOPTYPE|CTL_FORCETOSTART;
if(bIsSoundEditable)
pItemInfo->dwControlState|=CTL_FILENAME|CTL_PLAY;
}
m_allTreeItems.SetAt((HANDLE)hti,pItemInfo);
return hti;
}
void COXSoundCustomizeDlg::OnItemchangedExttreeEffectslist(NMHDR* pNMHDR,
LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
if((pNMListView->uChanged&LVIF_STATE)!=0)
{
if(((pNMListView->uNewState&LVIS_SELECTED)==0 &&
(pNMListView->uOldState&LVIS_SELECTED)!=0) ||
((pNMListView->uNewState&LVIS_SELECTED)!=0 &&
(pNMListView->uOldState&LVIS_SELECTED)==0))
PostMessage(SMDM_UPDATEVARS);
}
*pResult = 0;
}
void COXSoundCustomizeDlg::OnItemExpandingExttreeEffectslist(NMHDR* pNMHDR,
LRESULT* pResult)
{
LPNMTREEVIEW pnmtv=(LPNMTREEVIEW)pNMHDR;
// TODO: Add your control notification handler code here
// toggling is on/off depending on the specified at the creation time style
if((m_dwDlgStyle&SCDS_NOTOGGLE)!=0)
{
if(pnmtv->action==TVE_EXPAND)
*pResult=0;
else
*pResult=1;
}
else
*pResult=0;
}
void COXSoundCustomizeDlg::ShowControls(DWORD dwControlState)
{
if((m_dwDlgStyle&SCDS_READONLY)!=0)
dwControlState&=~(CTL_FILENAME|CTL_EVENT|CTL_SAVE|CTL_RESTORE|
CTL_REMOVE|CTL_ADD|CTL_FORCETOSTART|CTL_LOOPTYPE);
if((dwControlState&CTL_TREE)!=(m_dwControlState&CTL_TREE))
m_treeEffect.EnableWindow((dwControlState&CTL_TREE));
if((dwControlState&CTL_OK)!=(m_dwControlState&CTL_OK))
m_btnOk.EnableWindow((dwControlState&CTL_OK));
if((dwControlState&CTL_CANCEL)!=(m_dwControlState&CTL_CANCEL))
m_btnCancel.EnableWindow((dwControlState&CTL_CANCEL));
if((dwControlState&CTL_FILENAME)!=(m_dwControlState&CTL_FILENAME))
m_cmbFileName.EnableWindow((dwControlState&CTL_FILENAME));
if((dwControlState&CTL_EVENT)!=(m_dwControlState&CTL_EVENT))
m_cmbEvent.EnableWindow((dwControlState&CTL_EVENT));
if((dwControlState&CTL_STOP)!=(m_dwControlState&CTL_STOP))
m_btnStop.EnableWindow((dwControlState&CTL_STOP));
if((dwControlState&CTL_SAVE)!=(m_dwControlState&CTL_SAVE))
m_btnSave.EnableWindow((dwControlState&CTL_SAVE));
if((dwControlState&CTL_RESTORE)!=(m_dwControlState&CTL_RESTORE))
m_btnRestore.EnableWindow((dwControlState&CTL_RESTORE));
if((dwControlState&CTL_REMOVE)!=(m_dwControlState&CTL_REMOVE))
m_btnRemove.EnableWindow((dwControlState&CTL_REMOVE));
if((dwControlState&CTL_PLAY)!=(m_dwControlState&CTL_PLAY))
m_btnPlay.EnableWindow((dwControlState&CTL_PLAY));
if((dwControlState&CTL_ADD)!=(m_dwControlState&CTL_ADD))
m_btnAdd.EnableWindow((dwControlState&CTL_ADD));
if((dwControlState&CTL_FORCETOSTART)!=(m_dwControlState&CTL_FORCETOSTART))
m_btnForceToStart.EnableWindow((dwControlState&CTL_FORCETOSTART));
if((dwControlState&CTL_LOOPTYPE)!=(m_dwControlState&CTL_LOOPTYPE))
{
GetDlgItem(IDC_OX_RADIO_LOOPONCE_OXSOUND)->EnableWindow((dwControlState&CTL_LOOPTYPE));
GetDlgItem(IDC_OX_RADIO_LOOPINFINITELY_OXSOUND)->EnableWindow((dwControlState&CTL_LOOPTYPE));
GetDlgItem(IDC_OX_RADIO_LOOPREPEAT_OXSOUND)->EnableWindow((dwControlState&CTL_LOOPTYPE));
}
m_editLoopCount.EnableWindow(((dwControlState&CTL_LOOPTYPE)!=0)&(m_nLoopType==2));
DWORD dwStyle=m_btnForceToStart.GetStyle();
if((dwStyle&0x0f)!=BS_AUTO3STATE &&
(m_bForceToStart!=FALSE && m_bForceToStart!=TRUE))
VERIFY(::SetWindowLongPtr(m_btnForceToStart.GetSafeHwnd(),GWL_STYLE,
dwStyle+(BS_AUTO3STATE-BS_AUTOCHECKBOX)));
else if((dwStyle&0x0f)==BS_AUTO3STATE &&
(m_bForceToStart==FALSE || m_bForceToStart==TRUE))
VERIFY(::SetWindowLongPtr(m_btnForceToStart.GetSafeHwnd(),GWL_STYLE,
dwStyle-(BS_AUTO3STATE-BS_AUTOCHECKBOX)));
m_dwControlState=dwControlState;
}
void COXSoundCustomizeDlg::StartEditItem(BOOL bAddingNew/*=FALSE*/)
{
// make sure we are not editing any item
if(!m_bEditing)
{
m_bEditing=TRUE;
m_bAddingNew=bAddingNew;
DWORD dwControlState=m_dwControlState;
dwControlState&=~(CTL_TREE|CTL_ADD);
dwControlState|=(CTL_SAVE|CTL_RESTORE);
ShowControls(dwControlState);
}
}
BOOL COXSoundCustomizeDlg::VerifySoundFile(CString sFileName, BOOL bReportError)
{
// if COXSound::Open fail then there is something wrong with the specified
// sound source
BOOL bResult=m_TestSound.Open(sFileName);
if(!bResult && bReportError)
{
CString sMessage;
sMessage.Format(IDS_OX_SOUNDWRONGFILE,sFileName);//"Specified %s sound file doesn't exist or is not valid WAV object"
AfxMessageBox(sMessage,MB_OK|MB_ICONEXCLAMATION);
}
if(!bResult)
TRACE(_T("COXSoundCustomizeDlg::VerifySoundFile: failed to verify sound file"));
return bResult;
}
BOOL COXSoundCustomizeDlg::VerifyEvent(CString sEvent, CWnd* pWnd, BOOL bReportError)
{
BOOL bResult=FALSE;
// sound vent should be defined by default or set using
// COXSoundCustomizeDlg::SetEvent function
UINT nMsgID=SNDEVENT_NONE;
CString sEventCompare;
LPCTSTR* ppszText;
POSITION pos=m_allDefinedEvents.GetStartPosition();
while(pos!=NULL)
{
m_allDefinedEvents.GetNextAssoc(pos,nMsgID,ppszText);
ASSERT(ppszText!=NULL);
ASSERT(nMsgID!=SNDEVENT_NONE);
sEventCompare=ppszText[0];
if(sEvent==sEventCompare)
{
bResult=TRUE;
break;
}
}
CString sMessage;
if(!bResult)
{
sMessage.Format(IDS_OX_SOUNDSPECEVENT,sEvent);//"Specified %s event wasn't defined"
}
else
{
// check if specified sound event wasn't registered before
HTREEITEM hti=m_treeEffect.GetRootItem();
ASSERT(hti!=NULL);
COXTreeItem* xti=m_treeEffect.GetXItem(hti);
ASSERT(xti);
while((xti=xti->GetNextInTree())!=NULL)
{
hti=(HTREEITEM)xti;
LPITEMINFO pItemInfo=NULL;
VERIFY(m_allTreeItems.Lookup(hti,pItemInfo));
if(pItemInfo->pWnd==pWnd && pItemInfo->nMsgID==nMsgID &&
(pItemInfo->type==IT_PLAYEVENT || pItemInfo->type==IT_STOPEVENT))
{
bResult=FALSE;
if(pItemInfo->type==IT_PLAYEVENT)
{
ASSERT(pItemInfo->pSoundEffect!=NULL);
ASSERT(pItemInfo->pSoundSourceInfo!=NULL);
sMessage.Format(IDS_OX_SOUNDEVENTREGRED,sEvent);//"Specified %s event is already registered as start playing event"
}
else
sMessage.Format(IDS_OX_SOUNDEVENTREGSTOP,sEvent);//"Specified %s event is already registered as stop playing event"
break;
}
}
}
if(!bResult && bReportError)
AfxMessageBox(sMessage,MB_OK|MB_ICONEXCLAMATION);
if(!bResult)
TRACE(_T("COXSoundCustomizeDlg::VerifyEvent: failed to verify event"));
return bResult;
}
BOOL COXSoundCustomizeDlg::VerifyLoopType(int nLoopType, int nLoopCount,
BOOL bReportError)
{
UNREFERENCED_PARAMETER(bReportError);
UNUSED(nLoopType);
UNUSED(nLoopCount);
ASSERT(nLoopType>=0 && nLoopType<=2 && nLoopCount>=0);
return TRUE;
}
BOOL COXSoundCustomizeDlg::VerifyForceToStart(BOOL bForceToStart, BOOL bReportError)
{
UNREFERENCED_PARAMETER(bReportError);
BOOL bResult=((bForceToStart==FALSE) | (bForceToStart==TRUE));
if(!bResult && bReportError)
{
CString sMessage;
VERIFY(sMessage.LoadString(IDS_OX_SOUND_FORCEPLAYASSIGNED));//"<Force to start playing> has to be assigned TRUE or FALSE value"
AfxMessageBox(sMessage,MB_OK|MB_ICONEXCLAMATION);
}
if(!bResult)
TRACE(_T("COXSoundCustomizeDlg::VerifyForceToStart: failed to verify <Force to start playing> value"));
return bResult;
}
LRESULT COXSoundCustomizeDlg::OnPlaybackComplete(WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(wParam);
UNREFERENCED_PARAMETER(lParam);
DWORD dwControlState=m_dwControlState;
dwControlState&=~(CTL_STOP);
dwControlState|=(CTL_FILENAME|CTL_PLAY);
ShowControls(dwControlState);
return (LRESULT)0;
}
void COXSoundCustomizeDlg::OnCheckForce()
{
// TODO: Add your control notification handler code here
StartEditItem();
}
void COXSoundCustomizeDlg::OnEditchangeComboEvent()
{
// TODO: Add your control notification handler code here
StartEditItem();
}
void COXSoundCustomizeDlg::OnSelchangeComboEvent()
{
// TODO: Add your control notification handler code here
if(m_cmbEvent.GetCurSel()!=m_nEvent)
StartEditItem();
}
void COXSoundCustomizeDlg::OnEditchangeComboFilename()
{
// TODO: Add your control notification handler code here
StartEditItem();
}
void COXSoundCustomizeDlg::OnSelchangeComboFilename()
{
// TODO: Add your control notification handler code here
CString sText=m_sFileName;
int nCurSel=m_cmbFileName.GetCurSel();
if(nCurSel!=CB_ERR)
m_cmbFileName.GetLBText(nCurSel,sText);
if(sText!=m_sFileName)
StartEditItem();
}
void COXSoundCustomizeDlg::OnChangeEditLoopcount()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function to send the EM_SETEVENTMASK message to the control
// with the ENM_CHANGE flag ORed into the lParam mask.
// TODO: Add your control notification handler code here
StartEditItem();
}
void COXSoundCustomizeDlg::OnRadioLoopinfinitely()
{
// TODO: Add your control notification handler code here
if(m_nLoopType!=1)
StartEditItem();
m_editLoopCount.EnableWindow(FALSE);
}
void COXSoundCustomizeDlg::OnRadioLooponce()
{
// TODO: Add your control notification handler code here
if(m_nLoopType!=0)
StartEditItem();
m_editLoopCount.EnableWindow(FALSE);
}
void COXSoundCustomizeDlg::OnRadioLooprepeat()
{
// TODO: Add your control notification handler code here
if(m_nLoopType!=3)
StartEditItem();
m_editLoopCount.EnableWindow(TRUE);
}
void COXSoundCustomizeDlg::OnButtonAdd()
{
// TODO: Add your control notification handler code here
// it can happen only if one item in the tree is selected
ASSERT(m_treeEffect.GetSelectedCount()==1);
// get selected item in order to define whether start or stop playing event
// will be added
HTREEITEM htiSelected=m_treeEffect.GetNextItem(m_treeEffect.GetRootItem(),
TVGN_FIRSTSELECTED);
ASSERT(htiSelected!=NULL);
LPITEMINFO pItemInfo;
VERIFY(m_allTreeItems.Lookup(htiSelected,pItemInfo));
ASSERT(pItemInfo!=NULL);
ASSERT(pItemInfo->type==IT_PLAYEVENT || pItemInfo->type==IT_STOPEVENT ||
pItemInfo->type==IT_PLAYEVENTLIST || pItemInfo->type==IT_STOPEVENTLIST);
if((pItemInfo->type==IT_PLAYEVENTLIST || pItemInfo->type==IT_STOPEVENTLIST))
{
m_nEvent=0;
m_sFileName=_T("");
m_bForceToStart=TRUE;
m_nLoopCount=0;
m_nLoopType=0;
UpdateData(FALSE);
DWORD dwControlState=CTL_OK|CTL_CANCEL;
if(pItemInfo->type==IT_PLAYEVENTLIST)
dwControlState|=CTL_EVENT|CTL_FILENAME|CTL_PLAY|CTL_LOOPTYPE|
CTL_FORCETOSTART|CTL_REMOVE;
else
dwControlState|=CTL_EVENT|CTL_ADD|CTL_REMOVE;
ShowControls(dwControlState);
}
StartEditItem(TRUE);
}
void COXSoundCustomizeDlg::OnButtonPlay()
{
// TODO: Add your control notification handler code here
CString sFileName;
m_cmbFileName.GetWindowText(sFileName);
ASSERT(!m_TestSound.IsPlaying());
if(m_TestSound.Open(sFileName))
{
if(m_TestSound.Play())
{
DWORD dwControlState=m_dwControlState;
dwControlState|=(CTL_STOP);
dwControlState&=~(CTL_FILENAME|CTL_PLAY);
ShowControls(dwControlState);
}
}
}
void COXSoundCustomizeDlg::OnButtonRemove()
{
// TODO: Add your control notification handler code here
HTREEITEM htiSelected=m_treeEffect.GetNextItem(m_treeEffect.GetRootItem(),
TVGN_FIRSTSELECTED);
ASSERT(htiSelected!=NULL);
LPITEMINFO pItemInfo;
VERIFY(m_allTreeItems.Lookup(htiSelected,pItemInfo));
ASSERT(pItemInfo!=NULL);
switch(pItemInfo->type)
{
case IT_WINDOW:
{
// if item is on the window level then we remove all start and stop
// playing events registered with the window
HTREEITEM htiPlayEventsList=
m_treeEffect.GetNextItem(htiSelected,TVGN_CHILD);
ASSERT(htiPlayEventsList!=NULL);
HTREEITEM hti;
while((hti=m_treeEffect.GetNextItem(htiPlayEventsList,TVGN_CHILD))!=NULL)
VERIFY(m_treeEffect.DeleteItem(hti));
HTREEITEM htiStopEventsList=
m_treeEffect.GetNextSiblingItem(htiPlayEventsList);
ASSERT(htiStopEventsList!=NULL);
while((hti=m_treeEffect.GetNextItem(htiStopEventsList,TVGN_CHILD))!=NULL)
VERIFY(m_treeEffect.DeleteItem(hti));
break;
}
case IT_PLAYEVENT:
case IT_STOPEVENT:
{
VERIFY(m_treeEffect.DeleteItem(htiSelected));
ShowControls(CTL_TREE|CTL_OK|CTL_CANCEL);
break;
}
case IT_PLAYEVENTLIST:
case IT_STOPEVENTLIST:
{
HTREEITEM hti;
while((hti=m_treeEffect.GetNextItem(htiSelected,TVGN_CHILD))!=NULL)
VERIFY(m_treeEffect.DeleteItem(hti));
break;
}
}
}
void COXSoundCustomizeDlg::OnButtonSave()
{
// TODO: Add your control notification handler code here
if(m_TestSound.IsPlaying())
m_TestSound.Stop();
int nOldEvent=m_nEvent;
CString sOldFileName=m_sFileName;
BOOL bOldForceToStart=m_bForceToStart;
int nOldLoopCount=m_nLoopCount;
int nOldLoopType=m_nLoopType;
VERIFY(UpdateData());
CString sEvent;
m_cmbEvent.GetLBText(m_nEvent,0,sEvent);
BOOL bSaveEvent=((m_dwControlState&CTL_EVENT)!=0) &
(nOldEvent!=m_nEvent || m_bAddingNew);
BOOL bSaveFileName=((m_dwControlState&CTL_FILENAME)!=0) &
(sOldFileName!=m_sFileName || m_bAddingNew);
BOOL bSaveLoopType=((m_dwControlState&CTL_LOOPTYPE)!=0) &
(nOldLoopType!=m_nLoopType || m_bAddingNew ||
(m_nLoopType==2 && nOldLoopCount!=m_nLoopCount));
BOOL bSaveForceToStart=((m_dwControlState&CTL_FORCETOSTART)!=0) &
(bOldForceToStart!=m_bForceToStart || m_bAddingNew);
HTREEITEM htiSelected=m_treeEffect.GetNextItem(m_treeEffect.GetRootItem(),
TVGN_FIRSTSELECTED);
ASSERT(htiSelected!=NULL);
LPITEMINFO pItemInfo;
VERIFY(m_allTreeItems.Lookup(htiSelected,pItemInfo));
ASSERT(pItemInfo!=NULL);
// verified changed info
if(bSaveEvent && !VerifyEvent(sEvent,pItemInfo->pWnd,TRUE))
return;
if(pItemInfo->type==IT_PLAYEVENT || (m_bAddingNew &&
pItemInfo->type==IT_PLAYEVENTLIST))
if((bSaveFileName && !VerifySoundFile(m_sFileName,TRUE)) ||
(bSaveLoopType && !VerifyLoopType(m_nLoopType,m_nLoopCount,TRUE)) ||
(bSaveForceToStart && !VerifyForceToStart(m_bForceToStart,TRUE)))
return;
if(m_bAddingNew)
{
// add new tree item if needed
//
ASSERT(m_treeEffect.GetSelectedCount()==1);
ASSERT(pItemInfo->type==IT_PLAYEVENT || pItemInfo->type==IT_STOPEVENT ||
pItemInfo->type==IT_PLAYEVENTLIST || pItemInfo->type==IT_STOPEVENTLIST);
LPITEMINFO pNewItemInfo=new ITEMINFO;
*pNewItemInfo=*pItemInfo;
pItemInfo=pNewItemInfo;
HTREEITEM htiParent=NULL;
if(pItemInfo->type==IT_PLAYEVENTLIST || pItemInfo->type==IT_STOPEVENTLIST)
htiParent=htiSelected;
else
htiParent=m_treeEffect.GetParentItem(htiSelected);
ASSERT(htiParent!=NULL);
htiSelected=m_treeEffect.InsertItem(_T(""),htiParent);
ASSERT(htiSelected!=NULL);
if(pItemInfo->type==IT_PLAYEVENTLIST)
{
pItemInfo->type=IT_PLAYEVENT;
pItemInfo->pSoundSourceInfo->source=SNDSRC_FILE;
}
else if(pItemInfo->type==IT_STOPEVENTLIST)
pItemInfo->type=IT_STOPEVENT;
TV_ITEM tvi;
memset(&tvi,0,sizeof(tvi));
tvi.mask=TVIF_IMAGE|TVIF_HANDLE|TVIF_SELECTEDIMAGE;
tvi.hItem=htiSelected;
tvi.iImage=pItemInfo->type==IT_PLAYEVENT ? 3 : 4;
tvi.iSelectedImage=tvi.iImage;
VERIFY(m_treeEffect.SetItem(&tvi));
VERIFY(m_treeEffect.SetSubItem(htiSelected,1,OX_SUBITEM_COLOR,
NULL,0,NULL,RGB(0,128,0)));
VERIFY(m_treeEffect.SetItemDrawEllipsis(htiSelected,DT_PATH_ELLIPSIS,1));
VERIFY(m_treeEffect.SetSubItem(htiSelected,2,OX_SUBITEM_COLOR,
NULL,0,NULL,RGB(0,0,128)));
VERIFY(m_treeEffect.SetSubItem(htiSelected,3,OX_SUBITEM_COLOR,
NULL,0,NULL,RGB(255,0,0)));
pItemInfo->dwControlState=
CTL_TREE|CTL_OK|CTL_CANCEL|CTL_REMOVE|CTL_ADD|CTL_EVENT;
if(pItemInfo->type==IT_PLAYEVENT)
{
pItemInfo->dwControlState|=CTL_LOOPTYPE|CTL_FORCETOSTART|
CTL_FILENAME|CTL_PLAY;
}
m_allTreeItems.SetAt((HANDLE)htiSelected,pItemInfo);
}
else
{
ASSERT(pItemInfo->type==IT_PLAYEVENT || pItemInfo->type==IT_STOPEVENT);
}
while(htiSelected!=NULL)
{
// update item and subitems text
//
if(bSaveEvent)
{
TV_ITEM tvi;
memset(&tvi,0,sizeof(tvi));
tvi.mask=TVIF_HANDLE|TVIF_TEXT;
tvi.hItem=htiSelected;
tvi.pszText=sEvent.GetBuffer(sEvent.GetLength());
VERIFY(m_treeEffect.SetItem(&tvi));
sEvent.ReleaseBuffer();
CString sEventID;
m_cmbEvent.GetLBText(m_nEvent,1,sEventID);
VERIFY(m_treeEffect.SetSubItem(htiSelected,2,OX_SUBITEM_TEXT,sEventID));
pItemInfo->nMsgID=0;
UINT nMsgID;
CString sEventIDCompare;
LPCTSTR* ppszText;
POSITION pos=m_allDefinedEvents.GetStartPosition();
while(pos!=NULL)
{
m_allDefinedEvents.GetNextAssoc(pos,nMsgID,ppszText);
ASSERT(ppszText!=NULL);
ASSERT(nMsgID!=SNDEVENT_NONE);
sEventIDCompare=ppszText[1];
if(sEventID==sEventIDCompare)
{
pItemInfo->nMsgID=nMsgID;
break;
}
}
}
if(pItemInfo->type==IT_PLAYEVENT)
{
ASSERT(pItemInfo->pSoundEffect!=NULL);
ASSERT(pItemInfo->pSoundSourceInfo!=NULL);
}
if(bSaveFileName)
{
ASSERT(pItemInfo->type==IT_PLAYEVENT);
ASSERT(pItemInfo->pSoundSourceInfo->source==SNDSRC_FILE);
pItemInfo->pSoundSourceInfo->sFileName=m_sFileName;
VERIFY(m_treeEffect.SetSubItem(htiSelected,1,OX_SUBITEM_TEXT,m_sFileName));
}
if(bSaveLoopType)
{
ASSERT(pItemInfo->type==IT_PLAYEVENT);
CString sLoop;
pItemInfo->pSoundEffect->bLoop=TRUE;
if(m_nLoopType==0 || (m_nLoopType==2 &&
(m_nLoopCount==0 || m_nLoopCount==1)))
{
VERIFY(sLoop.LoadString(IDS_OX_SOUNDONETIME));//"One time"
pItemInfo->pSoundEffect->bLoop=FALSE;
pItemInfo->pSoundEffect->nLoopCount=0;
}
else if(m_nLoopType==1)
{
VERIFY(sLoop.LoadString(IDS_OX_SOUNDINFINITELY));//"Infinitely"
pItemInfo->pSoundEffect->nLoopCount=-1;
}
else if(m_nLoopType==2)
{
CString sExt;
VERIFY(sExt.LoadString(IDS_OX_SOUNDEXT));
sLoop.Format(IDS_OX_SOUNDTIMES,m_nLoopCount,//"%d time%s"
(m_nLoopCount>1 ? sExt : _T("")));
pItemInfo->pSoundEffect->nLoopCount=m_nLoopCount;
}
else
ASSERT(FALSE);
VERIFY(m_treeEffect.SetSubItem(htiSelected,3,OX_SUBITEM_TEXT,sLoop));
}
if(bSaveForceToStart)
{
ASSERT(pItemInfo->type==IT_PLAYEVENT);
pItemInfo->pSoundEffect->bForceToStart=m_bForceToStart;
}
if(!m_bAddingNew)
{
htiSelected=m_treeEffect.GetNextItem(htiSelected,TVGN_NEXTSELECTED);
if(htiSelected!=NULL)
{
VERIFY(m_allTreeItems.Lookup(htiSelected,pItemInfo));
ASSERT(pItemInfo!=NULL);
}
}
else
break;
}
m_bEditing=FALSE;
if(m_bAddingNew)
{
m_bAddingNew=FALSE;
m_treeEffect.EnsureVisible(htiSelected);
m_treeEffect.SelectItem(NULL);
m_treeEffect.SelectItem(htiSelected);
}
else
GetVars();
}
void COXSoundCustomizeDlg::OnButtonStop()
{
// TODO: Add your control notification handler code here
m_TestSound.Stop();
OnPlaybackComplete(0,0);
}
void COXSoundCustomizeDlg::OnButtonRestore()
{
// TODO: Add your control notification handler code here
if(m_TestSound.IsPlaying())
m_TestSound.Stop();
UpdateData(FALSE);
m_bEditing=FALSE;
m_bAddingNew=FALSE;
GetVars();
}
void COXSoundCustomizeDlg::OnOK()
{
// TODO: Add extra validation here
if(m_TestSound.IsPlaying())
m_TestSound.Stop();
if((m_dwDlgStyle&SCDS_SAVESTATE)!=0)
SaveState();
if((m_dwDlgStyle&SCDS_READONLY)!=0)
CDialog::OnOK();
if(m_bEditing)
{
CString sMsg;
VERIFY(sMsg.LoadString(IDS_OX_SOUNDCURRENTLYEDITING));//"You are currently editing a sound event.\n Would you like to save changes before exit?"
if(AfxMessageBox(sMsg,MB_YESNO|MB_ICONQUESTION)==IDYES)
OnButtonSave();
}
m_pSoundEffectOrganizer->StopPlaying();
// reregister all stop events
m_pSoundEffectOrganizer->UnregisterAllStopEvents();
// reregister all start playing events that use a file or resource ID
// as sound source
POSITION pos=m_pSoundEffectOrganizer->GetFirstRegisteredWindow();
while(pos!=NULL)
{
CWnd* pWnd=m_pSoundEffectOrganizer->GetNextRegisteredWindow(pos);
ASSERT(pWnd);
ASSERT(pWnd->GetSafeHwnd());
COXSoundEffectManager* pSoundEffectManager=
m_pSoundEffectOrganizer->GetManager(pWnd);
ASSERT(pSoundEffectManager);
POSITION posEvent=pSoundEffectManager->GetFirstPlayEvent();
while(posEvent!=NULL)
{
UINT nPlayMsgID=pSoundEffectManager->GetNextPlayEvent(posEvent);
ASSERT(nPlayMsgID!=SNDEVENT_NONE);
LPSOUNDEFFECT pSoundEffect=pSoundEffectManager->
GetSoundEffect(nPlayMsgID);
ASSERT(pSoundEffect!=NULL);
ASSERT(pSoundEffect->pSound!=NULL);
LPSOUNDSOURCEINFO pSoundSourceInfo=pSoundEffect->pSound->
GetSoundSourceInfo();
ASSERT(pSoundSourceInfo!=NULL);
ASSERT(pSoundSourceInfo->source!=SNDSRC_UNKNOWN);
if(pSoundSourceInfo->source==SNDSRC_FILE ||
pSoundSourceInfo->source==SNDSRC_INTRESOURCE)
pSoundEffectManager->UnregisterPlayEvent(nPlayMsgID);
}
}
// register all stop playing and sound events all start playing events
// that use a file or resource ID as sound source from the tree
HTREEITEM hti=m_treeEffect.GetRootItem();
ASSERT(hti!=NULL);
COXTreeItem* xti=m_treeEffect.GetXItem(hti);
ASSERT(xti);
while((xti=xti->GetNextInTree())!=NULL)
{
hti=(HTREEITEM)xti;
LPITEMINFO pItemInfo=NULL;
VERIFY(m_allTreeItems.Lookup(hti,pItemInfo));
if(pItemInfo->type==IT_PLAYEVENT || pItemInfo->type==IT_STOPEVENT)
{
ASSERT(pItemInfo->type!=IT_UNKNOWN);
ASSERT(pItemInfo->pWnd!=NULL);
ASSERT(pItemInfo->nMsgID!=SNDEVENT_NONE);
ASSERT(::IsWindow(pItemInfo->pWnd->GetSafeHwnd()));
if(pItemInfo->type==IT_PLAYEVENT)
{
ASSERT(pItemInfo->pSoundEffect!=NULL);
ASSERT(pItemInfo->pSoundSourceInfo!=NULL);
switch(pItemInfo->pSoundSourceInfo->source)
{
case SNDSRC_FILE:
VERIFY(m_pSoundEffectOrganizer->
RegisterPlayEvent(pItemInfo->pWnd,pItemInfo->nMsgID,
pItemInfo->pSoundSourceInfo->sFileName,
pItemInfo->pSoundEffect->bLoop,
pItemInfo->pSoundEffect->nLoopCount,
pItemInfo->pSoundEffect->bForceToStart));
break;
case SNDSRC_INTRESOURCE:
VERIFY(m_pSoundEffectOrganizer->
RegisterPlayEvent(pItemInfo->pWnd,pItemInfo->nMsgID,
pItemInfo->pSoundSourceInfo->nResourceID,
pItemInfo->pSoundSourceInfo->hInstance,
pItemInfo->pSoundEffect->bLoop,
pItemInfo->pSoundEffect->nLoopCount,
pItemInfo->pSoundEffect->bForceToStart));
break;
case SNDSRC_CFILE:
break;
default:
ASSERT(FALSE);
}
}
else if(pItemInfo->type==IT_STOPEVENT)
{
VERIFY(m_pSoundEffectOrganizer->
RegisterStopEvent(pItemInfo->pWnd,pItemInfo->nMsgID));
}
}
}
CDialog::OnOK();
}
void COXSoundCustomizeDlg::OnCancel()
{
// TODO: Add extra validation here
if(m_TestSound.IsPlaying())
m_TestSound.Stop();
if(m_bEditing)
{
CString sMsg;
VERIFY(sMsg.LoadString(IDS_OX_SOUNDCURRENTLYEDITING));//"You are currently editing a sound event.\n Would you like to save changes before exit?"
if(AfxMessageBox(sMsg,MB_YESNO|MB_ICONQUESTION)==IDYES)
return;
}
if((m_dwDlgStyle&SCDS_SAVESTATE)!=0)
SaveState();
CDialog::OnCancel();
}
void COXSoundCustomizeDlg::SaveState()
{
ASSERT(::IsWindow(m_treeEffect.GetSafeHwnd()));
CWinApp* pApp=AfxGetApp();
if(pApp!=NULL)
{
pApp->WriteProfileInt(_T("Sound Customize Dialog"),
_T("EventColWidth"),m_treeEffect.GetColumnWidth(0));
pApp->WriteProfileInt(_T("Sound Customize Dialog"),
_T("FileNameColWidth"),m_treeEffect.GetColumnWidth(1));
pApp->WriteProfileInt(_T("Sound Customize Dialog"),
_T("EventInfoColWidth"),m_treeEffect.GetColumnWidth(2));
pApp->WriteProfileInt(_T("Sound Customize Dialog"),
_T("LoopColWidth"),m_treeEffect.GetColumnWidth(3));
pApp->WriteProfileInt(_T("Sound Customize Dialog"),
_T("SortAscending"),(m_treeEffect.GetSortOrder()==1 ? TRUE : FALSE));
pApp->WriteProfileInt(_T("Sound Customize Dialog"),
_T("SortCol"),m_treeEffect.GetSortCol());
}
}