📄 monthcal.c
字号:
}
else {
retval = MCHT_CALENDARDATE;
lpht->st.wMonth = infoPtr->currentMonth;
lpht->st.wDay = day;
lpht->st.wDayOfWeek = MONTHCAL_CalculateDayOfWeek(day,lpht->st.wMonth,lpht->st.wYear);
}
goto done;
}
if(PtInRect(&infoPtr->todayrect, lpht->pt)) {
retval = MCHT_TODAYLINK;
goto done;
}
/* Hit nothing special? What's left must be background :-) */
retval = MCHT_CALENDARBK;
done:
lpht->uHit = retval;
return retval;
}
static void MONTHCAL_GoToNextMonth(MONTHCAL_INFO *infoPtr)
{
DWORD dwStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE);
TRACE("MONTHCAL_GoToNextMonth\n");
infoPtr->currentMonth++;
if(infoPtr->currentMonth > 12) {
infoPtr->currentYear++;
infoPtr->currentMonth = 1;
}
if(dwStyle & MCS_DAYSTATE) {
NMDAYSTATE nmds;
int i;
nmds.nmhdr.hwndFrom = infoPtr->hwndSelf;
nmds.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
nmds.nmhdr.code = MCN_GETDAYSTATE;
nmds.cDayState = infoPtr->monthRange;
nmds.prgDayState = Alloc(infoPtr->monthRange * sizeof(MONTHDAYSTATE));
SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
(WPARAM)nmds.nmhdr.idFrom, (LPARAM)&nmds);
for(i=0; i<infoPtr->monthRange; i++)
infoPtr->monthdayState[i] = nmds.prgDayState[i];
}
}
static void MONTHCAL_GoToPrevMonth(MONTHCAL_INFO *infoPtr)
{
DWORD dwStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE);
TRACE("\n");
infoPtr->currentMonth--;
if(infoPtr->currentMonth < 1) {
infoPtr->currentYear--;
infoPtr->currentMonth = 12;
}
if(dwStyle & MCS_DAYSTATE) {
NMDAYSTATE nmds;
int i;
nmds.nmhdr.hwndFrom = infoPtr->hwndSelf;
nmds.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
nmds.nmhdr.code = MCN_GETDAYSTATE;
nmds.cDayState = infoPtr->monthRange;
nmds.prgDayState = Alloc
(infoPtr->monthRange * sizeof(MONTHDAYSTATE));
SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
(WPARAM)nmds.nmhdr.idFrom, (LPARAM)&nmds);
for(i=0; i<infoPtr->monthRange; i++)
infoPtr->monthdayState[i] = nmds.prgDayState[i];
}
}
static LRESULT
MONTHCAL_RButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam)
{
static const WCHAR todayW[] = { 'G','o',' ','t','o',' ','T','o','d','a','y',':',0 };
HMENU hMenu;
POINT menupoint;
WCHAR buf[32];
hMenu = CreatePopupMenu();
if (!LoadStringW(COMCTL32_hModule,IDM_GOTODAY,buf,countof(buf)))
{
WARN("Can't load resource\n");
strcpyW(buf, todayW);
}
AppendMenuW(hMenu, MF_STRING|MF_ENABLED,1, buf);
menupoint.x=(short)LOWORD(lParam);
menupoint.y=(short)HIWORD(lParam);
ClientToScreen(infoPtr->hwndSelf, &menupoint);
if( TrackPopupMenu(hMenu,TPM_RIGHTBUTTON| TPM_NONOTIFY|TPM_RETURNCMD,
menupoint.x, menupoint.y, 0, infoPtr->hwndSelf, NULL))
{
infoPtr->currentMonth=infoPtr->todaysDate.wMonth;
infoPtr->currentYear=infoPtr->todaysDate.wYear;
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
}
return 0;
}
static LRESULT
MONTHCAL_LButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam)
{
static const WCHAR EditW[] = { 'E','D','I','T',0 };
MCHITTESTINFO ht;
DWORD hit;
HMENU hMenu;
RECT rcDay; /* used in determining area to invalidate */
WCHAR buf[32];
int i;
POINT menupoint;
TRACE("%lx\n", lParam);
if (infoPtr->hWndYearUpDown)
{
infoPtr->currentYear=SendMessageW( infoPtr->hWndYearUpDown, UDM_SETPOS, (WPARAM) 0,(LPARAM)0);
if(!DestroyWindow(infoPtr->hWndYearUpDown))
{
FIXME("Can't destroy Updown Control\n");
}
else
infoPtr->hWndYearUpDown=0;
if(!DestroyWindow(infoPtr->hWndYearEdit))
{
FIXME("Can't destroy Updown Control\n");
}
else
infoPtr->hWndYearEdit=0;
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
}
ht.pt.x = (short)LOWORD(lParam);
ht.pt.y = (short)HIWORD(lParam);
hit = MONTHCAL_HitTest(infoPtr, (LPARAM)&ht);
/* FIXME: these flags should be checked by */
/*((hit & MCHT_XXX) == MCHT_XXX) b/c some of the flags are */
/* multi-bit */
if(hit ==MCHT_TITLEBTNNEXT) {
MONTHCAL_GoToNextMonth(infoPtr);
infoPtr->status = MC_NEXTPRESSED;
SetTimer(infoPtr->hwndSelf, MC_NEXTMONTHTIMER, MC_NEXTMONTHDELAY, 0);
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return TRUE;
}
if(hit == MCHT_TITLEBTNPREV){
MONTHCAL_GoToPrevMonth(infoPtr);
infoPtr->status = MC_PREVPRESSED;
SetTimer(infoPtr->hwndSelf, MC_PREVMONTHTIMER, MC_NEXTMONTHDELAY, 0);
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return TRUE;
}
if(hit == MCHT_TITLEMONTH) {
hMenu = CreatePopupMenu();
for (i=0; i<12;i++)
{
GetLocaleInfoW(LOCALE_USER_DEFAULT,LOCALE_SMONTHNAME1+i, buf,countof(buf));
AppendMenuW(hMenu, MF_STRING|MF_ENABLED,i+1, buf);
}
menupoint.x=infoPtr->titlemonth.right;
menupoint.y=infoPtr->titlemonth.bottom;
ClientToScreen(infoPtr->hwndSelf, &menupoint);
i= TrackPopupMenu(hMenu,TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RIGHTBUTTON | TPM_RETURNCMD,
menupoint.x, menupoint.y, 0, infoPtr->hwndSelf, NULL);
if ((i>0) && (i<13))
{
infoPtr->currentMonth=i;
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
}
}
if(hit == MCHT_TITLEYEAR) {
infoPtr->hWndYearEdit=CreateWindowExW(0,
EditW,
0,
WS_VISIBLE | WS_CHILD |UDS_SETBUDDYINT,
infoPtr->titleyear.left+3,infoPtr->titlebtnnext.top,
infoPtr->titleyear.right-infoPtr->titleyear.left+4,
infoPtr->textHeight,
infoPtr->hwndSelf,
NULL,
NULL,
NULL);
SendMessageW( infoPtr->hWndYearEdit, WM_SETFONT, (WPARAM) infoPtr->hBoldFont, (LPARAM)TRUE);
infoPtr->hWndYearUpDown=CreateWindowExW(0,
UPDOWN_CLASSW,
0,
WS_VISIBLE | WS_CHILD |UDS_SETBUDDYINT|UDS_NOTHOUSANDS|UDS_ARROWKEYS,
infoPtr->titleyear.right+7,infoPtr->titlebtnnext.top,
18,
infoPtr->textHeight,
infoPtr->hwndSelf,
NULL,
NULL,
NULL);
SendMessageW( infoPtr->hWndYearUpDown, UDM_SETRANGE, (WPARAM) 0, MAKELONG (9999, 1753));
SendMessageW( infoPtr->hWndYearUpDown, UDM_SETBUDDY, (WPARAM) infoPtr->hWndYearEdit, (LPARAM)0 );
SendMessageW( infoPtr->hWndYearUpDown, UDM_SETPOS, (WPARAM) 0,(LPARAM)infoPtr->currentYear );
return TRUE;
}
if(hit == MCHT_TODAYLINK) {
infoPtr->currentMonth=infoPtr->todaysDate.wMonth;
infoPtr->currentYear=infoPtr->todaysDate.wYear;
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return TRUE;
}
if(hit == MCHT_CALENDARDATE) {
SYSTEMTIME selArray[2];
NMSELCHANGE nmsc;
MONTHCAL_CopyTime(&ht.st, &selArray[0]);
MONTHCAL_CopyTime(&ht.st, &selArray[1]);
MONTHCAL_SetSelRange(infoPtr, (LPARAM)&selArray);
MONTHCAL_SetCurSel(infoPtr, (LPARAM)&selArray);
TRACE("MCHT_CALENDARDATE\n");
nmsc.nmhdr.hwndFrom = infoPtr->hwndSelf;
nmsc.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
nmsc.nmhdr.code = MCN_SELCHANGE;
MONTHCAL_CopyTime(&infoPtr->minSel,&nmsc.stSelStart);
MONTHCAL_CopyTime(&infoPtr->maxSel,&nmsc.stSelEnd);
SendMessageW(infoPtr->hwndNotify, WM_NOTIFY,
(WPARAM)nmsc.nmhdr.idFrom,(LPARAM)&nmsc);
/* redraw both old and new days if the selected day changed */
if(infoPtr->curSelDay != ht.st.wDay) {
MONTHCAL_CalcPosFromDay(infoPtr, ht.st.wDay, ht.st.wMonth, &rcDay);
InvalidateRect(infoPtr->hwndSelf, &rcDay, TRUE);
MONTHCAL_CalcPosFromDay(infoPtr, infoPtr->curSelDay, infoPtr->currentMonth, &rcDay);
InvalidateRect(infoPtr->hwndSelf, &rcDay, TRUE);
}
infoPtr->firstSelDay = ht.st.wDay;
infoPtr->curSelDay = ht.st.wDay;
infoPtr->status = MC_SEL_LBUTDOWN;
return TRUE;
}
return 0;
}
static LRESULT
MONTHCAL_LButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam)
{
NMSELCHANGE nmsc;
NMHDR nmhdr;
BOOL redraw = FALSE;
MCHITTESTINFO ht;
DWORD hit;
TRACE("\n");
if(infoPtr->status & MC_NEXTPRESSED) {
KillTimer(infoPtr->hwndSelf, MC_NEXTMONTHTIMER);
infoPtr->status &= ~MC_NEXTPRESSED;
redraw = TRUE;
}
if(infoPtr->status & MC_PREVPRESSED) {
KillTimer(infoPtr->hwndSelf, MC_PREVMONTHTIMER);
infoPtr->status &= ~MC_PREVPRESSED;
redraw = TRUE;
}
ht.pt.x = (short)LOWORD(lParam);
ht.pt.y = (short)HIWORD(lParam);
hit = MONTHCAL_HitTest(infoPtr, (LPARAM)&ht);
infoPtr->status = MC_SEL_LBUTUP;
if(hit ==MCHT_CALENDARDATENEXT) {
MONTHCAL_GoToNextMonth(infoPtr);
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return TRUE;
}
if(hit == MCHT_CALENDARDATEPREV){
MONTHCAL_GoToPrevMonth(infoPtr);
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return TRUE;
}
nmhdr.hwndFrom = infoPtr->hwndSelf;
nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
nmhdr.code = NM_RELEASEDCAPTURE;
TRACE("Sent notification from %p to %p\n", infoPtr->hwndSelf, infoPtr->hwndNotify);
SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
/* redraw if necessary */
if(redraw)
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
/* only send MCN_SELECT if currently displayed month's day was selected */
if(hit == MCHT_CALENDARDATE) {
nmsc.nmhdr.hwndFrom = infoPtr->hwndSelf;
nmsc.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID);
nmsc.nmhdr.code = MCN_SELECT;
MONTHCAL_CopyTime(&infoPtr->minSel, &nmsc.stSelStart);
MONTHCAL_CopyTime(&infoPtr->maxSel, &nmsc.stSelEnd);
SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, (WPARAM)nmsc.nmhdr.idFrom, (LPARAM)&nmsc);
}
return 0;
}
static LRESULT
MONTHCAL_Timer(MONTHCAL_INFO *infoPtr, WPARAM wParam)
{
BOOL redraw = FALSE;
TRACE("%d\n", wParam);
switch(wParam) {
case MC_NEXTMONTHTIMER:
redraw = TRUE;
MONTHCAL_GoToNextMonth(infoPtr);
break;
case MC_PREVMONTHTIMER:
redraw = TRUE;
MONTHCAL_GoToPrevMonth(infoPtr);
break;
default:
ERR("got unknown timer\n");
break;
}
/* redraw only if necessary */
if(redraw)
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return 0;
}
static LRESULT
MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, WPARAM wParam, LPARAM lParam)
{
MCHITTESTINFO ht;
int oldselday, selday, hit;
RECT r;
if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0;
ht.pt.x = (short)LOWORD(lParam);
ht.pt.y = (short)HIWORD(lParam);
hit = MONTHCAL_HitTest(infoPtr, (LPARAM)&ht);
/* not on the calendar date numbers? bail out */
TRACE("hit:%x\n",hit);
if((hit & MCHT_CALENDARDATE) != MCHT_CALENDARDATE) return 0;
selday = ht.st.wDay;
oldselday = infoPtr->curSelDay;
infoPtr->curSelDay = selday;
MONTHCAL_CalcPosFromDay(infoPtr, selday, ht.st. wMonth, &r);
if(GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE) & MCS_MULTISELECT) {
SYSTEMTIME selArray[2];
int i;
MONTHCAL_GetSelRange(infoPtr, (LPARAM)&selArray);
i = 0;
if(infoPtr->firstSelDay==selArray[0].wDay) i=1;
TRACE("oldRange:%d %d %d %d\n", infoPtr->firstSelDay, selArray[0].wDay, selArray[1].wDay, i);
if(infoPtr->firstSelDay==selArray[1].wDay) {
/* 1st time we get here: selArray[0]=selArray[1]) */
/* if we're still at the first selected date, return */
if(infoPtr->firstSelDay==selday) goto done;
if(selday<infoPtr->firstSelDay) i = 0;
}
if(abs(infoPtr->firstSelDay - selday) >= infoPtr->maxSelCount) {
if(selday>infoPtr->firstSelDay)
selday = infoPtr->firstSelDay + infoPtr->maxSelCount;
else
selday = infoPtr->firstSelDay - infoPtr->maxSelCount;
}
if(selArray[i].wDay!=selday) {
TRACE("newRange:%d %d %d %d\n", infoPtr->firstSelDay, selArray[0].wDay, selArray[1].wDay, i);
selArray[i].wDay = selday;
if(selArray[0].wDay>selArray[1].wDay) {
DWORD tempday;
tempday = selArray[1].wDay;
selArray[1].wDay = selArray[0].wDay;
selArray[0].wDay = tempday;
}
MONTHCAL_SetSelRange(infoPtr, (LPARAM)&selArray);
}
}
done:
/* only redraw if the currently selected day changed */
/* FIXME: this should specify a rectangle containing only the days that changed */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -