// TDLReminderToolDlg.cpp : implementation file
//
#include "stdafx.h"
#include "TDLReminderTool.h"
#include "TDLReminderToolDlg.h"
#include "TDLConfig.h"
#include "ToDoListReaderWriter.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()
/////////////////////////////////////////////////////////////////////////////
// CTDLReminderToolDlg dialog
CTDLReminderToolDlg::CTDLReminderToolDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTDLReminderToolDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTDLReminderToolDlg)
m_remFrequency = 0;
m_StartStop = FALSE;
m_updRemFrequency = 0;
m_bPlayAudio = FALSE;
m_audioFilePath = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_pTodoList = NULL;
}
void CTDLReminderToolDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CTDLReminderToolDlg)
DDX_Control(pDX, IDC_UPDFREQUENCYTYPECMB2, m_updFreqCombo);
DDX_Control(pDX, IDC_FREQUENCYTYPECMB, m_freqCombo);
DDX_Text(pDX, IDC_FREQUENCYEDT, m_remFrequency);
DDX_Check(pDX, IDC_STARTSTOP, m_StartStop);
DDX_Text(pDX, IDC_UPDFREQUENCYEDT, m_updRemFrequency);
DDX_Check(pDX, IDC_PLAYAUDIO, m_bPlayAudio);
DDX_Text(pDX, IDC_AUDIOFILEPATH, m_audioFilePath);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CTDLReminderToolDlg, CDialog)
//{{AFX_MSG_MAP(CTDLReminderToolDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_STARTSTOP, OnStartstop)
ON_BN_CLICKED(IDOK, OnOk)
ON_WM_TIMER()
ON_WM_DESTROY()
ON_COMMAND(ID_SETREMINDER, OnSetreminder)
ON_COMMAND(ID_EXITTDL, OnExittdl)
ON_BN_CLICKED(IDC_UPDNOW, OnUpdnow)
ON_BN_CLICKED(IDC_BROWSEFORAUDIO, OnBrowseforaudio)
ON_EN_CHANGE(IDC_AUDIOFILEPATH, OnChangeAudiofilepath)
ON_BN_CLICKED(IDC_PLAYAUDIO, OnPlayaudio)
//}}AFX_MSG_MAP
ON_REGISTERED_MESSAGE(WM_TASKBARCREATED,OnTaskBarCreated)
ON_REGISTERED_MESSAGE(MYWM_NOTIFYICON,OnMyNotifyIcon)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CTDLReminderToolDlg message handlers
BOOL CTDLReminderToolDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
// 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
if(!SetupRemindersList())
return FALSE;
CTDLConfig cfg;
cfg.ReadConfiguration();
m_remFrequency = cfg.getRemFreq();
m_freqType = cfg.getRemFreqType();
m_updType = cfg.getUpdFreqType();
m_updRemFrequency = cfg.getUpdFreq();
m_bPlayAudio = cfg.getPlayAudio();
m_audioFilePath = cfg.getAudioFile();
if(m_bPlayAudio)
{
GetDlgItem(IDC_AUDIOFILEPATH)->EnableWindow(TRUE);
GetDlgItem(IDC_BROWSEFORAUDIO)->EnableWindow(TRUE);
}
else
{
GetDlgItem(IDC_AUDIOFILEPATH)->EnableWindow(TRUE);
GetDlgItem(IDC_BROWSEFORAUDIO)->EnableWindow(TRUE);
}
int freq = 0;
if(m_freqType==0)
freq = ((m_remFrequency*60)*60)*1000;
else
freq = (m_remFrequency*60)*1000;
SetTimer(ID_REMINDERTIMER,freq,NULL);
if(m_updType==0)
freq = ((m_updRemFrequency*60)*60)*1000;
else
freq = (m_updRemFrequency*60)*1000;
SetTimer(ID_UPDFREQTIMER,freq,NULL);
m_StartStop=1;
m_freqCombo.SetCurSel(m_freqType);
m_updFreqCombo.SetCurSel(m_updType);
m_hTrayMenu = LoadMenu(AfxGetApp()->m_hInstance,MAKEINTRESOURCE(IDR_TRAYMENU));
TrayAddIcon(NIM_ADD);
if(m_RemDlg.HasTasks())
{
m_RemDlg.InitDlg("Reminder for \""+m_taskListFileName+"\"");
if(m_bPlayAudio)
{
PlaySound(m_audioFilePath,NULL,SND_FILENAME);
}
m_RemDlg.DoModal();
PlaySound(NULL,NULL,0);
}
SetDlgItemText(IDC_STARTSTOP,"Stop");
UpdateData(FALSE);
return TRUE; // return TRUE unless you set the focus to a control
}
void CTDLReminderToolDlg::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 CTDLReminderToolDlg::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 CTDLReminderToolDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CTDLReminderToolDlg::OnStartstop()
{
UpdateData(TRUE);
switch(m_StartStop)
{
case 0:
{
SetDlgItemText(IDC_STARTSTOP,"Start");
KillTimer(ID_REMINDERTIMER);
break;
}
case 1:
{
SetDlgItemText(IDC_STARTSTOP,"Stop");
SetupRemindersList();
KillTimer(ID_REMINDERTIMER);
int freq = 0;
m_freqType = m_freqCombo.GetCurSel();
if(m_freqType==0)
freq = ((m_remFrequency*60)*60)*1000;
else
freq = (m_remFrequency*60)*1000;
SetTimer(ID_REMINDERTIMER,freq,NULL);
break;
}
}
}
void CTDLReminderToolDlg::OnOk()
{
UpdateData(TRUE);
int freq = 0;
m_freqType = m_freqCombo.GetCurSel();
if(m_StartStop==1)
{
KillTimer(ID_REMINDERTIMER);
m_freqType = m_freqCombo.GetCurSel();
if(m_freqType==0)
freq = ((m_remFrequency*60)*60)*1000;
else
freq = (m_remFrequency*60)*1000;
SetTimer(ID_REMINDERTIMER,freq,NULL);
}
KillTimer(ID_UPDFREQTIMER);
m_updType = m_updFreqCombo.GetCurSel();
if(m_updType==0)
freq = ((m_updRemFrequency*60)*60)*1000;
else
freq = (m_updRemFrequency*60)*1000;
SetTimer(ID_UPDFREQTIMER,freq,NULL);
ShowWindow(SW_HIDE);
CTDLConfig cfg;
cfg.setRemFreq(m_remFrequency);
cfg.setRemFreqType(m_freqType);
cfg.setUpdFreqType(m_updType);
cfg.setUpdFreq(m_updRemFrequency);
cfg.setPlayAudio(m_bPlayAudio);
cfg.setAudioFile(m_audioFilePath);
cfg.SaveConfiguration();
}
void CTDLReminderToolDlg::OnCancel()
{
ShowWindow(SW_HIDE);
}
void CTDLReminderToolDlg::OnTimer(UINT nIDEvent)
{
switch(nIDEvent)
{
case ID_REMINDERTIMER:
{
if(::IsWindowVisible(m_RemDlg.m_hWnd))
{
if(m_bPlayAudio)
{
::PlaySound(m_audioFilePath,NULL,SND_FILENAME);
}
return;
}
if(m_RemDlg.HasTasks())
{
m_RemDlg.InitDlg("Reminder for \""+m_taskListFileName+"\"");
if(m_bPlayAudio)
{
::PlaySound(m_audioFilePath,NULL,SND_FILENAME);
}
m_RemDlg.DoModal();
PlaySound(NULL,NULL,0);
}
break;
}
case ID_UPDFREQTIMER:
{
SetupRemindersList();
break;
}
}
CDialog::OnTimer(nIDEvent);
}
void CTDLReminderToolDlg::OnDestroy()
{
if(m_pTodoList)
{
delete m_pTodoList;
m_pTodoList = NULL;
}
DestroyMenu(m_hTrayMenu);
TrayAddIcon(NIM_DELETE);
CDialog::OnDestroy();
// TODO: Add your message handler code here
}
LRESULT CTDLReminderToolDlg::OnTaskBarCreated(WPARAM wParam,LPARAM lParam)
{
TrayAddIcon(NIM_DELETE);
TrayAddIcon(NIM_ADD);
return 1;
}
void CTDLReminderToolDlg::TrayAddIcon(DWORD dwMessage)
{
NOTIFYICONDATA tnd;
HICON hIcon = NULL;
tnd.cbSize = sizeof(NOTIFYICONDATA);
if(IsWindow(m_hWnd))
tnd.hWnd = m_hWnd;
else
return;
tnd.uID = 0;
tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP;
tnd.uCallbackMessage = MYWM_NOTIFYICON;
CString text;
text.Format("Reminder for \"%s\" task list",m_taskListFileName);
lstrcpyn(tnd.szTip, text, sizeof(tnd.szTip));
switch(dwMessage)
{
case NIM_ADD:
{
hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
tnd.hIcon = hIcon;
break;
}
case NIM_DELETE:
{
tnd.hIcon = NULL;
tnd.szTip[0] = '\0';
break;
}
}
Shell_NotifyIcon(dwMessage, &tnd);
if (hIcon)
DestroyIcon(hIcon);
}
LRESULT CTDLReminderToolDlg::OnMyNotifyIcon(WPARAM wParam,LPARAM lParam)
{
int uid = wParam;
switch(lParam)
{
case WM_RBUTTONDOWN:
case WM_CONTEXTMENU:
case WM_RBUTTONDBLCLK:
case WM_RBUTTONUP:
{
CPoint pt;
GetCursorPos(&pt);
APPBARDATA appBarData;
appBarData.cbSize = sizeof(APPBARDATA);
appBarData.hWnd = this->m_hWnd;
int res = SHAppBarMessage(ABM_GETTASKBARPOS,&appBarData);
if(res==1)
{
CRect rect(appBarData.rc);
if(rect.PtInRect(pt))
{
ClientToScreen(&pt);
HMENU hPopup =GetSubMenu(m_hTrayMenu,0);
SetForegroundWindow();
TrackPopupMenu(hPopup,TPM_RIGHTBUTTON|TPM_BOTTOMALIGN,pt.x,pt.y,0,m_hWnd,NULL);
::PostMessage(m_hWnd,WM_NULL,0,0);
}
}
break;
}
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_LBUTTONUP:
{
if(!IsWindowVisible())
ShowWindow(SW_SHOW);
SetForegroundWindow();
}
default:
break;
}
return 1;
}
void CTDLReminderToolDlg::OnSetreminder()
{
m_freqCombo.SetCurSel(m_freqType);
m_updFreqCombo.SetCurSel(m_updType);
UpdateData(FALSE);
ShowWindow(SW_SHOW);
}
void CTDLReminderToolDlg::OnExittdl()
{
PostQuitMessage(0);
}
void CTDLReminderToolDlg::OnUpdnow()
{
SetupRemindersList();
}
void CTDLReminderToolDlg::SetTaskList(CString taskList)
{
m_taskListFileName = taskList;
}
BOOL CTDLReminderToolDlg::SetupRemindersList()
{
CToDoListReaderWriter writer;
if(m_pTodoList)
{
delete m_pTodoList;
m_pTodoList = NULL;
}
m_pTodoList = writer.ReadXML(m_taskListFileName);
if(m_pTodoList==NULL)
{
AfxMessageBox("Error or corrupted ToDoList XML",MB_ICONSTOP);
PostQuitMessage(0);
return FALSE;
}
vector<CTask> overdue;
overdue.clear();
vector<CTask> tasks = m_pTodoList->getTasks();
COleDateTime date = COleDateTime::GetCurrentTime();
for(int i=0; i<tasks.size();++i)
{
CTask p = tasks[i];
CString dueDate = p.getDueDateString().c_str();
CString doneDate = p.getDoneDateString().c_str();
if(dueDate.IsEmpty() || doneDate.IsEmpty())
continue;
CString sCurDate = date.Format(VAR_DATEVALUEONLY);
if(sCurDate.CompareNoCase(dueDate)>=0)
overdue.push_back(p);
extractOverDueTasks(overdue,p);
}
m_RemDlg.addRemItems(overdue);
return TRUE;
}
void CTDLReminderToolDlg::extractOverDueTasks(vector<CTask>& overdue,CTask root)
{
COleDateTime date = COleDateTime::GetCurrentTime();
vector<CTask> tasks = root.getSubTasks();
for(int i=0; i<tasks.size();++i)
{
CTask p = tasks[i];
CString dueDate = p.getDueDateString().c_str();
CString doneDate = p.getDoneDateString().c_str();
if(dueDate.IsEmpty() || doneDate.IsEmpty())
continue;
CString sCurDate = date.Format(VAR_DATEVALUEONLY);
if(sCurDate.CompareNoCase(dueDate)>=0)
overdue.push_back(p);
extractOverDueTasks(overdue,p);
}
}
void CTDLReminderToolDlg::OnBrowseforaudio()
{
UpdateData(TRUE);
CFileDialog fDlg(TRUE,NULL,m_audioFilePath,OFN_HIDEREADONLY, "All Files (*.*)|*.*||",this);
if(fDlg.DoModal()==IDOK)
{
m_audioFilePath = fDlg.GetPathName();
UpdateData(FALSE);
}
}
void CTDLReminderToolDlg::OnChangeAudiofilepath()
{
}
void CTDLReminderToolDlg::OnPlayaudio()
{
UpdateData(TRUE);
if(m_bPlayAudio)
{
GetDlgItem(IDC_AUDIOFILEPATH)->EnableWindow(TRUE);
GetDlgItem(IDC_BROWSEFORAUDIO)->EnableWindow(TRUE);
}
else
{
GetDlgItem(IDC_AUDIOFILEPATH)->EnableWindow(FALSE);
GetDlgItem(IDC_BROWSEFORAUDIO)->EnableWindow(FALSE);
}
}