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

576 lines
15 KiB
C++

// MonthCalendarDlg.cpp : implementation file
//
#include "stdafx.h"
#include "MonthCalendar.h"
#include "MonthCalendarDlg.h"
#include "UTSampleAbout.h"
#include "UTBStrOp.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMonthCalendarDlg dialog
CMonthCalendarDlg::CMonthCalendarDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMonthCalendarDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CMonthCalendarDlg)
m_bBoldHolidays = FALSE;
m_bDayState = FALSE;
m_bMultiselect = FALSE;
m_bNotoday = FALSE;
m_bNotodaycircle = FALSE;
m_bWeeknumbers = FALSE;
m_nMaxSel = 0;
m_nScrollRate = 0;
m_nFirstDay = -1;
m_nDimension = -1;
m_sSelection = _T("");
m_sRangeFrom = _T("");
m_sRangeTo = _T("");
m_bInfoTip = FALSE;
m_sFontName = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_clrTrailingText=RGB(0,0,0);
m_clrTitleText=RGB(0,0,0);
m_clrTitleBk=RGB(0,0,0);
m_clrText=RGB(0,0,0);
m_clrMonthBk=RGB(0,0,0);
m_clrBk=RGB(0,0,0);
}
void CMonthCalendarDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMonthCalendarDlg)
DDX_Control(pDX, IDC_STATIC_FONTNAME, m_ctlFontName);
DDX_Control(pDX, IDC_COMBO_FIRSTDAY, m_cmbFirstDay);
DDX_Control(pDX, IDC_COMBO_DIMENSION, m_cmbDimension);
DDX_Control(pDX, IDC_BUTTON_CLRTRAILINGTEXT, m_btnClrTrailingText);
DDX_Control(pDX, IDC_BUTTON_CLRTITLETEXT, m_btnClrTitleText);
DDX_Control(pDX, IDC_BUTTON_CLRTITLEBK, m_btnClrTitleBk);
DDX_Control(pDX, IDC_BUTTON_CLRTEXT, m_btnClrText);
DDX_Control(pDX, IDC_BUTTON_CLRMONTHBK, m_btnClrMonthBk);
DDX_Control(pDX, IDC_BUTTON_CLRBK, m_btnClrBk);
DDX_Check(pDX, IDC_CHECK_BOLDHOLIDAYS, m_bBoldHolidays);
DDX_Check(pDX, IDC_CHECK_DAYSTATE, m_bDayState);
DDX_Check(pDX, IDC_CHECK_MULTISELECT, m_bMultiselect);
DDX_Check(pDX, IDC_CHECK_NOTODAY, m_bNotoday);
DDX_Check(pDX, IDC_CHECK_NOTODAYCIRCLE, m_bNotodaycircle);
DDX_Check(pDX, IDC_CHECK_WEEKNUMBERS, m_bWeeknumbers);
DDX_Text(pDX, IDC_EDIT_MAXSEL, m_nMaxSel);
DDX_Text(pDX, IDC_EDIT_SCROLLRATE, m_nScrollRate);
DDX_CBIndex(pDX, IDC_COMBO_FIRSTDAY, m_nFirstDay);
DDX_CBIndex(pDX, IDC_COMBO_DIMENSION, m_nDimension);
DDX_Text(pDX, IDC_SELECTION, m_sSelection);
DDX_Text(pDX, IDC_RANGEFROM, m_sRangeFrom);
DDX_Text(pDX, IDC_RANGETO, m_sRangeTo);
DDX_Check(pDX, IDC_CHECK_INFOTIP, m_bInfoTip);
DDX_Text(pDX, IDC_STATIC_FONTNAME, m_sFontName);
//}}AFX_DATA_MAP
DDX_ColorPicker(pDX, IDC_BUTTON_CLRTRAILINGTEXT, m_clrTrailingText);
DDX_ColorPicker(pDX, IDC_BUTTON_CLRTITLETEXT, m_clrTitleText);
DDX_ColorPicker(pDX, IDC_BUTTON_CLRTITLEBK, m_clrTitleBk);
DDX_ColorPicker(pDX, IDC_BUTTON_CLRTEXT, m_clrText);
DDX_ColorPicker(pDX, IDC_BUTTON_CLRMONTHBK, m_clrMonthBk);
DDX_ColorPicker(pDX, IDC_BUTTON_CLRBK, m_clrBk);
}
BEGIN_MESSAGE_MAP(CMonthCalendarDlg, CDialog)
//{{AFX_MSG_MAP(CMonthCalendarDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_APPLY, OnApply)
ON_BN_CLICKED(IDC_RESTORE, OnRestore)
ON_BN_CLICKED(IDC_BUTTON_FONTNAME, OnButtonFontname)
//}}AFX_MSG_MAP
ON_NOTIFY(MCN_SELCHANGE,IDC_MONTHCAL,OnSelChange)
ON_NOTIFY(MCN_SELECT,IDC_MONTHCAL,OnSelect)
ON_NOTIFY(MCN_GETDAYSTATE,IDC_MONTHCAL,OnGetDayState)
ON_NOTIFY(OXMCN_GETDAYSTATE,IDC_MONTHCAL,OnOXGetDayState)
ON_NOTIFY(OXMCN_GETINFOTIP,IDC_MONTHCAL,OnOXGetInfoTip)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMonthCalendarDlg message handlers
BOOL CMonthCalendarDlg::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
// TODO: Add extra initialization here
// populate combo boxes
//
m_cmbDimension.AddString(_T("One month"));
m_cmbDimension.AddString(_T("2x1 months"));
m_cmbDimension.AddString(_T("1x2 months"));
m_cmbDimension.AddString(_T("2x2 months"));
m_cmbFirstDay.AddString(_T("Monday"));
m_cmbFirstDay.AddString(_T("Tuesday"));
m_cmbFirstDay.AddString(_T("Wendsday"));
m_cmbFirstDay.AddString(_T("Thursday"));
m_cmbFirstDay.AddString(_T("Friday"));
m_cmbFirstDay.AddString(_T("Saturday"));
m_cmbFirstDay.AddString(_T("Sunday"));
/////////////////////////////
// enable tooltips for color picker buttons
//
m_btnClrTrailingText.SetToolTip(TRUE);
m_btnClrTitleText.SetToolTip(TRUE);
m_btnClrTitleBk.SetToolTip(TRUE);
m_btnClrText.SetToolTip(TRUE);
m_btnClrMonthBk.SetToolTip(TRUE);
m_btnClrBk.SetToolTip(TRUE);
/////////////////////////////
// create calendar control
//
CWnd *pFrame=GetDlgItem(IDC_MONTHCAL);
CRect rcWnd;
pFrame->GetWindowRect(rcWnd);
pFrame->DestroyWindow(); //pFrame was just a placeholder anyway.
ScreenToClient(rcWnd);
m_ctlMonthCal.Create(WS_CHILD|WS_VISIBLE,rcWnd.TopLeft(),this,IDC_MONTHCAL,
OXMCS_BOLDHOLIDAYS|OXMCS_INFOTIP,2,2);
HOLIDAYS holidays;
holidays.nMonth=-1;
holidays.nYear=-1;
holidays.arrWeekDays.AddTail(SATURDAY);
holidays.arrWeekDays.AddTail(SUNDAY);
m_ctlMonthCal.SetHolidays(&holidays);
holidays.Reset();
holidays.nMonth=7;
holidays.nYear=-1;
holidays.arrMonthDays.AddTail(FIRST);
m_ctlMonthCal.SetHolidays(&holidays);
/////////////////////////////
CFont* pFont=m_ctlMonthCal.GetFont();
ASSERT(pFont);
VERIFY(pFont->GetLogFont(&m_lfText));
m_lfText.lfWeight=FW_NORMAL;
m_sFontName.Format(_T("%d pt, %s"),(ConvertLogUnitToPoint(m_lfText.lfHeight)+5)/10,
m_lfText.lfFaceName);
m_ctlFontName.SetTextLogFont(&m_lfText);
m_ctlFontName.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
GetVars();
SetVars();
return TRUE; // return TRUE unless you set the focus to a control
}
void CMonthCalendarDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CUTSampleAboutDlg dlgAbout(IDR_MAINFRAME,ID_DESCRIPTION_FILE);
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 CMonthCalendarDlg::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 CMonthCalendarDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CMonthCalendarDlg::OnApply()
{
// TODO: Add your control notification handler code here
SetVars();
}
void CMonthCalendarDlg::OnRestore()
{
// TODO: Add your control notification handler code here
GetVars();
}
void CMonthCalendarDlg::GetVars()
{
DWORD dwCalStyle=m_ctlMonthCal.GetMonthCalStyle();
DWORD dwStyle=m_ctlMonthCal.GetStyle();
m_bBoldHolidays=(dwCalStyle&OXMCS_BOLDHOLIDAYS)!=0 ? TRUE : FALSE;
m_bInfoTip=(dwCalStyle&OXMCS_INFOTIP)!=0 ? TRUE : FALSE;
m_bDayState=(dwStyle&MCS_DAYSTATE)!=0 ? TRUE : FALSE;
m_bMultiselect=(dwStyle&MCS_MULTISELECT)!=0 ? TRUE : FALSE;
m_bNotoday=(dwStyle&MCS_NOTODAY)!=0 ? TRUE : FALSE;
#if (_WIN32_IE >= 0x0400)
m_bNotodaycircle=(dwStyle&MCS_NOTODAYCIRCLE)!=0 ? TRUE : FALSE;
#else
m_bNotodaycircle=FALSE;
#endif
m_bWeeknumbers=(dwStyle&MCS_WEEKNUMBERS)!=0 ? TRUE : FALSE;
m_nMaxSel=m_ctlMonthCal.GetMaxSelCount();
m_nScrollRate=m_ctlMonthCal.GetMonthDelta();
m_nFirstDay=m_ctlMonthCal.GetFirstDayOfWeek();
CSize szMonthFitCount;
VERIFY(m_ctlMonthCal.GetMonthFitCount(szMonthFitCount));
switch(szMonthFitCount.cx*szMonthFitCount.cy)
{
case 1:
m_nDimension=0;
break;
case 2:
if(szMonthFitCount.cy==1)
m_nDimension=1;
else
m_nDimension=2;
break;
case 4:
m_nDimension=3;
break;
default:
ASSERT(FALSE);
}
m_clrTrailingText=m_ctlMonthCal.GetTrailingTextColor();
m_clrTitleText=m_ctlMonthCal.GetTitleTextColor();
m_clrTitleBk=m_ctlMonthCal.GetTitleBkColor();
m_clrText=m_ctlMonthCal.GetTextColor();
m_clrMonthBk=m_ctlMonthCal.GetMonthBkColor();
m_clrBk=m_ctlMonthCal.GetBkColor();
GetLatestSelInfo();
UpdateData(FALSE);
}
void CMonthCalendarDlg::GetLatestSelInfo()
{
if((m_ctlMonthCal.GetStyle()&MCS_MULTISELECT)!=0)
{
m_sSelection.Empty();
COleDateTime ctmin, ctmax;
m_ctlMonthCal.GetSelRange(ctmin,ctmax);
m_sRangeFrom.Format(_T("%02d/%02d/%4d"),ctmin.GetMonth(),
ctmin.GetDay(),ctmin.GetYear());
m_sRangeTo.Format(_T("%02d/%02d/%4d"),ctmax.GetMonth(),
ctmax.GetDay(),ctmax.GetYear());
}
else
{
COleDateTime ct;
m_ctlMonthCal.GetCurSel(ct);
m_sSelection.Format(_T("%02d/%02d/%4d"),ct.GetMonth(),ct.GetDay(),ct.GetYear());
m_sRangeFrom.Empty();
m_sRangeTo.Empty();
}
}
void CMonthCalendarDlg::SetVars()
{
if(!UpdateData(TRUE))
return;
if((((m_ctlMonthCal.GetStyle()&MCS_MULTISELECT)!=0)!=m_bMultiselect) ||
(((m_ctlMonthCal.GetStyle()&MCS_DAYSTATE)!=0)!=m_bDayState) ||
(((m_ctlMonthCal.GetMonthCalStyle()&OXMCS_BOLDHOLIDAYS)!=0)!=m_bBoldHolidays))
{
// recreate calendar control
//
CWnd *pFrame=GetDlgItem(IDC_MONTHCAL);
CRect rcWnd;
pFrame->GetWindowRect(rcWnd);
pFrame->DestroyWindow();
ScreenToClient(rcWnd);
m_ctlMonthCal.Create(WS_CHILD|WS_VISIBLE|(m_bMultiselect ? MCS_MULTISELECT : 0)|
(m_bDayState ? MCS_DAYSTATE : 0),rcWnd.TopLeft(),this,IDC_MONTHCAL,
(m_bBoldHolidays ? OXMCS_BOLDHOLIDAYS : 0));
/////////////////////////////
}
if(m_bInfoTip)
m_ctlMonthCal.SetMonthCalStyle(m_ctlMonthCal.GetMonthCalStyle()|
OXMCS_INFOTIP);
else
m_ctlMonthCal.SetMonthCalStyle(m_ctlMonthCal.GetMonthCalStyle()&
~(OXMCS_INFOTIP));
if(m_bNotoday)
m_ctlMonthCal.ModifyStyle(0,MCS_NOTODAY);
else
m_ctlMonthCal.ModifyStyle(MCS_NOTODAY,0);
#if (_WIN32_IE >= 0x0400)
if(m_bNotodaycircle)
m_ctlMonthCal.ModifyStyle(0,MCS_NOTODAYCIRCLE);
else
m_ctlMonthCal.ModifyStyle(MCS_NOTODAYCIRCLE,0);
#endif
if(m_bWeeknumbers)
m_ctlMonthCal.ModifyStyle(0,MCS_WEEKNUMBERS);
else
m_ctlMonthCal.ModifyStyle(MCS_WEEKNUMBERS,0);
m_ctlMonthCal.SetMaxSelCount(m_nMaxSel);
m_ctlMonthCal.SetMonthDelta(m_nScrollRate);
m_ctlMonthCal.SetFirstDayOfWeek(m_nFirstDay);
m_ctlMonthCal.SetTrailingTextColor(m_clrTrailingText);
m_ctlMonthCal.SetTitleTextColor(m_clrTitleText);
m_ctlMonthCal.SetTitleBkColor(m_clrTitleBk);
m_ctlMonthCal.SetTextColor(m_clrText);
m_ctlMonthCal.SetMonthBkColor(m_clrMonthBk);
m_ctlMonthCal.SetBkColor(m_clrBk);
static CFont font;
if((HFONT)font!=NULL)
font.DeleteObject();
VERIFY(font.CreateFontIndirect(&m_lfText));
m_ctlMonthCal.SetFont(&font);
CSize szMargin(4,4);
switch(m_nDimension)
{
case 0:
m_ctlMonthCal.SetCtrlDimension(1,1,szMargin);
break;
case 1:
m_ctlMonthCal.SetCtrlDimension(2,1,szMargin);
break;
case 2:
m_ctlMonthCal.SetCtrlDimension(1,2,szMargin);
break;
case 3:
m_ctlMonthCal.SetCtrlDimension(2,2,szMargin);
break;
default:
ASSERT(FALSE);
}
}
//Notification handlers for notifications from the COXMonthCalCtrl
void CMonthCalendarDlg::OnGetDayState(NMHDR *pHdr, LRESULT *pRes)
{
NMDAYSTATE *pds = (NMDAYSTATE*)pHdr;
//this function just bolds the first four days of every visible
//month.
for(int i=0;i<pds->cDayState;i++)
BOLDDAY(pds->prgDayState[i],15);
*pRes=0;
}
void CMonthCalendarDlg::OnOXGetDayState(NMHDR *pHdr, LRESULT *pRes)
{
UNREFERENCED_PARAMETER(pHdr);
// LPOXNMDAYSTATE pds = (LPOXNMDAYSTATE)pHdr;
*pRes=0;
}
void CMonthCalendarDlg::OnOXGetInfoTip(NMHDR *pHdr, LRESULT *pRes)
{
LPOXNMMCINFOTIP pInfoTip = (LPOXNMMCINFOTIP)pHdr;
CString sText=_T("");
if(pInfoTip->pMCHitTest->uHit==MCHT_TITLEBTNNEXT)
sText=_T("Button next");
else if(pInfoTip->pMCHitTest->uHit==MCHT_TITLEBTNPREV)
sText=_T("Button previous");
else if(pInfoTip->pMCHitTest->uHit==MCHT_TITLEMONTH)
sText=_T("Month name");
else if(pInfoTip->pMCHitTest->uHit==MCHT_TITLEYEAR)
sText=_T("Year");
else if(pInfoTip->pMCHitTest->uHit==MCHT_TITLEBK)
sText=_T("Title background");
else if(pInfoTip->pMCHitTest->uHit==MCHT_NOWHERE)
sText=_T("Nowhere");
else if(pInfoTip->pMCHitTest->uHit==MCHT_CALENDARBK)
sText=_T("Calendar background");
else if(pInfoTip->pMCHitTest->uHit==MCHT_CALENDARDAY)
sText=_T("Week day");
else if(pInfoTip->pMCHitTest->uHit==MCHT_CALENDARWEEKNUM)
sText=_T("Week number");
else if(pInfoTip->pMCHitTest->uHit==MCHT_CALENDARDATENEXT)
sText=_T("Date from next month");
else if(pInfoTip->pMCHitTest->uHit==MCHT_CALENDARDATEPREV)
sText=_T("Date from previous month");
else if(pInfoTip->pMCHitTest->uHit==MCHT_CALENDARDATE)
sText=_T("Date from current month");
else if(pInfoTip->pMCHitTest->uHit==MCHT_TODAYLINK)
sText=_T("Today link");
UTBStr::tcsncpy(pInfoTip->szText,countof(pInfoTip->szText),
sText.GetBuffer(sText.GetLength()), countof(pInfoTip->szText));
sText.ReleaseBuffer();
*pRes=0;
}
void CMonthCalendarDlg::OnSelect(NMHDR *pHdr, LRESULT *pRes)
{
UNREFERENCED_PARAMETER(pHdr);
GetLatestSelInfo();
GetDlgItem(IDC_SELECTION)->SetWindowText(m_sSelection);
*pRes=0;
}
void CMonthCalendarDlg::OnSelChange(NMHDR *pHdr, LRESULT *pRes)
{
UNREFERENCED_PARAMETER(pHdr);
GetLatestSelInfo();
GetDlgItem(IDC_RANGEFROM)->SetWindowText(m_sRangeFrom);
GetDlgItem(IDC_RANGETO)->SetWindowText(m_sRangeTo);
*pRes=0;
}
void CMonthCalendarDlg::OnButtonFontname()
{
// TODO: Add your control notification handler code here
// Use font common dialog
CFontDialog fontDlg(&m_lfText);
if(fontDlg.DoModal()==IDOK)
{
fontDlg.GetCurrentFont(&m_lfText);
m_sFontName.Format(_T("%d pt, %s"),fontDlg.GetSize()/10,m_lfText.lfFaceName);
m_ctlFontName.SetTextLogFont(&m_lfText);
UpdateData(FALSE);
}
}
int CMonthCalendarDlg::ConvertPointToLogUnit(const int nPointSize, CDC* pDC/*=NULL*/)
{
HDC hDC;
if (pDC!=NULL)
{
ASSERT_VALID(pDC);
ASSERT(pDC->m_hAttribDC != NULL);
hDC=pDC->m_hAttribDC;
}
else
hDC=::GetDC(NULL);
// convert nPointSize to logical units based on pDC
POINT pt;
pt.y=::GetDeviceCaps(hDC,LOGPIXELSY)*nPointSize;
pt.y/=720; // 72 points/inch, 10 decipoints/point
::DPtoLP(hDC,&pt,1);
POINT ptOrg = {0,0};
::DPtoLP(hDC,&ptOrg,1);
if(pDC==NULL)
::ReleaseDC(NULL,hDC);
return -abs(pt.y-ptOrg.y);
}
int CMonthCalendarDlg::ConvertLogUnitToPoint(const int nLogUnitSize, CDC* pDC/*=NULL*/)
{
HDC hDC;
if (pDC!=NULL)
{
ASSERT_VALID(pDC);
ASSERT(pDC->m_hAttribDC != NULL);
hDC=pDC->m_hAttribDC;
}
else
hDC=::GetDC(NULL);
POINT ptOrg={0,0};
::DPtoLP(hDC,&ptOrg,1);
POINT pt={0,0};
pt.y=abs(nLogUnitSize)+ptOrg.y;
::LPtoDP(hDC,&pt,1);
pt.y*=720; // 72 points/inch, 10 decipoints/point
int nPointSize=(pt.y)/(::GetDeviceCaps(hDC,LOGPIXELSY));
if (pDC==NULL)
::ReleaseDC(NULL,hDC);
return nPointSize;
}