📄 monthcal.c
字号:
/* using InvalidateRect */
if(oldselday != infoPtr->curSelDay)
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return 0;
}
static LRESULT
MONTHCAL_Paint(MONTHCAL_INFO *infoPtr, WPARAM wParam)
{
HDC hdc;
PAINTSTRUCT ps;
if (wParam)
{
GetClientRect(infoPtr->hwndSelf, &ps.rcPaint);
hdc = (HDC)wParam;
}
else
hdc = BeginPaint(infoPtr->hwndSelf, &ps);
MONTHCAL_Refresh(infoPtr, hdc, &ps);
if (!wParam) EndPaint(infoPtr->hwndSelf, &ps);
return 0;
}
static LRESULT
MONTHCAL_KillFocus(MONTHCAL_INFO *infoPtr)
{
TRACE("\n");
InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
return 0;
}
static LRESULT
MONTHCAL_SetFocus(MONTHCAL_INFO *infoPtr)
{
TRACE("\n");
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return 0;
}
/* sets the size information */
static void MONTHCAL_UpdateSize(MONTHCAL_INFO *infoPtr)
{
static const WCHAR SunW[] = { 'S','u','n',0 };
static const WCHAR O0W[] = { '0','0',0 };
HDC hdc = GetDC(infoPtr->hwndSelf);
RECT *title=&infoPtr->title;
RECT *prev=&infoPtr->titlebtnprev;
RECT *next=&infoPtr->titlebtnnext;
RECT *titlemonth=&infoPtr->titlemonth;
RECT *titleyear=&infoPtr->titleyear;
RECT *wdays=&infoPtr->wdays;
RECT *weeknumrect=&infoPtr->weeknums;
RECT *days=&infoPtr->days;
RECT *todayrect=&infoPtr->todayrect;
SIZE size;
TEXTMETRICW tm;
DWORD dwStyle = GetWindowLongW(infoPtr->hwndSelf, GWL_STYLE);
HFONT currentFont;
int xdiv, left_offset;
RECT rcClient;
GetClientRect(infoPtr->hwndSelf, &rcClient);
currentFont = SelectObject(hdc, infoPtr->hFont);
/* get the height and width of each day's text */
GetTextMetricsW(hdc, &tm);
infoPtr->textHeight = tm.tmHeight + tm.tmExternalLeading + tm.tmInternalLeading;
GetTextExtentPoint32W(hdc, SunW, 3, &size);
infoPtr->textWidth = size.cx + 2;
/* recalculate the height and width increments and offsets */
GetTextExtentPoint32W(hdc, O0W, 2, &size);
xdiv = (dwStyle & MCS_WEEKNUMBERS) ? 8 : 7;
infoPtr->width_increment = size.cx * 2 + 4;
infoPtr->height_increment = infoPtr->textHeight;
left_offset = (rcClient.right - rcClient.left) - (infoPtr->width_increment * xdiv);
/* calculate title area */
title->top = rcClient.top;
title->bottom = title->top + 3 * infoPtr->height_increment / 2;
title->left = left_offset;
title->right = rcClient.right;
/* set the dimensions of the next and previous buttons and center */
/* the month text vertically */
prev->top = next->top = title->top + 4;
prev->bottom = next->bottom = title->bottom - 4;
prev->left = title->left + 4;
prev->right = prev->left + (title->bottom - title->top) ;
next->right = title->right - 4;
next->left = next->right - (title->bottom - title->top);
/* titlemonth->left and right change based upon the current month */
/* and are recalculated in refresh as the current month may change */
/* without the control being resized */
titlemonth->top = titleyear->top = title->top + (infoPtr->height_increment)/2;
titlemonth->bottom = titleyear->bottom = title->bottom - (infoPtr->height_increment)/2;
/* setup the dimensions of the rectangle we draw the names of the */
/* days of the week in */
weeknumrect->left = left_offset;
if(dwStyle & MCS_WEEKNUMBERS)
weeknumrect->right=prev->right;
else
weeknumrect->right=weeknumrect->left;
wdays->left = days->left = weeknumrect->right;
wdays->right = days->right = wdays->left + 7 * infoPtr->width_increment;
wdays->top = title->bottom ;
wdays->bottom = wdays->top + infoPtr->height_increment;
days->top = weeknumrect->top = wdays->bottom ;
days->bottom = weeknumrect->bottom = days->top + 6 * infoPtr->height_increment;
todayrect->left = rcClient.left;
todayrect->right = rcClient.right;
todayrect->top = days->bottom;
todayrect->bottom = days->bottom + infoPtr->height_increment;
TRACE("dx=%d dy=%d client[%s] title[%s] wdays[%s] days[%s] today[%s]\n",
infoPtr->width_increment,infoPtr->height_increment,
wine_dbgstr_rect(&rcClient),
wine_dbgstr_rect(title),
wine_dbgstr_rect(wdays),
wine_dbgstr_rect(days),
wine_dbgstr_rect(todayrect));
/* restore the originally selected font */
SelectObject(hdc, currentFont);
ReleaseDC(infoPtr->hwndSelf, hdc);
}
static LRESULT MONTHCAL_Size(MONTHCAL_INFO *infoPtr, int Width, int Height)
{
TRACE("(width=%d, height=%d)\n", Width, Height);
MONTHCAL_UpdateSize(infoPtr);
/* invalidate client area and erase background */
InvalidateRect(infoPtr->hwndSelf, NULL, TRUE);
return 0;
}
static LRESULT MONTHCAL_GetFont(MONTHCAL_INFO *infoPtr)
{
return (LRESULT)infoPtr->hFont;
}
static LRESULT MONTHCAL_SetFont(MONTHCAL_INFO *infoPtr, HFONT hFont, BOOL redraw)
{
HFONT hOldFont;
LOGFONTW lf;
if (!hFont) return 0;
hOldFont = infoPtr->hFont;
infoPtr->hFont = hFont;
GetObjectW(infoPtr->hFont, sizeof(lf), &lf);
lf.lfWeight = FW_BOLD;
infoPtr->hBoldFont = CreateFontIndirectW(&lf);
if (redraw)
InvalidateRect(infoPtr->hwndSelf, NULL, FALSE);
return (LRESULT)hOldFont;
}
/* update theme after a WM_THEMECHANGED message */
static LRESULT theme_changed (MONTHCAL_INFO* infoPtr)
{
HTHEME theme = GetWindowTheme (infoPtr->hwndSelf);
CloseThemeData (theme);
theme = OpenThemeData (infoPtr->hwndSelf, themeClass);
return 0;
}
/* FIXME: check whether dateMin/dateMax need to be adjusted. */
static LRESULT
MONTHCAL_Create(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
MONTHCAL_INFO *infoPtr;
/* allocate memory for info structure */
infoPtr =(MONTHCAL_INFO*)Alloc(sizeof(MONTHCAL_INFO));
SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr);
if(infoPtr == NULL) {
ERR( "could not allocate info memory!\n");
return 0;
}
infoPtr->hwndSelf = hwnd;
infoPtr->hwndNotify = ((LPCREATESTRUCTW)lParam)->hwndParent;
MONTHCAL_SetFont(infoPtr, GetStockObject(DEFAULT_GUI_FONT), FALSE);
/* initialize info structure */
/* FIXME: calculate systemtime ->> localtime(substract timezoneinfo) */
GetLocalTime(&infoPtr->todaysDate);
MONTHCAL_SetFirstDayOfWeek(infoPtr, (LPARAM)-1);
infoPtr->currentMonth = infoPtr->todaysDate.wMonth;
infoPtr->currentYear = infoPtr->todaysDate.wYear;
MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->minDate);
MONTHCAL_CopyTime(&infoPtr->todaysDate, &infoPtr->maxDate);
infoPtr->maxDate.wYear=2050;
infoPtr->minDate.wYear=1950;
infoPtr->maxSelCount = 7;
infoPtr->monthRange = 3;
infoPtr->monthdayState = Alloc
(infoPtr->monthRange * sizeof(MONTHDAYSTATE));
infoPtr->titlebk = GetSysColor(COLOR_ACTIVECAPTION);
infoPtr->titletxt = GetSysColor(COLOR_WINDOW);
infoPtr->monthbk = GetSysColor(COLOR_WINDOW);
infoPtr->trailingtxt = GetSysColor(COLOR_GRAYTEXT);
infoPtr->bk = GetSysColor(COLOR_WINDOW);
infoPtr->txt = GetSysColor(COLOR_WINDOWTEXT);
/* call MONTHCAL_UpdateSize to set all of the dimensions */
/* of the control */
MONTHCAL_UpdateSize(infoPtr);
OpenThemeData (infoPtr->hwndSelf, themeClass);
return 0;
}
static LRESULT
MONTHCAL_Destroy(MONTHCAL_INFO *infoPtr)
{
/* free month calendar info data */
if(infoPtr->monthdayState)
Free(infoPtr->monthdayState);
SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0);
CloseThemeData (GetWindowTheme (infoPtr->hwndSelf));
Free(infoPtr);
return 0;
}
static LRESULT WINAPI
MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
MONTHCAL_INFO *infoPtr;
TRACE("hwnd=%p msg=%x wparam=%x lparam=%lx\n", hwnd, uMsg, wParam, lParam);
infoPtr = MONTHCAL_GetInfoPtr(hwnd);
if (!infoPtr && (uMsg != WM_CREATE))
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
switch(uMsg)
{
case MCM_GETCURSEL:
return MONTHCAL_GetCurSel(infoPtr, lParam);
case MCM_SETCURSEL:
return MONTHCAL_SetCurSel(infoPtr, lParam);
case MCM_GETMAXSELCOUNT:
return MONTHCAL_GetMaxSelCount(infoPtr);
case MCM_SETMAXSELCOUNT:
return MONTHCAL_SetMaxSelCount(infoPtr, wParam);
case MCM_GETSELRANGE:
return MONTHCAL_GetSelRange(infoPtr, lParam);
case MCM_SETSELRANGE:
return MONTHCAL_SetSelRange(infoPtr, lParam);
case MCM_GETMONTHRANGE:
return MONTHCAL_GetMonthRange(infoPtr);
case MCM_SETDAYSTATE:
return MONTHCAL_SetDayState(infoPtr, wParam, lParam);
case MCM_GETMINREQRECT:
return MONTHCAL_GetMinReqRect(infoPtr, lParam);
case MCM_GETCOLOR:
return MONTHCAL_GetColor(infoPtr, wParam);
case MCM_SETCOLOR:
return MONTHCAL_SetColor(infoPtr, wParam, lParam);
case MCM_GETTODAY:
return MONTHCAL_GetToday(infoPtr, lParam);
case MCM_SETTODAY:
return MONTHCAL_SetToday(infoPtr, lParam);
case MCM_HITTEST:
return MONTHCAL_HitTest(infoPtr, lParam);
case MCM_GETFIRSTDAYOFWEEK:
return MONTHCAL_GetFirstDayOfWeek(infoPtr);
case MCM_SETFIRSTDAYOFWEEK:
return MONTHCAL_SetFirstDayOfWeek(infoPtr, lParam);
case MCM_GETRANGE:
return MONTHCAL_GetRange(hwnd, wParam, lParam);
case MCM_SETRANGE:
return MONTHCAL_SetRange(infoPtr, wParam, lParam);
case MCM_GETMONTHDELTA:
return MONTHCAL_GetMonthDelta(infoPtr);
case MCM_SETMONTHDELTA:
return MONTHCAL_SetMonthDelta(infoPtr, wParam);
case MCM_GETMAXTODAYWIDTH:
return MONTHCAL_GetMaxTodayWidth(infoPtr);
case WM_GETDLGCODE:
return DLGC_WANTARROWS | DLGC_WANTCHARS;
case WM_KILLFOCUS:
return MONTHCAL_KillFocus(infoPtr);
case WM_RBUTTONDOWN:
return MONTHCAL_RButtonDown(infoPtr, lParam);
case WM_LBUTTONDOWN:
return MONTHCAL_LButtonDown(infoPtr, lParam);
case WM_MOUSEMOVE:
return MONTHCAL_MouseMove(infoPtr, wParam, lParam);
case WM_LBUTTONUP:
return MONTHCAL_LButtonUp(infoPtr, lParam);
case WM_PRINTCLIENT:
case WM_PAINT:
return MONTHCAL_Paint(infoPtr, wParam);
case WM_SETFOCUS:
return MONTHCAL_SetFocus(infoPtr);
case WM_SIZE:
return MONTHCAL_Size(infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam));
case WM_CREATE:
return MONTHCAL_Create(hwnd, wParam, lParam);
case WM_SETFONT:
return MONTHCAL_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam);
case WM_GETFONT:
return MONTHCAL_GetFont(infoPtr);
case WM_TIMER:
return MONTHCAL_Timer(infoPtr, wParam);
case WM_THEMECHANGED:
return theme_changed (infoPtr);
case WM_DESTROY:
return MONTHCAL_Destroy(infoPtr);
default:
if ((uMsg >= WM_USER) && (uMsg < WM_APP))
ERR( "unknown msg %04x wp=%08x lp=%08lx\n", uMsg, wParam, lParam);
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}
}
void
MONTHCAL_Register(void)
{
WNDCLASSW wndClass;
ZeroMemory(&wndClass, sizeof(WNDCLASSW));
wndClass.style = CS_GLOBALCLASS;
wndClass.lpfnWndProc = MONTHCAL_WindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = sizeof(MONTHCAL_INFO *);
wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndClass.lpszClassName = MONTHCAL_CLASSW;
RegisterClassW(&wndClass);
}
void
MONTHCAL_Unregister(void)
{
UnregisterClassW(MONTHCAL_CLASSW, NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -